Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

【チュートリアル】Ansible 基本のキ (インストールから複数サーバへの変更適用)

More than 3 years have passed since last update.

Ansible基本のキ

images.png

Ansibleとは?

Ansibleは、サーバに対する設定を、
再利用性の高いコードで記述するためのツールです。

ChefやPuppetが同様のツールとして挙げられます。
(こうした一連のツールを、プロビジョニングツール、と云うそうです。)

Ansibleの特徴

1. YAMLで記述する

モジュールなどはPythonやその他言語を利用することになりますが、
基本的にはYAMLという、データ形式を利用します。
Rubyで記述していくChefなどと比較すると、
(複雑な事をする場合を除いては)
可読性が高く、記述量が少なくて済みます。

YAMLでの記述

playbook.yml
---
- hosts: webservers
  become: True
  tasks:
  - name: install Apache
    yum: name=httpd

2. プッシュ型

設定を反映したいタイミングで、
対象サーバにSSHで接続し、設定を反映していきます。
他の形式では、プル型があります。Chefはこちらに分類されます。
プル型では、プロビジョニングツールでは、
定期的に対象サーバが、中央サーバに対して変更を取得しに行き、
差分があれば実行する形をとっています。
プル型に対しての優位な点は、SSHで接続できる環境であれば、
変更対象のサーバには何も入れる必要がないことです。

3. 最低限のことをするだけなら、非常にシンプル

最低限のことをするだけなら、
接続先を定義するインベントリというファイルと、
変更手順が記述されたPlaybookの2つで事足ります。

チュートリアル

基本的な使い方を一通り試してみましょう。
設定内容は、Vagrantを利用して複数の仮想環境を作成し、
それぞれの環境に対してNginxをインストールする、というものです。

実行環境

利用しているマシンは、"MacOS X El Capitan"です。
また、作業ディレクトリは、
ホームディレクトリ直下にansibleという名前のディレクトリです。

[you@local] $ cd ~
[you@local] $ mkdir ansible
[you@local] $ cd ansible

最終的には、ansibleディレクトリの内部は、以下の様になります。

ansible
├── Vagrantfile
├── ansible.cfg
├── hosts
└── nginx.yml

Vagrantでの環境構築

変更を反映するために、Vagrantを利用します。
今回は、80番ポートが開放された仮想環境を2つ作成します。

1. VirtualBoxのインストール

下記のリンクからダウンロードして、インストールしてください。
https://www.virtualbox.org/

2. Vagrantのインストール

Vagrantをインストールします。
私の環境はMacOSでhomebrewを導入しているので、
brewでインストールしました。
brew install vagrant
もちろん、他のインストール方法をとっても構いません。

3.Vagrantで仮想環境を立ち上げる

VagrantFileを設置し、仮想環境を立ち上げます。

まず、初期化します。

[you@local] $ vagrant init bento/centos-6.7

VagrantFileを、下記の内容に変更します。

ansible/Vagrantfile
# -*- mode:ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|
  config.ssh.insert_key = false
  config.vm.define "webserver1" do |webserver1|
    webserver1.vm.hostname = "webserver1"
    webserver1.vm.box = "bento/centos-6.7"
    webserver1.vm.network "private_network", ip: "192.168.11.21"
  end
  config.vm.define "webserver2" do |webserver2|
    webserver2.vm.hostname = "webserver2"
    webserver2.vm.box = "bento/centos-6.7"
    webserver2.vm.network "private_network", ip: "192.168.11.22"
  end
end

仮想環境を立ち上げます。

[you@local] $ vagrant up

仮想環境が作成できたら、sshでの接続方法の確認の為、下記のコマンドを実行します

[you@local] $ vagrant ssh-config

私の環境だと、下記のような内容になりました

Host webserver1
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /Users/you/.vagrant.d/insecure_private_key
  IdentitiesOnly yes
  LogLevel FATAL

Host webserver2
  HostName 127.0.0.1
  User vagrant
  Port 2200
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /Users/you/.vagrant.d/insecure_private_key
  IdentitiesOnly yes
  LogLevel FATAL

Ansibleのインストール

ansibleをインストールします。
Macを利用していて、Homebrewを導入しているなら、下記のコマンドでインストール可能です。

[you@local] $ brew install ansible

あるいは、Pythonのパッケージマネージャ pip が利用可能であればインストールできます。

[you@local] $ sudo pip install ansible

インベントリ

