برچسب تخصیص هزینه AWS: راهنمای حاکمیت ۲۰۲۶

برچسب‌های تخصیص هزینه AWS ستون فقرات مدل Showback در محیط چند حسابی هستند. در این راهنمای عملی طرح‌واره، Tag Policy، SCP، AWS Config و سازگاری با FOCUS ۱٫۲ را با نمونه‌های JSON و CLI پوشش می‌دهم.

به‌روزرسانی: ۲۸ اوت ۲۰۲۶

برچسب تخصیص هزینه AWS (Cost Allocation Tag) یک جفت کلید-مقدار است که به منابع AWS پیوست می‌شود تا هزینه‌ها را در Cost Explorer، Cost and Usage Report (CUR) و Budgets بر اساس مالک، محیط، محصول یا مرکز هزینه گروه‌بندی کند. برای اینکه یک برچسب در گزارش‌های هزینه ظاهر شود، باید در کنسول Billing به‌طور صریح «فعال» شود و پس از فعال‌سازی حدود ۲۴ ساعت طول می‌کشد تا داده‌های تاریخی همگام شوند. در محیط‌های چند حسابی، بدون یک طرح‌واره منسجم و اعمال مرکزی، این برچسب‌ها به‌سرعت به «سطل بدون برچسب» تبدیل می‌شوند و مدل تخصیص هزینه از هم می‌پاشد.

  • در ۲۰۲۶، AWS از ۵۰ برچسب کاربر-تعریف در هر منبع پشتیبانی می‌کند و از این میان ۵۰۰ برچسب می‌تواند به‌عنوان Cost Allocation Tag در سازمان فعال شود.
  • Tag Policy در AWS Organizations فقط «راهنمای انطباق» است؛ اجرای اجباری واقعی از طریق Service Control Policy (SCP) با شرط aws:RequestTag و aws:TagKeys انجام می‌شود.
  • حداقل طرح‌واره پیشنهادی شامل ۶ کلید است: Environment، Owner، CostCenter، Application، DataClassification و ManagedBy. این مجموعه مبنای مدل Showback/Chargeback است.
  • استاندارد FOCUS ۱٫۲ (منتشرشده در ژوئن ۲۰۲۶) ستون Tags را به‌عنوان یک شیء JSON استاندارد می‌کند و باعث می‌شود گزارش‌های چند-ابری یکسان تفسیر شوند.
  • منابع بدون برچسب باید در «سطل Unallocated» شمارش شوند و به تیم پلتفرم اختصاص یابند، نه اینکه بین همه تقسیم شوند.
  • خودکارسازی برچسب‌گذاری از طریق EventBridge + Lambda هنگام رویداد RunInstances یا CreateBucket از افت پوشش برچسب جلوگیری می‌کند.

برچسب تخصیص هزینه AWS چیست؟

برچسب تخصیص هزینه (Cost Allocation Tag) در واقع یک برچسب معمولی AWS است که در Billing Console «فعال» شده است. تا زمانی که آن را فعال نکنید، AWS داده‌های هزینه را بر اساس آن گروه‌بندی نمی‌کند، حتی اگر برچسب روی تک‌تک منابع وجود داشته باشد. صادقانه بگویم، در مدل ذهنی من (بعد از سال‌ها کار روی حساب‌های چند صد میلیون دلاری)، برچسب‌ها لایه‌ای هستند که «هزینه فنی» (چه سرویسی، چه منطقه‌ای) را به «هزینه تجاری» (کدام تیم، کدام محصول، کدام مشتری) ترجمه می‌کنند.

