Ansibleを通じて「べき等性」を理解してみよう
- date:
2019-09-17
- author:
Kazuya Takei
- location:
PyCon JP 2019
イントロ
Who am I?
Who am I?
話すこと(目標)
冪等性の概要
あっさり
Ansibleについて
前置き
Ansibleはどうやって「冪等性」を担保しているか
メイン予定
冪等性の概要
※超概要です
「冪等性」とは
冪等 = べきとう
ある操作を何度実施しても、同じ結果になる性質を持つこと。
f(x) = f(f(x)) = f(f(f(x))) ...
「冪等性」の例
>>> def add_zero(x):
>>> return x + 0
>>>
>>> x = 2019
>>> x = add_zero(x)
>>> x
2019
>>> x = add_zero(x)
>>> x
2019
>>> add_zero(add_zero(add_zero(add_zero(x))))
2019
「冪等性」の例
>>> def multi_one(x):
>>> return x * 1
>>>
>>> x = 2019
>>> x = multi_one(x)
>>> x
2019
>>> x = multi_one(x)
>>> x
2019
>>> multi_one(multi_one(multi_one(multi_one(x))))
2019
Ansibleについて
Ansibleとは
Python製の「構成管理ツール」
「動作」ではなく「状態」を定義して適用する
主にサーバーのセットアップなどに使われる
etc
クライアントPC
ネットワーク機器
クラウドサービス
コミュニティあります

Connpass: https://ansible-users.connpass.com/
Ansibleの動き(概要)

Ansibleの動き(中身)
インベントリファイル
処理実行先のサーバー一覧や簡単な情報を定義
[local]
localhost ansible_connection=local
Ansibleの動き(中身)
Playbook
# ------------------
# RedHat系OSのマシンで、Apacheを使えるようにするPlaybook
# ------------------
- hosts: local
# sudoが必要なケースではbecomeを指定する
become: yes
tasks:
# 1個ずつ「モジュール」を指定する
- yum:
# nameでパッケージ名を指定
name: httpd
Ansibleの動き(中身)
Playbook
実際にAnsibleが操作したい状態を定義したもの
動作ではなく状態
「httpdをインストールする」という動作ではない
「httpdをインストールされていること」という状態
処理の流れ
Playbookに定義された状態になるように、各モジュールがよしなに処理する
処理の結果、「状態に変化があったか」の報告を受ける。
変化があれば
changed
変化がなければ
ok
同じPlaybookを実行すると、2回め以降は状態に変化がないのでOKとしかでない
= ある操作を何度実施しても、同じ結果になる
= 冪等性がある
Ansibleが担保する冪等性
定義された 「状態に対する冪等性」 を担保するように設計されている
※ログ出力があるので、マシン全体の冪等性は無理
Ansibleはどうやって、冪等性を担保するか?(1)
pip モジュール
pip
コマンド経由で、Pythonパッケージの状態を管理するモジュールvirtualenv
の指定や作成もできるextra_args
経由で全部のオプションを指定可能
- hosts: local
tasks:
pip:
name: django
executable: pip3
extra_args: --user
モジュールの全体像

モジュールの全体像
全771行!
前半の約半分はドキュメント
残りのソースには、処理に必要な全内容がコードで書かれがち
そのため、モジュールのソースは長めにになる傾向が強い
モジュールの全体像
大まかな流れ
実行環境の設定
実行コマンドの組み立て
コマンドの実行
実行結果の検査
モジュールとしての結果を返す
モジュールから抜粋

モジュールから抜粋

モジュールから抜粋

モジュールから抜粋

モジュールから抜粋

モジュールから抜粋

モジュールから抜粋

モジュールから抜粋

モジュールの単体実行の様子
1回目

モジュールの単体実行の様子
2回目

ここまで
パラメーターに従って、
pip
コマンドをただただ実行実行結果(リターンコード、標準出力、標準エラー)をもとに、どうなったかを判定
pip
コマンド自体が冪等性を持っているため、割とそれに信頼性を委任
Ansibleはどうやって、冪等性を担保するか?(2)
amazon-linux-extras モジュール
Amazon Linux 2が持つパッケージリポジトリの状態を管理できるもの
コマンド自体が割と冪等性を持っているけど、
command
モジュールで呼ぶのもあれなので自作してみた
※前述のpipモジュールなどを見る前に、ドキュメントだけ読んで作ってみたものです
- hosts: local
tasks:
- amazon2extras: name=php7.3
- yum: name=php7.3
モジュールの全体像

モジュールの全体像
全771行!
前半の約半分はドキュメント
残りのソースには、処理に必要な全内容がコードで書かれがち
そのため、モジュールのソースは長めにになる傾向が強い
モジュールの全体像
やってること
トピックの検索
状態の確認(有効/無効の判定)
状態と設定をもとにしたコマンドの実行
コマンド実行の際には結果を確認
モジュールのコード(抜粋)

モジュールのコード(抜粋)

ここまで
必ず状態をチェックして、「コマンドの実行可否」を決めている
present
なのに、「まだ有効になってない」なら有効にするコマンドを実行absent
なのに、「すでに有効になっている」なら無効にするコマンドを実行「状態を変える必要がない」なら、なにもしない
「余計なことはしない」ことで冪等性を担保している
おわりに
まとめ
- 冪等性とAnsibleの概要をふまえて、モジュルールのコードを追ってみました
- 冪等性の担保には、「現在と目標とのズレ」や「初期状態x処理のパターン把握」が重要
冪等性を担保するソフトを利用してても、それは変わらない
冪等性はどこにでもいる
おまけ:他にもある「冪等性」
git pull
リモートが変化しない間の正常なpullは何度やっても結果が同じ
データベースマイグレーション
スキーマの状態に対して、冪等性を担保する
Let's Encrypt
「FQDNへの証明書があること」に対して、冪等性を担保する
(終)