Ansibleつかって、このブログサーバーの設定変更をやってみたよ。
目次
Ansibleとは
超ざっくり書くとサーバー設定の手順的なものをファイルに書くと、それを元に自動でサーバー設定してくれるツールです。
他にもいくつか似たようなツールはあるようですが、Ansibleは設定されるサーバーにSSHが繋がれば大抵のことができるのが利点です。
なぜAnsible使おうと思ったのか
うちのサーバーはfluentdというログ収集ツールを使ってGoogle Cloud Platformにログを飛ばしています。飛ばすログは設定ファイルで指定が必要なのですが、ひとつログファイルについて飛ばす設定が漏れていたことに気づいたのです。
サーバーの設定変更はEvernoteにメモしながら作業しているので、サーバーに設定を加えた後、変更した設定を作業メモに書き足すわけですが、メモが見つからなかったり散在していたり、メモに転記したときに書き間違えたり、そもそもメモに追記忘れて内容が古かったりします。今回は最新のメモがどれかよくわからない状態になっていました。
Ansibleのような構成管理ツールを使えば、まず手順をファイルに書いて、その手順通りにツールが設定変更してくれるので、実際に行った変更内容と残された手順に差異が出ません。手順のファイルをgitで管理していけば、どういう変更をしていったのかもちゃんと履歴に残ってどれが最新の手順かも明確になります。Evernoteのメモは本当に試行錯誤のメモと割り切って、ちゃんとした手順はgitできっちり管理することができるようになります。
Ansibleでfluentdの設定を追加する
具体的に今回どういう風にAnsibleを使ったか雰囲気で書いてみます。実際は各ファイルの置き場所とかつじつま合ってないとうごきやしません。他の入門ページをみたりAnsible公式の英語ドキュメントを頑張って読む必要があるでしょう。
今回やりたいのは以下の内容をfluentdの設定ファイルに追記することです。
<source>
type tail
path /var/log/nginx/access80.log
tag nginx.access80
pos_file /var/lib/google-fluentd/pos/nginx-access_log80.pos
format none
read_from_head true
</source>
<source>
type tail
path /var/log/nginx/error80.log
tag nginx.error80
pos_file /var/lib/google-fluentd/pos/nginx-error_log80.pos
format none
read_from_head true
</source>
いろいろすっとばしますが、ansible-galaxyコマンドを使ってロールのテンプレを作りました。
ansible-galaxy init ansible-role-fluentd-setting
できたテンプレートのtaskの中にあるmain.ymlに以下のような記述をしました。
- name: 'access80なども転送対象にする'
blockinfile:
dest: /etc/google-fluentd/config.d/nginx.conf
content: |
<source>
type tail
path /var/log/nginx/access80.log
tag nginx.access80
pos_file /var/lib/google-fluentd/pos/nginx-access_log80.pos
format none
read_from_head true
</source>
<source>
type tail
path /var/log/nginx/error80.log
tag nginx.error80
pos_file /var/lib/google-fluentd/pos/nginx-error_log80.pos
format none
read_from_head true
</source>
- name: 'fluentd再起動'
service:
name: google-fluentd
state: restarted
blockinfileというのはcontentに書かれている文字列を指定したファイルに追記するansibleのモジュールです。今回、特に場所は指定していないので末尾に追加されます。
同じようにserviceというのはサービスを制御するansibleモジュールですね。設定変更後にfluentdを再起動させています。
こんな感じでわりとシンプルに設定をかけるのはansibleの良い所だと思います。
そしてinvnetoryファイルに接続するサーバーのIPを指定しました。今回は一台のマシンなのでこれだけですが、複数台に同じ設定したい場合もここにIP追加していくだけでよいのがansibleの便利な所だと思います。
all:
hosts:
a-tak:
ansible_host: xxx.xxx.xxx.xxx
ansible_user: hoge
本当はIP指定じゃ無くてGCPのサーバー情報を自動取得するプラグインを使う方法もあるのですが使いこなせなかったので今回使っていません。
あとで出てきますが実行するときにこのinventoryファイルを指定するのですが、テスト環境と本番でinventoryをわければ、テスト時はテスト環境用のinventoryを使って手順を確立し、本番適用時にはinvnetoryだけ本番用に差し替えて確立した手順で本番に設定適用することもできます。よく考えられてますね。
さっきつくったロールを実行するプレイブックを書きます。ひとつ上のディレクトリのroles内でansible-galaxyした場合はこんな書き方になります。
- hosts: all
become: yes
roles:
- ../roles/ansible-role-fluentd-setting
で、実行。
ansible-playbook -i inventory --private-key ~/.ssh/google_compute_engine playbook.yml
-i のあとにinventoryファイルを指定。playbook.ymlはプレイブックのファイル名。
次がドはまりポイントで今回の記事で一番共有したい事項なのですが、Google Cloud Platformのサーバーに接続する場合は.sshのgoogle_compute_engineというファイルにプライベートキーが作られるので、–private-keyオプションでこのファイルを指定してあげないとPermission denyになります。
もちろんSSHのプライベートキーをサーバーに登録していて普通にSSHで繋げられるようにしているならば必要ないと思いますが、普段gcloudコマンドで接続している場合は、この指定が必要です。
ansible公式のドキュメントに繰り返し書かれているのですが、何も指定しないと普段のSSH接続で使用するデフォルトの設定や現在のユーザーで接続しようとしますので、うまく接続出来ない場合はそのあたりで勘を働かせるといいかもしません。
これで設定ファイルの書き換えとサービスの再起動ができました。
Ansibleは冪等性を重視
「べきとうせい」と読みます。どういうことかというと、ある操作を1度実行しても、何度実行しても同じ結果になることを言います。Ansibleのモジュールは冪等性を重視しており、何度実行しても同じ状態になります。
さっきの設定ファイルに設定追記する処理も2度実行しても追記されるのは一回目だけです。2回目は変更が行われません(変更されない処理はchanged=0と出てくる)。これは楽でいいですね。
ちなみにLinuxコマンドを実行することもできるのですが、これについては冪等性は保証されません。ファイル書き換えるならさっきのblockinfileモジュール、ファイルを置きたいならcopyモジュールというようにansibleのモジュールをつかうようにすべきです。
Ansibleの設定ファイルはgit管理
こうして作ったansibleの各ファイルはgitで管理しておくとどういう設定を行ったか記録もばっちり残ります。設定変更を繰り返した場合も「つぎはぎ」だらけの手順ではなく、一気通貫で設定出来るちゃんとした手順が残ります。
と、言うのもさきほどの冪等性のおかげで、必要な手順を元の手順に追加して流し直すだけで今回追加したい手順だけ実行されるので、変更手順書を別管理する必要がありません。何気にありがたいポイントですね。
慣れるまでは面倒かもしれないが
ansibleをつかっていくと自然と手順がちゃんと残っていくのがありがたいですね。手順書を育てていくのもやりやすいですし。inventoryや変数を切り替えて開発環境と本番で同じ手順を試すのも簡単そうなので、使いこなせるようになるといろいろと楽になりそうです。
Ansible実践ガイド 第3版 (impress top gear)
Ansible構築・運用ガイドブック ~インフラ自動化のための現場のノウハウ~ (Compass Booksシリーズ)