ページ

2016-01-25

Ansibleを複数ホストへのコマンド投げツールとしてad-hocに使う

Ansibleは普通「playbook」と呼ばれるファイルを記述し、それを使って動かすのだけど、もっとてきとーに使っても便利なときは便利なので、今日はその使い方の紹介。実行する側は、ansibleがインストールされている必要はあるが(apt-get install ansibleでよい)、対象ホストはsshでアクセスできればOK。

複数ホストにコマンドを投げる

シンプルな例: 適当なファイルをcatする

もっとも理解が簡単なのは、権限だとかは気にせずにただコマンドが実行できればよい、という使い方。サーバがたくさんあるんだけど、ひとつひとつ実行するのはダルい。そんなときは、こんな風に実行すると、実行して結果を並べてくれる。

$ ansible -a "cat /etc/hostname" -i host1,host2 -u yoichi all
host1 | success | rc=0 >>
host1

host2 | success | rc=0 >>
host2

-aにコマンドを指定し、-iで対象ホストをカンマ区切りで並べ、-uにユーザを指定し、allをつける。

ユーザの指定なくsshできる状態なら、-uはなくてもいい。また、playbookを書いていてinventory fileを持っているなら、そのファイルを-iで指定したほうが当然楽。この例ではありがたみが全然ないが、もし1ホストにしたければ「-i hostname,」のように最後に,をつける。

sudoする例: crontabに設定された内容を見る

Ansibleをansible-playbookコマンドで使っている人にはお馴染みの、-sでsudo(-Kでパスワード)、-Sでsuさせることもできる。例えば、crontabに設定された項目を見たい、とか。
$ ansible -s -a "crontab -u root -l" -i host1,host2 all
host1 | FAILED | rc=1 >>
no crontab for root

host2 | success | rc=0 >>
# Edit this file to introduce tasks to be run by cron.
(略)
# m h  dom mon dow   command
30 5 * * * /usr/local/bin/rotate.sh

切り離す例: 一斉シャットダウン

停電準備で一斉シャットダウンしたいです、とかいうこともあると思う。shutdownのケースでは、結果を待てないので-Bオプションを使ってバックグラウンドで切り離す。

$ ansible -s -K -B 1 -a "shutdown -h now" -i host1,host2 all
SUDO password: 
background launch...

host1 | success >> {
    "ansible_job_id": "867312552566.13878",
    "results_file": "/root/.ansible_async/867312552566.13878",
    "started": 1
}

host1 | success >> {
    "ansible_job_id": "867312552566.2418",
    "results_file": "/root/.ansible_async/867312552566.2418",
    "started": 1
}

Ansibleのモジュールを活用する

上述の例はすべてコマンドだったが、当然ながら、Ansibleのモジュールも活用できる。

モジュール活用例1: サービスを再起動させる

例えば、サービス再起動では、serviceコマンドでもいいが、serviceモジュールを使うとこのようになる。

$ ansible -s -m service -a "name=myservice state=restarted" -i host1,host2 all
host1 | success >> {
    "changed": true,
    "name": "myservice",
    "state": "started"
}

host2 | success >> {
    "changed": true,
    "name": "myservice",
    "state": "started"
}

-mでモジュール名を指定し、-aでモジュールの引数を指定する。実は-aはいつでもモジュールの引数なのだが、-mのデフォルトが「command」なので、コマンドを実行できるというわけだ。

モジュール活用例2: copyモジュールでファイルを配置する

ad-hocに使う例ではない気がするが、その気になればファイルを持っていくことも可能。

$ echo hoge > hogefile
$ ansible -m copy -a "src=hogefile dest=/tmp/hogefile1" -i host1,host2 all
host1 | success >> {
    "changed": true,
    (略)
}

host2 | success >> {
    "changed": true,
    (略)
}

注意

あくまで一回限りで使うようなものであって、残したいものだったり、ansibleコマンドを3つも4つも打つようであれば、playbookを作るのがよい。上述のコマンドを羅列すればyaml書かなくても呼べるじゃん?っていうのはナシで。ベストプラクティス構成にしておくのがよいと思うが、1ファイルplaybookでもまぁansibleコマンドがたくさん書いてあるよりは良いと思う。

参考

こういうのをad-hoc commandsと呼ぶらしい→Introduction To Ad-Hoc Commands
他にも例がいくつかあるので、参考にされたい。

おわりに

「ansible」というソフトウェア名がついているコマンドがこの動作であるところから、もともとはこういう風に使うように始まったのではないかと私は勝手に思っている。現時点ではメインではない使い方になった(と思う)ので、知らなくても全然使えないことはないが、ベースの考え方はこのエージェントなしにリモートホストに任意にモジュールを投げ込んで実行するツールだと思うと、理解も応用もしやすいと思うので、触ってみておいて損はないかなと思う。

2016-01-10

avahi-browse で mDNS/DNS-SD のホスト・サービスの探索をする

apt-get install avahi-utilsして「avahi-browse -alr」とすればよい。たいした話ではないけれど、多分忘れるので。

出力例はこんな感じ。
$ avahi-browse -alr
+   eth0 IPv6 sample [00:11:22:33:44:55]                      Workstation          local
+   eth0 IPv4 sample [00:11:22:33:44:55]                      Workstation          local
+   eth0 IPv4 Jenkins                                         Web Site             local
+   eth0 IPv4 jenkins                                         _jenkins._tcp        local
+   eth0 IPv4 jenkins                                         _hudson._tcp         local
=   eth0 IPv6 sample [00:11:22:33:44:55]                      Workstation          local
   hostname = [sample.local]
   address = [fe80::82ee:1234:5678:9999]
   port = [9]
   txt = []
=   eth0 IPv4 sample [00:11:22:33:44:55]                      Workstation          local
   hostname = [sample.local]
   address = [192.168.1.152]
   port = [9]h
   txt = []
=   eth0 IPv4 Jenkins                                       Web Site             local
   hostname = [jenkins.local]
   address = [192.168.1.101]
   port = [8005]
   txt = ["version=1.643" "url=http://jenkins.example.local:8005/" "slave-port=46298" "path=/" "server-id=5ca870f7e5eb41888299af4853b2021b"]
=   eth0 IPv4 jenkins                                       _jenkins._tcp        local
   hostname = [jenkins.local]
   address = [192.168.1.101]
   port = [8005]
   txt = ["version=1.643" "url=http://jenkins.example.local:8005/" "slave-port=46298" "path=/" "server-id=5ca870f7e5eb41888299af4853b2021b"]
=   eth0 IPv4 jenkins                                       _hudson._tcp         local
   hostname = [jenkins.local]
   address = [192.168.1.101]
   port = [8005]
   txt = ["version=1.643" "url=http://jenkins.example.local:8005/" "slave-port=46298" "path=/" "server-id=5ca870f7e5eb41888299af4853b2021b"]