در ۲۰۲۶، هر منبع AWS می‌تواند تا ۵۰ برچسب داشته باشد و در سطح سازمان (Organization) تا ۵۰۰ کلید برچسب قابل فعال‌سازی به‌عنوان Cost Allocation Tag هستند. محدودیت طول کلید (۱۲۸ کاراکتر) و مقدار (۲۵۶ کاراکتر) هنوز پابرجاست. یک اشتباه رایج این است که تیم‌ها گمان می‌کنند برچسب‌گذاری منابع کافی است؛ در حالی که بدون فعال‌سازی در Billing، کلید هرگز در گزارش UnblendedCost ستون‌بندی نمی‌شود. من دقیقاً همین اشتباه را در اولین پروژه FinOps خودم مرتکب شدم و سه هفته منتظر داده‌ای ماندم که هیچ‌وقت نیامد.

برای درک عمیق‌تر مکانیزم گزارش‌گیری هزینه، مطلب کاهش هزینه‌های انتقال داده AWS نشان می‌دهد که چرا حتی وقتی تگ درست است، هزینه Data Transfer در ستون lineItem/UsageType ظاهر می‌شود و ممکن است به منبع اشتباه نسبت داده شود.

تفاوت برچسب‌های AWS-generated و کاربر-تعریف

AWS دو خانواده برچسب برای تخصیص هزینه ارائه می‌دهد که سردرگمی زیادی ایجاد می‌کنند:

ویژگیAWS-generatedکاربر-تعریف (User-defined)
پیشوند کلیدaws:هر رشته‌ای غیر از aws:
مثالaws:createdByEnvironment، CostCenter
ویرایش‌پذیر توسط کاربرخیربله
نیاز به فعال‌سازی در Billingبله، جداگانهبله
پوشش سرویس‌هامحدود (عمدتاً EC2، S3، RDS)تقریباً همه سرویس‌ها
هزینه ذخیره‌سازی در CURرایگانرایگان

برچسب aws:createdBy در بسیاری از حساب‌ها یک نجات‌دهنده است، چون به‌طور خودکار principal (IAM user، role، یا حتی root) که منبع را ایجاد کرده ثبت می‌کند. برای منابعی که یک اسکریپت Terraform یا Lambda ساخته، این کلید نشان می‌دهد کدام role مسئول است، که برای پیدا کردن ریشه leak فوق‌العاده مفید است. اما به تنهایی برای Chargeback کافی نیست، چون تیم‌ها اغلب از role مشترک استفاده می‌کنند.

در تجربه من روی محیط‌های بزرگ، ترکیب بهینه این است: aws:createdBy را فعال کنید تا حفره‌های حاکمیتی را ببینید، اما مدل تخصیص هزینه اصلی را روی برچسب‌های کاربر-تعریف بسازید که تیم پلتفرم بر آن‌ها کنترل دارد.

چگونه برچسب‌های تخصیص هزینه را فعال کنیم؟

فعال‌سازی فقط از حساب مدیریت (Management Account) سازمان قابل انجام است. مسیر کنسول: Billing and Cost Management ← Cost Allocation Tags ← انتخاب کلیدها ← Activate. اما در محیط چند حسابی این کار را از طریق CLI انجام دهید تا قابل نسخه‌بندی باشد:

aws ce update-cost-allocation-tags-status \
  --cost-allocation-tags-status \
  '[{"TagKey":"Environment","Status":"Active"},
    {"TagKey":"CostCenter","Status":"Active"},
    {"TagKey":"Owner","Status":"Active"},
    {"TagKey":"Application","Status":"Active"},
    {"TagKey":"DataClassification","Status":"Active"},
    {"TagKey":"ManagedBy","Status":"Active"}]' \
  --region us-east-1

برای بررسی وضعیت فعال‌سازی از این دستور استفاده کنید:

aws ce list-cost-allocation-tags \
  --status Active \
  --query 'CostAllocationTags[].{Key:TagKey,Type:Type,Status:Status}' \
  --output table

طراحی طرح‌واره برچسب‌گذاری برای محیط چند حسابی