インベントリは、反映先サーバの一覧です。
一般的には、hostsという名前で利用されるようです。
早速、hostsを作成してみましょう
bash
[you@local] $ vi hosts

ansible/hosts
[webservers]
192.168.11.21
192.168.11.22

[webservers:vars]
ansible_ssh_user=vagrant
ansible_ssh_private_key_file=~/.vagrant.d/insecure_private_key

webserversというグループに、先ほど作成した仮想環境のIPアドレスを登録し、
webserversのグループに適用する変数として、
- ansible_ssh_user
- ansible_ssh_private_key_file
の2つに値を設定しています。
この2つの変数は、ansibleがSSH接続時に利用するものです。
他にも、
- ansible_ssh_host
- ansible_ssh_port
- ansible_ssh_pass
- ansible_connection
などの変数が利用され、それぞれデフォルトの値を持っています。

とにかく、疎通を確認してテンションをあげよう

ここで、実際にansibleで通信できるか、一度試してみましょう。

[you@local] $ ansible webservers -i hosts -m ping

-iのオプションで、インベントリ(hosts)を指定します。
-mのオプションで、利用するモジュールを指定しています。
pingは、sshでの疎通を確認するためのモジュールです。

最初の接続では、
The authenticity of host '192.168.11.21 (192.168.11.21)' can't be established.
といった表示がでるかと思います。
続けて、yesとタイプしてください。

私の環境では、このように出力されました。

192.168.11.21 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
192.168.11.22 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

これで、疎通の確認は完了です。

ついでに、ansible.cnfも書いておく

ansible.cnfを記述しておくと、インベントリへの記述を減らしたり、
コマンドで記述する内容を減らすことができます。
まず、インベントリを編集します。

ansible/hosts
[webservers]
192.168.11.21
192.168.11.22

varsの内容を削除しました。
続けて、ansible.cnfを作成します。

ansible/ansible.cfg
[defaults]
hostfile=hosts
remote_user=vagrant
private_key_file=~/.vagrant.d/insecure_private_key

ansible.cfgのなかで、
- hostfile(インベントリ)
- remote_user(ansible_ssh_user)
- private_key_file(ansible_ssh_private_key_file)
以上3点を指定しています。

今回は、インベントリを指定せず実行します。

[you@local] $ ansible webservers -m ping

同様の内容が返却されれば、ansible.cfgの設置は成功です。

Playbookでnginxをインストール

準備だけで結構かかっちゃいましたが、
ここでやっと、Playbook(環境構築)の記述です。
冒頭で述べましたが、環境構築をYAML形式で記述します。
nginx.ymlというPlaybookを作成します。

ansible/nginx.yml
---
- hosts: webservers
  become: True
  tasks:
  - name: install nginx repo
    yum: name=http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present
  - name: install nginx
    yum: name=nginx
  - name: restart nginx
    service: name=nginx state=restarted

基本的なYAMLの基本的な読み方は、Wikipediaあたりを参考にしてください。
内容を一行ずつみていきます

nginx.yml 説明
hosts: webservers hostの指定。今回はグループ名webservers
become: True sudoerとして実行
tasks: 実行するタスクを順に並べた辞書
name: install nginx repo ひとつ目のタスクの名前。Nginxのレポジトリをインストール
yum: name=http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present yumモジュールを使ったタスクの内容。記載のURLからYUMレポジトリをインストール。
name: install nginx Nginxをインストールする旨の名前
yum: name=nginx YUMモジュールを利用してNginxをインストール
name: restart nginx Nginxを再起動する旨の名前
service: name=nginx state=restarted Serviceモジュールを利用してNginxを再起動

では、このPlaybookを実行してみましょう。
Playbookの実行には、ansible-playbookコマンドを利用します。

[you@local] $ ansible-playbook nginx.yml

Playbookの中で、変更対象のhostsを指定しているため、コマンドの引数はymlファイルのみです。

実行結果は以下のようになります。

TASK [setup] *******************************************************************
ok: [192.168.11.22]
ok: [192.168.11.21]

TASK [install nginx repo] ******************************************************
changed: [192.168.11.22]
changed: [192.168.11.21]

TASK [install nginx] ***********************************************************
changed: [192.168.11.21]
changed: [192.168.11.22]

TASK [restart nginx] ***********************************************************
changed: [192.168.11.21]
changed: [192.168.11.22]

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

試しに、ブラウザで反映先にアクセスしてみてください。
http://192.168.11.21
Nginxが正しくインストールされていることがわかるかと思います。
スクリーンショット 2016-08-03 18.59.51.png

