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

Terraform実戦

プランが遅くなると、人はプランを飛ばし始めた

TT Labで続きを見る

目標

300個の状態を作ってプランの時間を自分で測り、リフレッシュ・並列度・対象の絞り込み・状態の分割という4つのノブが、時間とプランの内容をそれぞれどう変えるかを、保存したプランで確認したあと、計測記録を表と結論として残します。

なぜ重要なのか

プランが遅くなることは、不便さではなく、安全の問題です。3分待つ必要があると、人々は小さな変更でプランを飛ばし、その瞬間に、「適用前に何が変わるのかを見る」という規律が失われます。ところが、遅いプランを扱うノブは、いずれも何かを代償にします。リフレッシュをオフにすると、外で生じた変化を見られず、対象を絞ると、そのプランは設定全体を代表できず、状態を分割すると、層の間を出力でつなぐ必要があります。そのため、順序が重要です。先に測り、何が時間を食っているかを確認したあと、失ってもよいものを選んでノブを引きます。このラボの絶対的な時間は、実際のクラウドとは違います(このPodのプロバイダーには、リモート呼び出しがありません)。学ぶのは、数字ではなく、測り方と、各ノブがプランの内容をどう変えるかです。

ステップ

  1. /root/tfa-perf/main.tfに、var.sizeの数だけのrandom_pet.nと、それぞれの名前を/root/tfa-perf/out/<인덱스>.txt(プレースホルダーはインデックスです)に書くlocal_file.nを、countで宣言してください。/root/tfa-perf/terraform.tfvarsにsize = 150を置いて、init・applyします。状態には、インスタンスが300個入ります。
  2. /root/tfa-perf/measure.shを作成してください。最初の引数をラベルとして受け取り、残りの引数をtofu planにそのまま渡して、かかった時間をミリ秒で測り、プランは/root/tfa-perf/plans/<이름표>.tfplanに、出力は/root/tfa-perf/plans/<이름표>.logに保存し、/root/tfa-perf/times.tsvに、<이름표>・<밀리초>・<실행한 명령>の3つの列をタブで書きます(プレースホルダーは順に、ラベル、ミリ秒、実行したコマンドです)。同じラベルをもう一度測ると、行が増えずに置き換わる必要があります。そのあと、オプションなしで、fullというラベルで1回測ってください。
  3. /root/tfa-perf/out/7.txtをツールの外で削除してドリフトを作ったあと、no-refreshラベルで-refresh=falseを付けて測り、続けて、refreshラベルでオプションなしで測ってください。2つのプランファイルに含まれる変更数が異なる必要があります。最後に、applyして、削除したファイルを元に戻します。
  4. par1ラベルで-parallelism=1を付けて測ってください。保存されたプランに含まれる変更項目数が、fullと同じである必要があります。
  5. targetラベルで-target=random_pet.n[0]を付けて測ってください。保存されたプランには、項目が数個しか残らない必要があり、/root/tfa-perf/plans/target.logには、ツールが出した警告が入っている必要があります。
  6. /root/tfa-perf/split/aと/root/tfa-perf/split/bに、同じ設定を置いて、それぞれsize = 75でinit・applyしてください(合わせると最初と同じ300個です)。そのあと、各ディレクトリで、/root/tfa-perf/measure.shを、split-a・split-bラベルで1回ずつ実行してください。
  7. staleラベルでプランを1つ保存したあと、/root/tfa-perfでtofu apply -replace=random_pet.n[0] -auto-approveを実行して、状態を変更してください。そのあと、保存しておいたplans/stale.tfplanを適用してみて、その出力を/root/tfa-perf/stale.txtに保存します。最後に、プランはきれいである必要があります。
  8. /root/tfa-perf/report.mdを作成してください。| label | ms | command |のヘッダーと区切り線で始まる表に、times.tsvのすべての行を、ラベル順に入れ、表のあとに、fastest: <가장 빠른 이름표>(プレースホルダーは最も速いラベルです)の1行を書きます。数字は作り上げず、times.tsvからそのまま写します。

参考

測るのにふさわしいサイズを作る

/root/tfa-perf/main.tfに、var.sizeの数だけのrandom_pet.nと、それぞれの名前を/root/tfa-perf/out/<인덱스>.txt(プレースホルダーはインデックスです)に書くlocal_file.nを、countで宣言してください。/root/tfa-perf/terraform.tfvarsにsize = 150を置いて、init・applyします。状態には、インスタンスが300個入ります。

ここでcountを使う理由は、インデックスで互いを参照して、2つのリソースを対にして増やすためです。実際のインフラなら、この300個が毎回リモートAPIで確認されます。その確認が、プラン時間の大部分です。

計測ツールを先に作る

