Terraform plan drift po manualnej zmianie w konsoli AWS/Azure/GCP
Naprawa Terraform drift po manualnych zmianach w konsoli: identyfikacja zmienionych zasobów, import lub reset do pożądanego stanu, wdrożenie wykrywania drift i policy.
terraform plan i widzisz 47 zmian, których nikt nie commitował. Security group ma dodatkową regułę, RDS ma zmieniony parametr, ktoś ręcznie dodał tag. Pipeline CI/CD blokuje się, bo plan nie jest czysty. Ten runbook pokazuje jak rozwiązać drift i zapobiec jego powstawaniu.
Jeśli Twój problem to zablokowany state lock (nie drift), zobacz runbook o zablokowanym Terraform state. Dla ogólnego zarządzania state, zobacz runbook o drift detection i force-unlock.
Objaw
terraform plan pokazuje zmiany, których nie ma w kodzie:
# Typowy output po manualnej zmianie w konsoli:
terraform plan
# aws_security_group.app:
# ~ ingress {
# + cidr_blocks = ["10.0.5.0/24"] # <-- ktoś dodał ręcznie
# from_port = 443
# protocol = "tcp"
# to_port = 443
# }
# aws_db_instance.main:
# ~ parameter_group_name = "default.postgres15" -> "custom-pg15" # zmieniono w konsoli
# aws_instance.web:
# ~ tags = {
# + "CostCenter" = "marketing" # tag dodany ręcznie
# }
Plan chce „naprawić” zasoby do stanu z kodu - ale te zmiany mogą być celowe (hotfix, ręczna interwencja podczas incydentu).
Przyczyna
- Ręczna zmiana w konsoli AWS/Azure/GCP - ktoś z zespołu zmienił coś przez UI zamiast przez kod
- Hotfix podczas incydentu - inżynier otworzył port w SG lub zmienił parametr DB podczas awarii i nie wrócił do kodu
- Auto-scaling lub automatyczne zmiany AWS - niektóre zasoby AWS modyfikują się same (np. ASG desired count, Lambda concurrent executions)
- Inny pipeline Terraform - dwa workspace operują na tym samym zasobie
- Manualna zmiana w state - ktoś użył
terraform state rmlubterraform importbez odpowiedniego kodu
Naprawa
A) Zidentyfikuj, co się zmieniło i dlaczego
# Szczegółowy plan z pełnym diff
terraform plan -detailed-exitcode 2>&1 | tee plan-output.txt
# Kod wyjścia 2 = są zmiany do wprowadzenia
# Dla konkretnego zasobu - pokaż aktualny stan vs kod
terraform state show aws_security_group.app
# Sprawdź, kto zmienił (AWS CloudTrail)
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=ResourceName,AttributeValue=sg-0123456789abcdef0 \
--start-time $(date -u -v-7d +%Y-%m-%dT%H:%M:%S) \
--query 'Events[].{Time:EventTime,User:Username,Event:EventName}'
B) Decyzja: zaakceptować zmianę, czy cofnąć?
Dla każdego zasobu z odchyleniem (drift) podejmij decyzję:
| Sytuacja | Akcja |
|---|---|
| Zmiana była celowa i powinna zostać | Zaktualizuj kod Terraform, aby odzwierciedlał zmianę |
| Zmiana była tymczasowa i powinna wrócić | Uruchom terraform apply - Terraform przywróci stan z kodu |
| Zmiana dotyczy zasobu, którego Terraform nie powinien zarządzać | Dodaj do lifecycle { ignore_changes = [...] } |
| Nie wiesz co to zmiana | Nie rób apply. Zbadaj najpierw. |
C) Zaakceptuj zmianę (zaktualizuj kod)
# Jeśli zmiana w konsoli była celowa - dodaj ją do kodu:
resource "aws_security_group" "app" {
# ... istniejące reguły ...
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["10.0.5.0/24"] # Dodane: dostęp z nowej sieci
description = "Added during incident INC-1234, formalized in TF"
}
}
D) Cofnij zmianę (terraform apply)
# UWAGA: to przywróci stan zasobu do definicji w kodzie
# Upewnij się, że cofnięcie zmiany nie spowoduje incydentu!
# Najpierw plan, sprawdź co się stanie:
terraform plan -target=aws_security_group.app
# Jeśli jesteś pewien:
terraform apply -target=aws_security_group.app
E) Ignoruj zmianę (lifecycle ignore)
Dla zasobów, które zmieniają się poza Terraform (np. ASG desired count, tags dodawane przez AWS):
resource "aws_autoscaling_group" "app" {
# ...
desired_capacity = 3
lifecycle {
ignore_changes = [
desired_capacity, # Zmieniane przez autoscaling policy
target_group_arns, # Zarządzane przez inny moduł
]
}
}
resource "aws_instance" "web" {
# ...
lifecycle {
ignore_changes = [
tags["CostCenter"], # Tag zarządzany przez AWS Organizations
]
}
}
F) Import niezarządzanego zasobu
Jeśli ktoś utworzył zasób w konsoli, który powinien być zarządzany przez Terraform:
# 1. Napisz blok resource w kodzie (pusty lub z szacowanymi wartościami)
# 2. Import istniejącego zasobu do state
terraform import aws_security_group.new_sg sg-0abcdef1234567890
# 3. Uruchom plan i uzupełnij brakujące atrybuty w kodzie
terraform plan
# Wynik pokaże, co trzeba dodać lub zmienić w kodzie HCL
Zapobieganie
Wykrywanie drift w CI/CD
# GitHub Actions - codzienny drift check
name: Terraform Drift Detection
on:
schedule:
- cron: '0 6 * * *' # Codziennie o 6:00 UTC
jobs:
drift-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- name: Terraform Init
run: terraform init
- name: Terraform Plan (drift detection)
id: plan
run: terraform plan -detailed-exitcode -no-color
continue-on-error: true
- name: Alert on drift
if: steps.plan.outcome == 'failure'
run: |
curl -X POST "$SLACK_WEBHOOK" -d '{
"text": "Terraform drift detected in production. Run terraform plan to review changes."
}'
AWS Config Rules
# Włącz AWS Config rule, która wykrywa zmiany w security groups
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "sg-no-manual-changes",
"Source": {
"Owner": "AWS",
"SourceIdentifier": "EC2_SECURITY_GROUP_ATTACHED_TO_ENI_PERIODIC"
}
}'
SCP (Service Control Policy) blokujący ręczne zmiany
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Deny",
"Action": [
"ec2:AuthorizeSecurityGroupIngress",
"ec2:RevokeSecurityGroupIngress"
],
"Resource": "*",
"Condition": {
"StringNotLike": {
"aws:PrincipalArn": "arn:aws:iam::*:role/terraform-*"
}
}
}]
}
Weryfikacja
# Po naprawie - plan powinien być czysty
terraform plan
# "No changes. Your infrastructure matches the configuration."
# Jeśli nadal są zmiany - sprawdź, czy to nie atrybuty zarządzane automatycznie
# i dodaj ignore_changes tam gdzie potrzeba
Jeśli terraform plan zwraca „No changes” po naprawie, odchylenie rozwiązane. Wdróż wykrywanie drift w CI/CD, aby wyłapywać przyszłe zmiany w ciągu 24h zamiast przy kolejnym wdrożeniu.
Terraform drift wymknął się spod kontroli?
Umów bezpłatną 30-minutową rozmowę. Pomożemy oczyścić state i wdrożyć automatyczne wykrywanie odchyleń.