もういちど先ほどのansible-playbookコマンドを実行すると、どうなるでしょうか。

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

TASK [setup] *******************************************************************
ok: [192.168.11.21]
ok: [192.168.11.22]

TASK [install nginx repo] ******************************************************
ok: [192.168.11.22]
ok: [192.168.11.21]

TASK [install nginx] ***********************************************************
ok: [192.168.11.21]
ok: [192.168.11.22]

TASK [restart nginx] ***********************************************************
changed: [192.168.11.22]
changed: [192.168.11.21]

PLAY RECAP *********************************************************************
192.168.11.21              : ok=4    changed=1    unreachable=0    failed=0
192.168.11.22              : ok=4    changed=1    unreachable=0    failed=0

install nginx repoinstall nginxのステータスが、changedからokになりました。
これは、YUMモジュールが、インストールがされているかどうかを確認して、インストールされている場合、
OKを返すのみで、実際にインストールを実行していない事を指しています。
何度もインストールすることは、予期しないバグやダウンタイムに繋がります。
それを避けるため、モジュールが勝手にそうしてくれているわけです。

ハンドラ

しかしながら、nginxの再起動のタスク(restart nginx)は、
それ以上でもそれ以下でもなく、ただただ再起動するだけのタスクであり、
2回目以降の実行でも、再起動後、changedとなっています。
これは、(ごく一瞬ではありますが)ダウンタイムにつながります。
これを避けるために、ハンドラという仕組みがあります。
これは、指定したタスクが終了した場合にのみ実行する変更です。
実際に使ってみるために、nginx.ymlを編集しましょう

ansible/nginx.yml
---
- hosts: webservers
  become: True
  tasks:
  - name: install nginx repo
    yum: name=http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present
  - name: install nginx
    yum: name=nginx
    notify: restart nginx
  handlers:
  - name: restart nginx
    service: name=nginx state=restarted

変更したのは、install nginxの箇所にnotifyを追加し、内容をrestart nginxとしたこと、
restart nginxのタスクを、tasksとは別のhandlersに移動させたことです。
これは、install nginxのタスクで、実際に変更が起きた場合にのみ、
handlers内のrestart nginxを実行することを意味しています。

実際に、先ほど同様にansible-playbook nginx.ymlのコマンドを叩いてみると、
結果は下の様になるかと思います。

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

TASK [setup] *******************************************************************
ok: [192.168.11.21]
ok: [192.168.11.22]

TASK [install nginx repo] ******************************************************
ok: [192.168.11.21]
ok: [192.168.11.22]

TASK [install nginx] ***********************************************************
ok: [192.168.11.21]
ok: [192.168.11.22]

PLAY RECAP *********************************************************************
192.168.11.21              : ok=3    changed=0    unreachable=0    failed=0
192.168.11.22              : ok=3    changed=0    unreachable=0    failed=0

restart nginxのタスクは実行されなくなりました。

では、本当にNginxがインストールされた場合に、Nginxを再起動するのでしょうか。
確認するために、Vagrantの仮想環境を作りなおしてみましょう。

[you@local] $ vagrant destroy
[you@local] $ vagrant up

仮想環境が再び立ち上がったら、もう一度、ansible-playbook nginx.ymlのコマンドを叩いてみます。

[you@local] $ ansible-playbook nginx.yml

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

TASK [setup] *******************************************************************
ok: [192.168.11.22]
ok: [192.168.11.21]

TASK [install nginx repo] ******************************************************
changed: [192.168.11.21]
changed: [192.168.11.22]

TASK [install nginx] ***********************************************************
changed: [192.168.11.21]
changed: [192.168.11.22]

RUNNING HANDLER [restart nginx] ************************************************
changed: [192.168.11.21]
changed: [192.168.11.22]

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

restart nginxが実行されています!成功です!

終わりに

他にもいろいろなTipsがありますが、基本的な利用の流れは以上かと思います。
一通り、実際に試したコードと手順で説明したつもりですが、
もし、なにか足りない箇所があれば、どんどん突っ込んでくださればとおもいます。
Gitなどと組み合わせて、人に優しいインフラ構築を目指していきましょう!

参考書籍

  1. Lorin Hochstein (2016) 初めての Ansible Sky株式会社 玉川 竜司 訳  オライリー・ジャパン
  2. 新原 雅史 (2016) サーバ/インフラエンジニア養成読本 DevOps 編 特集1: 最速攻略! Ansible 2 によるサーバ構築 技術評論社
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away