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

Ansible実戦

バッチに分けロードバランサへ委譲して無停止で上げる

TT Labで続きを見る

目標

ホストの集合をバッチに分割し、デプロイ中のサーバーをロードバランサーから外して戻し、バッチごとに状態を判定して、事故が次のバッチへ広がらないようにするプレイブックを書けるようになります。

なぜ重要なのか

デフォルトの動作では、Ansibleはタスク1つを全ホストで終えてから次のタスクへ進みます。サービスを再起動するタスクがあれば、その瞬間に全ホストが一緒に落ちます。そのため、無停止デプロイはツールではなくプレイブックの構造で作ります。分割し(serial)、外して戻し(delegate_to)、バッチごとに判定します(max_fail_percentage)。このうち1つでも欠けると、無停止ではありません。外さなければ、リクエストがデプロイ中のサーバーに入り、判定しなければ、壊れたバージョンが残りのサーバーへ広がります。そして、serialを掛けると、run_onceとハンドラーの意味まで、静かに変わります。その事実を知らずに使うと、「1回だけ動くと思っていたタスク」が、バッチの数だけ動きます。

ステップ

  1. /root/ans/roll/inventory/hosts.iniにwebグループ(web1・web2・web3、ansible_host=127.0.0.1、ansible_port=2222)とlbグループ(lb1、ansible_connection=local)を書いてください。/root/ans/roll/p01.ymlにserial: 2を掛け、ホストごとに自分のバッチのメンバーをカンマでつないで、/root/ans/roll/out/01-<호스트>.txt(プレースホルダーはホスト名です)に書くようにしてください。
  2. /root/ans/roll/p02.ymlで、serialをリスト[1, 100%]で指定してカナリアのバッチを作り、ステップ1と同じ方法で/root/ans/roll/out/02-<호스트>.txtにバッチのメンバーを書いてください。
  3. /root/ans/roll/p03.ymlにserial: 2を掛け、run_once: trueとdelegate_to: lb1を付けたタスク1つで、/root/ans/roll/out/03-runonce.txtにbatch <배치구성원> ran on <실행한호스트>(プレースホルダーは順に、バッチのメンバーと、実行したホストです)の形式の行を残してください。
  4. /root/ans/roll/p04.ymlをserial: 1にし、すべてのタスクをlb1に委譲して/root/ans/roll/out/lb/ディレクトリを作成したあと、ホストごとにdrained-<호스트>.txtとenabled-<호스트>.txtを、それぞれhost=<호스트>の内容で残してください(プレースホルダーはホスト名です)。
  5. /root/ans/roll/p05.ymlで、delegate_to: lb1とdelegate_facts: trueを一緒に指定したset_factで、lb_pool_sizeをプレイの対象の数として立て、その値をhostvarsで読み取って、/root/ans/roll/out/05-lbfact.txtにlb_pool_size=<값> on_web=<웹 호스트에서 본 값>(プレースホルダーは順に、値と、Webホストから見た値です)の形式で残してください。Webホスト側には値がない必要があります。
  6. /root/ans/roll/p06.ymlをserial: 2にし、ホストごとに/root/ans/roll/out/06-<호스트>.conf(プレースホルダーはホスト名です)を置くタスクが、ハンドラーを呼び出すようにしてください。ハンドラーは、run_once: trueとdelegate_to: lb1で、/root/ans/roll/out/06-handlers.txtにrestarted: <배치구성원>(プレースホルダーはバッチのメンバーです)の行を残します。
  7. /root/ans/roll/p07.ymlをserial: 1・max_fail_percentage: 0にし、プレイのvarsのhealthy_hostsを[web1, web3]にしてください。タスクは、/root/ans/roll/out/07-deployed-<호스트>.txt(プレースホルダーはホスト名です)を残すデプロイのマーカーと、healthy_hostsに入っているかを見るassertによる確認の、2つです。実行出力を/root/ans/roll/out/07-run.txtに保存してください。
  8. /root/ans/roll/p08.ymlにプレイを2つ置いてください。最初のプレイは、webをserial: [1, 100%]・max_fail_percentage: 0で回しながら、バッチの記録を/root/ans/roll/out/08-batches.txtに残し、ホストごとに/root/ans/roll/out/08/の下にdrained-・release-(内容はrelease=2.4.0)・enabled-のマーカーを残し、その間にassertで状態を確認します(3台とも正常)。2つ目のプレイは、lb1でその記録を集めて、/root/ans/roll/out/rolling.jsonにbatches・drained・enabledを書きます。最後に、同じプレイブックをもう1回実行して、出力を/root/ans/roll/out/08-run2.txtに保存してください。changed=0である必要があります。

参考

2台ずつ区切ってデプロイする

/root/ans/roll/inventory/hosts.iniにwebグループ(web1・web2・web3、ansible_host=127.0.0.1、ansible_port=2222)とlbグループ(lb1、ansible_connection=local)を書いてください。/root/ans/roll/p01.ymlにserial: 2を掛け、ホストごとに自分のバッチのメンバーをカンマでつないで、/root/ans/roll/out/01-<호스트>.txt(プレースホルダーはホスト名です)に書くようにしてください。

