Ansible - コレクション

はじめに

今回はansible-coreに含まれるbuiltinモジュールだけではなく、後から追加可能な"コレクション"に含まれるモジュールを使用するPlaybookを作成します。
前回までの本ブログのAnsible記事で、Ansible Playbookのモジュール指定で記載していたservice、template等は、ansible-coreに含まれているbuilt-inモジュールです。built-inモジュールはAnsibleをインストールした時点で利用可能なモジュールです。built-inモジュールとしてAnsible-coreに含まれているモジュールは以下のサイトで確認できます。

Ansible Community Documentation - Ansible.Builtin

コレクションに含まれるモジュールを使用して、以下の操作を行うPlaybookを作成し、実行してみます。SELinuxコンテキスト操作とfirewallの操作はbuilt-inモジュールには含まれておらず、これらの処理ができるように必要なコレクションを追加して、処理が実行できるところまで確認していきます。

  • nginxをインストール
  • ドキュメントルートの変更(Redhat系ではnginxのドキュメントルートは/user/share/nginx/htmlなので、Apache HTTPDと同じ/var/wwwに変更)
  • SELinuxコンテキスト設定(ドキュメントルートを/var/wwwに変更するとSELinuxによりアクセスを拒否されるのでSELinuxコンテキストの変更)
  • firewallポート開放

推奨ディレクトリとPlaybookの作成

今回のPlaybook用のansibleディレクトリを作成します。(今回は使用しないAnsible推奨ディレクトリも含め作成しておきます。)

$ mkdir /home/user01/ansible/roles/nginx /home/user01/ansible/roles/nginx/{defaults,files,handlers,meta,tasks,templates,vars}

tasksのmain.ymlを作成します。前回までと同じように、main.ymlではOSの判定を行い、Red hatファミリー且つバージョンが8または9の場合に処理を行うように記載します。

$ cd roles/nginx/
$ vi tasks/main.yml
# Check the OS information and perform the processing.
---
- name: Define OS condition variable
  set_fact:
    is_redhat: "{{ ansible_os_family == 'RedHat' and ansible_distribution_major_version in ['8', '9'] }}"

- name: install and setting nginx
  import_tasks: nginx_intall_setting.yml
  when: is_redhat

nginx用の変数を定義します。nginxのコンフィグファイルとドキュメントルートに設定するパスを変数定義します。

$ vi defaults/main.yml
# default vars of nginx server.
---
docroot: /var/www
nginx_conf: /etc/nginx/nginx.conf

nginxのconfigファイルのテンプレートを作成します。テンプレートの元としてnginx.confはrpmパッケージ含まれるファイルを使用します。
元々、/usr/share/nginx/htmlと定義されている箇所を変数に置き換えます。変数箇所はansible実行時にdefaults/main.ymlで設定したdocrootの値に置き換えられます。

$ vi templates/nginx.conf.j2
(省略)
    server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        #root         /usr/share/nginx/html;
        root         {{ docroot }};
(省略)

nginxのインストール、firewall穴あけ、nginx起動を行うyamlファイルを作成します。
policycoreutils-python-utils、firewalldをインストールする処理も記載しています。既にインストール済みの場合もありますが、Ansibleでは既にインストール済みの状態の場合は処理をスキップし、何も変更しないので気にせず記載しておきます。

$ vi tasks/nginx_install_setting.yml
---
- name: Install required packages
  ansible.builtin.dnf:
    name:
      - nginx
      - policycoreutils-python-utils   # for semanage (SELinux)
      - firewalld
    state: present

- name: replace nginx.conf
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.con
    mode: 0644
    owner: root
    group: root
  notify: Reload nginx

- name: Ensure docroot exists
  ansible.builtin.file:
    path: "{{ docroot }}"
    state: directory
    owner: nginx
    group: nginx
    mode: "0755"

- name: Validate nginx config
  ansible.builtin.command: nginx -t
  changed_when: false

