この記事は Wanoグループ Advent Calendar 2016 の22日目の記事です。
構成管理ツールとして使われる Ansible ですが、日常のちょっとした作業に活用しても便利です。
特定のパッケージをインストールする、ログを確認するなどの作業は、1回行うだけなら大したことありませんが、対象サーバの数が多くなると1台1台にログインして作業することの繰り返しになり大変です。
こういう作業を行うための環境をあらかじめ構築しておき、作業時には実行用の Ansible Playbook を1回書くだけですべてのサーバに適用できるようにしておくと作業の手間を軽減できます。
サンプルで使用する構成
管理対象サーバ
OS
Ubuntu 14.04
Production x 2
- sample_prod_01
- sample_prod_02
- パスワード: prodpasswd
Staging x 2
- sample_stage_01
- sample_stage_02
- パスワード: stagepasswd
development x 2
- sample_dev_01
- sample_dev_02
- パスワード: devpasswd
ユーザ
admin
- sudo 権限あり
- パスワードは上記の通り
- 管理マシン側から公開鍵認証にてSSHログイン可能
構築手順
今回は作業用ディレクトリを ansible-work という名前にします。(名前はなんでもいいです)
$ mkdir ansible-work
$ cd ansible-work
デフォルト設定の追加
[defaults]
hostfile=hosts
管理対象サーバの設定
管理対象サーバを hosts ファイルに設定します。(/etc/hosts とは別物です。現在の作業ディレクトリである ansible-work 直下にこのファイルを作ってください。)
[production]
sample_prod_01
sample_prod_02
[stage]
sample_stage_01
sample_stage_02
[development]
sample_dev_01
sample_dev_02
[production][stage][development]がグループ名で、各サーバをここでグループ分けしています。
sudo 時のパスワード入力を不要にする
今回の例では、環境ごとにパスワードが異なります。
ansible-playbook を -K オプション付きで実行して sudo パスワードを入力する方法では、1回に1つのパスワードしか指定できず、環境ごとに ansible-playbook を実行する必要があり面倒です。
以下のように環境ごとにあらかじめパスワードを指定しておくと、パスワードの入力が不要になります。
$ mkdir group_vars
---
ansible_ssh_user: admin
ansible_sudo_pass: prodpasswd
---
ansible_ssh_user: admin
ansible_sudo_pass: stagepasswd
---
ansible_ssh_user: admin
ansible_sudo_pass: devpasswd
---
remote_user: admin
ファイル名はグループ名に合わせてください。all.yml には全サーバ共通の設定を記述します(これはあとでPlaybook内で使います)。
パスワードファイルの暗号化
で、個人で使用する分にはこれでも良いのですが、実行環境を複数メンバーで共有する場合、パスワードを平文で書いておくのは望ましくありません。(あるいは個人で使うだけであっても、パスワードを平文で書いたファイルを持ってるのはなんか不安ではある)
そこで ansible-vault を使用して、パスワードが記述してあるファイルを共通鍵方式で暗号化します。
まず共通鍵をバージョン管理管轄外の場所に保存します。
$ echo samplepasswd > ~/.ansible_vault_pass
※ samplepasswd がパスワードになります。適宜変更してください。またファイル名も上記の通りでなくて大丈夫です。
暗号化します。
$ ansible-vault encrypt group_vars/production.yml --vault-password-file ~/.ansible_vault_pass
$ ansible-vault encrypt group_vars/stage.yml --vault-password-file ~/.ansible_vault_pass
$ ansible-vault encrypt group_vars/development.yml --vault-password-file ~/.ansible_vault_pass
実例
実行例 1: パッケージをインストールする
例として libxml2-dev パッケージをインストールします。以下のようなファイルを作成します。
$ mkdir tasks
---
- name: Install libxml2-dev
hosts: all
remote_user: "{{ remote_user }}"
become: yes
tasks:
- apt:
name: libxml2-dev
state: present
update_cache: yes
実行します。
$ ansible-playbook tasks/install_libxml2-dev.yml --vault-password-file ~/.ansible_vault_pass
PLAY [Install libxml2-dev] *****************************************************
TASK [setup] *******************************************************************
ok: [sample_dev_02]
ok: [sample_prod_01]
ok: [sample_prod_02]
ok: [sample_dev_01]
ok: [sample_stage_01]
ok: [sample_stage_02]
TASK [apt] *********************************************************************
changed: [sample_dev_01]
changed: [sample_dev_02]
changed: [sample_prod_02]
changed: [sample_stage_01]
changed: [sample_prod_01]
changed: [sample_stage_02]
PLAY RECAP *********************************************************************
sample_dev_01 : ok=2 changed=1 unreachable=0 failed=0
sample_dev_02 : ok=2 changed=1 unreachable=0 failed=0
sample_prod_01 : ok=2 changed=1 unreachable=0 failed=0
sample_prod_02 : ok=2 changed=1 unreachable=0 failed=0
sample_stage_01 : ok=2 changed=1 unreachable=0 failed=0
sample_stage_02 : ok=2 changed=1 unreachable=0 failed=0
これで管理対象のサーバすべてに libxml2-dev パッケージがインストールされました。
すべてのサーバにではなく、一旦開発環境(development)にだけインストールしたい場合は以下のように --limit オプションを追加します。
$ ansible-playbook --limit development tasks/libxml2-dev.yml --vault-password-file ~/.ansible_vault_pass
以下のコマンドでお手軽に実行することもできます。上の方法のほうが履歴が残る、結果が見やすいという意味で個人的には望ましいと思いますが。
ansible all -s -m apt -a 'name=libxml2-dev state=present update_cache=yes' --vault-password-file ~/.ansible_vault_pass
実行例 2: パッケージのバージョンを確認する
openssl など、セキュリティパッチが度々公開されるパッケージについては、現在インストールされているバージョンが最新かどうか確認したいケースが度々あります。そこでバージョンをファイルに書き出しローカルに転送する Playbook を作成します。
- name: Check version of openssl
hosts: all
remote_user: "{{ remote_user }}"
become: no
vars:
outfile: /tmp/{{ inventory_hostname }}.txt
tasks:
- shell: echo {{ inventory_hostname }}
&& sh -c 'dpkg -l | grep openssl | grep -v gnutls'
&& echo >> {{ outfile }}
- fetch:
src: "{{ outfile }}"
dest: /tmp/openssl_version
flat: yes
fail_on_missing: yes
あらかじめ管理マシン上に /tmp/openssl_version というディレクトリを作成しておき、その後実行します。
$ mkdir /tmp/openssl_version
$ ansible-playbook tasks/openssl_version.yml --vault-password-file ~/.ansible_vault_pass
PLAY [Check version of openssl] ************************************************
TASK [setup] *******************************************************************
(...略...)
TASK [command] *****************************************************************
(...略...)
TASK [fetch] *******************************************************************
(...略...)
PLAY RECAP *********************************************************************
sample_dev_01 : ok=3 changed=2 unreachable=0 failed=0
sample_dev_02 : ok=3 changed=2 unreachable=0 failed=0
sample_prod_01 : ok=3 changed=2 unreachable=0 failed=0
sample_prod_02 : ok=3 changed=2 unreachable=0 failed=0
sample_stage_01 : ok=3 changed=2 unreachable=0 failed=0
sample_stage_02 : ok=3 changed=2 unreachable=0 failed=0
その後、
cat /tmp/openssl_version/*
を実行すれば、各サーバの openssl のバージョンを一覧することができます。
sample_dev_01
ii openssl 1.0.1f-1ubuntu2.21 amd64 Secure Sockets Layer toolkit - cryptographic utility
sample_dev_02
ii openssl 1.0.1f-1ubuntu2.21 amd64 Secure Sockets Layer toolkit - cryptographic utility
(...略...)
sample_stage_02
ii openssl 1.0.1f-1ubuntu2.21 amd64 Secure Sockets Layer toolkit - cryptographic utility
追記
Ansible Documentation の Vault のページに
New in Ansible 1.5, “Vault” is a feature of ansible that allows keeping sensitive data such as passwords or keys in encrypted files, rather than as plaintext in your playbooks or roles. These vault files can then be distributed or placed in source control.
「暗号化したファイルが配布可能になる」と書いてありますが、暗号化されているとはいえ復号可能ではあるので、バージョン管理からは外しておいたほうが安全でしょう。