今のバッチに誰が入っているかは、実行中に変数でわかります。ansible_play_batchをカンマでつないで書けば、バッチがどう分かれたかがファイルに残ります。

まずカナリア1台、残りは一度に

/root/ans/roll/p02.ymlで、serialをリスト[1, 100%]で指定してカナリアのバッチを作り、ステップ1と同じ方法で/root/ans/roll/out/02-<호스트>.txt(プレースホルダーはホスト名です)にバッチのメンバーを書いてください。

リストの要素には、数字と割合を混ぜて書けます。最後の要素を100%にすると、「残りすべて」という意味になります。

run_onceはバッチごとに1回

/root/ans/roll/p03.ymlにserial: 2を掛け、run_once: trueとdelegate_to: lb1を付けたタスク1つで、/root/ans/roll/out/03-runonce.txtにbatch <배치구성원> ran on <실행한호스트>(プレースホルダーは順に、バッチのメンバーと、実行したホストです)の形式の行を残してください。

同じ行を何回実行してもファイルが増えないようにしてください。行単位で「なければ入れる」モジュールを使います。何行出力されるかを数えれば、run_onceの範囲が明らかになります。

ロードバランサーから外して、また戻す

/root/ans/roll/p04.ymlをserial: 1にし、すべてのタスクをlb1に委譲して/root/ans/roll/out/lb/ディレクトリを作成したあと、ホストごとにdrained-<호스트>.txtとenabled-<호스트>.txtを、それぞれhost=<호스트>の内容で残してください(プレースホルダーはホスト名です)。

委譲されたタスクの中でも、対象は元のホストです。ファイル名と内容にその名前をそのまま使えば、「誰を外したか」がロードバランサー側の記録に残ります。このステップでは、バッチごとではなく、ホストごとに行われる必要があります。

ファクトを誰の分として書くか

/root/ans/roll/p05.ymlで、delegate_to: lb1とdelegate_facts: trueを一緒に指定したset_factで、lb_pool_sizeをプレイの対象の数として立て、その値をhostvarsで読み取って、/root/ans/roll/out/05-lbfact.txtにlb_pool_size=<값> on_web=<웹 호스트에서 본 값>(プレースホルダーは順に、値と、Webホストから見た値です)の形式で残してください。Webホスト側には値がない必要があります。

プレイの対象の数は、実行中に変数でわかります。Webホスト側で同じ名前を読むときは、ない場合もあるので、デフォルト値を指定して、없음(韓国語で「なし」を意味する語です)が出力されるようにしてください。

ハンドラーはプレイの終わりではなくバッチの終わりに動く

/root/ans/roll/p06.ymlをserial: 2にし、ホストごとに/root/ans/roll/out/06-<호스트>.conf(プレースホルダーはホスト名です)を置くタスクが、ハンドラーを呼び出すようにしてください。ハンドラーは、run_once: trueとdelegate_to: lb1で、/root/ans/roll/out/06-handlers.txtにrestarted: <배치구성원>(プレースホルダーはバッチのメンバーです)の行を残します。

ハンドラーは名前で結び付けられます。何行残るかを数えれば、ハンドラーがいつ動くかわかります。プレイの終わりに1回なら、1行であるはずです。

1台が壊れたらそこで止まる

/root/ans/roll/p07.ymlをserial: 1・max_fail_percentage: 0にし、プレイのvarsのhealthy_hostsを[web1, web3]にしてください。タスクは、/root/ans/roll/out/07-deployed-<호스트>.txt(プレースホルダーはホスト名です)を残すデプロイのマーカーと、healthy_hostsに入っているかを見るassertによる確認の、2つです。実行出力を/root/ans/roll/out/07-run.txtに保存してください。

このプレイブックは、わざと失敗します。出力をファイルで受けるとき、失敗でスクリプトが止まらないようにしてください。3台目のホストのデプロイのマーカーが作られるかどうかが、このステップの答えです。

一連の流れを回してサマリーを残す

/root/ans/roll/p08.ymlにプレイを2つ置いてください。最初のプレイは、webをserial: [1, 100%]・max_fail_percentage: 0で回しながら、バッチの記録を/root/ans/roll/out/08-batches.txtに残し、ホストごとに/root/ans/roll/out/08/の下にdrained-・release-(内容はrelease=2.4.0)・enabled-のマーカーを残し、その間にassertで状態を確認します(3台とも正常)。2つ目のプレイは、lb1でその記録を集めて、/root/ans/roll/out/rolling.jsonにbatches・drained・enabledを書きます。最後に、同じプレイブックをもう1回実行して、出力を/root/ans/roll/out/08-run2.txtに保存してください。changed=0である必要があります。

切り離しと復帰はロードバランサーに委譲し、デプロイは対象で行います。マーカーを数えるのはファイルを探すモジュールで、バッチの記録を読むのはファイルを読み込むモジュールで行えば、2つ目のプレイが短くなります。2回目の実行が静かであるためには、すべてのタスクが冪等である必要があります。