状態だけを直す命令と消す順序
一言でいうと
プランは、コードと状態、状態と実物という、2つの比較を一緒に行います。リフレッシュ系のコマンドは、後ろのほうの比較だけを切り出し、破棄は、そのグラフを逆にたどります。
なぜ分ける必要があったのか
apply1回には、実は3つの仕事が入っています。実物を読んで状態を最新にし、その状態をコードと比べて、やることを決め、決めたことを実行します。大半は、この束ねられた形が便利です。ところが、束ねられているために困る場合があります。
1つ目は、状態だけが間違っている場合です。誰かがコンソールで、リソースを手で削除したり、名前を変えたりしたとします。コードは問題なく、実物も(その変更を認めるなら)問題ないのに、状態だけが昔のことを言っています。このとき、そのまま適用すると、ツールは、ないものを新しく作ったり、あるものを上書きしたりします。必要なのは、「状態を実物に合わせる」ことだけです。
2つ目は、逆に、実物を読むコストが大きい場合です。リソースが数千個あるリポジトリでは、リフレッシュだけで数分かかります。急いでいるときに、その段階を飛ばして、プランを出したくなります。
そこで、2つの比較を別に扱うオプションができました。
どう動くのか
リフレッシュ専用のプランは、コードをそもそも見ません。状態と実物だけを比べて、状態をどう直すかを示します。
Note: Objects have changed outside of OpenTofu
# local_file.conf has been deleted
- resource "local_file" "conf" {
ここで適用すると、状態だけが変わります。実物には一切触れず、直前の状態はバックアップファイルに残ります。状態のserialが上がり、なくなった項目が状態から抜けます。
実物を読まないプランは、正反対です。状態に書かれた値を事実として信じるので、外で何が変わったかを知りません。
No changes. Your infrastructure matches the configuration.
同じ瞬間に、通常のプランを実行すると、まったく違うことを言います。なくなったものを作り直し、その値を参照していたものまで置き換えます。同じコード、同じ状態、同じ瞬間なのに、結論が違います。違いは、実物を読んだかどうかだけです。そのため、速度のためにこのオプションを使ったプランで、承認を得てはいけません。
破棄のほうに進みましょう。作るとき、ツールは、依存グラフに沿って、前から作ります。ネットワークができてはじめてデータベースができ、そのあとでアプリケーションができます。削除するときは、まさにその逆順でなければなりません。アプリケーションがまだデータベースを指しているのに、データベースを先に削除すると、残った側が、ないものを指すことになります。
破棄のプランも、通常のプランと同じように、ファイルに保存できます。元に戻せない作業ほど、保存してレビューしたあと、そのファイルだけを適用するほうが安全です。保存したプランファイルは、機械が読む形式でも見られるので、何が削除されるかを一覧として取り出して、承認に添付できます。
対象を絞るオプションは、違います。これを使うと、ツールが普段守ってくれているグラフ全体の一貫性を、人が責任を持つという意味になり、そのため、警告が付きます。
Warning: Resource targeting is in effect
Warning: Applied changes may be incomplete
最後に、すべて削除しても、状態ファイル自体はなくなりません。項目の一覧と出力が空になり、serialが上がるだけで、その状態のlineage番号はそのままです。同じ場所でもう一度適用すれば、同じ記録の延長線につながります。状態ファイルを削除することは、リソースを削除することとはまったく別のことです。削除すると、実物は残り、記録だけが消えて、ツールは、それらを知らないものとして扱うことになります。
現場での姿
最も高くつく事故は、状態だけが食い違っている状況で、そのまま適用してしまうことです。本番で誰かが手で直したリソースを、ツールが作り直し、その間、トラフィックが途切れます。リフレッシュ専用のプランを先に実行して、「コードではなく状態の問題か」を切り分ける習慣が、この事故を防ぎます。
2つ目は、速いプランの落とし穴です。大規模なリポジトリで、リフレッシュを切ったプランをCIに入れておくと、レビューは速くなりますが、外で生じた変更は、承認のあとではじめて明らかになります。速度が必要なら、適用の直前にもう一度、実物を読むプランを実行するのが、妥協点です。
3つ目は、対象を絞った適用が習慣になる場合です。急いでいるときに一度使ったオプションが、チームの標準手順になると、グラフ全体が一貫していたことのないリポジトリになります。使ったあとは、必ず絞っていないプランを一度回して、きれいかを確認します。
4つ目は、破棄をコマンド1行で終える慣行です。削除は元に戻せないのに、対話的な確認を一度通しただけで終えると、何が削除されたのか、あとで誰も再構成できません。プランをファイルに保存して、機械が読む形式で一覧を取り出しておけば、承認の根拠が残り、事故が起きたときに、何を復旧すべきかが一度にわかります。ファイルに保存したプランを適用すれば、レビューしたものと実際の作業が食い違う余地もありません。
次のラボですること
8つのステップを進めます。ベースラインを作り、ツールを経由せずにファイルを直したあと、リフレッシュ専用のプランを出し、実物を読まなかったプランと、読んだプランを並べて保存して比較します。続けて、リフレッシュだけを適用して、状態のserialと項目数がどう変わるか、手で直したファイルはそのままかを確認します。後ろの4つのステップでは、3段階の連鎖を作って、破棄のプランをファイルに保存し、そのファイルを適用して、削除される順序をログで確認し、対象を絞った破棄の警告を読み、最後に、すべて削除した状態に何が残るかを、バックアップと比べます。