- name: Open HTTP service in firewalld
  ansible.posix.firewalld:
    service: http
    permanent: true
    state: enabled
    immediate: true

- name: Enable and start nginx
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: true

- name: Define SELinux file context for web root (persistent)
  community.general.sefcontext:
    target: "{{ docroot }}(/.*)?"
    setype: httpd_sys_content_t
    state: present

- name: Apply SELinux labels to web root
  ansible.builtin.command: "restorecon -Rv {{ docroot }}"
  changed_when: false

- name: Enable and start nginx
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: true

ansibleコマンド実行時に引数として渡すplaybookファイルを作成します。

$ vi /home/user01/ansible/nginx.yml
---
# nginx install setting play book
- name: Apply nginx settings
  hosts: all
  gather_facts: yes
  become: true

  roles:
    - nginx

コレクションをインストール

まずはコレクションをインストールしていない状態でテスト実行してみます。

$ ansible-playbook -i hosts.ini nginx.yml --vault-password-file=~/.vault_pass.txt --check
ERROR! couldn't resolve module/action 'ansible.posix.firewalld'. This often indicates a misspelling, missing collection, or incorrect module path.

The error appears to be in '/home/user01/ansible/roles/nginx/tasks/nginx_install_setting.yml': line 23, column 3, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:


- name: Open HTTP service in firewalld
  ^ here

ansible.posix.firewalldモジュールがないのでエラーとなります。
コレクションをインストールしてから、もう一度テスト実行してエラーが出ないことを確認します。

$ ansible-galaxy collection install ansible.posix
Starting galaxy collection install process
Process install dependency map
Starting collection install process
Downloading https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/artifacts/ansible-posix-2.1.0.tar.gz to /home/user01/.ansible/tmp/ansible-local-84812hzf1uyf7/tmpk4xouj6b/ansible-posix-2.1.0-132gdbvu
Installing 'ansible.posix:2.1.0' to '/home/user01/.ansible/collections/ansible_collections/ansible/posix'
ansible.posix:2.1.0 was installed successfully

$ ansible-playbook -i hosts.ini nginx.yml --vault-password-file=~/.vault_pass.txt --check
[WARNING]: Collection ansible.posix does not support Ansible version 2.14.18
ERROR! couldn't resolve module/action 'community.general.sefcontext'. This often indicates a misspelling, missing collection, or incorrect module path.

The error appears to be in '/home/user01/ansible/roles/nginx/tasks/nginx_install_setting.yml': line 36, column 3, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:


- name: Define SELinux file context for web root (persistent)
  ^ here

ansible.posix.firewalldのエラーは出なくなりましたが、新たにcommunity.general.sefcontextがないといわれていますので、追加でコレクションをインストールします。

$ ansible-galaxy collection install community.general
Starting galaxy collection install process
Process install dependency map
Starting collection install process
Downloading https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/artifacts/community-general-12.4.0.tar.gz to /home/user01/.ansible/tmp/ansible-local-85927alao4kj_/tmpkp3x2dvm/community-general-12.4.0-0w5go9vr
Installing 'community.general:12.4.0' to '/home/user01/.ansible/collections/ansible_collections/community/general'
community.general:12.4.0 was installed successfully

再度テスト実行してエラーが出ないことを確認します。[WARNING]表示で非サポートのバージョンであると警告がでてきました。

$ ansible-playbook -i hosts.ini nginx.yml --vault-password-file=~/.vault_pass.txt --check
[WARNING]: Collection ansible.posix does not support Ansible version 2.14.18
[WARNING]: Collection community.general does not support Ansible version 2.14.18
(省略)

インストールしたコレクションは2つとも今回の環境のansible-coreは2.14は非サポートの様です。
コレクションがサポート(テスト済み)しているansible-coreのバージョンは、コレクションのドキュメントや、gitlabのソースで確認が可能です。過去のコレクションバージョンまで遡って確認し、ansible-core2.14でテスト済みのバージョンを探します。

