システム管理者の多くは仕事に忙殺され、時間に追われています。DNS サーバーの単純な変更や、サーバーファーム全体でのカーネルパラメーターの調整といった作業を思い浮かべるだけで、嫌気が差してくるのではないでしょうか。搭載されたメモリーやリリースバージョンなど、対象ごとに異なるシステム特性に基づく変更なら、なおさらです。さらには、開発者が DevOps というものについて、あなたの知らない表現を使って話しかけてきます。  

Red Hat Ansible Automation は人間が読み取れるエージェントレスの自動化ツールで、SSH を使用して構成管理、アプリケーションデプロイ、プロビジョニングをフラットな環境または多層環境でオーケストレーションします。オープンソース Ansible テクノロジーに基づいており、このテクノロジーは世界で最も普及したオープンソース IT 自動化テクノロジーとなっています。

このブログ記事では、Ansible の基礎と、システム管理者がシステム管理の効率を向上させるために使用できる方法を説明します。

始めに、いくつかの用語を定義する必要があります。

コントロールノード:Ansible を使用してマネージドノードでタスクを実行するホスト

マネージドノード:コントロールノードによって構成されているホスト

ホストインベントリー:マネージドノードのリスト

アドホックコマンド:1 回限りのシンプルなタスク

Playbook:より複雑な構成向けの繰り返しタスクのセット

モジュール:ユーザーの追加やパッケージのインストールなど、特定の共通タスクを実行するコード

べき等性:ある操作を 1 回行ったときの結果と、介入処理なしで複数回行ったときの結果がまったく同じになること

環境

この記事で扱う環境は、 1 つのコントロールノード (vm1) と 4 つのマネージドノード (vm2、vm3、vm4、vm5) で構成され、このすべてが、最小インストールの Red Hat Enterprise Linux 7.4 の仮想環境で実行されています。簡単にするため、コントロールノードの /etc/hosts ファイルに以下のエントリーがあるとします。

192.168.102.211 vm1 vm1.redhat.lab
192.168.102.212 vm2 vm2.redhat.lab
192.168.102.213 vm3 vm3.redhat.lab
192.168.102.214 vm4 vm4.redhat.lab
192.168.102.215 vm5 vm5.redhat.lab

話を簡単にするため、このデモではシステムユーザーにパスワード不要の sudo を付与します。実際のセキュリティポリシーは異なることがありますが、Ansible はさまざまな特権エスカレーションのユースケースを処理できます。このユーザーアカウントは、/etc/sudoers ファイルの以下のエントリーによる特権エスカレーションを行うように設定されています。

%wheel ALL=(ALL) NOPASSWD: ALL

これは例にすぎないので、お使いの環境に合わせた sudo 構成モデルを使用してください。  

最後に、コントロールノードから各マネージドノードに対して、このユーザーアカウントの SSH 公開鍵認証が設定され、テストされます。

インストール

Ansible for Red Hat Enterprise Linux 7 は Extras チャンネルにあります。Red Hat Enterprise Linux 6 を使用している場合は、EPEL リポジトリを有効にします。Extra Packages for Enterprise Linux (EPEL) の場合、カスタマーポータルのこのソリューションを参考にすることができます。Fedora システムでは Ansible はベースリポジトリにあります。

適切なリポジトリを設定したら、すばやく簡単にインストールできます。

[curtis@vm1 ~]$ sudo yum install -y ansible 

バージョンを確認しましょう。

