Zum Hauptinhalt springen
← Blog

Der Engineer ist weg, die Cloud-Rechnung nicht: Ein Runbook für Ownership-Tagging aller Ressourcen

Ownership-Tagging für alle Cloud-Ressourcen: Runbook mit SCPs, IaC-Policies und Audit-Skripten zur Kostensenkung.

7 Min. LesezeitSimon-Daniel März
Der Engineer ist weg, die Cloud-Rechnung nicht: Ein Runbook für Ownership-Tagging aller RessourcenMit Hilfe von KI generiert

Eine EC2-Instanz läuft in eu-central-1. Sie kostet 142 € pro Monat. Niemand in Ihrem aktuellen Team weiß, was sie tut, welches Team sie bereitgestellt hat oder ob das Abschalten um 3 Uhr nachts die Produktion lahmlegt. Der Engineer, der sie aufgesetzt hat, ist vor acht Monaten gegangen. Kommt Ihnen das bekannt vor?

Das ist kein seltener Einzelfall. Es ist der Standardzustand jedes Cloud-Kontos, das Ownership-Tagging überspringt. Und je länger Sie warten, desto schmerzhafter wird die Bereinigung, verwaiste Volumes, unattached Elastic IPs, veraltete RDS-Snapshots und eine monatliche Rechnung, die sich wie ein Lösegeldforderung liest.

Dieser Beitrag führt Sie durch ein konkretes Runbook, um jeder Cloud-Ressource, die Sie finden können, einen Owner zuzuweisen, dieses Ownership bereits bei der Erstellung durchzusetzen und Ressourcen zu erkennen, die durchrutschen.

Warum die meisten Tagging-Strategien scheitern, bevor sie beginnen

Das Kernproblem ist nicht technischer, sondern organisatorischer Natur. Teams verabschieden Tagging-Richtlinien auf einer Wiki-Seite, und sechs Monate später hat die Hälfte der Ressourcen überhaupt keine Tags. Hier ist der Grund:

  • Keine Durchsetzung bei der Erstellung. Entwickler erstellen Ressourcen über die Konsole, CLI oder IaC, ohne dass ein Gate untaggete Ressourcen ablehnt.
  • Vage Ownership-Definitionen. Ein Tag wie owner: devops sagt Ihnen nichts darüber, wer alarmiert wird, wenn die Rechnung explodiert. „Devops" ist ein Team, keine Person oder ein Cost Center.
  • Kein retrospektives Scannen. Ressourcen, die vor der Einführung der Tagging-Richtlinie erstellt wurden, bleiben unangetastet und für jede Reporting-Pipeline unsichtbar.
  • Tag-Key-Proliferation. Ein Team nutzt Owner, ein anderes owner, ein drittes responsible. Ohne ein kanonisches Schema scheitern Aggregations-Tools.

Jedes dieser Probleme hat eine spezifische technische Lösung. Die folgenden Abschnitte gehen sie der Reihe nach durch.

Schritt 1: Das Ownership-Schema definieren

Bevor Sie eine einzige Zeile Policy-as-Code schreiben, legen Sie den Mindestsatz an Tags fest, den jede Ressource tragen muss. Eine praktikable Basis sieht so aus:

Tag-KeyErforderlichBeispielwertZweck
OwnerJa[email protected]Einzelne verantwortliche Person
TeamJaplatform-infraBesitzendes Team oder Cost Center
CostCenterJaCC-4710Finanz-Allokationscode
EnvironmentJaproductionproduction, staging, dev
ProjectNeininvoice-syncProdukt- oder Initiativname
ManagedByNeinterraformBereitstellungsmethode

Warum die einzelne Owner-E-Mail wichtig ist: Ein Teamname verfällt in dem Moment, in dem jemand die Abteilung wechselt. Eine E-Mail-Adresse ermöglicht Ihnen eine Slack- oder Teams-Integration, die die richtige Person direkt benachrichtigt. Wenn die Adresse zurückkommt, wissen Sie, dass das Tag veraltet ist und die Ressource neu zugewiesen werden muss.