یک طرح‌واره برچسب خوب کوتاه، اجرایی و بدون تناقض است. طرح‌واره‌ای که ۲۰ کلید اجباری دارد در عمل روی هیچ منبعی به‌درستی اعمال نمی‌شود. من همیشه با یک هسته حداقلی ۶ کلیدی شروع می‌کنم و هرگز از ۱۲ فراتر نمی‌روم.

هسته اجباری (Mandatory)

  • Environment: مجموعه بسته: prod | staging | dev | sandbox
  • Owner: آدرس ایمیل تیم (نه فرد)، مثلاً [email protected]
  • CostCenter: کد مالی از سیستم ERP (مثلاً CC-4521)
  • Application: شناسه اپلیکیشن از CMDB (مثلاً checkout-api)
  • DataClassification: public | internal | confidential | restricted
  • ManagedBy: ابزار مدیریت: terraform | cdk | manual | console

اختیاری (Optional)

  • Project: شناسه پروژه Jira/Asana
  • ExpiryDate: تاریخ ISO 8601 برای منابع موقت
  • Compliance: pci، hipaa، gdpr
  • BackupPolicy: daily، weekly، none

اعمال حاکمیت با Tag Policy در AWS Organizations

Tag Policy در AWS Organizations یک سند JSON است که کلیدهای مجاز، مقادیر مجاز و حساسیت به حروف بزرگ/کوچک را تعریف می‌کند. نکته بحث‌برانگیز: Tag Policy به‌طور پیش‌فرض جلوی ساخت منبع را نمی‌گیرد. فقط انطباق را گزارش می‌کند و اگر enforced_for برای سرویس مشخص شود، عملیات TagResource بعدی را مسدود می‌کند، نه ساخت اولیه را. این نقطه‌ای است که بسیاری از تیم‌ها اشتباه می‌کنند.

{
  "tags": {
    "environment": {
      "tag_key": {
        "@@assign": "Environment"
      },
      "tag_value": {
        "@@assign": ["prod", "staging", "dev", "sandbox"]
      },
      "enforced_for": {
        "@@assign": [
          "ec2:instance",
          "ec2:volume",
          "s3:bucket",
          "rds:db"
        ]
      }
    },
    "costcenter": {
      "tag_key": {
        "@@assign": "CostCenter"
      },
      "tag_value": {
        "@@assign": ["CC-*"]
      }
    }
  }
}

این Tag Policy را در ریشه سازمان یا OU خاص متصل کنید:

aws organizations create-policy \
  --name "cost-allocation-baseline" \
  --type TAG_POLICY \
  --content file://tag-policy.json

aws organizations attach-policy \
  --policy-id p-xxxxxxxxxx \
  --target-id ou-yyyy-zzzzzzzz

برای اطلاعات کامل درباره سینتکس Tag Policy، به مستندات رسمی AWS Organizations Tag Policy Syntax مراجعه کنید. به‌ویژه بخش @@append که در ارث‌بری OU حیاتی است.

اجرای اجباری با SCP و AWS Config

خب، برای اینکه واقعاً از ساخت منبع بدون برچسب جلوگیری کنید به Service Control Policy (SCP) نیاز دارید. SCP در لایه IAM اعمال می‌شود و می‌تواند ec2:RunInstances بدون CostCenter را رد کند:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyRunInstanceWithoutCostCenter",
      "Effect": "Deny",
      "Action": "ec2:RunInstances",
      "Resource": [
        "arn:aws:ec2:*:*:instance/*",
        "arn:aws:ec2:*:*:volume/*"
      ],
      "Condition": {
        "Null": {
          "aws:RequestTag/CostCenter": "true"
        }
      }
    },
    {
      "Sid": "DenyRemoveMandatoryTags",
      "Effect": "Deny",
      "Action": [
        "ec2:DeleteTags",
        "rds:RemoveTagsFromResource",
        "s3:DeleteObjectTagging"
      ],
      "Resource": "*",
      "Condition": {
        "ForAnyValue:StringEquals": {
          "aws:TagKeys": [
            "Environment",
            "CostCenter",
            "Owner"
          ]
        }
      }
    }
  ]
}

