Ansibleを自分のローカル環境上で試す

株式会社プライムストラクチャーのエンジニアのSayaです。

インフラ構築を自動化してくれるツールであるAnsible
今回はこれを実際に自分のローカル環境上で試す方法を紹介します。

Ansibleのインストール

  • macOSの場合
    $ brew install ansible

  • Linux, CentOSなど
    $ sudo yum install -y epel-release
    $ sudo yum install -y ansible

  • Pythonパッケージを使う方法
    $ sudo easy_install pip
    $ sudo pip install ansible

インストールの確認

以下のコマンドでAnsibleのバージョンを確認します。
$ ansible --version

Ansibleがちゃんとインストールされていれば以下のような表示が出てきます。

ansible 2.7.5
~省略~

AdHocコマンドでモジュールの実行

以下のコマンドでshellモジュールをAdHocコマンドで実行します。

$ ansible localhost -m shell -a 'hostname'

すると以下のように表示されます。

localhost | CHANGED | rc=0 >>
自分の端末名.local

-m shellでshellモジュールを呼び出し、-a 'hostname'でhostnameというパラメータを与えています。

shellモジュールはパラメータで与えられたコマンドを実行するモジュールなので、今回はhostnameコマンドをlocalhostに実行しています。


同様に以下のコマンドも入力します。

$ ansible localhost -m setup -a 'filter=ansible_distribution*'

すると以下のようにlocalhostの情報が表示されます。

localhost | SUCCESS => {
    "ansible_facts": {
        "ansible_distribution": "MacOSX",
        "ansible_distribution_major_version": "10",
        "ansible_distribution_release": "18.0.0",
        "ansible_distribution_version": "10.14"
    },
    "changed": false
}

ここではsetupモジュールをfilter=ansible_distribution* というパラメータで呼び出しています。

setupモジュールは対象ノードの情報を収集します。
パラメータを何も与えなければ全ての情報を収集、パラメータとしてfilter=文字列を与えると文字列と一致する情報のみを収集してくれます。

インベントリファイルの作成

対象ノードを管理する為のインベントリファイルを作成します。
「inventory」という名前の拡張子なしのインベントリファイルを作成します。
中身は以下のようにします。

[localhost]
127.0.0.1 ansible_connection=local

[sample]
127.0.0.1 ansible_connection=local

[nodes]
node-1 ansible_host=127.0.0.1 ansible_connection=local
node-2 ansible_host=127.0.0.1 ansible_connection=local

このインベントリは3つのグループを持ち、各グループには1台もしくは複数の対象ノードが所属しています。

ホストに与えられているansible_connectionオプションは、対象ノードに接続する際に接続方法に関する情報を与えます。
ここではlocalが与えられています。

ansible_hostオプションはホストのIPアドレスを与えるオプションです。
ホストに別名をつけたい場合に使います。


このインベントリファイルを用いて、以下のAdHocコマンドを実行してみます。

以下は各AdHocコマンドとその実行結果です。

$ ansible localhost -i inventory -m ping -o

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

$ ansible sample -i inventory -m ping -o

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

$ ansible nodes -i inventory -m ping -o

node-1 | SUCCESS => {"changed": false,"ping": "pong"}
node-2 | SUCCESS => {"changed": false,"ping": "pong"}

$ ansible all -i inventory -m ping -o

node-1 | SUCCESS => {"changed": false,"ping": "pong"}
node-2 | SUCCESS => {"changed": false,"ping": "pong"}
127.0.0.1 | SUCCESS => {"changed": false,"ping": "pong"}

第一引数に対象とするインベントリのグループの指定、-iオプションでインベントリを記述したファイルの指定を行ないました。

第一引数をallとすることで全てのホストを指定します。

-mで指定しているpingモジュールは、対象がAnsibleで自動化可能な状態であれば「pong」と返します。

-oオプションは出力結果を1ホスト1行にまとめます。

クレデンシャル

クレデンシャルは、Ansibleが対象ノードに接続する際に使用する認証情報です。

以下ではコマンドラインの引数として与えています。

$ ansible sample -i inventory -m ping -u userA -k

グループへの接続に-uオプションで指定されたuserAを使いました。

-kオプションによってパスワード入力プロンプトが起動して、ここで入力されたパスワードが接続に用いられます。

Playbookの作成

playbook.ymlという名前のPlaybookを作成します。
PlaybookはYAML形式なのでインデントに注意します。

- hosts: nodes
  vars:
    sample_vars: ansible_test
  tasks:
    - shell: uptime
      register: result

    - debug:
        msg: "{{ result.stdout }}"

    - debug:
        msg: "{{ sample_vars }}"

このPlaybookを下記のコマンドで実行してみます。

$ ansible-playbook -i inventory playbook.yml

ansible-playbookコマンドでPlaybookを実行、-iでインベントリを指定してそのあとに実行するPlaybookを指定します。

PLAY [nodes] ************************************************************************************

TASK [Gathering Facts] **************************************************************************
ok: [node-1]
ok: [node-2]

TASK  ************************************************************************************
changed: [node-1]
changed: [node-2]

TASK [debug] ************************************************************************************
ok: [node-1] => {
    "msg": "19:31  up 4 days, 10:16, 2 users, load averages: 1.84 1.88 1.98"
}
ok: [node-2] => {
    "msg": "19:31  up 4 days, 10:16, 2 users, load averages: 1.84 1.88 1.98"
}

TASK [debug] ************************************************************************************
ok: [node-1] => {
    "msg": "ansible_test"
}
ok: [node-2] => {
    "msg": "ansible_test"
}

PLAY RECAP **************************************************************************************
node-1                     : ok=4    changed=1    unreachable=0    failed=0   
node-2                     : ok=4    changed=1    unreachable=0    failed=0   

まず最初にplaybook.yml内に書かれているtasksで指定されたshellモジュールが起動し、パラメータとしてuptimeが与えられてuptimeコマンドが実行されます。

その次にあるregisterがこのモジュールの実行結果をresultという名前の変数に格納しています。

次にdebugモジュールがデバッグを行い、msgで与えられた変数や文字列を実行時に出力します。

一番目のdebugモジュールはmsgに変数result.stdoutを渡し、uptimeコマンドの結果が格納されているresultの中の標準出力が格納されたstdoutがmsgで出力されています。

二番目のdebugモジュールはmsgに変数sample_varsを渡してPlaybook内で定義された変数の値を出力しています。


次に以下のコマンドで変数を上書きしてみます。

$ ansible-playbook -i inventory playbook.yml -e 'sample_vars=overwrite_vars'

すると以下のようにmsgの出力が変わります。

~~~省略~~~
TASK [debug] ************************************************************************************
ok: [node-1] => {
    "msg": "overwrite_vars"
}
ok: [node-2] => {
    "msg": "overwrite_vars"
}
~~~省略~~~

-eはコマンドラインから変数を与えるオプションです。

このように定義した変数を上書きして実行することもできます。

まとめ

今回はAnsibleを実際に自分のローカル環境上で試してみました。
インベントリで対象ノードを指定して、Playbookに沿って実行されるという流れが実際に動かしてみると分かります。

この内容はSoftwareDesign-2018年12月号の中島倫明氏の記事を参考にしています。
中島氏はAnsibleに関して他にもチュートリアルなどを出しています。(前回以前の記事参照)
こちらもとても分かりやすいので、やってみることをオススメします。

参考文献

Software-Design-2018年12月号, p.26-31
Ansible Documentation