GitHub - ansible-collections/ansible.posix
GitHub - ansible-collections/community.general

上記のGitHubからansible2.14.18でも動作する(テスト済み)のバージョンをインストールしますが、その前に既にインストールされている非推奨のバージョンのコレクションを削除します。一度インストールしたコレクション/モジュールは、ディレクトリを削除すれば消すことが可能です。

$ rm -rf ~/.ansible/collections/ansible_collections

削除が完了したら、コレクションのバージョンを指定して再度インストールします。
ansible.posix(ansible.posix.firewall)は1.6.0未満のバージョンを、community.general(community.general.sefcontext)は10.0.0未満のバージョンをインストールするように指定しています。

$ ansible-galaxy collection install 'ansible.posix:<1.6.0'
Starting galaxy collection install process
Process install dependency map
Starting collection install process
Downloading https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/artifacts/ansible-posix-1.5.4.tar.gz to /home/user01/.ansible/tmp/ansible-local-86241u8trw28y/tmpe_dek7_w/ansible-posix-1.5.4-b4akf9h3
Installing 'ansible.posix:1.5.4' to '/home/user01/.ansible/collections/ansible_collections/ansible/posix'
ansible.posix:1.5.4 was installed successfully

$ ansible-galaxy collection install 'community.general:<10.0.0'
Starting galaxy collection install process
Process install dependency map
Starting collection install process
Downloading https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/artifacts/community-general-9.5.13.tar.gz to /home/user01/.ansible/tmp/ansible-local-86143dykwe5i_/tmpyqf5nri6/community-general-9.5.13-dk7lg5qs
Installing 'community.general:9.5.13' to '/home/user01/.ansible/collections/ansible_collections/community/general'
community.general:9.5.13 was installed successfully

Starting galaxy collection install process
Process install dependency map
Starting collection install process
Downloading https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/artifacts/ansible-posix-1.6.2.tar.gz to /home/user01/.ansible/tmp/ansible-local-85957ab1amlkt/tmp4gcjyhj3/ansible-posix-1.6.2-rpl9ambf
Installing 'ansible.posix:1.6.2' to '/home/user01/.ansible/collections/ansible_collections/ansible/posix'
ansible.posix:1.6.2 was installed successfully

ansible.posixは1.6.0より古い1.5.4が、community.generalは10.0.0より古い9.5.13がインストールされました。

稼働しているansible-coreのバージョンに対応したコレクションをインストールできたので、playbookのテスト実行を行ってみます。

$ ansible-playbook -i hosts.ini nginx.yml --vault-password-file=~/.vault_pass.txt --check

PLAY [Apply nginx settings] *****************************************************************************************************

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

TASK [nginx : Define OS condition variable] *************************************************************************************
ok: [nginx01]

TASK [nginx : Install required packages] ****************************************************************************************
changed: [nginx01]

TASK [nginx : replace nginx.conf] ***********************************************************************************************
changed: [nginx01]

TASK [nginx : Validate nginx config] ********************************************************************************************
skipping: [nginx01]

TASK [nginx : Open HTTP service in firewalld] ***********************************************************************************
ok: [nginx01]

TASK [nginx : Enable and start nginx] *******************************************************************************************
ok: [nginx01]

TASK [nginx : Define SELinux file context for web root (persistent)] ************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ModuleNotFoundError: No module named 'seobject'
fatal: [nginx01]: FAILED! => {"changed": false, "msg": "Failed to import the required Python library (policycoreutils-python) on nginx01.cvtk.test's Python /usr/bin/python3. Please read the module documentation and install it in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter"}

PLAY RECAP **********************************************************************************************************************
nginx01                    : ok=6    changed=2    unreachable=0    failed=1    skipped=1    rescued=0    ignored=0

[WARNING]表示は消えましたが、別のエラーがでてきました。
メッセージの通り、policycoreutils-pythonが不足しています。tasks/nginx_install_setting.ymlの最初にpolicycoreutils-python-utilsをインストールするように記載していますが、テスト実行では実際には実行されていないので不足してしまいます。今回は手動でインストールして、テスト実行が通るようにします。