لایه دوم دفاع AWS Config است. قانون مدیریت‌شده required-tags منابع غیرمنطبق را شناسایی می‌کند و می‌توانید یک Remediation Action با SSM Automation برای اضافه کردن برچسب پیش‌فرض تعریف کنید. من ترجیح می‌دهم Remediation به‌جای Add-Tag، منبع را در یک SNS topic ثبت کند تا مالک تیم مطلع شود. اضافه کردن برچسب خودکار اشتباه بدتر از نبود برچسب است.

aws configservice put-config-rule --config-rule '{
  "ConfigRuleName": "required-tags-cost-allocation",
  "Source": {
    "Owner": "AWS",
    "SourceIdentifier": "REQUIRED_TAGS"
  },
  "InputParameters": "{\"tag1Key\":\"Environment\",\"tag2Key\":\"CostCenter\",\"tag3Key\":\"Owner\"}",
  "Scope": {
    "ComplianceResourceTypes": [
      "AWS::EC2::Instance",
      "AWS::S3::Bucket",
      "AWS::RDS::DBInstance",
      "AWS::Lambda::Function"
    ]
  }
}'

مدیریت منابع بدون برچسب و سطل Unallocated

حتی با بهترین حاکمیت، ۵ تا ۱۵ درصد از هزینه ماهانه به «سطل بدون برچسب» می‌رود: منابع قدیمی، منابعی که AWS خودش می‌سازد (VPC Endpoint، NAT، Route 53)، سرویس‌های حساب-محور که برچسب پشتیبانی نمی‌کنند (CloudFront distribution قبل از ۲۰۲۴)، و هزینه‌های Data Transfer بین منطقه‌ای. طبق تجربه من، این هزینه‌ها را نباید بین همه تیم‌ها تقسیم کرد. باید به تیم پلتفرم منتسب شوند تا انگیزه برای بهبود ابزار داشته باشند.

یک کوئری Athena روی CUR 2.0 برای پیدا کردن ۱۰ سرویس گران با بیشترین هزینه بدون برچسب:

SELECT
  line_item_product_code AS service,
  ROUND(SUM(line_item_unblended_cost), 2) AS untagged_cost,
  COUNT(DISTINCT line_item_resource_id) AS resource_count
FROM cur2.data
WHERE billing_period = '2026-08-01'
  AND line_item_line_item_type = 'Usage'
  AND (resource_tags['user_CostCenter'] IS NULL
       OR resource_tags['user_CostCenter'] = '')
GROUP BY line_item_product_code
ORDER BY untagged_cost DESC
LIMIT 10;

برای مطالعه بیشتر درباره استراتژی‌های عملی کاهش هزینه، مقاله مقایسه Savings Plans و Reserved Instances نشان می‌دهد که وقتی برچسب‌ها درست باشند، تصمیم‌گیری بین این دو تعهد کاملاً متفاوت می‌شود.

خودکارسازی برچسب‌گذاری با EventBridge و Lambda

بدون خودکارسازی، پوشش برچسب در طول زمان افت می‌کند. این یک قانون تجربی است. هر بار یک تیم جدید وارد شود یا یک stack Terraform با پیش‌فرض ناقص deploy شود، درصد انطباق کاهش می‌یابد. راه‌حل: به‌محض ساخت منبع، یک Lambda برچسب‌های ارثی از حساب/OU/tag‌های Terraform را کپی کند.

# auto_tag.py - Lambda triggered by CloudTrail via EventBridge
import boto3
import os

ec2 = boto3.client("ec2")
DEFAULT_TAGS = {
    "ManagedBy": "auto-tagger",
    "Owner": os.environ.get("DEFAULT_OWNER", "[email protected]"),
}

