Ansibleに触れると必ずでてくる単語「冪等性」。
「Ansible 冪等性 意味」等で検索すると冪等性の意味に関する記事が沢山見つかります。
しかし、文字ベースではその言葉の意味を調べても中々しっくりこないものです。
本記事では、実際にAnsibleの検証環境にて、コマンドを実行しつつ「冪等性」という概念を理解していこうと思います。
事前準備
本記事では、以下の記事にて構築したAnsibleの検証環境を使用して実機検証を行います。
Ansibleを試してみたいけど、環境構築の手順が分からない..環境構築が面倒くさい..といった方は是非上記記事をお読みいただき、環境構築を行っていただければと思います。
冪等性とは?
冪等性とは一言で言うと、「同じ操作を何度繰り返しても、同じ結果が得られる概念」という数学的概念です。
と言ってもイマイチピンとこないですよね(笑)
分かりやすく一度Ansibleという概念を捨てて数学的な観点から「冪等性」を考えてみましょう。
次の絶対数を求める関数(abs)と平方根を求める関数(sqrt)を使用した関数式を比較してみると非常に分かりやすく理解することができます。
■ 冪等性のある関数式
以下の関数式では、abs(-10)の結果は10になります。そのbas(-10)を何度abs()に渡しても、結果は変わる10になります。
このように同じ処理を何度実行しても同じ結果が変えることを冪等性のある状態と言います。
bas(-10) = abs(abs(-10))
■ 冪等性のない関数式
以下の関数式では、sqrt(-16)の結果は4になりますが、そのbas(-10)を更にabs()に渡すと、結果は2になります。
このように同じ処理を実行する度に結果が変わることを冪等性のない状態と言います。
sqrt(16) ≠ sqrt(sqrt(16))
■ Apacheのインストールで確かめる冪等性
では、ここで話をサーバ処理に話を置き換えてみます。
適当にLinuxサーバを立てて、以下のコマンドを実行してみます。
コマンドの内容は「最新verのApacheサーバをインストールする」といったものになります。
$ yum install httpd
インストールされたApacheのバージョンを確認してみます。
$ httpd -version
Server version: Apache/2.2.2 (CentOS)
Server built: xxx xx xxxx xx:xx:xx
Apache ver2.2.2がインストールされたことが確認できます。
では、また同じコマンドを実行してみます。
すると以下のような結果が出力されます。
$ yum install httpd
パッケージ Server version: Apache/2.2.2 (CentOS) はインストール済みか最新バージョンです
何もしません
そのApacheは既にインストール済だから何もしませんよ!といった結果が出力されます。
同じコマンドを連続して実行してもサーバにApache 2.2.2がインストールされた状態は変わりませんので、この時点では冪等性が保たれてるといえます。
しかし、月日が立ちApacheのバージョンが2.4.4にアップデートされたとします。
するとインストールコマンド実行時に新たに2.4.4のパッケージがインストールされます。
※古いバージョンのApacheパッケージが削除されている前提
$ yum install httpd
~~~ インストール処理 ~~~
$ httpd -version
Server version: Apache/2.4.4 (CentOS)
Server built: xxx xx xxxx xx:xx:xx
yum install httpd
という同じコマンドを実行しているのに、サーバの状態が変わって(Apacheのバージョンが2.2.2から2.4.4に変わってしまった)しまいました。
これは冪等性が保たれていない状態となります。
ここまで関数式やコマンドで例えてきて、徐々に冪等性という概念がイメージできてきたのではないでしょうか。
では次項で実際にAnsibleを実行しつつ冪等性を確認していきます。
Ansibleにおける冪等性
本記事の肝であるAnsibleの冪等性に関して、実機を用いて確認していきます。
以下のplaybook.ymlを用意しました。
内容は「ターゲットホストA, Bの指定のディレクトリにカレントディレクトリのhoge.txtをコピーする」といった感じです。
- hosts: Web
tasks:
- name: copy hoge.txt
copy:
src: /etc/ansible/hoge.txt
dest: /home/ec2-user/
owner: ec2-user
group: ec2-user
mode: '0644'
ちなみにhostsファイルの中身は以下の通りとなっています。
[Web]
web01
web02
[all:vars]
ansible_ssh_user=ec2-user
ansible_ssh_private_key_file=/home/ec2-user/.ssh/id_rsa
早速playbookを実行してみます。
$ pwd
/etc/ansible
# playbookの実行
$ ansible-playbook -i hosts playbook.yml
初回実行の場合、ターゲットホストA,Bに新規にhoge.txtが作成されますので、taskの実行結果は以下の通り「changed」と出力されます。
TASK [test] ********************************************************************
changed: [web01]
changed: [web02]
PLAY RECAP *********************************************************************
web01 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
web02 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
各ターゲットホストにてhoge.txtが作成されているか確認します。
■ ターゲットホストA,B
$ pwd
/home/ec2-user
$ ls
hoge.txt # playbookの内容が反映されている
では先程のplaybookを再度実行してみます。
すると先程とは違って以下の通り、TASKの実行結果は「OK」と出力されます。
サーバの変更が加えられていないわけですからね。
PLAY RECAPセクションを見ても先程は[OK=2 cheanged=1]だったのが[OK=2 cheanged=0]と変わっています。
以降、playbookを何度実行しても同じ結果が出力されます。
同じ処理を何度実行してもサーバの状態は変わらないので、冪等性が保たれているといえます。
TASK [copy hoge.txt] ***********************************************************
ok: [web01]
ok: [web02]
PLAY RECAP *********************************************************************
web01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
web02 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
この通り、Ansibleでの処理は基本的に冪等性が保証されるものとなっています。
冪等性を保たない例外モジュール
Ansibleでは基本的に冪等性が保たれます。
しかし、モジュールによっては冪等性を無視した処理を行うことができます。
例でその中の一つである「command」モジュールを紹介しようと思います。
「command」モジュールとは、Ansibleの組み込みモジュールでは処理しきれない処理をサーバ上にて任意のコマンドを実行できるようにして、無理やり処理を行うモジュールです。
先程のplaybook.ymlを以下のように書き換えてみました。
※ Apacheサーバをインストールするコマンドです
- hosts: Web
tasks:
- name: Install httpd latest
command: "sudo yum install -y httpd"
ではplaybookを実行してみます。
初回実行はもちろんコピー処理が実行されるわけですので、TASKの実行結果は以下の通り「changed」と出力されます。
TASK [test] ********************************************************************
changed: [web01]
changed: [web02]
PLAY RECAP *********************************************************************
web01 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
web02 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ではもう一度playbookを実行してみます。
TASK [test] ********************************************************************
changed: [web01]
changed: [web02]
PLAY RECAP *********************************************************************
web01 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
web02 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Ansibleの性質上、何回同じ処理を行おうと冪等性が担保されるので、TASKの実行結果は「OK」と出力されるはずです。
しかし、「command」モジュールで実行した処理は冪等性を担保しません。
なので上記のようにTASKの実行結果は「changed」と出力されます。
「command」モジュールは性質上、あまり使用することはないかとは思いますが、このように冪等性を担保せずに処理を実行する方法もあるということを頭の片隅に置いておいて下さい。
まとめ
Ansibleを使っていく以上、「冪等性」という概念は必ず理解しておくようにして下さい。
特にplaybookの出力結果の見方は非常に重要です。
業務レベルで使用するような複雑な処理になってくると、どの処理がどうなっていて、どこが冪等性が保たれているのかとてもわかりづらくなってきます。
Ansibleヘビーユーザもこの機会に是非「冪等性」単語について再考してみて下さい。
コメント
Ansible勉強中です。大変記事参考になりました!ありがとうございます。一つ質問させてください。commandモジュールですが、どのOSにも基本対応しているんでしょうか?CLIで設定できるNW機器に対してこのモジュールが使えないかと考えているのですが。。対応表等探すも見つからなかったので、ご存じであれば教えて頂けると幸いです。
みる様
お問い合わせありがとうございます。
当サイト管理人の chibiharu です。
回答が遅くなってしまい大変申し訳ございませんでした。
以下回答致します。
>commandモジュールですが、どのOSにも基本対応しているんでしょうか?
→ 対応OSについては以下のページから探すことが可能かと思われます。
Ansibleでは基本的にOSに応じたcommandモジュールが用意されています。(例:Cisco->ios_command)
利用したいOSに応じたcommandoモジュールをご使用頂ければと思います。
以上、ご回答になっておりますでしょうか。
また何かございましたらご連絡下さい。