2022年8月6日土曜日

Ansibleのベストプラクティスのディレクトリ構成でPlaybookを実行する

AnsibleはPlaybookを1つのファイルで作成することもできるが、その場合処理が多く複雑になるほど、一つのファイルの情報量が膨大となり、ファイルの可読性や再利用が難しくなるという問題がある。そのため、Ansibleではベストプラクティスとして、ディレクトリを分割し、Playbookをvars、tasksなどで分割して配置することを定めている。

今までは1つのファイルでPlaybookを作成したが、今回は、Ansibleのベストプラクティスのディレクトリ構成にてPlaybookを実行できるよう構成してみる。

今までのAnsible関連記事

環境

コントロールノード及び実行対象サーバのLinuxのOSは、AlmaLinuxにて構築している。

  • コントロールノード
    • OS : AlmaLinux 8.5
    • Ansible : ansible [core 2.13.1]
  • Ansible実行対象サーバ
    • OS : AlmaLinux 8.5
    • IPアドレス : 192.168.1.101

今回は前回の記事で作成した、Linuxサーバの初期設定と単体テストを行うPlaybookをAnsibleのベストプラクティスのディレクトリにて再構成する。

Ansibleのベストプラクティスのディレクトリ構成

ベストプラクティスの構成は以下URLに記載されている。

各ディレクトリの説明を以下表に記載する。

ファイル名 説明
production 本番環境用のインベントリファイル。
staging 検証環境用のインベントリファイル。
group_vars/all.yml すべての実行対象サーバが利用する変数。
group_vars/[グループ名].yml インベントリファイルに記載したグループに所属する実行対象サーバが利用する変数。
host_vars/[サーバ名].yml 個別の実行対象サーバが利用する変数。
site.yml Playbook実行の主体。本YAMLファイルから、[任意の処理名].ymlを呼び出す。
[任意の処理名].yml site.ymlから呼び出されて実行される。実行対象のロールを記載する。
roles/[ロール名]/tasks/main.yml Playbookのタスクが記載されたファイル。
roles/[ロール名]/handlers/main.yml Playbookのハンドラーが記載されたファイル。
roles/[ロール名]/files/[任意のファイル名] 実行対象サーバにコピーして利用するための、定型化された設定ファイルなどを配置する。
roles/[ロール名]/vars/main.yml 本ロールのみで有効となる変数。優先度が高く、他箇所で宣言された変数によって上書きされない。
roles/[ロール名]/defaults/main.yml 本ロールのみで有効となる変数。優先度が低く、他箇所で宣言された変数によって上書きされる。

これをもとに、前回作成したsetup_linux_serverのPlaybookのディレクトリ構成は以下の通りとした。不要なディレクトリは作成していないため、比較的シンプルになっている。

また、ロールは以下2種類を配置している。

  • restore_vmware_vm_snapshot : テスト用Linuxサーバを初期化 (スナップショットリストア) を行うロール
  • setup_linux_server : 初期化されたLinuxサーバの初期設定と単体テストを行うロール
.
├── staging                                     # インベントリファイル (テスト環境)
├── site.yml                                    # Playbookを呼び出すファイルとして利用
├── setup_linux_server.yml                      # Playbook本体 (実行対象のロールを定義)
├── group_vars
│   ├── all.yml                                 # 全体共通変数
│   ├── linux_servers.yml                       # Linuxサーバ用変数
│   └── vmware_servers.yml                      # ESXi用変数
└── roles
    ├── restore_vmware_vm_snapshot              # ロール① (スナップショットリストア)
    │   └── tasks
    │       ├── main.yml                        # タスクを呼び出すファイルとして利用
    │       └── restore_vmware_vm_snapshot.yml  # タスク本体 (スナップショットリストア)
    └── setup_linux_server                      # ロール② (Linux初期設定)
        └── tasks
            ├── main.yml                        # タスクを呼び出すファイルとして利用
            ├── build.yml                       # タスク本体 (Linux初期設定)
            └── unit_test.yml                   # タスク本体 (Linux単体テスト)

それでは、実際のファイルの内容を具体的に見ていこう。

各ファイルの内容

Ansibleのベストプラクティスのディレクトリ構成に伴い、ファイル分割や新たなファイル作成が必要となる。マニュアルだけでは実際にどのような内容が記載されているかイメージしにくいと思うので、以下に各ファイルの内容を記載する。参考にしてもらい、Playbookの分割を行えば、同様に動作させることができるだろう。

