どうも、ちゃだいん(@chazuke4649)です。
tainted(汚染されている/壊れている)とは?
Terraformを使っていると、たまにapply実行後にエラーが起きて、期待していない状態のリソースが作成されることがあります。
そんな場合にterraform taint
コマンドでtaintedマークを付けておいて、次回apply時に再作成することが可能でした。
(ただし、現在ではtaintコマンドは非推奨で、代わりにterraform apply -replace=aws_instance.example
のような手法が推奨されています)
Forcing Re-creation of Resources - Terraform CLI | Terraform | HashiCorp Developer
Replace(再作成)したくない場合はどうする?
上記は明示的にtaintedマークをつけるのでよいですが、そうでなく、意図せずtaintedマークがついてて、再作成してほしくない場合もあります。
例えば以下のように、plan時にxxx is tainted, so must be replaced
と言われ、再作成する実行計画が返ってきて異変に気づきます。
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
-/+ destroy and then create replacement
Terraform will perform the following actions:
# aws_ec2_transit_gateway_vpc_attachment.network_dev is tainted, so must be replaced
-/+ resource "aws_ec2_transit_gateway_vpc_attachment" "network_dev" {
~ id = "tgw-attach-xxxxxxxxxxxxxxx" -> (known after apply)
tags = {
"Name" = "example-vpcattach"
}
~ vpc_owner_id = "111111111111" -> (known after apply)
# (9 unchanged attributes hidden)
}
Plan: 1 to add, 0 to change, 1 to destroy.
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
こんな時に再作成したくない場合は、どうすればよいでしょうか?
答えはカンタンで、"terraform untaint" コマンドで、stateに登録されているtaintedマークを外せばOKのようです。
やってみた
現状確認する
上記例ではAWS Transit GatewayのVPCアタッチメントが対象のリソースとなります。
terraform state show
コマンドでstateがどうなっているか確認します。
すると、リソースアドレスの横にtaintedマークがついていました。
% terraform state show aws_ec2_transit_gateway_vpc_attachment.network_dev
# aws_ec2_transit_gateway_vpc_attachment.network_dev: (tainted)
resource "aws_ec2_transit_gateway_vpc_attachment" "network_dev" {
appliance_mode_support = "disable"
dns_support = "enable"
id = "tgw-attach-xxxxxxxxxxxxx"
ipv6_support = "disable"
...
## 以下割愛
}
stateファイル自体も見てみると、status に tainted と書かれていました。
{
"mode": "managed",
"type": "aws_ec2_transit_gateway_vpc_attachment",
"name": "network_dev",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"status": "tainted",
"schema_version": 0,
"attributes": {
"appliance_mode_support": "disable",
...
## 以下割愛
修正する
リソースアドレスを指定して、シンプルにterraform untaint
コマンドを実行します。
% terraform untaint aws_ec2_transit_gateway_vpc_attachment.network_dev
Resource instance aws_ec2_transit_gateway_vpc_attachment.network_dev has been successfully untainted.
たったこれだけでした。
修正を確認する
taintedマークが取れていました。
% terraform state show aws_ec2_transit_gateway_vpc_attachment.network_dev
# aws_ec2_transit_gateway_vpc_attachment.network_dev:
resource "aws_ec2_transit_gateway_vpc_attachment" "network_dev" {
appliance_mode_support = "disable"
dns_support = "enable"
id = "tgw-attach-xxxxxxxxxxxxx"
ipv6_support = "disable"
...
## 以下割愛
再度stateファイルをpullし、diffしたところ、statusという項目自体なくなっていました。
% diff temp.tfstate temp2.tfstate
4c4
< "serial": 2,
---
> "serial": 3,
38d37
< "status": "tainted",
これで、planすると、taintedマーク理由での強制的に再作成はなくなりました。
No changes. Your infrastructure matches the configuration.