def lambda_handler(event, context):
    detail = event["detail"]
    if detail["eventName"] != "RunInstances":
        return

    instance_ids = [
        item["instanceId"]
        for item in detail["responseElements"]["instancesSet"]["items"]
    ]

    principal = detail["userIdentity"].get("principalId", "unknown")
    account_id = detail["userIdentity"]["accountId"]

    tags = [
        {"Key": k, "Value": v} for k, v in DEFAULT_TAGS.items()
    ]
    tags.append({"Key": "aws:createdBy", "Value": principal})
    tags.append({"Key": "SourceAccount", "Value": account_id})

    ec2.create_tags(Resources=instance_ids, Tags=tags)
    print(f"Tagged {len(instance_ids)} instances by {principal}")

الگوی EventBridge که این Lambda را trigger می‌کند:

{
  "source": ["aws.ec2"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
    "eventSource": ["ec2.amazonaws.com"],
    "eventName": ["RunInstances", "CreateVolume"]
  }
}

تحلیل با CUR 2.0 و سازگاری با FOCUS ۱٫۲

CUR 2.0 (Cost and Usage Report نسخه ۲) که در ۲۰۲۴ عرضه شد، برچسب‌ها را در ستون resource_tags به‌صورت یک نگاشت (map) ذخیره می‌کند، نه ستون‌های تخت. این تغییر ساختاری کوئری‌های Athena و QuickSight را تسهیل می‌کند اما نیاز دارد پرس‌وجوها را با سینتکس resource_tags['user_Environment'] بنویسید.

استاندارد FOCUS ۱٫۲ که توسط FinOps Foundation در ژوئن ۲۰۲۶ منتشر شد، ستون Tags را به‌عنوان یک شیء JSON استاندارد تعریف می‌کند. اگر مدل تخصیص هزینه شما امروز بر پایه FOCUS باشد، تعویض ارائه‌دهنده ابری در آینده هزینه‌بر نخواهد بود، چون همان کلیدها روی Azure Cost Management و GCP Billing نیز معنا دارند.

نمونه ستون‌های FOCUS ۱٫۲ که برای تخصیص هزینه اهمیت دارند:

  • BilledCost: هزینه پرداخت‌شده (شامل تخفیف)
  • EffectiveCost: هزینه پس از تخصیص تعهدات (RI/SP)
  • Tags: نگاشت JSON از تمام برچسب‌ها
  • ResourceId: ARN منبع
  • ServiceCategory: دسته‌بندی استاندارد (Compute، Storage، AI/ML)

برای دیدن نحوه استفاده از FinOps مبتنی بر عامل هوش مصنوعی برای ارزیابی خودکار برچسب‌ها، به مقاله FinOps عامل‌محور مراجعه کنید که نشان می‌دهد چطور یک LLM می‌تواند از CUR انطباق برچسب را ارزیابی و به تیم‌ها گزارش دهد.

مرجع فنی مکمل برای طراحی مدل تخصیص هزینه، سند AWS Tagging Best Practices Whitepaper است که نمونه‌های صنعتی خوبی برای صنایع مختلف (فین‌تک، رسانه، سلامت) ارائه می‌دهد.

نقشه راه پیاده‌سازی در ۹۰ روز

در پروژه‌های واقعی، این ترتیب را دنبال می‌کنم و نتایج قابل اندازه‌گیری داشته است:

  1. هفته ۱–۲: ممیزی وضعیت فعلی. پرس‌وجوی CUR برای درصد پوشش هر کلید کاندید.
  2. هفته ۳–۴: تعریف طرح‌واره ۶ کلیدی، بحث با تیم مالی برای هم‌راستایی CostCenter با ERP.
  3. هفته ۵–۶: فعال‌سازی کلیدها در Billing (۲۴ ساعت انتظار)، انتشار Tag Policy در حالت غیراجباری.
  4. هفته ۷–۸: اتصال SCP در OU‌های sandbox و dev برای تست، پایش خطاها.
  5. هفته ۹–۱۰: استقرار Lambda خودکارسازی و قواعد AWS Config.
  6. هفته ۱۱–۱۲: اعمال SCP روی prod، انتشار داشبورد Cost Explorer با گروه‌بندی بر اساس CostCenter.

