ansibleには「playbook」という機能があります。
簡単に言うと
- ansibleコマンド → 単純に1コマンドもしくはワンライナーのコマンドを実行したい
- ansible-playbookコマンド → playbookに「変数」や「繰り返し」など複雑な処理を書いて実行したい
です。
今回は更に「ansible-playbook」の作成方法や使い方を解説します。
Ansible のインストールや初期設定に関しては以下の記事を参照ください。
AWS EC2 を Ansible で構成管理をする場合の設定方法です。
Ansible プレイブックの基礎
ansibleのプレイブック「playbook」の機能を使うと、サーバーの構築や運用管理の質が大幅に向上します。
※playbookとは「ドラマの脚本」、「アメフトの作戦計画書」などの意味です。
プレイブックにはターゲットノード上で実行したい処理を記述します。
単純な構成で、プレイブックに書かれてある処理を上から順番にやっていくだけです。
以下、詳しく見ていきましょう。
プレイブックは YAML 形式で記述するから簡単
YAMLは「ヤムル」と呼びます。
YAMLは「YAML Ain’t a Markup Language」の略で「YAMLはマークアップ言語ではありません」という意味です。
YAMLはインデントやハイフンなどを使ってデータの構造を表します。
YAML形式のファイルは「.yml」の拡張子が付きます。
YAMLの大きな特徴
YAML形式ファイルの大きな特徴は
- テキストファイルで読める
- プログラムに詳しくなくても何となく分かる
です。
この特徴が非常に重要で、今まで「Chef」や「Puppet」にはなかった「簡単さ・気軽さ」を Ansible にもたらしています。
実際、サーバー周りを運用管理するインフラのエンジニアはプログラマーではないので、プログラムに関する理解度はバラつきがあります。
しかしYAML形式でプレイブックを書けることで、様々なレベルのエンジニアが共通の理解ができるようになります。
→大きな組織ではこの共通の理解が重要になります。
プレイブックの構造
プレイブックの構造は、いつくかのセクションに分かれています。
例えば pingの疎通確認をするプレイブックの場合
プレイブックはインデントが大きな役割を担っています。
インデントで処理・動作が変わります。
そのためインデントには注意しましょう。
$ cat playbook.yml |
ansible-playbook を実行してみます。
$ ansible-playbook ping-playbook.yml -i hostlist PLAY [all] *********************************************************************************************************************** TASK [Gathering Facts] *********************************************************************************************************** TASK [ping] ********************************************************************************************************************** PLAY RECAP *********************************************************************************************************************** |
もう1度 yaml ファイルを確認してみましょう。
$ cat playbook.yml |
このように Ansible のプレイブックは複数のセクションから成り立っています。
例えば、プレイブックに Task が3つあれば、1 play 3 task のプレイブックになります。
ターゲット(Targets)セクション
ターゲットノードを指定します。
※ターゲット(Targets)セクションとインベントリファイルは違います。
インベントリファイルは、構成管理をしたいサーバー一覧であるのに対して、ターゲット(Targets)セクションは、サーバー一覧の中からどのサーバーに対して処理をしたいのかを選択するために使用します。
【例】インベントリファイルが以下の場合
$ cat hostlist [local] 192.168.1.10 [remote] [aws] [all:vars] |
ターゲット(Targets)セクションは以下のようになります。
全台に対してタスクを実行したい場合
単純に all を指定するだけで、インベントリファイルに記述されている全台に対してタスクを実行します。
– hosts: all ← インベントリファイルに記載されている全台に対してタスクを実行します。「*」も「all」の意味になります。 |
特定のグループだけに対してタスクを実行したい場合
例えば、[local] グループだけに対してタスクを実行したい場合は、以下のように設定します。
– hosts: local ← グループ名を指定します。 |
特定の1台だけに対してタスクを実行したい場合
例えば、グループではなく特定の1台に対してのみタスクを実行したい場合は、以下のように設定します。
– hosts: 192.168.1.10 ← ホスト名、IPアドレス、FQDNなど直接指定してもOKです。 |
※もちろん、ここで指定する特定の1台は、あらかじめインベントリファイルに記載されている必要があります。
仕様上、Ansibleはインベントリファイルに記載のないマシンに対してはタスクを実行しません。
特定の複数のグループを指定したい場合
例えば、[local]グループと、[remote]グループの2つのみに対してタスクを実行したい場合は以下のようになります。
グループは、コロン[:]で区切ることで複数指定することができます。
– hosts: local:remote ← 複数のグループ名を[:]で区切って指定します。 |
タスク(Tasks)セクション
タスク(Tasks)セクションで具体的な処理を定義します。
ping 確認をする場合
以下のように ping 確認用のプレイブック「ping-playbook.yml」を作成します。
$ vi ping-playbook.yml
$ cat ping-playbook.yml
|
ansible-playbook で実行します。
$ ansible-playbook -i hostlist ping-playbook.yml
PLAY [192.168.1.10] *********************************************************************************
TASK [Gathering Facts] ******************************************************************************
TASK [ping check] ***********************************************************************************
PLAY RECAP ******************************************************************************************
|
httpd をインストールする場合
例としてローカルサーバーの「192.168.1.10」に「httpd」をインストールします。
$ vi httpd-install-playbook.yml – hosts: 192.168.1.10 ← 1台だけ指定します。
$ cat httpd-install-playbook.yml
|
ansible-playbook で実行します。
$ ansible-playbook -i hostlist httpd-install-playbook.yml
PLAY [192.168.1.10] *********************************************************************************
TASK [Gathering Facts] ******************************************************************************
TASK [httpd install] ********************************************************************************
PLAY RECAP ******************************************************************************************
|
httpdのインストール結果を確認ます。
$ rpm -qa | grep httpd |
wgetをインストールする場合
CentOS6に「wget」をインストールする手順を紹介します。
Ansibleを使えば、個別パッケージのインストールも可能です。
※CentOSを「minimum」でインストールすると、よく使うコマンドが入ってない時があります。
$ cat wget-install-playbook.yml |
ansible-playbookを実行します。
$ ansible-playbook -i hostlist wget-install-playbook.yml
PLAY [192.168.1.11] *********************************************************************************
TASK [Gathering Facts] ******************************************************************************
TASK [wget install] *********************************************************************************
PLAY RECAP ******************************************************************************************
|
wgetコマンドがインストールされました。
[root@cent06 ~]# wget
詳しいオプションは `wget –help’ を実行してください。
|
[DEPRECATION WARNING]: Instead of sudo/sudo_user, が出力される場合
以下のように警告が表示される場合があります。
$ ansible-playbook -i hostlist httpd-install-playbook.yml
|
以下の設定が原因です。
$ cat httpd-install-playbook.yml
|
これはエラーではなく警告でタスク自体は実行できますが、Ansibleの仕様で将来的に「sudo」は廃止するようなので使用しない方がいいでしょう。
ハンドラー(Handlers)セクション
Tasks セクションと同じように処理を定義します。
Tasks セクションとの違いは、例えば yum update でアップデート処理が走った時だけサービスを再起動するなど、更新された場合のみ特定の処理を実行したい場合に利用します。
httpdをアップデートした場合のみサービスを再起動したい場合
実際にハンドラー(Handlers)セクションを使って少々複雑なプレイブックを作成してみましょう。
1.プレイブックを作成する
$ vi httpd-update-playbook.yml – hosts: 192.168.1.11 handlers:
$ cat httpd-update-playbook.yml
handlers:
|
2.以前のバージョンの httpd をターゲットノードにインストールする
ターゲットノードにログインして以前のバージョンの httpd をダウンロードしてインストールします。
# wget http://vault.centos.org/6.0/os/x86_64/Packages/httpd-2.2.15-5.el6.centos.x86_64.rpm # wget http://vault.centos.org/6.0/os/x86_64/Packages/httpd-tools-2.2.15-5.el6.centos.x86_64.rpm
# yum install httpd-2.2.15-5.el6.centos.x86_64.rpm httpd-tools-2.2.15-5.el6.centos.x86_64.rpm
インストール:
完了しました! # chkconfig | grep httpd
httpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
# chkconfig httpd on
# chkconfig | grep httpd httpd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
# service httpd start
# service httpd status
|
3.ansible-playbookを実行する
ansible-playbookを実行します。
$ ansible-playbook -i hostlist httpd-update-playbook.yml
PLAY [192.168.1.11] *********************************************************************************
TASK [Gathering Facts] ******************************************************************************
TASK [httpd update] *********************************************************************************
RUNNING HANDLER [Restart httpd] *********************************************************************
PLAY RECAP ******************************************************************************************
$ |
4.チェックをする
最後にアップデートがされていることを確認します。
# rpm -qa | grep httpd
|
バー(Vars)セクション
変数を定義します。
変数を定義することで
- プレイブックが読みやすくなる
- 変更がしやすくなる
- タスクを効率化できる
などのメリットがあります。
変数を使って複数のアカウントを作成する場合
test01~test06まで6アカウントを作成します。
パスワードは6アカウント共通にします。
初めに事前準備としてハッシュ化したパスワードを作成します。
その理由は、
- パスワードをそのまま yml ファイルに記述すると漏えいする可能性がある
- /etc/passwd にパスワードが平文で登録されてしまい漏えいする可能性がある
などセキュリティホールになる可能性があるため、パスワードをハッシュ化してからアカウントを作成します。
CentOS6 の場合、パスワードのハッシュ化は「grub-crypt」コマンドを使います。
# grub-crypt –sha-512 |
CentOS7の場合は、「grub-crypt」コマンドがないので、以下の Python コマンドで作成します。
以下、パスワードが「password12345」の場合のハッシュ化したパスワード生成コマンドです。
[ansible_test@cnt07 ansible]$ python -c ‘import crypt; print crypt.crypt(“password12345”, “$6$random_salt”)’ |
詳しく解説しますと、
「import crypt」で crypt モジュールをインポートしています。
「crypt.crypt(”任意のパスワード”, “salt値”)」で「任意のパスワード」をハッシュ化しています。
「salt」とは暗号化アルゴリズムにブレを生じさせるために使うキーワードです。
そのため、「test」でも「1234」でも何でもいいです。
その「crypt.crypt」の結果を「print」で表示しています。
ちょっとややこしいかもしれませんが、CentOS7の場合はこの方法でハッシュ化されたパスワードを生成することができます。
ハッシュ化したパスワードを yml ファイルに記載します。
$ vi create-account-playbook.yml
– name: Create Users
$ cat create-account-playbook.yml – name: Create Users
|
ansible-playbookを実行します。
$ ansible-playbook -i hostlist create-account-playbook.yml
PLAY [192.168.1.11] ************************************************************************************
TASK [Gathering Facts] *********************************************************************************
TASK [Create Group] ************************************************************************************
TASK [Create Users] ************************************************************************************
PLAY RECAP *********************************************************************************************
|
結果を確認します。
# cat /etc/passwd | grep test
# cat /etc/shadow | grep test
|
with_item ディレクディブ
上の例で記載した通り「with_item」ディレクディブを利用することで、プレイブックをスッキリとまとめることができるようになります。
ただあまり使いすぎると却って可読性が低下するので、ほどほどに利用するのがいいと思います。
例えば、with_itemsディレクディブを利用してグループを複数作る例ですが、{{ item.groups }}が「変数」となり、変数の中に「test01」が代入されます。
処理の順番は、tasks の「name(- name: Create Groupのこと)」が1セットになるので、グループ「test01 3001」が代入され、1セットの処理が完了したら(グループが作成されたら)、グループ「test02 3002」が作成されるというようにシーケンシャルに(1つ1つ連続的に)処理されます。
つまりパラレルで順不同で一気にグループが6つ作られるわけではありません。
tasks:
|
まとめ
最初にプレイブックを作り込めれば、これほど簡単に確実にサーバーを管理できるツールは他にないと思いました。
ターゲットノードのディストリビューションもバージョンの違いも吸収してくれますし、何台サーバーがあっても(それこそ数千台レベルでも)何度も繰り返し全台に対して任意の設定を入れることができます。
体感的には1台2~3秒レベルで設定できるように感じました。
100台に対して ansible-playbook を実行した時は1~2分程度で処理が完了したと思います。
今後も ansible について詳しく調べて業務で活用できるように playbook 作成と実行結果からの検証を積み重ねていきたいと思います。
コメント