Ansible基礎 #3 - プレイブック 続

Last Edited: 12/4/2025

このブログ記事では、Ansibleにおけるプレイブックの更なる機能について紹介します。

DevOps

前回の記事では、すべての管理対象ノードにパッケージをインストールするための基本的なアドホックコマンドとプレイブックについて説明しました。 しかし、実際のプロジェクトでよく必要とされる、サーバーを柔軟に設定するための機能は他にもあります。 そこで、この記事では、Ansibleプレイブックの他の機能について議論を続けていきます。

ノードとタスクのターゲティング

前回の記事では、すべてのノードに同じパッケージをインストールしましたが、リバースプロキシ、 Webサーバー、データベースサーバー、ファイルサーバーなど、異なるサーバーに対して異なるインストール要件を持つことがよくあります。 異なるサーバーセットに対して異なるコマンドを実行するには、以下に示すようにインベントリでそれらをグループ化できます。

inventory
[web_servers]
253.78.154.178
84.246.7.193
 
[db_servers]
156.72.61.90

プレイブックでは、hostsフィールドの値をweb_serversまたはdb_serversに設定して、 指定されたノードでタスクを実行できます。例えば、WebサーバーにApacheとPHPをインストールしながら、 データベースサーバーにPostgreSQLをインストールするといったことです。 ただし、これらのタスクを同時に実行したくない場合があります。 実行するタスクをターゲットにするには、各タスクにapachepostgresのようなtagフィールドを追加し、 --tags <tag>フラグを付けてansible-playbookコマンドを実行できます。 指定されたタグに関係なく実行する必要があるタスクには、特別なタグalwaysを利用でき、 他のすべてのタスクの前に実行する必要があるタスクには、tasksの代わりにpre_tasksを使用できます。

ファイルとサービス

これまで、パッケージマネージャーを扱い、ノードにパッケージをインストールしてきました。 しかし、ローカルファイルやリモートファイルをノードにコピーする必要があることがよくあり、 これは以下に示すようにcopyモジュールで行うことができます。ソースファイルをsrc (プレイブックと同じ親ディレクトリ内のfilesディレクトリのファイル名)で指定し、 宛先をdestで指定し、ユーザーとグループの権限を他のフィールドで指定できます。

web.yaml
...
  # ローカルのhtmlをコピー
  - name: copy html file
    tags: apache
    copy:
      src: site.html
      dest: /var/www/html/index.html
      owner: root
      group: root
      mode: 0644
 
  # unzipをインストール & リモートのファイルのインストールと解凍
  - name: install unzip
    package: 
      name: unzip
 
  - name: install terraform
    unarchive:
      src: https://releases.hashicorp.com/terraform/0.12.28/terraform_0.12.28_linux_amd64.zip
      dest: /usr/local/bin
      remote_src: yes
      owner: root
      group: root
      mode: 0755
...

(Webサーバーよりもローカルワークステーションで必要とされることが多いとはいえ)上のように、 Terraformなどのリモートアーカイブをインストールして解凍することもできます。 管理対象ノードにファイルをコピーしてインストールすることで、 単にパッケージをインストールするよりもはるかに多くのことが可能になります。 さらに、httpdのような一部のパッケージでは、特定のノードでサービスを開始するためにsystemctlが必要であり、 これはserviceモジュールを使用して実現できます。

web.yaml
...
  - name: start httpd (CentOS)
    tags: apache
    service: 
      name: httpd
      state: started
      enabled: yes
    when: ansible_distribution == "CentOS"
 
  - name: change http config
    tags: apache
    lineinfile: 
      path: /etc/httpd/conf/httpd.conf
      regexp: '^ServerAdmin'
      line: ServerAdmin example@exmaple.com
    when: ansible_distribution == "CentOS"
    register: httpd
 
  - name: restart httpd upon config change
    tags: apache
    service:
      name: httpd
      state: restarted
    when: httpd.changed
...

最初のタスクはhttpdサービスを開始し、サービスがすでに開始されていて何らかの理由で無効になっている場合でも、 サービスが有効になっていることを確認します。2番目のタスクはlineinfileモジュールを使用してhttpd.confに変更を適用します。 httpd変数は、設定の変更時に実行される3番目のタスクのために登録され、httpd.changedで検出できます。 重要なのは、httpd.changedは、httpdが登録された直前のタスクが実行された場合にのみtrueを返すということです。 (間にhttpdが登録された別のタスクがあり、それが実行されなかった場合、httpd.changedfalseと評価されます。)

ユーザーとブートストラップ

これまで、管理対象ノードでsudoコマンドを実行するために、すべてのコマンド実行で--ask-become-passを使用してsudoパスワードを使用してきました。 しかし、Ansible用の新しいユーザー(デフォルトユーザーではない)を作成し、そのユーザーのSSHキーを登録し、 ユーザーをsudoersファイルに追加し、そのユーザーを使用することでこのフラグを使わずにコマンドを実行することができます。 これらのプロセスは各ノードに対して手動で行うか、Ansibleプレイブックを利用してブートストラップすることができます。

boostrap.yml
- hosts: all
  become: true
 
  vars:
    ansible_manager_user: ansible_user
    ssh_public_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
 
  tasks:
  - name: create ansible user
    tags: user
    user: 
      name: "{{ ansible_manager_user }}"
      group: "{{ 'wheel' if ansible_os_family == 'RedHat' else 'sudo' }}"
      create_home: true
      shell: /bin/bash
 
  - name: add ssh key for ansible
    tags: user
    authorized_key:
      user: "{{ ansible_manager_user }}"
      key: "{{ ssh_public_key }}"
 
  - name: add sudoer file for ansible
    tags: user
    copy:
      src: sudoer_ansible # 'ansible ALL=(ALL) NOPASSWD: ALL' in it
      dest: /etc/sudoers.d/{{ ansible_manager_user }}
      owner: root
      group: root
      mode: 0440
      validate: /usr/sbin/visudo -cf %s

上記のbootstrap.yamlプレイブックは、varsフィールド、userauthorized_key、 およびcopyモジュールを利用して、ユーザー、そのSSHキー、およびsudoer権限を設定します。 -u <initial_user>--ask-pass--ask-become-passなどのフラグを使用してプレイブックを実行し、 ansible.cfgを編集してデフォルトユーザーをansible_userに設定することができます。 これが正常に実行された後は、--ask-become-passやsudoパスワードの使用なしに今後のプレイブックを実行できます。

結論

この記事では、Ansibleプレイブックで特定のノードやタスクをターゲットにし、ファイルやサービスを管理し、 ユーザーを設定する方法について説明しました。これらの機能により、実世界のアプリケーションに対してより柔軟で便利なサーバー設定が可能になります。 しかし、プレイブックがより長く、より複雑になってきています。そのため、次の記事では、Ansibleで必要なコンポーネントをきれいに整理するために利用できる追加機能について説明します。

リソース