本連載では、「マニュアルやシェルスクリプトを使ったサーバ管理に課題を持つ方」を対象に、Ansibleの基本的な使い方を紹介。今回は、プレイブックの作成に焦点を当て、変数、繰り返し実行、条件分岐といった基本的な機能を紹介します
「マニュアルやシェルスクリプトを使ったサーバ管理に課題を持つ方」を対象に、Ansibleの基本的な使い方を紹介する本連載「Ansibleで始めるサーバ作業自動化入門」。前回の「Ansibleにおける環境構築やリリース作業でよく使う5つのModule+α」では、環境構築やリリース作業でよく使うモジュールについて、使い方とよく使う引数を紹介しました。
今回はプレイブックの作成に焦点を当て、変数、繰り返し実行、条件分岐といった基本的な機能を紹介します。これらを用いることで、ほとんどのサーバ作業は自動化できるようになるかと思います。
連載初回の最後のプレイブックの例では、以下のようにユーザーの追加とファイルの転送を行いました。
- hosts: all become: yes become_user: root tasks: - user: name=piyo - copy: src=/home/foo/bar.txt dest=/home/piyo
例えば、ここで「piyo」ではなく別のユーザーを追加したい場合、「user」「copy」の両方の行で「piyo」と書かれた箇所を新しいユーザー名に変更する必要があります。このように、変更し得る値をタスクに直接書いてしまうと変更箇所が多くなり、保守性が低下してしまいます。
そこで、変数を利用し、別のユーザー名のユーザーを追加する場合も変更が1カ所で済むようにしてみます。以下のように連載初回で作成した「main.yml」を修正してください。
- hosts: all become: yes become_user: root vars: user_name: piyo tasks: - user: name={{ user_name }} - copy: src= /home/foo/bar.txt dest=/home/{{ user_name }}/
変数定義は「vars」要素を使用します。今回は「user_name」という名前の変数に「piyo」という値を設定しました。変数名には、アルファベット、数字、アンダースコアのみが利用でき、変数名の先頭はアルファベットから始まる必要があります。
定義した変数の値を参照するには「{{ user_name }}」のように「{{変数名}}」という形式を使います。また、以下のように変数の宣言時に他の変数の値を使うことも可能です。
vars: user_name: piyo dest_file_path: /home/{{ user_name }}/
ただし、以下のように値の定義の最初に変数の参照を書いた場合、YAMLの構文エラーとなってしまいます。
vars: user_name: piyo file_name: {{ user_name }}.txt
このような場合は以下のように値の箇所をダブルクオートで囲むことで参照できるようになります。
vars: user_name: piyo file_name: "{{ user_name }}.txt"
あるユーザーのユーザー名とパスワードのように、セットで扱った方が可読性が高まるような情報があります。
この場合、以下のようにマッピングを使って階層的に変数を定義できます。
vars: admin_user_data: name: momo password: $6$rounds=656000$3Co6RKpfjN.qj23.
マッピングの値については以下のように変数名に「.」を付けて参照します。
tasks: - user: name={{ admin_user_data.name }} password={{ admin_user_data.password }}
変数はあらかじめプレイブックに書いておくだけではなく、ユーザーの入力を受け付けて値を設定することもできます。これは、例えばリリースを行う際、ファイル名にリリースバージョンが入っていてそれを参照したい、というような場面で便利です。
この時、もしもリリースバージョンを変数にしてプレイブックに値を記載するようにすると、リリースの度にプレイブックを書き換える手間が掛かり、また変更漏れもあり得るためです。
変数の値を入力させるには、「vars」の代わりに「vars_prompt」要素を利用します。vars_promptの利用例は以下の通りです。
vars_prompt: - name: release_version prompt: "input release_version. (ex.20160204 )" private: no tasks: - copy: src=/home/foo/release_{{release_version}}.zip dest=/home/piyo
「name」で指定した値が変数名となり、ユーザーが入力した値がこの変数に設定されます。「prompt」で指定したメッセージがユーザーに表示されます。「private」はユーザーの入力値がコンソールに表示されるかどうかを示します。もしパスワードのように他人に見られたくない入力をする場合はprivateに「yes」を指定します(デフォルト値はyes)。
また、前回紹介したPasslibがインストールされている場合、以下のように入力値を暗号化することが可能です。
vars_prompt: - name: password prompt: "input newuser password" encrypt: sha512_crypt confirm: yes tasks: - user: name=momo password={{ password }}
「encrypt」では暗号化の種類を、「confirm」ではユーザーに確認用に2度入力をさせるかどうかを指定しています。
プレイブックを実行した際、プレイブック内に存在していない「setup」というタスクが最初に実行されていることに疑問を持った人もいたかもしれません。実は、このsetupというタスクでAnsibleは被管理ホストの情報を取得し、変数にセットしてくれています。
setupタスクで取得される値については、以下のコマンドで確認可能です。
ansible -i hosts ホスト名 -m setup
setupでは以下のような値が取得されています。
変数名 | 内容 | 値の例 |
---|---|---|
ansible_distribution | 被管理ホストのディストリビューション | CentOS |
ansible_date_time.date | Ansibleの実行日時 | 2016-03-11 |
ansible_hostname | 被管理ホスト名 | localhost |
ansible_pkg_mgr | 被管理ホストで利用できるパッケージマネジャー名 | yum |
複数のファイルをコピーしたり、複数のユーザーを追加したりしたい場合、追加したい数だけ対応するモジュールを書くことでも実現できますが、プレイブックが長く読みづらくなってしまいます。
このような場合にはタスクの繰り返しを扱う機能を使うと便利です。
userコマンドを使い複数のユーザーを追加したいとします。このような場合、「with_items」をタスクに指定することで、一括で追加が可能です。
tasks: user: name={{ item }} with_items: - momo - sora
with_itemsに渡されたシーケンスの内容が順に「item」という名称の変数に設定され、繰り返し実行されます。
以下のようにあらかじめシーケンスを変数で作っておき、with_itemsで指定することも可能です。
vars: users: - momo - sora tasks: user: name={{ item }} with_items: "{{ users }}"
上記の例で、ユーザー名と一緒にパスワードも指定したい場合は以下のようになります。
vars: users: - name: momo password: $6$rounds=656000$3Co6RKpfjN.qj23. - name: sora password: $6$rounds=656000$3Co6RKpfjN.qj23. tasks: - user: name={{ item.name }} password={{item.password}} with_items: "{{ users }}"
先ほどの例では、シーケンスでユーザーの追加を繰り返していました。しかし、以下のようにマッピングを使っており、マッピングの全ての要素で繰り返し実行したい場合はwith_itemsは使えません。
vars: users: admin: - name: momo password: $6$rounds=656000$3Co6RKpfjN.qj23. workes: - name: sora password: $6$rounds=656000$3Co6RKpfjN.qj23.
マッピングを繰り返しに利用する場合は「with_items」の代わりに「with_dict」を利用します。with_dictを利用すると、with_itemsと同様に「items」変数からマッピングのキーとバリューを取得できます。キーを取得するにはitem.keyを、バリューを取得するにはitem.valueを指定します。with_dictの利用例は以下の通りです。
tasks: - user: name={{ item.value.name }} password={{item.value.password}} with_dict: "{{ users }}"
copyモジュールでファイルをコピーする際、ある拡張子のファイルだけコピーしたい、というような場合もあるかと思いますが、「src」引数にはワイルドカードを利用することはできません。以下のようにプレイブックを記述した場合、「*.txt」という名称のファイルをコピーしようとしてしまいます。
tasks: - copy: src=/home/vagrant/*.txt dest=/home/piyo/txt/
このような場合には「with_fileglob」が使えます。with_itemsと同じようにシーケンスでファイルパスを指定することで、ヒットしたファイルパスだけタスクが繰り返し実行されます。with_fileglobの利用例は以下の通りです。
tasks: - copy: src={{ item }} dest=/home/piyo/dest/txt/ with_fileglob: - /home/vagrant/*.txt
Copyright © ITmedia, Inc. All Rights Reserved.