Ansible使ってみた
Ansibleの使い方を調べました。 VirtualBox上に作成した仮想マシンに対して、Ansibleを使ってnginxの構築を自動化してみます。
Ansibleとは
Ansible は、システムの設定やソフトウェアのデプロイなどを自動化するためツールです。
操作対象記述したhosts
ファイルと、操作対象に対する設定を記述したyaml
形式のファイルを作成するだけでインフラ構築作業を自動化し、構築する内容をコードとして管理することができます。
Ansibleで対象を操作するために必要な条件は、AnsibleがインストールされたマシンからSSHでログイン可能である
ことだけなので、ターゲットに対してワーカープログラムなどをインストールするといった設定作業が少ない(pythonのインストールとsshdの設定だけ)というメリットがあります。
確認用の環境
まず、対象となるサーバーを用意する必要があるので、Vagrantを使って作成します。 今回使ったファイルは、githubにプッシュしました。→nnnamani/example-for-ansible
$ git clone https://github.com/nnnamani/example-for-ansible.git
$ cd example-for-ansible
$ vagrant up
$ vagrant status
Current machine states:
my_site running (virtualbox)
The VM is running. To stop this VM, you can run `vagrant halt` to
shut it down forcefully, or you can run `vagrant suspend` to simply
suspend the virtual machine. In either case, to restart it again,
simply run `vagrant up`.
これでmy_site
という仮想マシンが起動します。
ansibleのインストール
ansibleをインストールします。 環境によって違うと思うので、こちら を参考にすると良いと思います。
UbuntuやCentOSが多いと思うので、以下に抜粋したものを記載しておきます。
- Ubuntu
$ sudo apt update
$ sudo apt install software-properties-common
$ sudo apt-add-repository --yes --update ppa:ansible/ansible
$ sudo apt install ansible
- CentOS
$ sudo yum install ansible
僕はNixOSを使っていたので以下で入りました。
$ nix-env --install ansible
今回使ったansibleはバージョン2.8
でした。最新は2.9
っぽいですが、今は気にしないでおきます。
$ ansible --version
ansible 2.8.13
config file = None
configured module search path = ['/home/mani/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /nix/store/qd0vsq2j7kwb8vy89fqnq3a9al12kxx2-python3.7-ansible-2.9.11/lib/python3.7/site-packages/ansible
executable location = /nix/store/qd0vsq2j7kwb8vy89fqnq3a9al12kxx2-python3.7-ansible-2.9.11/bin/ansible
python version = 3.7.6 (default, Dec 18 2019, 19:23:55) [GCC 9.2.0]
ansibleを使ってみる
ここから本題です。 ansibleによる自動化では、対象のサーバーにSSHで入れるようにしておく必要があります。
今回は、Vagrantで対象のサーバーを構築したので、SSHは設定済みになります。
あとは、AnsibleがSSHの設定を使って対象サーバーにログインできれば準備完了です。
vagrant ssh-config
コマンドで、vagrantが作成したSSHの設定をダンプすることができます。
↓の感じで、秘密鍵の場所やホスト名、ポート番号などが、~/.ssh/config
に設定できる形で取れるようです。
$ vagrant ssh-config
Host my_site
HostName 127.0.0.1
User vagrant
Port 2222
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
PasswordAuthentication no
IdentityFile /path/to/my_site/virtualbox/private_key
IdentitiesOnly yes
LogLevel FATAL
余談ですが、VagrantはVMのSSHポートとホストのポートでフォワーディングしているようです。
で、この設定を~/.ssh/config
に追記すると、ansibleが使用できるようになるみたいです。
$ vagrant ssh-config >> ~/.ssh/config
ansibleの実行に必要な設定を用意する
今回は、対象となる仮想マシン上にnginxをインストールして、適当に作ったhtmlを公開してみます。
ansibleの実行に最低限必要な設定は、以下の2つになります。
- Inventoryファイル
- ansibleで操作する対象ホストを記述したファイル
- Playbookファイル
- yaml形式で対象に対する操作を記述したファイル
これらに加えて、今回はnginxで公開するhtmlファイルhtml/index.html
を作成しています。
すべてGithubのリポジトリに格納してあります。
hostsファイルを用意したので、ansibleの接続確認をすると対象のサーバーから応答が返ってきていることがわかります。
$ ansible -i hosts my_site -m ping
my_site | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
今回実行するPlaybookファイルは、以下のようになっています。
---
- hosts: my_site
become: yes
tasks:
- name: install epel repository
yum: name=epel-release state=present
- name: install nginx
yum: name=nginx state=present
- name: copy index.html
copy:
src: html/index.html
dest: /usr/share/nginx/html/index.html
owner: root
group: root
mode: '755'
- name: nginx running and enabled
service: name=nginx state=started enabled=yes
tasks
に記述した処理が上から順に対象のサーバーで実行されます。
tasks
はShellスクリプトではなく、用意されたモジュールに対する設定という形になります。
Ansible
では冪等性を担保するために、必要なモジュールを使用することを推奨しているようです。
tasks
でやっていることを一つずつ見ていきます。
yumにepelリポジトリを追加
- name: install epel repository
yum: name=epel-release state=present
nginx
をインストールするために、yum
パッケージマネージャがepel
リポジトリを参照できるようにします。
これは、Ansibleのyum
モジュールを使って行います。
yumを使ってnginxをインストール
- name: install nginx
yum: name=nginx state=present
yum
モジュールを使ってnginxをインストールしています。
state=present
オプションを指定しており、インストール済みであればスキップされます
index.htmlファイルの配置
- name: copy index.html
copy:
src: html/index.html
dest: /usr/share/nginx/html/index.html
owner: root
group: root
mode: '755'
今回確認用に使うHTMLファイルをnginx
が公開しているディレクトリにコピーします。
これは、copy
モジュールを使うことで可能です。ローカルに用意したhtml/index.html
ファイルが仮想マシン上の/usr/share/nginx/html/index.html
にコピーされます。
nginxの起動と有効化
- name: nginx running and enabled
service: name=nginx state=started enabled=yes
service
モジュールを使って、nginxの起動を行います。
state=started
がnginxを起動した状態にする指定で、enabled=yes
は仮想マシン起動時に自動起動する設定になります。
servicectl
コマンドに対応しているイメージがわかりやすいです。
Playbookを実行する
実際にPlaybookを実行してみます。
ansible-playbook
コマンドを使ってPlaybookを実行します。
$ ansible-playbook -i hosts site.yml
PLAY [my_site] ******************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************
ok: [my_site]
TASK [install epel repository] **************************************************************************************
changed: [my_site]
TASK [install nginx] ************************************************************************************************
changed: [my_site]
TASK [copy index.html] **********************************************************************************************
changed: [my_site]
TASK [nginx running and enabled] ************************************************************************************
changed: [my_site]
PLAY RECAP **********************************************************************************************************
my_site : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
結果がすべてok
となったら、ブラウザでhttp:192.168.33.101
にアクセスすると、Hello Ansible
というメッセージが表示された画面を確認できると思います。
公開するファイルを編集してみる
html/index.html
を編集し、再度Playbookを実行してみます。
index.htmlを編集して、HelloをHappyに書き換えてみます。
$ sed -ie 's/Hello/Happy/g' html/index.html
以下の状態になっています。
$ git diff
diff --git a/html/index.html b/html/index.html
index a1e267e..b713886 100644
--- a/html/index.html
+++ b/html/index.html
@@ -1,8 +1,8 @@
<html>
<head>
- <title>Hello Ansible</title>
+ <title>Happy Ansible</title>
</head>
<body>
- <h1>Hello Ansible</h1>
+ <h1>Happy Ansible</h1>
</body>
</html>
この状態でPlaybookを再実行してみます。
$ ansible-playbook -i hosts site.yml
PLAY [my_site] ******************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************
ok: [my_site]
TASK [install epel repository] **************************************************************************************
ok: [my_site]
TASK [install nginx] ************************************************************************************************
ok: [my_site]
TASK [copy index.html] **********************************************************************************************
changed: [my_site]
TASK [nginx running and enabled] ************************************************************************************
ok: [my_site]
PLAY RECAP **********************************************************************************************************
my_site : ok=5 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
TASK [copy index.html]
がchanged
になりました。copyモジュールがindex.htmlの変更を検知して、コピー処理を実行したようです。
再度ブラウザでhttp:192.168.33.101
にアクセスすると、Happy Ansible
というメッセージが表示され変更を反映できたことが確認できます。
まとめ
Ansibleを最小限の構成で使って、仮想マシンを操作する方法を試してみました。
最小で2ファイル用意すれば簡単に環境構築を自動化できることがわかりました。
AnsibleはShellスクリプトを実行するモジュールなどもあり、より柔軟な設定ができるようです。 しかし、冪等性を担保するためにも適切なモジュールを使うほうが良いので、モジュールを調べて使うための学習コストはそれなりに必要なのかなと思いました。
インフラをコードで管理できるメリットは計り知れないと思うので、ベストプラクティス的なところも勉強したいです。