Speichern Sie dieses Schema in einem gemeinsamen Repository, nicht auf einer Confluence-Seite, die niemand liest. Eine JSON-Schema-Datei eignet sich gut, weil Tooling automatisch dagegen validieren kann:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "RequiredResourceTags",
  "type": "object",
  "required": ["Owner", "Team", "CostCenter", "Environment"],
  "properties": {
    "Owner": {
      "type": "string",
      "pattern": "^[a-z.]+@acme\\.de$"
    },
    "Team": {
      "type": "string",
      "minLength": 3
    },
    "CostCenter": {
      "type": "string",
      "pattern": "^CC-[0-9]{4}$"
    },
    "Environment": {
      "type": "string",
      "enum": ["production", "staging", "dev"]
    }
  },
  "additionalProperties": true
}

Committen Sie diese Datei zusammen mit Ihrem Infrastruktur-Code. Jeder Pull Request, der IaC betrifft, kann darauf referenzieren.

Schritt 2: Tags bei der Erstellung durchsetzen

Die Durchsetzung ist der Punkt, an dem die meisten Teams scheitern. Wenn Sie Tags erst nach dem Deployment prüfen, zahlen Sie bereits für den Fehler. Hier sind drei Durchsetzungsebenen, von einfach bis am stärksten.

2a. AWS Service Control Policies (SCPs)

SCPs fungieren als Leitplanke auf Organisationsebene. Die folgende SCP verweigert die Ressourcenerstellung, wenn das Owner-Tag fehlt:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "RequireOwnerTag",
      "Effect": "Deny",
      "Action": [
        "ec2:RunInstances",
        "rds:CreateDBInstance",
        "s3:CreateBucket",
        "lambda:CreateFunction",
        "ecs:CreateService"
      ],
      "Resource": "*",
      "Condition": {
        "Null": {
          "aws:RequestTag/Owner": "true"
        }
      }
    }
  ]
}

Wenden Sie diese SCP auf jede Organizational Unit außer der Root an. Entwickler, die das Tag vergessen, erhalten beim Deployment eine klare Fehlermeldung, schnelles Feedback, keine stillen Orphans.

2b. Terraform Sentinel / OPA-Richtlinien

Wenn Ihr Team über Terraform bereitstellt, fügen Sie eine Sentinel- oder Open-Policy-Agent-Regel hinzu, die terraform apply blockiert, wenn erforderliche Tags fehlen:

# variables.tf
variable "required_tags" {
  type    = list(string)
  default = ["Owner", "Team", "CostCenter", "Environment"]
}

Validieren Sie dann in Ihrer CI-Pipeline vor dem Apply:

# validate_tags.py
import json, sys

REQUIRED_TAGS = ["Owner", "Team", "CostCenter", "Environment"]

def check_plan(plan_file: str) -> list[str]:
    with open(plan_file) as f:
        plan = json.load(f)

    violations = []
    for resource in plan.get("resource_changes", []):
        if resource["change"]["actions"] == ["create"]:
            tags = resource["change"]["after"].get("tags", {}) or {}
            missing = [t for t in REQUIRED_TAGS if t not in tags]
            if missing:
                violations.append(
                    f"{resource['address']}: missing tags {missing}"
                )
    return violations

if __name__ == "__main__":
    errors = check_plan(sys.argv[1])
    for e in errors:
        print(f"ERROR: {e}", file=sys.stderr)
    if errors:
        sys.exit(1)

Dieses Skript prüft das Terraform-Plan-JSON und lässt die Pipeline fehlschlagen, wenn eine neu erstellte Ressource erforderliche Tags vermissen lässt. Binden Sie es in Ihren CI-Schritt zwischen terraform plan -out=plan.json und terraform apply plan.json ein.

2c. CI-Pipeline-Gate für Konsolen-/CLI-Ressourcen

Für Ressourcen, die außerhalb von IaC erstellt werden (ja, das kommt immer noch vor), fügen Sie einen geplanten Scan hinzu, der untaggete Ressourcen innerhalb von 24 Stunden nach der Erstellung kennzeichnet und in einen Slack-Kanal postet. Das Erkennungsskript behandeln wir in Schritt 3.

Schritt 3: Ressourcen erkennen, die durchgerutscht sind

Selbst mit SCPs und IaC-Richtlinien können Ressourcen einschleichen, Lambda@Edge-Funktionen in us-east-1, DynamoDB-Global-Tables oder manuell erstellte IAM-Rollen. Ein nächtliches Audit fängt sie ab.

Das folgende Python-Skript verwendet Boto3, um EC2-Instanzen und RDS-Instanzen ohne Owner-Tag zu scannen:

