TT Lab
はじめる
学ぶ 学習パス コース

Terraform実戦

遅いプランを扱う四つのつまみとその代償

TT Labで続きを見る

一言でいうと

プランの時間を縮めるノブは、4つあります。リフレッシュをオフにする・並列度・対象の絞り込み・状態の分割です。4つとも、何かを代償にするので、計測したあとで、失ってもよいものを選ぶ必要があります。

なぜ問題なのか: 遅いプランは安全の問題

planに3分かかり始めると、人々の行動が変わります。1行直して3分待つのが嫌で、「これは明白な変更だから」と、すぐにapplyを打ちます。その習慣が定着すると、「適用前に何が変わるのかを見る」という規律自体が失われます。事故は、その次に起きます。

そのため、プランの性能は、利便性の問題ではなく、規律を守れるようにするための問題です。ただし、ノブを手当たり次第に引いてはいけません。各ノブが正確に何を諦めるのかを知っている必要があります。

どう動くのか

プラン1回は、大きく3つのことを行います。設定を読んでグラフを作り(速い)、状態に書かれたものが実際にまだそのままかを1つずつ確認し(たいていここが大部分)、その結果と設定を比較して変更の一覧を作ります(速い)。大きな状態で遅い理由は、ほとんどいつも真ん中です。

1. リフレッシュをオフにする。真ん中のステップを、まるごと飛ばします。最も大きく短縮できますが、外で生じた変化を見られません。誰かがコンソールで手で直していても、プランは「変更なし」と言います。急いで元に戻す必要がある状況や、直前に自分で適用して、状態が確実に最新であるときにだけ、使う価値があります。

2. 並列度。同時に進める作業数を決めます。プランの内容はまったく変わらず、時間だけが変わります。上げれば常に速くなるかというと、そうではありません。相手のAPIがレート制限をかけると、リトライが増えて、かえって遅くなります。下げるほうが必要な場合もあります(制限が厳しいAPI、共用アカウント)。

3. 対象の絞り込み。指定したアドレスと、それが依存するものだけをプランに入れます。確実に速いですが、そのプランは設定全体を代表しません。ツールも、プランするたびに警告を出します。OpenTofuのドキュメントは、このオプションを「ミスからの復旧や、ツールの限界を回避するための、例外的な状況でのみ」使うよう書いています。日常の作業でこれを使っているなら、それは性能の問題ではなく、設計の問題だというサインです。

4. 状態の分割。根本的な解決策です。毎日変わる層と、ほとんど変わらない層を、別の状態に置けば、人は自分の層だけを待てばよくなります。全体の時間の合計は、かえって増えることがありますが、1人の待ち時間が減り、おまけに、ロックの競合と爆発半径も減ります。代償は、層の間を出力でつなぐ必要があることと、その接続が契約になることです。

ここに、保存したプラン(-out)が加わります。CIでプランと適用を分けて回すときに使いますが、ルールが1つあります。保存したプランは、そのときの状態を前提としています。その間に状態が変わると、適用が拒否されます。不便に見えますが、これこそが、「レビューしたそのプランが適用される」ことを保証する仕組みです。

現場での姿

最もよくある間違いは、計測せずに選ぶことです。「遅いからrefreshをオフにしよう」で始めて、半年後には、ドリフトが溜まったまま、誰も気づかない状態になります。計測してみると、たいてい原因はもっと具体的です。特定のデータソース1つが、毎回数千件を列挙していたり、1つのモジュールが、状態の半分を占めていたりします。

2つ目は、1回測って結論を出すことです。最初の実行は、キャッシュが空なので遅いです。同じ条件で2回測って、2回目の数字を使う習慣が必要です。

3つ目は、計測の記録を積み上げるだけにすることです。同じラベルが何行も積み重なると、あとでどの行が最新かわかりません。記録も冪等にして、同じラベルは上書きするようにします。

そして、実務でよく見落とされる事実が1つあります。時間はマシンごとに違いますが、プランの内容は違いません。保存したプランをJSONで開いて、変更項目の数を数えれば、どのマシンで回しても、同じ数字が出ます。そのため、「対象を絞るとプランがその分だけ残る」「リフレッシュをオフにするとドリフトを見られない」のような主張は、時間ではなく、この数字で証明する必要があります。

4つ目に、どこまでが性能の問題で、どこからが設計の問題なのかを分ける基準があれば、会話が楽になります。ノブを1つ引いて、耐えられる程度になったなら、性能の問題です。日常の作業で、対象を絞らないと仕事にならない状態なら、それはすでに設計の問題であり、答えはオプションではなく、状態を分割する作業です。この区別をしておかないと、チームは、応急処置を標準手順として固めてしまいます。

最後に、計測そのもののコストを忘れてはいけません。プランを10回測れば、その分の時間がかかります。そのため、実務では、変更前後の1組だけを測って記録しておきます。記録には、数字だけでなく、そのとき使ったコマンドを丸ごと残します。半年後に、「この数字は、どんな条件から出たものか」を聞かれることになりますが、コマンドがないと、その質問に答えられず、測り直すしかありません。

次のラボですること

/root/tfa-perfに300個の状態を作り、計測するスクリプトを先に作ります。続いて、ファイル1つをツールの外で削除してドリフトを作り、リフレッシュをオフにしたときとオンにしたときで、プランに含まれる変更数がどう変わるかを見て、並列度と対象の絞り込みを計測し、状態を2つに分けて再度測ります。最後に、保存したプランが状態の変化で拒否されることを確認し、測った数字を、表と結論として残します。