はじめに
Terraform で API Gateway を構築していて、メソッドや統合を多用していると、たまに
Error: error deleting API Gateway Integration Response (xxxx-xxxxxxxxxx-xxxxxx-PUT-500): ConflictException: Unable to complete operation due to concurrent modification. Please try again later.
みたいな感じでエラーが出て悩まされることがある。
これはおそらく、API Gateway を更新する API(Terraform が裏で叩いていると思われるもの)が、並列処理に対応していない(処理を排他している)と考えられる。
Terraform はお利口なので、依存関係のないリソースについてはなるべく並列で処理をして高速化をしてくれる。この仕様が仇になって、排他処理しているところに並列でAPIを叩きんでエラーになっているようだ。
対処策
その1: もう一度 terraform apply
する
一番原始的な方法。別に HCL が悪いわけではないので、ConflictException が出ている限りは何度も apply すれば良い。でもこれ、他のエラーとか見落としてしまうとかありそうだよね……。
その2: Terraform の実行並列度を下げる
こんな感じ。
$ terraform destroy --parallelism=1
別に 1 多重まで落とす必要はないのかもしれないけど、冪等性を考えるなら絶対に処理が並列にならない 1 を指定すべき。リソースがいっぱいあるとめちゃくちゃ遅くなるので選択したくない案。
その3: 排他される処理については depends_on
で順序性を持たせる
仕方がないので、aws_api_gateway_integration_response
のように排他されるリソースについては、全部 depends_on
で他の aws_api_gateway_integration_response
の名前を書いて順序を持たせる。
resource "aws_api_gateway_integration_response" "example1" {
depends_on = []
(中略)
}
resource "aws_api_gateway_integration_response" "example2" {
depends_on = [aws_api_gateway_integration_response.example1]
(中略)
}
resource "aws_api_gateway_integration_response" "example3" {
depends_on = [aws_api_gateway_integration_response.example2]
(中略)
}
分かりにくい!
これ、後になって知らない人が見たら「なぜ関係のないリソースに依存関係を持たせるんだろう……」と思ってしまうよね。
結論
どの案もイマイチだったので、作っている人の好みに合わせれば良いのではないかと思う。
ただ、いずれも初めてこの問題にあたる人は悩むことになるだろうから、ちゃんとドキュメンテーションはしておいてあげよう(めちゃくちゃ悩んだ)。