import boto3
from datetime import datetime, timezone

REQUIRED_TAG = "Owner"
REGIONS = ["eu-central-1", "eu-west-1", "us-east-1"]

def audit_ec2(region: str) -> list[dict]:
    ec2 = boto3.client("ec2", region_name=region)
    paginator = ec2.get_paginator("describe_instances")
    orphans = []

    for page in paginator.paginate():
        for reservation in page["Reservations"]:
            for instance in reservation["Instances"]:
                if instance["State"]["Name"] == "terminated":
                    continue
                tags = {t["Key"]: t["Value"] for t in instance.get("Tags", [])}
                if REQUIRED_TAG not in tags:
                    orphans.append({
                        "resource_type": "EC2",
                        "region": region,
                        "id": instance["InstanceId"],
                        "launched": instance["LaunchTime"].isoformat(),
                        "tags": tags,
                    })
    return orphans

def audit_rds(region: str) -> list[dict]:
    rds = boto3.client("rds", region_name=region)
    paginator = rds.get_paginator("describe_db_instances")
    orphans = []

    for page in paginator.paginate():
        for db in page["DBInstances"]:
            tag_list = rds.list_tags_for_resource(
                ResourceName=db["DBInstanceArn"]
            )["TagList"]
            tags = {t["Key"]: t["Value"] for t in tag_list}
            if REQUIRED_TAG not in tags:
                orphans.append({
                    "resource_type": "RDS",
                    "region": region,
                    "id": db["DBInstanceIdentifier"],
                    "launched": db["InstanceCreateTime"].isoformat(),
                    "tags": tags,
                })
    return orphans

if __name__ == "__main__":
    all_orphans = []
    for region in REGIONS:
        all_orphans.extend(audit_ec2(region))
        all_orphans.extend(audit_rds(region))

    print(f"Found {len(all_orphans)} resources missing '{REQUIRED_TAG}' tag:")
    for o in all_orphans:
        print(f"  [{o['resource_type']}] {o['id']} in {o['region']} "
              f"(launched {o['launched']})")

Führen Sie dieses Skript nächtlich über eine CI/CD-Pipeline oder eine Lambda-Funktion aus. Senden Sie die Ausgabe an einen dedizierten Slack-Kanal wie #cloud-orphans. Wenn die Liste Woche für Woche wächst, hat Ihre Durchsetzungsebene eine Lücke.

Hypothetisches Szenario: Ein mittelgroßes SaaS-Unternehmen führt diesen Scan über drei Konten und 14 Regionen aus. Nacht eins fördert 237 Ressourcen ohne Owner-Tag zutage. Nach zwei Wochen Triage identifizieren sie 89 Ressourcen, die bedenkenlos terminiert werden können, das spart geschätzte 3.200 € pro Monat an Compute- und Speicherkosten. Die restlichen 148 werden getaggt, und der nächtliche Scan sinkt auf nahezu null Befunde, sobald die Durchsetzung aktiv ist.

Schritt 4: Sanieren und Ownership zuweisen

Erkennung ohne Aktion ist nur Rauschen. Bauen Sie einen Sanierungs-Workflow auf:

  1. Orphan-Liste triagieren. Gruppieren Sie nach AWS-Konto, Region und Ressourcentyp. Weisen Sie jede Gruppe dem wahrscheinlichsten Besitzerteam anhand der Benennung von VPC, Subnetz oder Security Group zu.
  2. Team kontaktieren. Wenn Ihr Owner-Tag-Schema eine E-Mail enthält, benachrichtigen Sie den mutmaßlichen Besitzer: „Ressource i-0abc123 in eu-central-1 hat kein Owner-Tag. Übernehmen Sie sie oder sie wird in 14 Tagen zur Stilllegung eingeplant."
  3. Automatisch taggen, was möglich ist. Für Ressourcen in einer klar benannten VPC oder einem CloudFormation-Stack wenden Sie die Owner- und Team-Tags automatisch aus den Stack-Metadaten an.
  4. Löschung planen. Nach der Gnadenfrist terminieren Sie Ressourcen, die niemand übernommen hat. Verwenden Sie eine Lambda-Funktion, die vor dem Handeln eine DynamoDB-„Claims"-Tabelle prüft.