در پایان ۹۰ روز، هدف واقعی «۹۵٪ پوشش» است، نه ۱۰۰٪. باقی‌مانده ۵٪ (منابع خدماتی AWS، برخی سرویس‌های مدیریت‌شده) هرگز پوشش کامل نمی‌گیرند و باید در سطل Unallocated باقی بمانند.

پرسش‌های متداول

چه مدت طول می‌کشد تا برچسب‌های تخصیص هزینه در گزارش‌های AWS ظاهر شوند؟

پس از فعال‌سازی در Billing Console، معمولاً تا ۲۴ ساعت طول می‌کشد تا برچسب در Cost Explorer و CUR ظاهر شود. مهم است بدانید که AWS داده‌های تاریخی را عقب‌گرد پر نمی‌کند؛ برچسب فقط از تاریخ فعال‌سازی به بعد در گزارش‌ها موجود است.

آیا Tag Policy در AWS Organizations جلوی ساخت منبع بدون برچسب را می‌گیرد؟

خیر، به‌طور پیش‌فرض Tag Policy فقط انطباق را گزارش می‌کند. حتی با تنظیم enforced_for، این پالیسی فقط جلوی عملیات TagResource بعدی را می‌گیرد، نه ساخت اولیه منبع. برای مسدود کردن ساخت باید از Service Control Policy با شرط aws:RequestTag استفاده کنید.

تفاوت بین برچسب‌های AWS-generated و کاربر-تعریف چیست؟

برچسب‌های AWS-generated (با پیشوند aws:) توسط خود AWS به‌طور خودکار پیوست می‌شوند و قابل ویرایش نیستند، مثل aws:createdBy. برچسب‌های کاربر-تعریف را شما ایجاد می‌کنید، پوشش سرویس گسترده‌تری دارند و برای مدل Chargeback مناسب‌ترند.

حداکثر چند برچسب می‌توانم به یک منبع AWS پیوست کنم؟

در ۲۰۲۶، هر منبع AWS می‌تواند تا ۵۰ برچسب کاربر-تعریف داشته باشد. طول کلید حداکثر ۱۲۸ و طول مقدار حداکثر ۲۵۶ کاراکتر یونی‌کد است. در سطح سازمان، تا ۵۰۰ کلید متمایز می‌توانید به‌عنوان Cost Allocation Tag فعال کنید.

آیا تغییر برچسب یک منبع، هزینه گذشته آن را در گزارش تغییر می‌دهد؟

خیر. برچسب هزینه در CUR بر اساس مقدار برچسب در زمان مصرف ثبت می‌شود. اگر امروز CostCenter یک EC2 را عوض کنید، هزینه ماه‌های قبلی همچنان به مقدار قبلی نسبت داده می‌شود. این نکته در مدل Chargeback بسیار مهم است چون تغییرات مالکیت را باید در تاریخچه ثبت کنید.

استاندارد FOCUS چه کمکی به مدل تخصیص هزینه چند-ابری می‌کند؟

FOCUS ۱٫۲ ستون‌های استاندارد از جمله Tags، BilledCost و EffectiveCost را تعریف می‌کند که در AWS، Azure و GCP معنی یکسان دارند. اگر مدل تخصیص شما بر پایه FOCUS باشد، همان طرح‌واره برچسب و همان کوئری‌های Athena روی داده‌های Azure Cost Management نیز کار می‌کند.

Sara Al-Mahmoud
درباره نویسنده Sara Al-Mahmoud

Cloud cost architect specialising in the gnarly multi-account, multi-region setups. Spreadsheet enthusiast.