terraform v1.11.0でS3-nativeなstate lockが実装された。 これによって、今まではDynamoDBが必要だったstate lockをS3だけで実現できるようになった。
ベースとなる実装はこちらのPRで実装されている。
S3 Conditional Writes
PRのDescriptionによると、S3でconditional writes(条件付き書き込み)がサポートされたことで、この実装が可能になったとのこと。
conditional writesとは何かというと、「あるファイルをS3に書き込む際に、そのファイルが既に存在している場合は書き込みを防ぐことができる」というもの。
PutObjectリクエストに'If-None-Match': '*'
ヘッダーを追加することで、conditional writesを利用できる。(詳細)
そんな単純なものが今までサポートされてなかったのか? そしてそんな単純なものがサポートされて何が嬉しいのか?
という気持ちになるのだが、これが複数クライアントの競合Lockを実装するのに必要な機能だった。
TerraformのS3-nativeなstate lockの仕組み
次の仕組みで、S3-nativeなstate lockが実現されている。
ロックの動作
- Terraformの操作(plan、apply等)を開始すると、まずS3バケットに
.tflock
ファイルをconditinal writesで作成を試みる .tflock
ファイル作成に成功した場合:- ロックの取得に成功したと判断し、操作を続行
- Terraformの操作完了後、
.tflock
ファイルを削除
.tflock
ファイル作成に失敗した場合:- 他のユーザーが操作中と判断し、エラーを返す
conditinal writesでただファイルを書き込むだけで、他のユーザーが操作中かどうかを判断できるのがとてもシンプル。
GCSのstate lockはどのようになっているのか
GCSはconditional writesに相当する機能が、以前からサポートされている。 仕組み自体は上記のS3-nativeなstate lockと同じようだった。
つまりは、S3の方が遅れていたということだろうか。