↓の本の「5章 Terraformを使うためのヒントとコツ:ループ、条件分岐、デプロイ、その他つまずきポイント」のメモを残します。
前章のメモ
ループ
Terraformには数種類のループをする文法があります。
- リソースのループをするcount
- リソースおよびインラインブロックのループをするfor_each
- リストやマップのループをするfor
- 文字列内のリストやマップのループをするfor文字列命令
count
countパラメータに設定した数だけリソースを複数作成する。
1 2 3 4 5 |
// countパラメータでIAMユーザを3つ作る resource "aws_iam_user" "example" { count = 3 name = "name.${count.index}" } |
countで作成すると、単一のリソースではなく、複数リソースの配列となります。
なので、参照する際にはインデックスを使用します。
1 2 3 4 5 |
// 作成したIAMユーザのうち2番のユーザのARNを出力 output "second_arn" { value = aws_iam_user.example[1].arn description = "The ARN for the second user" } |
すべてのリソースを出力する際にはスプラット式(*)を使用します。
配列で出力される点に注意してください
1 2 3 4 5 |
// 作成したIAMユーザすべてのARNを出力 output "all_arns" { value = aws_iam_user.example[*].arn description = "The ARN for all users" } |
countの問題点
- インラインブロックには使えない
- 値の変更が意図しない挙動になってしまう
2. 値の変更が意図しない挙動になってしまう についてもう少し掘り下げます
先ほどのようにIAMユーザ1~3が作成したとします。
IAMユーザ1の名前:first
IAMユーザ2の名前:second
IAMユーザ3の名前:third
IAMユーザ2(second)を削除しようとコードを変更しデプロイすると
×:IAMユーザ2(second)が削除されるのみで、他のユーザに影響はない。
〇:IAMユーザ2がthirdとなり、IAMユーザ3が削除される。
これは、意図した挙動ではなく、場合によってはリソースの再作成になってしまうためダウンタイムが生じてしまいます。
for_each式
- リソースやインラインブロック、モジュールのループが可能
- 集合やマップをfor_eachパラメータに指定することで使える
- each.valueやeach.keyで集合やマップ内の値を取り出せる
- リソースの削除時にも希望のリソースのみ削除でき、他へ影響はない。
- dyanmicブロックを使用して動的にインラインブロックを生成できる
for文
- リソースではなく、リストやマップ、集合のループ
- PythonのLambda式に近い文法
1 2 3 4 5 6 7 8 9 |
// リストのループ [for <ITEM> in <LIST> : <OUTPUT>] // マップのループ [for <KEY>, <VALUE> in <MAP> : <OUTPUT>] // 集合での出力 {for <ITEM> in <LIST> : <OUTPUT>} {for <KEY>, <VALUE> in <MAP> : <OUTPUT>} |
for文字列命令
文字列内でfor文を使ってループする。
1 2 3 4 5 6 |
// 文法 %{ for <ITEM> in <COLLECTION> }<BODY>%{ endfor } // インデックスも取り出す %{ for <INDEX>, <ITEM> in <COLLECTION> }<BODY>%{ endfor } |
条件分岐
- count:条件付きリソースの作成
- for_each, for :条件付きリソース、インラインブロックの作成
- if文字列ディレクティブ:文字列内の分岐
count
- count = 0 ⇒ リソース作成しない、count = 1 ⇒ リソース作成する
- 条件式の文法 <CONDITION> ? <TRUE_VAL> : <FALSE_VAL>
この2つより、countの値を条件式で制御し、リソースを作成するしないを決められます
for_each, for
for_eachのループ内でforループを使って条件分岐させる。
if文字列ディレクティブ
1 2 |
// 文法 %{ if <CONDITION> }<TRUE_VAL>%{ else }<FALSE_VAL>%{ endif } |
countとfor_eachの使い分け
リソースやモジュールを条件付きで作成したい ⇒ count
リソースやモジュールの複数作成や条件分岐 ⇒ for_each
ゼロダウンタイムデプロイ
リソースの変更は場合によっては作り直しになります。
Terraformのデフォルトの挙動は既存を削除⇒新規に作成なので、ダウンタイムが生じます。
これを回避するためにcreate_before_destroyをtrueにして、作成⇒削除の順番にします
1 2 3 |
lifecycle { create_before_destroy = true } |
Terraformのつまずきポイント
- countやfor_eachはハードコードされた値は〇だが、出力結果などは受け付けない
- プロバイダのネイティブなデプロイ方法でゼロダウンタイムならそちらを使った方がいい
⇒自前でゼロダウンタイムを実現しようとすると複雑になりやすい - planが成功したからといって、必ずしもapplyが成功するとは限らない。(私も経験ありです)
- Terraformのみを使う、コンソールやCLIを使わない
- 管理外のインフラリソースはTerraformに取り込む
- 変更が意図せぬリソースの作り直しになるなど、リファクタリングが難しい
- planの結果をしっかり見る
- 削除前に作成する
- ステートファイルの変更が必要なこともある
- 手動では絶対に行わず、state mvコマンドやmovedブロックを使用すること
次章のメモ
コメント