[curtis@vm1 ~]$ ansible --version
ansible 2.4.1.0
 config file = /etc/ansible/ansible.cfg
 configured module search path = [u'/home/curtis/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
 ansible python module location = /usr/lib/python2.7/site-packages/ansible
 executable location = /bin/ansible
 python version = 2.7.5 (default, May 3 2017, 07:55:04) [GCC 4.8.5 20150623 (Red Hat 4.8.5-14)]

デフォルトの設定ファイルには、ここで使用する Red Hat Enterprise Linux 7.4 最小インストールに必要な Python があります。

設定

ユーザーアカウント、特権エスカレーション、SSH 公開鍵認証をマネージドノードで設定済みなので、コントロールノードの設定に進みます。

コントロールノードの設定には、Ansible 設定ファイルとホストインベントリーファイルの両方を使用します。

設定ファイル

先に確認したように、デフォルトの設定ファイルは /etc/ansible/ansible.cfg です。

このグローバル設定ファイルは、修正することも、特定のディレクトリに固有のコピーを作ることもできます。設定ファイルは以下の順序で配置されます。

  • ANSIBLE_CONFIG (環境変数)
  • ansible.cfg (ディレクトリごと)
  • ~/.ansible.cfg (ホームディレクトリ)
  • /etc/ansible/ansible.cfg (グローバル)

この記事では、以前追加したユーザーアカウントのホームディレクトリにある最小の設定ファイルを使用します。

[curtis@vm1 ~]$ cat ansible.cfg
[defaults]
inventory = $HOME/hosts

ホストインベントリー

デフォルトのホストインベントリー・ファイル /etc/ansible/hosts は、設定ファイル (上記を参照) を使用するか Ansible コマンドに -i オプションを使用して変更できます。ここではシンプルな静的インベントリーファイルを使用します。動的インベントリーを使用することもできますが、この記事では扱いません。

ホストインベントリー・ファイルは以下のとおりです。

[webservers]
vm2
vm3

[dbservers]
vm4

[logservers]
vm5

[lamp:children]
webservers
dbservers

vm2 と vm3 に webservers、vm4 に dbservers、vm5 に logservers、webservers と dbservers からなる lamp という 4 つのグループを定義しました。

この設定ファイルを使用してすべてのホストを特定できることを確認しましょう。

[curtis@vm1 ~]$ ansible all --list-hosts
 hosts (4):
   vm5
   vm2
   vm3
   vm4

同様に、webservers グループなど、個々のグループについても確認します。

[curtis@vm1 ~]$ ansible webservers --list-hosts
 hosts (2):
   vm2
   vm3

これでホストインベントリーが検証されたので、すべてのホストが稼働していることを手早く確認しましょう。これには、ping モジュールを使うアドホックコマンドを使用します。

[curtis@vm1 ~]$ ansible all -m ping
vm4 | SUCCESS => {
   "changed": false, 
   "failed": false, 
   "ping": "pong"
}
vm5 | SUCCESS => {
   "changed": false, 
   "failed": false, 
   "ping": "pong"
}
vm3 | SUCCESS => {
   "changed": false, 
   "failed": false, 
   "ping": "pong"
}
vm2 | SUCCESS => {
   "changed": false, 
   "failed": false, 
   "ping": "pong"
}

上記の出力から、すべてのシステムから正常な結果が返され、何も変更がなく、それぞれの “ping” から “pong” が返されたことがわかります。

利用できるモジュールの一覧を、以下のコマンドを使用して取得できます。

[curtis@vm1 ~]$ ansible-doc -l 

組み込みモジュールの数は Ansible リリースと連動して増加します。

[curtis@vm1 ~]$ ansible-doc -l | wc -l 
1378 

この環境での最後のセットアップタスクは、vm1 を Apache と Red Hat Enterprise Linux 7 Yum リポジトリで設定し、マネージドノードで追加パッケージをインストールすることです。

[root@vm1 ~]# yum install -y httpd
[root@vm1 ~]# systemctl enable httpd
[root@vm1 ~]# systemctl start httpd
[root@vm1 ~]# mkdir /media/iso
[root@vm1 ~]# mount -o loop /root/rhel-server-7.4-x86_64-dvd.iso /media/iso
[root@vm1 ~]# ln -s /media/iso /var/www/html/rhel7

Ansible を始めよう!

環境を設定して準備ができたので、Ansible を実際に操作してみましょう。

マネージドノードではいくつかの追加パッケージをインストールしておく必要があるので、最初のタスクは、この設定ファイルを使用して各ホストに Yum リポジトリを設定することです。

[curtis@vm1 ~]$ cat dvd.repo
[RHEL7]
name = RHEL 7
baseurl = http://vm1/rhel7/
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
enabled = 1
gpgcheck = 1

以下のようにして、 -m オプションを使用して copy モジュールを指定したアドホックコマンドで、 -a オプションを使用して必要な引数を指定して、各マネージドノードにこのファイルをコピーできます。

[curtis@vm1 ~]$ ansible all -m copy -a 'src=dvd.repo dest=/etc/yum.repos.d owner=root group=root mode=0644' -b
vm5 | SUCCESS => {
   "changed": true, 
   "checksum": "c15fdb5c1183f360ce29a1274c5f69e4e43060f5", 
   "dest": "/etc/yum.repos.d/dvd.repo", 
   "failed": false, 
   "gid": 0, 
   "group": "root", 
   "md5sum": "db5a5da08d1c4be953cd0ae6625d8358", 
   "mode": "0644", 
   "owner": "root", 
   "secontext": "system_u:object_r:system_conf_t:s0", 
   "size": 135, 
   "src": "/home/curtis/.ansible/tmp/ansible-tmp-1516898124.58-210025572567032/source", 
   "state": "file", 
   "uid": 0
}

[...]

残りのホストからのその他の出力は、省略されています。

ここで注目すべき点がいくつかあります。

  1. 各ノードから SUCCESS と “changed” : true と報告されますが、これはモジュール実行が成功し、ファイルが作成/変更されたということです。コマンドを再度実行すると、“changed” : false と出力されます。ファイルがすでに存在し、必要に応じて設定されたことを示します。つまり Ansible は、指定された状況が存在していない場合に限って必要な変更のみを行うということです。これが「べき等性」です。

  2. -b オプション (http://docs.ansible.com/ansible/latest/become.html を参照) を使用すると、リモートタスクが、ファイルを /etc/yum.repos.d ディレクトリにコピーするために必要な特権エスカレーション (sudo) を使用します。

  3. コピーモジュールに必要な引数は、以下のコマンドで確認できます。

[curtis@vm1 ~]$ ansible-doc copy 

 

Playbook

アドホックコマンドはテストやシンプルな単発のタスクには便利ですが、今後実行する繰り返しタスクのセットをキャプチャするには Playbook を使用します。Playbook には、設定対象の一連のホストと、実行するタスクのリストを定義する、1 つ以上の play が含まれています。

このシナリオでは、Web サーバー、データベースサーバー、一元化されたロギングサーバーを設定する必要があります。具体的には以下の要件があります。

  1. httpd パッケージは Web サーバー上でインスト-ル、有効化、起動されている

  2. 各 Web サーバーには「Welcome to <hostname> on <ip address>」というテキストを表示するデフォルトページがある

  3. 各 Web サーバーには、コンテンツ管理の適切なアクセス権を持つユーザーアカウントがある

  4. MariaDB パッケージがデータベースサーバー上でインストール、有効化、起動されている

  5. ログサーバーホストがリモート・ロギング・メッセージを受理するように設定されている

  6. webservers および dbservers グループのホストがログメッセージのコピーをログサーバーホストに送信する

 

以下の Playbook (myplaybook.yml) で、必要なすべてのものを設定します。

Playbook では、以下のことに注意してください。

  1. ユーザーモジュールにはプレーンテキストのハッシュが必要です (詳細は「ansible-doc user」を参照してください)。これは以下のようにして達成できます。

    • [curtis@vm1 ~]$ python -c "from passlib.hash import sha512_crypt; import getpass; print sha512_crypt.encrypt(getpass.getpass())" Password: $6$rounds=656000$bp7zTIl.nar2WQPS$U5CBB15GHnzBqnhY0r7UX65FrBI6w/w9YcAL2kN9PpDaYQIDY6Bi.CAEL6PRRKUqe2bJYgsayyh9NOP1kUy4w.
  2. デフォルトの Web ページのコンテンツはホストから収集された「ファクト」を使用して作成されます。setup モジュールを使用してホストファクトを検出して使用できます。

[curtis@vm1 ~]$ ansible vm2 -m setup

---
- hosts: webservers
 become: yes
 tasks:
   - name: install Apache server
     yum:
       name: httpd
       state: latest

   - name: enable and start Apache server
     service:
       name: httpd
       enabled: yes
       state: started

   - name: open firewall port
     firewalld:
       service: http
       immediate: true
       permanent: true
       state: enabled

   - name: create web admin group
     group:
       name: web
       state: present

   - name: create web admin user
     user:
       name: webadm
       comment: "Web Admin"
       password: $6$rounds=656000$bp7zTIl.nar2WQPS$U5CBB15GHnzBqnhY0r7UX65FrBI6w/w9YcAL2kN9PpDaYQIDY6Bi.CAEL6PRRKUqe2bJYgsayyh9NOP1kUy4w.
       groups: web
       append: yes

   - name: set content directory group/permissions 
     file:
       path: /var/www/html
       owner: root
       group: web
       state: directory
       mode: u=rwx,g=rwx,o=rx,g+s

   - name: create default page content
     copy:
       content: "Welcome to {{ ansible_fqdn}} on {{ ansible_default_ipv4.address }}"
       dest: /var/www/html/index.html
       owner: webadm
       group: web
       mode: u=rw,g=rw,o=r

- hosts: dbservers
 become: yes
 tasks:
   - name: install MariaDB server
     yum:
       name: mariadb-server
       state: latest

   - name: enable and start MariaDB server
     service:
       name: mariadb
       enabled: yes
       state: started

- hosts: logservers
 become: yes
 tasks:
   - name: configure rsyslog remote log reception over udp
     lineinfile:
       path: /etc/rsyslog.conf
       line: "{{ item }}"
       state: present
     with_items:
       - '$ModLoad imudp'
       - '$UDPServerRun 514'
     notify:
       - restart rsyslogd

   - name: open firewall port
     firewalld:
       port: 514/udp
       immediate: true
       permanent: true
       state: enabled

 handlers:
   - name: restart rsyslogd
     service:
       name: rsyslog
       state: restarted

- hosts: lamp
 become: yes
 tasks:
   - name: configure rsyslog
     lineinfile:
       path: /etc/rsyslog.conf
       line: '*.* @192.168.102.215:514'
       state: present
     notify:
       - restart rsyslogd

 handlers:
   - name: restart rsyslogd
     service:
       name: rsyslog
       state: restarted

Playbook の実行

今回の Playbook は以下のコマンドを使用して実行できます。

[curtis@vm1 ~]$ ansible-playbook myplaybook.yml 

以下の出力から、Web サーバーの設定は vm2 と vm3 でのみ実行され (play 1)、データベースは vm4 (play 2) にインストールされ、logserver (vm5) は play 3 で設定されることがわかります。最後に、play 4 はリモートロギング向けに “lamp” グループを通じて webservers と dbservers のホストを設定します。

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

TASK [Gathering Facts] ****************************************************************
ok: [vm2]
ok: [vm3]

TASK [install Apache server] **********************************************************
changed: [vm3]
changed: [vm2]

TASK [enable and start Apache server] *************************************************
changed: [vm2]
changed: [vm3]

TASK [open firewall port] *************************************************************
changed: [vm2]
changed: [vm3]

TASK [create web admin group] *********************************************************
changed: [vm3]
changed: [vm2]

TASK [create web admin user] **********************************************************
changed: [vm3]
changed: [vm2]

TASK [set content directory group/permissions] ****************************************
changed: [vm3]
changed: [vm2]

TASK [create default page content] ****************************************************
changed: [vm3]
changed: [vm2]

PLAY [dbservers] **********************************************************************

TASK [Gathering Facts] ****************************************************************
ok: [vm4]

TASK [install MariaDB server] *********************************************************
changed: [vm4]

TASK [enable and start MariaDB server] ************************************************
changed: [vm4]

PLAY [logservers] *********************************************************************

TASK [Gathering Facts] ****************************************************************
ok: [vm5]

TASK [configure rsyslog remote log reception over udp] ********************************
changed: [vm5] => (item=$ModLoad imudp)
changed: [vm5] => (item=$UDPServerRun 514)

TASK [open firewall port] *************************************************************
changed: [vm5]

RUNNING HANDLER [restart rsyslogd] ****************************************************
changed: [vm5]

PLAY [lamp] ***************************************************************************

TASK [Gathering Facts] ****************************************************************
ok: [vm3]
ok: [vm2]
ok: [vm4]

TASK [configure rsyslog] **************************************************************
changed: [vm2]
changed: [vm3]
changed: [vm4]

RUNNING HANDLER [restart rsyslogd] ****************************************************
changed: [vm3]
changed: [vm2]
changed: [vm4]

PLAY RECAP ****************************************************************************
vm2                        : ok=11 changed=9 unreachable=0    failed=0 
vm3                        : ok=11 changed=9 unreachable=0    failed=0 
vm4                        : ok=6 changed=4 unreachable=0    failed=0 
vm5                        : ok=4 changed=3 unreachable=0    failed=0 

これで完了です。

以下のコマンドを使用して webserver ホストを確認できます。

[curtis@vm1 ~]$ curl http://vm2
Welcome to vm2 on 192.168.102.212
[curtis@vm1 ~]$ curl http://vm3
Welcome to vm3 on 192.168.102.213 

logger コマンドを webservers および dbservers ホストで使用してリモートロギングを確認します。

[curtis@vm1 ~]$ ansible lamp -m command -a 'logger hurray it works'
vm3 | SUCCESS | rc=0 >>

vm4 | SUCCESS | rc=0 >>

vm2 | SUCCESS | rc=0 >>

中央ロギングサーバーで確認します。

[curtis@vm1 ~]$ ansible logservers -m command -a "grep 'hurray it works$' /var/log/messages" -b
vm5 | SUCCESS | rc=0 >>
Jan 30 13:28:29 vm3 curtis: hurray it works
Jan 30 13:28:29 vm2 curtis: hurray it works
Jan 30 13:28:29 vm4 curtis: hurray it works

ヒントとコツ

YAML を初めて使う場合、とくにスペースの使い方 (タブは使用しない) を含め構文が難しく思われるかもしれません。

Playbook を実行する前に、以下を使用して構文をチェックできます。

$ ansible-playbook --syntax-check myplaybook.yml 

vim で構文ハイライト機能を使用すると、yaml の学習のほか、構文上の問題の発見にも役立ちます。vim で yaml 構文のハイライトを有効にするには、~/.vimrc ファイルに以下の行を追加するのが簡単な方法です。

 

autocmd Filetype yaml setlocal tabstop=2 ai colorcolumn=1,3,5,7,9,80

色分けなど、さらに機能を追加したい場合は、こちらから該当するプラグインを見つけられます。
vim ではなく emacs を使用したい場合は、EPEL リポジトリを有効にして、emacs-yaml-mode パッケージをインストールします。

ターゲットホストで実際に変更しなくても、Playbook をテストできます。

$ ansible-playbook --check myplaybook.yml 

Playbook をステップ実行する方法も便利です。

$ ansible-playbook --step myplaybook.yml 

シェルスクリプトと同様に、Ansible Playbook 実行可能ファイルを作成して、以下の行をファイルの先頭に追加できます。

#!/bin/ansible-playbook 

任意のアドホックシェルコマンドを実行するには、command モジュール (-m が指定されていない場合のデフォルトモジュール) を使用します。リダイレクトやパイプラインなどを使用する必要がある場合は、shell モジュールを使用します。

Playbook を迅速に作成するには、個々のモジュールのマニュアルにある “EXAMPLES:” セクションを確認してください。

Playbook 内で文字列には引用符を使用して、文字列内の特殊文字に関する問題を回避します。

ロギングはデフォルトでは無効です。ロギングを有効にするには、Ansible 設定ファイルで log_path パラメーターを使用します。

この記事を通して、Ansible のしくみと、Playbook を使用して日常的なタスクを簡単かつ正確に文書化し、これを繰り返すことで、時間と作業量を削減できるかについてご理解いただければ幸いです。さらに詳しい内容は http://docs.ansible.com および https://www.redhat.com/ja/technologies/management/ansible をご覧ください。

ハッピー・オートメーティング! (自動化で毎日を快適にしましょう!)

 

画像Curtis Rempel 氏 (RHCA) は、カナダのシニアプラットフォーム TAM およびチームリーダーで、元 Red Hat 認定インストラクター兼試験官 (RHCI/RHCX) です。同氏の Linux 歴は 1994 年、Jon “maddog” Hall の Red Hat Linux 2.1 CD から始まりました。TAM として、金融、通信、航空産業におけるエンタープライズ顧客を、自動化、カーネル、ストレージの専門知識でサポートしてきました。Rempel 氏の詳細はこちらをご覧ください。

Red Hat テクニカル・アカウント・マネージャー (TAM) は専門の製品エキスパートで、IT 組織と協力しながらデプロイを成功に導くよう戦略的な計画を練り、最適なパフォーマンスと成長の実現を支援します。TAM は Red Hat のワールドクラスの カスタマーエクスペリエンス & エンゲージメント組織の一部で、事前にアドバイスとガイダンスを提供して、潜在的な問題が発生する前に特定して対処できるよう支援します。問題が発生すると、TAM が問題の所有権を持ち、最適なリソースを可能な限り速やかに解決に当たらせ、お客様のビジネスの中断を最小限に抑えます。

お近くの Red Hat Convergence イベントで TAM にご連絡ください。Red Hat Convergence は招待制の無料イベントで、テクニカルユーザーが Red Hat 製品の知識を深め、オープンソース・テクノロジーを適用してビジネス目標を達成する新たな方法を見出す機会を提供します。これは世界中の都市を巡って開催される 1 日のイベントで、その地域の Red Hat のエキスパートや同業者から学び、交流する場となります。

オープンソースとは好奇心のコラボレーションです。サンフランシスコで 5 月 8 - 10 日に開催される Red Hat Summit にご参加ください。TAM やその他の Red Hat エキスパートと直に対話するチャンスです。ぜひご登録ください。コード CEE18 を利用すると 1,100 米ドルになります。

Red Hat Cloud Success は、製品の詳しい専門知識、ガイダンス、サポートにより、IT の変革を単純化し、クラウド・テクノロジーの導入を加速することを目的としています。PoC 段階からプロダクションまで、高度なスキルを持つクラウド・テクニカルスペシャリストがパートナーとなり、中断を招くことなくお客様のクラウド・ソリューションの実装を成功に導きます。このような短期的な取り組みを通じて、Red Hat Cloud Success はクラウド・ソリューションの効果的な計画とデプロイ、および将来に向けた戦略的な計画の策定を支援できます。