(nginxインストール対象サーバ)
# dnf install policycoreutils-python-utils

再度テスト実行してみます。

$ ansible-playbook -i hosts.ini nginx.yml --vault-password-file=~/.vault_pass.txt --check

PLAY [Apply nginx settings] *****************************************************************************************************

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

TASK [nginx : Define OS condition variable] *************************************************************************************
ok: [nginx01]

TASK [nginx : Install required packages] ****************************************************************************************
ok: [nginx01]

TASK [nginx : replace nginx.conf] ***********************************************************************************************
changed: [nginx01]

TASK [nginx : Validate nginx config] ********************************************************************************************
skipping: [nginx01]

TASK [nginx : Open HTTP service in firewalld] ***********************************************************************************
ok: [nginx01]

TASK [nginx : Enable and start nginx] *******************************************************************************************
ok: [nginx01]

TASK [nginx : Define SELinux file context for web root (persistent)] ************************************************************
ok: [nginx01]

TASK [nginx : Apply SELinux labels to web root] *********************************************************************************
skipping: [nginx01]

TASK [nginx : Enable and start nginx] *******************************************************************************************
ok: [nginx01]

RUNNING HANDLER [nginx : Reload nginx] ******************************************************************************************
changed: [nginx01]

PLAY RECAP **********************************************************************************************************************
nginx01                    : ok=9    changed=2    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0

エラーも消えましたので本実行します。

実際に実行する

実際に実行する前に、先ほど操作対象サーバでインストールした、policycoreutils-python-utilsを削除して、ansibleの処理でインストールされるように変更しておきます。

$ ansible-playbook -i hosts.ini nginx.yml --vault-password-file=~/.vault_pass.txt

PLAY [Apply nginx settings] *******************************************************************************************************

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

TASK [nginx : Define OS condition variable] ***************************************************************************************
ok: [nginx01]

TASK [nginx : Install required packages] ******************************************************************************************
changed: [nginx01]

TASK [nginx : replace nginx.conf] *************************************************************************************************
changed: [nginx01]

TASK [nginx : Ensure docroot exists] **********************************************************************************************
changed: [nginx01]

TASK [nginx : Validate nginx config] **********************************************************************************************
ok: [nginx01]

TASK [nginx : Open HTTP service in firewalld] *************************************************************************************
changed: [nginx01]

TASK [nginx : Enable and start nginx] *********************************************************************************************
changed: [nginx01]

TASK [nginx : Define SELinux file context for web root (persistent)] **************************************************************
ok: [nginx01]

TASK [nginx : Apply SELinux labels to web root] ***********************************************************************************
ok: [nginx01]

TASK [nginx : Enable and start nginx] *********************************************************************************************
ok: [nginx01]

RUNNING HANDLER [nginx : Reload nginx] ********************************************************************************************
changed: [nginx01]

PLAY RECAP ************************************************************************************************************************
nginx01                    : ok=12   changed=6    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

これでnginxのセットアップが完了し、ブラウザからアクセス可能となりました。
docrootに指定した/var/www/にコンテンツファイルを用意していないのでアクセスすると「403 Forbidden」が表示されます。nginxの初期コンテンツが/usr/share/nginx/html/にあるので、コピーして配置すれば初期ページを表示することも可能です。

コレクションにはOS操作やベンダーネットワーク機器の操作、クラウド環境操作、コンテナ環境操作等、様々なものが存在しており、以下のサイトで検索できます。コレクションを利用することで様々なOSや外部装置、外部環境の操作を自動化することが可能になります。

Ansible Galaxy - コレクション

お問い合わせ

弊社では様々なサービスを取り扱っております。
詳細はサービス一覧からご覧ください。

お気軽にお問い合わせください。応対時間 9:30-17:30 [ 土・日・祝日除く ]

お問い合わせ