Dieser Workflow macht aus einer einmaligen Bereinigung einen kontinuierlichen Prozess. Neue Orphans tauchen nächtlich auf; das 14-Tage-Fenster gibt Teams Zeit zu reagieren, ohne die Entwicklung zu verlangsamen.

Schritt 5: Kosten nach Owner berichten

Tagging ist nutzlos, wenn die Finanzabteilung es nicht verwenden kann. Richten Sie einen Cost-Allocation-Report ein, der Ausgaben nach Owner, Team und CostCenter gruppiert. In AWS aktivieren Sie Cost Allocation Tags in der Billing-Konsole, sowohl benutzerdefinierte als auch AWS-generierte Tags erscheinen nach einer 24-stündigen Propagierungsverzögerung im Cost Explorer.

Ein praktischer Reporting-Rhythmus:

  • Wöchentlich: Senden Sie jedem Teamleiter eine einseitige Zusammenfassung der getaggten Ausgaben im Vergleich zum Budget.
  • Monatlich: Präsentieren Sie ein teamübergreifendes Kosten-Review mit den 10 teuersten Ressourcen und deren Besitzern.
  • Quartalsweise: Prüfen Sie die Tag-Genauigkeit, führen Sie das Erkennungsskript aus und vergleichen Sie es mit dem Vorquartal.

Wenn Ingenieure ihren Namen neben einer 400-€-Rechnung für eine vergessene Dev-Datenbank sehen, ändert sich das Verhalten schneller als durch jedes Policy-Dokument.

Best Practices: 5 Regeln, die Ihre Tags sauber halten

  1. Bei der Erstellung durchsetzen, nicht nach dem Deployment. SCPs und IaC-Policy-Checks sind nicht verhandelbar. Eine Ressource, die ohne Tags erstellt wurde, wird sich nie selbst taggen.
  2. Eine Person pro Owner-Tag, kein Team-Alias. Teams reorganisieren sich; Verantwortlichkeit sollte nicht mitwandern. Verwenden Sie eine menschliche E-Mail-Adresse.
  3. Tag-Keys in Code standardisieren, nicht in Dokumentation. Speichern Sie die kanonische Tag-Liste in einem gemeinsamen Modul (Terraform-Modul, Pulumi-Komponente oder eine Python-Konstante) und importieren Sie es überall.
  4. Nächtlichen Orphan-Scan über jedes Konto und jede Region ausführen. Das Erkennungsskript aus Schritt 3 sollte ein geplanter Pipeline-Job sein, keine manuelle Übung.
  5. Kostenberichte an Ownership-Daten koppeln. Wenn die Finanzabteilung monatlich eine „Ihre Cloud-Ausgaben sind zu hoch"-E-Mail ohne Aufschlüsselung nach Owner sendet, wird sie ignoriert. Kostenberichte mit Ownership-Tags schaffen Verantwortlichkeit, die hält.

Teams, die Cloud-Infrastruktur aufbauen oder refaktorieren, stellen oft fest, dass die Tagging- und Governance-Ebene der Teil ist, den niemand anfassen will, sie ist querschnittlich, mühsam falsch zu machen und unsichtbar, wenn sie funktioniert. ProjectMakers liefert dies als Festpreis-Engagement: Schema-Design, SCP- und IaC-Durchsetzung, nächtliche Audit-Pipelines und Kosten-Reporting-Dashboards, damit sich Ihr Team auf das Produkt konzentrieren kann, nicht auf die Infrastruktur.

Wenn Sie eine Cloud-Migration planen oder Ihre Infrastruktur neu architektonisieren, sollte das Ownership-Modell entworfen werden, bevor die erste Ressource bereitgestellt wird. Kontaktieren Sie uns über unsere Individualsoftware-Entwicklungsdienste, um den Umfang einer ordentlichen Governance-Ebene für Ihre Umgebung zu ermitteln.

Fangen Sie klein an: Wählen Sie ein AWS-Konto, führen Sie das Audit-Skript heute Nacht aus und taggen Sie alles, was es findet. Morgen aktivieren Sie die SCP. In einer Woche haben Sie eine saubere Ownership-Bilanz, und eine Cloud-Rechnung, die endlich Sinn ergibt.


Quelle: So weisen Sie jeder Cloud-Ressource einen Owner zu

In diesem Thema weiterlesen

Betrieb und Open Source