誰かが手で直したサーバー
午前2時、店の掲示は「休業」のはずが「営業中」になっています。誰かが本番サーバーのファイルを直し、誰にも伝えませんでした。
次にプレイブックを実行したとき、それに気づいてファイルを戻してほしいところです。このレッスンでは、その方法と、何も変えずに先に確認する方法を学びます。
このレッスンのゴール
メモ
プレイブックを2回実行し、何が変わったか、なぜ変わったかを言える。
重要な言葉
| ことば | いみ | れい |
|---|---|---|
| 冪等 | もう一度実行しても、何も変わらないこと | |
| ドリフト | 現実が、書いた説明と合わなくなること | |
| チェックモード | 変更を行わず、変わる内容だけ知らせる実行 | --check |
| 差分 | 変わる行 | --diff |
| リキャップ | 実行の最後に出る合計 | PLAY RECAP |
学生が入力するセルは、このプレビューでは空白です。
プレイブックは手順でなく結果を書く
タスクは、ファイルがどうあるべきかを書きます。何を打つかは書きません。ファイルがすでに正しければ、何もせず ok と知らせます。違っていれば、直して changed と知らせます。
だから良いプレイブックは冪等です。2回目の実行は、変更なしと知らせます。
フォルダを作って入る
mkdir -p ~/iac-demo/drift && cd ~/iac-demo/driftここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
タスク1つのプレイブックを書く
printf '%s\n' '- hosts: localhost' ' connection: local' ' gather_facts: false' ' vars:' ' hours: "9時から17時まで営業"' ' tasks:' ' - name: write the notice' ' ansible.builtin.copy:' ' dest: ./notice.txt' ' content: "{{ hours }}\n"' ' mode: "0644"' > site.ymlここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
1回目の実行
ansible-playbook -i localhost, site.yml | grep -E "changed="ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
もう一度実行する
ansible-playbook -i localhost, site.yml | grep -E "changed="ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ドリフトは記録されない変更
ドリフトとは、現実が説明と合わなくなることです。多くは、誰かが手で直したことで起きます。冪等だと、ドリフトを直しやすくなります。
まずプレイブックをチェックモードで実行します。変わる内容を知らせ、--diff は行を見せますが、何も書き込みません。
ファイルを手で直す
echo "一週間休業" > notice.txt; cat notice.txtここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
まずチェックと差分で見る
ansible-playbook -i localhost, site.yml --check --diff | grep -E "^[-+][^-+]|changed="ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ファイルをもう一度読む
cat notice.txtここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
本当に実行し、もう一度実行する
ansible-playbook -i localhost, site.yml | grep -E "changed="; cat notice.txt; ansible-playbook -i localhost, site.yml | grep -E "changed="ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
shellタスクは変化を見分けられない
copy モジュールは、ファイルを望む内容と比べます。shell モジュールはコマンドを実行するだけで、何か変わったかを知りません。毎回 changed と知らせます。
Ansible のラボが、shell コマンドだけのプレイブックを断るのは、この理由です。
同じ仕事をshellコマンドで書く
printf '%s\n' '- hosts: localhost' ' connection: local' ' gather_facts: false' ' tasks:' ' - name: write with a shell' ' ansible.builtin.shell: echo "9時から17時まで営業" > ./shell.txt' > shell.ymlここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
2回実行する
ansible-playbook -i localhost, shell.yml | grep -E "changed="; ansible-playbook -i localhost, shell.yml | grep -E "changed="ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
よくある間違い
注意
1回目に changed=0 なら、プレイブックは役に立つことをしていない、と考える人が多くいます。意味するのは、マシンがすでに望む状態だったということです。毎回 changed と出る実行はドリフトを隠します。本物の変更が、普通の変更と同じに見えるからです。
OpenTofuはstateでドリフトを探す
本物のプロバイダがあれば、tofu plan はまず本物のサービスに何があるかを尋ね、stateとの違いを見せます。手での変更に気づけるのは、そのためです。
ラボの terraform_data は値だけを持ち、OpenTofu の外には何もありません。手で直せるものがないので、このレッスンではファイルを使います。
収束をPythonで計算
# マシンを望む状態に合わせ、変わった数を数えます。
wish = {"hours": "9時から17時まで営業", "phone": "0100"}
machine = {"hours": "休業", "extra": "そのままにする"}
changed = 0
for name in wish:
if name not in machine or machine[name] != wish[name]:
machine[name] = wish[name]
changed = changed + 1
print("changed =", changed)
# ループをもう一度実行して、changed を見てみましょう。
さらに進む: 望む状態を変える
ansible-playbook -i localhost, site.yml -e '{"hours": "10時から16時まで営業"}' | grep -E "changed=" を実行し、続けて cat notice.txt を実行します。同じコマンドをもう一度実行します。
1回目はファイルが変わり、2回目は変わらないのはなぜですか。どの変数が勝ちましたか。