変数の優先順位と出力の設計
目標
同じ変数に、4つの方法で値を入れて、優先順位を直接確認し、検証・ローカル値・出力・機密値まで備えた設定を1つ完成させます。
なぜ重要なのか
「変数を変えたのに反映されない」という質問の答えは、ほとんどいつも優先順位です。ツールは、同じ名前の値を複数の場所から受け入れ、衝突してもエラーを出さず、静かにより強いほうを使います。便利な分、デバッグが難しくなるので、上書きするために作った値は弱い場所に、必ず守るべき値は強い場所に置く感覚が必要です。特に、コマンドラインで渡した値は、何にでも勝ちますが、どこにも記録されないので、障害対応で使って、コードに反映しなければ、次のデプロイがそれを静かに元に戻します。最後に、sensitive = trueは、画面の出力を隠すだけで、状態ファイルとJSON出力には、値がそのまま残ります。この限界を知らないまま、「機密の指定をしたから安全だ」と信じることが、最もよくある事故の始まりです。
ステップ
/root/tf/vars/variables.tfに、environment変数を宣言してください。type = string、default = "dev"、descriptionがすべてある必要があります。/root/tf/vars/outputs.tfに、名前がenvironmentの出力を作り、デフォルト値のまま適用したあと、出力をJSONで/root/tf/vars/out/default-outputs.jsonに保存してください(.environment.valueがdev)。/root/tf/vars/terraform.tfvarsにenvironment = "stage"を書いて、再び適用したあと、出力を/root/tf/vars/out/tfvars-outputs.jsonに保存してください。値がstageに変わっている必要があります。ファイルがデフォルト値に勝ちます。- 今度は、コマンドラインから
-var environment=prodで値を与えて適用したあと、出力を/root/tf/vars/out/cli-outputs.jsonに保存してください。tfvars-outputs.jsonは、そのままにしておく必要があります(依然としてstage)。 variables.tfにowner変数を宣言してください。ただし、デフォルト値をplatformとして書き込んでおかないでください。TF_VAR_owner=platform環境変数で値を渡して適用し、出力を/root/tf/vars/out/env-outputs.jsonに保存してください(.owner.valueがplatform)。outputs.tfにownerの出力も追加します。variables.tfにreplica_count変数を追加して、1以上5以下だけを許容するvalidationブロックを入れてください。conditionとerror_messageが両方ある必要があり、error_messageの中に、許容範囲が1-5という文字のまま入っている必要があります。範囲を外れた値(例:-var replica_count=9)で実行して、拒否された出力を、/root/tf/vars/out/validation.txtに保存してください。/root/tf/vars/main.tfにlocalsブロックを作り、name_prefixを、environmentとownerをハイフンでつないだ値として定義してください。outputs.tfにname_prefixの出力を追加します。ステップ8で再作成するcli-outputs.jsonのname_prefixは、prod-platformでなければなりません。- 出力を
/root/tf/vars/outputs.tfの1か所にまとめて、最低4つ(environment、owner、name_prefix、config_path)を置いてください。ただし、すべての出力にdescriptionを付けてください。config_pathは、この設定が作るlocal_fileのfilenameをそのまま出力します。 variables.tfにapi_token変数をsensitive = trueで宣言して、値はTF_VAR_api_tokenで渡してください。outputs.tfにもapi_tokenの出力をsensitive = trueで追加します。最後に、-var environment=prodとTF_VAR_owner=platform、TF_VAR_api_tokenを一緒に与えて適用したあと、cli-outputs.jsonを再作成して、人が読む形式の出力も/root/tf/vars/out/sensitive.txtに保存してください。後者には、値の代わりに隠された表示があり、実際のトークンの文字列が見えてはいけません。
参考
- 値の強さは、弱いものから順に
default→TF_VAR_*→terraform.tfvars→*.auto.tfvars→-var-file→-varです。 terraform output -jsonは機械が読む形式、terraform outputは人が読む形式です。機密の指定は、後者でだけ隠されます。cli-outputs.jsonは、ステップ6・7・8の採点がすべて見るファイルです。出力を追加するたびに、最後にはステップ8の値の組み合わせで、必ず再作成してください。- よくある間違い1: ステップごとに同じファイルに保存して、前のステップの結果を失うこと。ステップ1–4は、それぞれ別のファイルに残す必要があります。
- よくある間違い2:
ownerのデフォルト値をplatformと書いておくこと。そうすると、環境変数が効いたことを証明できず、採点が拒否します。
型・デフォルト値・説明を備えた変数を宣言する
/root/tf/vars/variables.tfに、environment変数を宣言してください。type = string、default = "dev"、descriptionがすべてある必要があります。/root/tf/vars/outputs.tfに、名前がenvironmentの出力を作り、デフォルト値のまま適用したあと、出力をJSONで/root/tf/vars/out/default-outputs.jsonに保存してください(.environment.valueがdev)。
変数ブロックには、値のほかに付けられるものがあります。3つともないと、数か月後に、この値が何なのか、誰にもわかりません。出力は-jsonで取り出して保存してください。
tfvarsファイルでデフォルト値を上書きする
/root/tf/vars/terraform.tfvarsにenvironment = "stage"を書いて、再び適用したあと、出力を/root/tf/vars/out/tfvars-outputs.jsonに保存してください。値がstageに変わっている必要があります。ファイルがデフォルト値に勝ちます。
ディレクトリの中の特定の名前のファイルは、別に指定しなくても、自動的に読み込まれます。ファイルの中では、이름 = 값の形式だけを使います(プレースホルダーは、順に名前と値です)。
コマンドラインの値でファイルに勝つ
今度は、コマンドラインから-var environment=prodで値を与えて適用したあと、出力を/root/tf/vars/out/cli-outputs.jsonに保存してください。tfvars-outputs.jsonは、そのままにしておく必要があります(依然としてstage)。
優先順位の頂点は、実行するときに直接与えた値です。前のステップで保存した出力ファイルは、上書きせずに、新しいファイルに残してください。
環境変数で値を注入する
variables.tfにowner変数を宣言してください。ただし、デフォルト値をplatformとして書き込んでおかないでください。TF_VAR_owner=platform環境変数で値を渡して適用し、出力を/root/tf/vars/out/env-outputs.jsonに保存してください(.owner.valueがplatform)。outputs.tfにownerの出力も追加します。
変数名の前に決まった接頭辞を付けた環境変数を、ツールが自動的に読みます。デフォルト値に同じ値を書き込んでおくと、環境変数が効いたことを証明できません。
許容範囲をコードで固定する
variables.tfにreplica_count変数を追加して、1以上5以下だけを許容するvalidationブロックを入れてください。conditionとerror_messageが両方ある必要があり、error_messageの中に、許容範囲が1-5という文字のまま入っている必要があります。範囲を外れた値(例: -var replica_count=9)で実行して、拒否された出力を、/root/tf/vars/out/validation.txtに保存してください。
変数ブロックの中に、条件とメッセージを入れるブロックを入れます。メッセージは、ユーザーがそれだけを見て直せる必要があるので、許容範囲を文字のまま書いてください。
localsで名前の接頭辞を組み合わせる
/root/tf/vars/main.tfにlocalsブロックを作り、name_prefixを、environmentとownerをハイフンでつないだ値として定義してください。outputs.tfにname_prefixの出力を追加します。ステップ8で再作成するcli-outputs.jsonのname_prefixは、prod-platformでなければなりません。
localsは、外から注入できない、名前を付けた式です。2つの変数をハイフンでつないだ値を作って、出力として出してください。
説明が付いた出力をまとめておく
出力を/root/tf/vars/outputs.tfの1か所にまとめて、最低4つ(environment、owner、name_prefix、config_path)を置いてください。ただし、すべての出力にdescriptionを付けてください。config_pathは、この設定が作るlocal_fileのfilenameをそのまま出力します。
出力は、この設定の公開インターフェースなので、1つのファイルにまとめます。1つでも説明が抜けていると、採点が個数を数えて見つけます。
機密値を隠す方法と、その限界を確認する
variables.tfにapi_token変数をsensitive = trueで宣言して、値はTF_VAR_api_tokenで渡してください。outputs.tfにもapi_tokenの出力をsensitive = trueで追加します。最後に、-var environment=prodとTF_VAR_owner=platform、TF_VAR_api_tokenを一緒に与えて適用したあと、cli-outputs.jsonを再作成して、人が読む形式の出力も/root/tf/vars/out/sensitive.txtに保存してください。後者には、値の代わりに隠された表示があり、実際のトークンの文字列が見えてはいけません。
変数と出力の両方に、機密の指定が必要です。人が見る出力と機械が読む出力を、それぞれ保存して、2つの結果がどう違うかを比較してください。