staging : インベントリファイル (テスト環境)

通常のPlaybookでもインベントリファイルは作成をするが、Ansibleのベストプラクティスでは、以下ファイル名でインベントリファイルを作成する。本Playbookではテスト環境のみ対象となるため、stagingのみ作成した。

  • staging : テスト環境用インベントリファイル
  • production : 本番環境用インベントリファイル
[linux_servers]
server1 ansible_host=192.168.1.101

[vmware_servers]
esxi1 ansible_host=192.168.1.201

site.yml : Playbookを呼び出すファイルとして利用

site.ymlでは、今後の拡張性を考慮してimport_playbookを用いてPlaybook本体を呼び出す構成とする。当然だが、直接呼出し先のPlaybookの内容を記載しても動作する。

---
- import_playbook: setup_linux_server.yml

setup_linux_server.yml : Playbook本体 (実行対象のロールを定義)

Playbook本体では、実行対象のロールを定義する。前述したとおり今回実行するロールは以下2つとなる。

  • restore_vmware_vm_snapshot : テスト用Linuxサーバを初期化 (スナップショットリストア) を行うロール
  • setup_linux_server : 初期化されたLinuxサーバの初期設定と単体テストを行うロール

それぞれのロールに対して、hostsgather_factsといった内容を定義する。なお、タグ情報をtagsで付与しているが、これはPlaybook実行時に特定のロールだけ実行したい場合に利用する。タグを用いたPlaybookの実行方法は後述する。

---
- name: Build test vm
  hosts: vmware_servers
  gather_facts: true

  roles:
    - role: restore_vmware_vm_snapshot
      tags: restore_vmware_vm_snapshot

- name: Setup linux server
  hosts: linux_servers
  gather_facts: true

  roles:
    - role: setup_linux_server
      tags: setup_linux_server

group_vars/all.yml : 全体共通変数

実行対象サーバ全台で共通して利用する変数を定義する。今回は、Linuxサーバに接続するためのユーザやプロキシサーバの環境変数を定義した。

---
ansible_ssh_user: ansibleuser

proxy_env:
  http_proxy: 192.168.1.1:8080
  https_proxy: 192.168.1.1:8080

group_vars/linux_servers.yml : Linuxサーバ用変数

Linuxサーバ用の変数を定義する。これは、もともとのPlaybookのvarsに記載されているものがそのまま記載されている。

---
package_install_list:
  - open-vm-tools
  - rsyslog
  - chrony
  - sos
  - sysstat
  - tcpdump
  - cifs-utils
  - nfs-utils
  - bind-utils

service_disable_list:
  - firewalld

service_enable_list:
  - chronyd

ntp_server: 192.168.1.2

nmcli_ipv4_gateway: 192.168.1.254
nmcli_ipv4_dns: "192.168.1.4"
nmcli_ipv4_dns_search: test.local

roles/setup_linux_server/tasks/main.yml : タスクを呼び出すファイルとして利用

各ロール内のmain.ymlでは、今後の拡張性を考慮してinclude_tasksを用いて別のファイルに記載したタスクを呼び出す構成とする。当然だが、直接呼出し先のタスクの内容を記載しても動作する。

ここでもタグ情報をtagsで付与しているが、これはPlaybook実行時に特定のタスクだけ実行したい場合に利用する。タグを用いたPlaybookの実行方法は後述する。

---
# Build
- block:
  - name: Include build tasks
    include_tasks: file=build.yml
  tags: linux-build

# Unit test
- block:
  - name: Include unit test tasks
    include_tasks: file=unit_test.yml
  tags: linux-unit_test

roles/setup_linux_server/tasks/build.yml : タスク本体 (Linux初期設定)

ここには、もともとのPlaybookのtasksに記載されているLinuxサーバの初期設定個所がそのまま記載されている。

---
- name: Set timezone
  community.general.timezone:
    name: Asia/Tokyo
  become: true

- name: Set network interface
  ansible.builtin.command: nmcli c mod ens192 {{ item }}
  loop:
    - connection.autoconnect yes
    - ipv4.gateway "{{ nmcli_ipv4_gateway }}"
    - ipv4.dns "{{ nmcli_ipv4_dns }}"
    - ipv4.dns-search "{{ nmcli_ipv4_dns_search }}"
  changed_when: false
  become: true