/root/tfa-perf/measure.shを作成してください。最初の引数をラベルとして受け取り、残りの引数をtofu planにそのまま渡して、かかった時間をミリ秒で測り、プランは/root/tfa-perf/plans/<이름표>.tfplanに、出力は/root/tfa-perf/plans/<이름표>.logに保存し、/root/tfa-perf/times.tsvに、<이름표>・<밀리초>・<실행한 명령>の3つの列をタブで書きます(プレースホルダーは順に、ラベル、ミリ秒、実行したコマンドです)。同じラベルをもう一度測ると、行が増えずに置き換わる必要があります。そのあと、オプションなしで、fullというラベルで1回測ってください。

ミリ秒は、dateの%s%3N形式で得ます。同じラベルの古い行を消して、新しく書けば、何度測っても記録がきれいです。計測記録がappendだけで積み上がると、あとでどの行が最新かわかりません。プランを-outで保存しておく理由は、あとで「何が入っていたか」を再び見られるようにするためです。

リフレッシュをオフにすると、何が速くなり、何を失うか

/root/tfa-perf/out/7.txtをツールの外で削除してドリフトを作ったあと、no-refreshラベルで-refresh=falseを付けて測り、続けて、refreshラベルでオプションなしで測ってください。2つのプランファイルに含まれる変更数が異なる必要があります。最後に、applyして、削除したファイルを元に戻します。

リフレッシュとは、状態に書かれたものが、実際にまだそのままかを、1つずつ確認する作業です。オフにすると、その確認をまるごと飛ばすので速くなりますが、外で生じた変化を見られません。保存したプランをtofu show -jsonで開いて、変更数を数えてみてください。

並列度を下げると、時間だけが変わり、結果は同じ

par1ラベルで-parallelism=1を付けて測ってください。保存されたプランに含まれる変更項目数が、fullと同じである必要があります。

並列度は、ツールが同時にいくつの作業(主にリモート呼び出し)を進めるかを決める値です。プランの内容とは無関係なので、結果は同じで、時間だけが変わります。逆に、上げれば常に速くなるかというと、そうではありません。相手のAPIがレート制限をかけると、リトライが増えて、かえって遅くなります。

対象を絞ると、プランがその分だけ残る

targetラベルで-target=random_pet.n[0]を付けて測ってください。保存されたプランには、項目が数個しか残らない必要があり、/root/tfa-perf/plans/target.logには、ツールが出した警告が入っている必要があります。

対象を絞ると、ツールは、そのリソースとそれが依存するものだけをプランに入れます。そのため、このプランは設定全体を代表せず、ツールもその事実を警告で知らせます。公式ドキュメントは、このオプションを、ミスからの復旧のような例外的な状況でのみ使うよう書いています。

状態を2つに分けて、同じ数を測り直す

/root/tfa-perf/split/aと/root/tfa-perf/split/bに、同じ設定を置いて、それぞれsize = 75でinit・applyしてください(合わせると最初と同じ300個です)。そのあと、各ディレクトリで、/root/tfa-perf/measure.shを、split-a・split-bラベルで1回ずつ実行してください。

measure.shは、自分が置かれた位置を基準に記録するため、どのディレクトリから呼び出しても、記録は1か所に集まります。分割後の2つの時間を足すと、最初の1つより大きくなるとしても、人は自分の状態1つだけを待てばよい、という点が核心です。分割は、全体の時間ではなく、1人の待ち時間を減らします。

保存したプランは、状態が変わると使えない

staleラベルでプランを1つ保存したあと、/root/tfa-perfでtofu apply -replace=random_pet.n[0] -auto-approveを実行して、状態を変更してください。そのあと、保存しておいたplans/stale.tfplanを適用してみて、その出力を/root/tfa-perf/stale.txtに保存します。最後に、プランはきれいである必要があります。

保存したプランは、「そのときの状態で、この変更を行う」という約束です。状態がその後に変わると、約束の前提が崩れるため、ツールが適用を拒否します。CIでplanとapplyを分けて回すとき、このルールが、そのまま安全装置になります。

計測記録を表にまとめて、結論を書く

/root/tfa-perf/report.mdを作成してください。| label | ms | command |のヘッダーと区切り線で始まる表に、times.tsvのすべての行を、ラベル順に入れ、表のあとに、fastest: <가장 빠른 이름표>(プレースホルダーは最も速いラベルです)の1行を書きます。数字は作り上げず、times.tsvからそのまま写します。

結論の行は、自分が測った数字から出てくる必要があります。採点ツールも、times.tsvを読んで、同じ計算をします。どのノブが最も大きく短縮したかは、マシンごとに違うことがあり、それが、「測って選べ」という言葉の意味です。