エイリアスとバージョン制約 — どの設定で作るのか
一言でいうと
aliasは、同じプロバイダーの2つ目の設定にラベルを付けることで、バージョン制約は、明日の朝、CIがどこまで新しいバージョンを取得してよいかを決めることです。どちらも、「選択」をコードに残す仕組みです。
なぜ必要なのか
プロバイダーの設定は、認証情報・エンドポイント・リージョンのような接続情報を持ちます。リソースは、そのうちの1つを選んで作られます。設定が1つだけのときは、選ぶものがないので、この選択が見えません。2つ目ができた瞬間、すべてのリソースが答える必要があります。あなたはどちらで作られるのか、と。
この質問に答えないと、ツールはデフォルトの設定を使います。黙って使います。そのため、「DRリージョンに作るつもりが、メインのリージョンにまた作ってしまった」という事故は、エラーなしで通り過ぎます。さらに悪いのは、その次です。状態ファイルには、そのリソースがどの設定で作られたかが書かれるため、あとで削除するときも、同じ設定で削除します。間違った組み合わせが、そのまま固まります。
バージョン制約は、別の方向の同じ問題です。制約を書かないと、今日はうまくいっても、明日CIで、初めて見るエラーが出ます。新しいバージョンが出たからです。逆に、1つのバージョンに固定すると、セキュリティ修正が出ても、手で上げる必要があります。制約は、この2つの間のどこに立つのかを書く文です。
どう動くのか
3つを区別する必要があります。
provider "random" {} # 기본 설정 — 이름표 없음
provider "random" {
alias = "seeded" # 두 번째 설정 — 이름표 seeded
}
resource "random_pet" "a" {
provider = random.seeded # 리소스는 provider (단수)
}
module "site" {
providers = { # 모듈은 providers (복수, 맵)
random.east = random
random.west = random.seeded
}
}
- リソースは
provider、モジュールはprovidersです。名前が似ていて、よく間違えますが、1つは「私はこの設定を使う」、もう1つは「モジュール内のこの名前は、外のこの設定だ」で、意味がまったく違います。 - モジュールは、自分の設定を作りません。モジュール内で
providerブロックを宣言すると、そのモジュールは認証情報を自分で決めてしまい、2回使えなくなります。代わりに、configuration_aliasesで「こういう名前の設定を受け取る」と、場所だけを宣言します。呼び出す側がその場所を埋めないと、initが、どの名前を受け取れなかったかをピンポイントで示して止めます。 - 状態が記憶します。状態ファイルのリソースごとに、
providerの文字列があり、エイリアスで作られたものだけ末尾が違います。コードをいくら直しても、すでに作られたものの組み合わせは、状態に書かれたとおりです。
バージョン制約は、桁数が意味を作ります。チルダ制約は、一番右の桁だけが上がれるように許可します。桁を2つ書くと、真ん中の桁が上がるところまで受け入れ、3つ書くと、一番末尾の桁だけを受け入れます。ラボで、同じミラーを使って、この2つが異なる結果を出すことを、自分で確認します。
コアのバージョン制約(required_version)は、また別の層です。これは、プラグインを取得する前に検査するため、required_providersがまったくなくても止まります。止まるとき、ツールは、いま使っているバージョンをそのまま教えてくれます。
現場での姿
最もよくある事故は、モジュールを2回呼び出すときに、プロバイダーのマップをコピーして、1行だけ直し忘れることです。文法は合っており、initも通ります。2回目の呼び出しが、1回目と同じ設定を使うことになり、2つのリージョンに分かれるべきものが、片方に集中します。レビューで見つけるには、モジュールの呼び出しごとに、マップ全体を見るようにするしかありません。
2つ目は、制約なしで使っていて、ある日CIだけが壊れることです。人の手元の作業ディレクトリには、すでにロックファイルがあるため、以前のバージョンが使われ続け、きれいなCIの作業スペースだけが、新しいバージョンを取得します。「自分のPCでは動くのに」の典型です。ロックファイルをコミットする理由が、ここにあります。
3つ目は、制約を狭めすぎて、忘れてしまうことです。1つのバージョンに固定した設定が、数十のリポジトリに散らばると、セキュリティ修正が出たときに、上げるべき場所を探すことが、まず仕事になります。実務では、dev側のリポジトリだけ制約を緩めておき、先に上げてみるという形で、順序を作ります。
4つ目は、エイリアス名を環境名にすることです。provider "aws" { alias = "prod" }のように書いておくと、読みやすいですが、その設定がどのリージョン・どのアカウントなのかは、やはり見えません。あとでアカウントを移すと、名前と実態がずれ、ずれた名前は誰も直しません。エイリアスは、接続先を指す名前で付けるほうが、長持ちします。
まとめると、このモジュールが扱う2つは、どちらも「選択をコードに残す」ことです。どの設定で作るかをリソースごとに書いておけば、状態がその選択を記憶し、どこまで新しいバージョンを取得してよいかを制約として書いておけば、ロックファイルがその決定の根拠を残します。どちらも書かないと、ツールが黙って代わりに決め、その決定は、事故が起きてから初めて見えます。
次のラボですること
/root/tfa-aliasで、randomプロバイダーを2つ設定して、リソースごとに選び、モジュールにその設定を渡してみます。続いて、マップから1行を抜いて、initが何と言うかをエラーで受け取り、ミラーにないバージョンを要求して拒否され、チルダ制約の2通りが、互いに異なるものを許可することを確認したあと、ロックファイルと状態から値を読み取って、表にまとめます。