~(以下略)~

roles/setup_linux_server/tasks/unit_test.yml : タスク本体 (Linux単体テスト)

ここには、もともとのPlaybookのtasksに記載されているLinuxサーバの単体テスト個所がそのまま記載されている。

---
- name: Test timezone
  ansible.builtin.shell: set -o pipefail && timedatectl status | grep 'Asia/Tokyo'
  changed_when: false

- name: Test network interface
  ansible.builtin.shell: set -o pipefail && nmcli c show ens192 | grep -E {{ item }}
  loop:
    - '^connection.autoconnect.*yes'
    - '^ipv4.addresses.*{{ ansible_host }}'
    - '^ipv4.gateway.*{{ nmcli_ipv4_gateway }}'
    - '^ipv4.dns.*$(echo "{{ nmcli_ipv4_dns }}" | tr " " ",")'
    - '^ipv4.dns-search.*{{ nmcli_ipv4_dns_search }}'
  changed_when: false
  register: result
  environment:
    LANG: C

~(以下略)~

ファイルの内容の説明は以上となる。このPlaybookを実際に実行してみよう。

Playbook実行結果

全処理実行

Playbookの実行結果を以下に抜粋して記載する。

# ansible-playbook -i staging site.yml 

★ロール「restore_vmware_vm_snapshot」を開始
PLAY [Build test vm] **************************************************************************************************************

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

★ロール「restore_vmware_vm_snapshot」のタスクをmain.ymlから読み込み
TASK [restore_vmware_vm_snapshot : Include build tasks] ***************************************************************************
included: /root/ansible/setup_linux_server/roles/restore_vmware_vm_snapshot/tasks/restore_vmware_vm_snapshot.yml for esxi1

★テスト用Linuxサーバを初期化のタスクを実行
TASK [restore_vmware_vm_snapshot : Restore test vm from snapshot] *****************************************************************
changed: [esxi1]

~(以下略)~

★ロール「setup_linux_server」を開始
PLAY [Setup linux server] *********************************************************************************************************

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

★ロール「setup_linux_server」のLinux初期構築のタスクをmain.ymlから読み込み
TASK [setup_linux_server : Include build tasks] ***********************************************************************************
included: /root/ansible/setup_linux_server/roles/setup_linux_server/tasks/build.yml for server1

★Linux初期構築のタスクを実行
TASK [setup_linux_server : Set timezone] ******************************************************************************************
changed: [server1]

~(以下略)~

★ロール「setup_linux_server」の単体テストのタスクをmain.ymlから読み込み
TASK [setup_linux_server : Include unit test tasks] *******************************************************************************
included: /root/ansible/setup_linux_server/roles/setup_linux_server/tasks/unit_test.yml for server1

★単体テストのタスクを実行
TASK [setup_linux_server : Test timezone] *****************************************************************************************
ok: [server1]

~(以下略)~

PLAY RECAP ************************************************************************************************************************
esxi1                  : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
server1                  : ok=21   changed=5    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

単体テストのみ実行 (タグを指定して実行)

Playbook実行時にtagsにて記載しているタグ名を指定することで、特定の処理のみ実行することが可能となる。ここでは、例として単体テストのみ実行をさせてみる (タグ名:linux-unit_test)。

# ansible-playbook -i staging site.yml -t linux-unit_test

PLAY [Build test vm] **********************************************************************************************

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

★テスト用Linuxサーバを初期化のタスクがスキップされる

PLAY [Setup linux server] *****************************************************************************************

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

★Linux初期構築のタスクがスキップされ、単体テストのタスクが実行される
TASK [setup_linux_server : Include unit test tasks] ***************************************************************
included: /root/ansible/setup_linux_server/roles/setup_linux_server/tasks/unit_test.yml for server1

TASK [setup_linux_server : Test timezone] *************************************************************************
ok: [server1]

~(以下略)~

PLAY RECAP ********************************************************************************************************
esxi1                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 
server1                  : ok=9    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

以上の通り、Ansibleのベストプラクティスのディレクトリ構成にてPlaybookを実行することができた。

0 件のコメント:

コメントを投稿

人気の投稿