ときどきAnsible日記

主にITインフラ基盤の自動化に関する事を書いているブログです

Ansibleでテストを試してみる

お疲れ様です。伊藤です。

先日インフラの自動化に関するセミナーに参加してきました。無料のセミナーでしたがなかなかの規模で確か定員300名のところにそれ以上の応募が来て抽選になる状態。何とか当選して行ってまいりましたが、特にAnsible関連のところは人が多かった印象です。席に座れずに立ち見まで出てましたんで。。

こんなスマホ防水(防滴?)ポーチもらいました。
f:id:pj_doaa:20170810095906j:plain


でその中でインフラ試験についてもちょっと話が出ていました。簡単に言うとインフラ試験についてもAnsibleでやれるよ、みたいな話。このブログでもTestInfraというツールを使ってみようと思っていましたし、世の中的にはServerSpec全盛なので、テストを全てAnsibleに任せるのは少々敷居が高そうですが、実用できそうかどうかちょっと検討してみたいと思います。

  • Moduleによるテスト

基本的にAnsibleには冪等性という、「何度実行しても同じ結果を保証する」性質があります。
そして、実行結果から

  1. 値を変更した
  2. 値を変更していない(する必要がない)
  3. 値を変更したかったけどできなかった

がわかります。これを利用すればAnsibleを実行して「すべて値の変更する必要なし」となれば設定値の確認完了、と言えてテスト完了となります。
がしかし現実はそうはいきません。たとえAnsibleが正常終了したところでPlaybookが間違っていたら元も子もないし、間違っていなかったとしてもModuleが誤動作を起こしてないと保証できるのか!と言われたら厳しいところ。ディレクトリ変更はPlaybook通り出来ています、といったところで「lsの結果を見るまで信用できん!」というお客様も多いかと思います(私も不安です)
というわけで。

  • シェルを使ったテスト

結局はディレクトリだったらfindで全部取ってくるとか、ユーザ情報は/etc/passwdをcatするとか、そういうことが必要になるかと思います。が、今までであればシェルを作り、各サーバに配布して、結果をリダイレクトして、そのファイルをftpでもってきて、ファイル消して、シェルも消して、みたいなことをやっていました。これがAnsibleで自動化出来たらそれだけでもまあまあ有益です(この作業を100台やるかと思うとぞっとしますし)

Ansibleでこのようなことをやりたい場合にはshellかcommandのどちらかのMoudleを使います。違いは次のような感じのようです。

  • shell
    • 実行環境の環境変数に依存。パイプとかリダイレクトとか使える。
  • command
    • Playbookに書かれた変数しか使わない。パイプとかリダイレクトとか使えない。

ん~、一長一短ありますね。。
一応公式としては実行環境に影響を受けないcommandを推奨している模様。とりあえずcommandで試してみます。

ちょいと調べてこんな感じ

- name: dir check
  command: find / -type d -printf "%M %u %g %TY-%Tm-%Td %TH:%TM:%TS %p\n"
  register: result

- name: dir disp
  debug: var=result

リダイレクトは使えないので結果はregisterを使ってresultに突っ込み、その後にdebugで結果を標準出力に吐き出します。これでcommandに書いたfindの結果が表示されるはず。実行してみると。。。

       "stdout_lines": [
            "dr-xr-xr-x root root 2017-07-27 14:07:30.2480000000 /",
            "dr-xr-xr-x root root 2017-06-21 17:20:41.8637935380 /boot",
            "drwx------ root root 2017-06-21 17:19:35.7020000000 /boot/grub2",
            "drwxr-xr-x root root 2017-06-21 17:12:18.7280000000 /boot/grub2/themes",
            "drwxr-xr-x root root 2016-08-30 00:26:32.0000000000 /boot/grub2/themes/system",
            "drwxr-xr-x root root 2017-06-21 17:19:00.1140000000 /boot/grub2/i386-pc",
            "drwxr-xr-x root root 2017-06-21 17:18:59.6520000000 /boot/grub2/locale",
            "drwxr-xr-x root root 2017-06-21 17:18:59.6640000000 /boot/grub2/fonts",
            "drwxr-xr-x root root 2017-08-10 10:09:27.0460000000 /dev",
            "drwxr-xr-x root root 2017-08-10 10:09:24.6970000000 /dev/vfio",

一応こんな感じで表示されます(前半部分に全ても文字列がつながったものが出ましたが、その後に上記の出力が出ます)ただしこのままだと標準出力にだらっと出てきちゃって複数台なんてやったら大変なことになりそうです。結果をファイルとかに出力できるといいんだけど。。。


shellだったらリダイレクトがつかえるので簡単にできそう、やってみます。どりゃ

- name: dir check
  shell: find / -type d  -printf "%M %u %g %TY-%Tm-%Td %TH:%TM:%TS %p\n" > /tmp/{{inventory_hostname}}.dir

- name: file get
  fetch: src=/tmp/{{inventory_hostname}}.dir dest=/tmp/

- name: file del
  file: path=/tmp/{{inventory_hostname}}.dir state=absent

リダイレクトでファイルにfind結果を出力(inventory_hostnameはマジック変数と言われる定義済みの変数で、インベントリファイルで設定したホスト名が入ります)、fetchコマンドでリダイレクト結果を管理サーバ側に持ってきて、fileのabsentで削除します。これを実行

[root@RHEL7]# ansible-playbook -i development site.yml -u root

PLAY [webservers] *************

TASK [Gathering Facts] ********
ok: [192.168.1.105]

TASK [common : dir check] *****
changed: [192.168.1.105]

TASK [common : file get] ******
changed: [192.168.1.105]

TASK [common : file del] ******
changed: [192.168.1.105]

PLAY RECAP ********************
192.168.1.105              : ok=4    changed=3    unreachable=0    failed=0

[root@RHEL7]# ls -al /tmp/192.168.1.105/tmp/192.168.1.105.dir
-rw-r--r--. 1 root root 825623 Aug 10 02:29 /tmp/192.168.1.105/tmp/192.168.1.105.dir

[root@RHEL7]# view /tmp/192.168.1.105/tmp/192.168.1.105.dir
dr-xr-xr-x root root 2017-07-27 14:07:30.2480000000 /
dr-xr-xr-x root root 2017-06-21 17:20:41.8637935380 /boot
drwx------ root root 2017-06-21 17:19:35.7020000000 /boot/grub2
drwxr-xr-x root root 2017-06-21 17:12:18.7280000000 /boot/grub2/themes
drwxr-xr-x root root 2016-08-30 00:26:32.0000000000 /boot/grub2/themes/system
drwxr-xr-x root root 2017-06-21 17:19:00.1140000000 /boot/grub2/i386-pc
drwxr-xr-x root root 2017-06-21 17:18:59.6520000000 /boot/grub2/locale
drwxr-xr-x root root 2017-06-21 17:18:59.6640000000 /boot/grub2/fonts
drwxr-xr-x root root 2017-08-10 10:09:27.0460000000 /dev
・
・
・

ふう。。何とか成功。。
出力されたファイルのパスがあれなのは、出力対象の/tmpの配下に元のディレクトリ構成が再現されているからですね。一応管理サーバ側に変なファイルがないことを確認して完了です。


まだまだ試行錯誤中ですが何とかテスト的なことはAnsibleでできそうです。今後はこのラインで攻めていきたいと思います。お疲れ様でした。