hana_shinのLinux技術ブログ

Linuxの技術情報を掲載しています。特にネットワークをメインに掲載していきます。

Ansibleの使い方(ansible.posixモジュール編)



1 はじめに

ansible.posixは、POSIXLinux/Unix系システム)ベースの操作をサポートするためのモジュールやプラグインが含まれているAnsibleコレクションです。Linuxのシステム管理に役立ちます。詳細は、Ansible.Posix — Ansible Community Documentationを参照してください。

モジュール名 概要
acl ファイルACL情報の設定と取得
at atコマンドを使用してコマンドまたはスクリプトファイルの実行をスケジュール
authorized_key SSHの認証キーの追加または削除
firewalld firewalldを使用して任意のポート/サービスを管理
firewalld_info firewalldに関する情報の収集
mount マウントポイントの制御
patch パッチツールを使用してパッチファイルを適用
rhel_facts RHEL固有のファクトを設定またはオーバーライドするためのファクトモジュール
rhel_rpm_ostree RHEL for Edge rpm-ostreeベースのシステムでパッケージが存在することを確認
rpm_ostree_upgrade rpm-ostreeアップグレードトランザクションの管理
seboolean SELinuxブール値の切り替え
selinux SELinuxのポリシーと状態の変更
synchronize rsyncコマンドを使って、ローカルホストとリモートホスト間でファイルやディレクトリを同期するためのモジュール
sysctl カーネルパラメータを操作するためのモジュール

2 検証環境

動作検証を行うための環境は以下のとおりです。enp1s0はNIC(ネットワークインターフェースカード)の名前です。

                          192.168.122.0/24
control(enp1s0) -------------------------------------(enp1s0) node1
               .220                               .87
ホスト名 役割
control コントロールノードとして動作します。Ansibleをインストールします
node1 ターゲットノードとして動作します

コントロールノード、ターゲットノードのAlmaLinux版数は以下のとおりです。

[root@server ~]# cat /etc/redhat-release
AlmaLinux release 9.2 (Turquoise Kodkod)

コントロールノード、ターゲットノードのカーネル版数は以下のとおりです。

[root@server ~]# uname -r
5.14.0-284.11.1.el9_2.x86_64

私の環境では、ansible.posixがデフォルトでインストールされていました。ansible.posixのバージョンは以下のとおりです

[root@control ~]# ansible-galaxy collection list

# /usr/lib/python3.9/site-packages/ansible_collections
Collection                    Version
----------------------------- -------
amazon.aws                    5.5.1
ansible.netcommon             4.1.0
ansible.posix                 1.5.4
-snip-

3 事前準備

Ansibleのインストールや公開鍵認証の設定方法などは、Ansibleの使い方(モジュール編) - hana_shinのLinux技術ブログを参照してください。

4 firewalldモジュールの使い方

firewalldモジュールは、firewalld ルールに対してサービス/ポート(TCPまたはUDPのいずれか)の追加/削除するモジュールです。詳細は、ansible.posix.firewalld module – Manage arbitrary ports/services with firewalld — Ansible Community Documentationを参照してください。

4.1 ポートを解放する方法

playbookを作成します。このplaybookは、nodesグループ内のホストで、publicゾーンにおいてポート80/tcpを許可します。設定は永続的(permanent: yes)かつ即時的(immediate: yes)に行われます。なお、firewalldモジュールに渡すパラメータの意味は以下のとおりです。

パラメータ 意味
zone ファイアウォールのゾーンを指定します。publicはpublicゾーンを指し、そこでポートの変更が行われます。ゾーンは他にdmz,internal等があります
permanent yesに設定することで、ファイアウォールの設定が永続的に保存されます。次回OS再起動後も設定が保持されます
immediate yesに設定することで、即時にファイアウォールの設定を反映します
port 許可またはブロックするポートとプロトコルを指定します。たとえば、80/tcpは80番ポートのTCPプロトコルを示しています
state enabledに設定することで、指定されたポートを有効にします。つまり、ポート80/tcpがpublicゾーンで解放されていることを意味します
[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: nodes
  tasks:
    - name: Allow port 80/tcp in the public zone
      ansible.posix.firewalld:
        zone: public
        permanent: yes
        immediate: yes
        port: 80/tcp
        state: enabled

playbookの実行前に、ターゲットノードで開放されているポート番号を確認します。TCPの80番ポートが開放されていないことが確認できます。なお、firewall-cmdの使い方はfirewall-cmdの使い方 - hana_shinのLinux技術ブログを参照してください。

[root@node1 ~]# firewall-cmd --list-ports

[root@node1 ~]#

playbookを実行します。

[root@control ~]# ansible-playbook -i hosts.ini test.yml

PLAY [Sample Playbook] *************************************************************************

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

TASK [Allow port 80/tcp in the public zone] ****************************************************
changed: [node1]

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

[root@control ~]#

playbookを実行すると、TCPの80番ポートが解放されたことが確認できます。

[root@node1 ~]# firewall-cmd --list-ports
80/tcp
[root@node1 ~]#

4.2 ポートをブロックする方法

playbookを作成します。このplaybookは、nodesグループ内のホストで、publicゾーンにおいてポート80/tcpを無効にします。設定は永続的(permanent: yes)かつ即時的(immediate: yes)に行われます。

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: nodes
  tasks:
    - name: Allow port 80/tcp in the public zone
      ansible.posix.firewalld:
        zone: public
        permanent: yes
        immediate: yes
        port: 80/tcp
        state: disabled

playbookの実行前にターゲットノードで解放されているポート番号を確認すると、TCPの80番ポートが開放されていることがわかります。

[root@node1 ~]# firewall-cmd --list-ports
80/tcp

playbookを実行します。

[root@control ~]# ansible-playbook -i hosts.ini test.yml

PLAY [Sample Playbook] *************************************************************************

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

TASK [Allow port 80/tcp in the public zone] ****************************************************
changed: [node1]

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

[root@control ~]#

playbookを実行すると、TCPの80番ポートがブロックされていることが確認できます。

[root@node1 ~]# firewall-cmd --list-ports

[root@node1 ~]#

5 firewalld_infoモジュールの使い方

firewalld_infoモジュールは、firewalldのルールに関する情報を取得するモジュールです。詳細は、ansible.posix.firewalld_info module – Gather information about firewalld — Ansible Community Documentationを参照してください。

5.1 全ての情報を取得する方法

playbookを作成します。このplaybookは、nodesグループ内のホストについて、firewalldのアクティブなゾーンに関する情報を取得し、その結果をresultに格納します。そして、取得した情報をdebugモジュールを使って表示します。なお、debugモジュールについては、Ansibleの使い方(デバッグ編) - hana_shinのLinux技術ブログを参照してください。

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: nodes
  tasks:
    - name: Gather information about active zones
      ansible.posix.firewalld_info:
        active_zones: true
      register: result
    - name: Display the result
      ansible.builtin.debug:
        var: result

playbookを実行すると、firewalldの各種情報が表示されることがわかります。

[root@control ~]# ansible-playbook -i hosts.ini test.yml

PLAY [Sample Playbook] ************************************************************************

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

TASK [Gather information about active zones] **************************************************
ok: [node1]

TASK [Display the result] *********************************************************************
ok: [node1] => {
    "result": {
        "active_zones": true,
        "changed": false,
        "collected_zones": [
            "public"
        ],
        "failed": false,
        "firewalld_info": {
            "default_zone": "public",
            "version": "1.2.1",
            "zones": {
                "public": {
                    "forward": true,
                    "forward_ports": [],
                    "icmp_block_inversion": false,
                    "icmp_blocks": [],
                    "interfaces": [
                        "enp1s0"
                    ],
                    "masquerade": false,
                    "ports": [],
                    "protocols": [],
                    "rich_rules": [],
                    "services": [
                        "ssh",
                        "dhcpv6-client",
                        "cockpit"
                    ],
                    "source_ports": [],
                    "sources": [],
                    "target": "default"
                }
            }
        },
        "undefined_zones": []
    }
}

PLAY RECAP ************************************************************************************
node1                      : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

[root@control ~]#

5.2 特定の情報を取得する方法

playbookを作成します。このplaybookは、nodesグループ内のホストで、firewalldのアクティブなゾーンに関する情報を取得し、その結果をresultに格納します。その後、firewalldのバージョン情報をdebugモジュールを使って表示します。

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: nodes
  tasks:
    - name: Gather information about active zones
      ansible.posix.firewalld_info:
        active_zones: true
      register: result
    - name: Display the result
      ansible.builtin.debug:
        var: result.firewalld_info.version

playbookを実行すると、firewalldのバージョンが1.2.1であることがわかります。

[root@control ~]# ansible-playbook -i hosts.ini test.yml

PLAY [Sample Playbook] ************************************************************************

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

TASK [Gather information about active zones] **************************************************
ok: [node1]

TASK [Display the result] *********************************************************************
ok: [node1] => {
    "result.firewalld_info.version": "1.2.1"
}

PLAY RECAP ************************************************************************************
node1                      : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

[root@control ~]#

6 sysctlモジュールの使い方

sysctlモジュールは、カーネルパラメータを操作するためのモジュールです。カーネルパラメータは/proc/sys/配下のファイルに保存されます。たとえば、IPフォワーディングの有効化または無効化を制御するカーネルパラメータは、/proc/sys/net/ipv4/ip_forwardファイルに保存されています。また、sysctlモジュールのsysctl_fileパラメータを使用すると、指定したファイルにカーネルパラメータを設定できます。詳細は、ansible.posix.sysctl module – Manage entries in sysctl.conf. — Ansible Community Documentationを参照してください。

6.1 ルーティングを有効にする方法

playbookを作成します。このplaybookは、nodesグループ内のホストで、カーネルパラメータのnet.ipv4.ip_forwardを1に設定します。これにより、IPフォワーディングが有効になります。なお、sysctlモジュールに渡すパラメータの意味は以下のとおりです。

パラメータ 意味
name カーネルパラメータの名前を指定します
value カーネルパラメータに設定する値を指定します。'1'はIPフォワーディングを有効にすることを意味します
sysctl_set trueに設定することで、システムファイルにカーネルパラメータの変更を永続的に反映します。OS再起動後も設定を保持します
state このタスクで扱うリソースの状態を指定します。presentは、指定されたカーネルパラメータが存在していること、または期待値に設定されていることを確認します
reload trueに設定することで、変更が適用された後に設定ファイルをリロードし、システムに変更を反映します
sysctl_file カーネルパラメータを保存するファイルのパスを指定します
[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: nodes
  tasks:
    - name: Set ip forwarding on in /proc and in the sysctl file and reload if necessary
      ansible.posix.sysctl:
        name: net.ipv4.ip_forward
        value: '1'
        sysctl_set: true
        state: present
        reload: true

playbookを実行する前に、ターゲットノードのip_forwardの値を確認すると、0であることがわかります。

[root@node1 ~]# sysctl -n net.ipv4.ip_forward
0

playbookを実行します。

[root@control ~]# ansible-playbook -i hosts.ini test.yml

PLAY [Sample Playbook] ************************************************************************

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

TASK [Set ip forwarding on in /proc and in the sysctl file and reload if necessary] ***********
changed: [node1]

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

[root@control ~]#

playbookを実行すると、ターゲットノードのip_forwardの値が1に変更されたことが確認できます。

[root@node1 ~]# sysctl -n net.ipv4.ip_forward
1

6.2 カーネルパニックを有効にする方法

playbookを作成します。このplaybookは、nodesグループ内のホストで、/etc/sysctl.d/10-test.confファイルのkernel.panicを1に設定します。

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: nodes
  tasks:
    - name: Set kernel.panic to 1 in /etc/sysctl.d/10-test.conf
      ansible.posix.sysctl:
        name: kernel.panic
        value: '1'
        sysctl_file: /etc/sysctl.d/10-test.conf

playbookを実行します。

[root@control ~]# ansible-playbook -i hosts.ini test.yml

PLAY [Sample Playbook] ************************************************************************

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

TASK [Set ip forwarding on in /proc and in the sysctl file and reload if necessary] ***********
changed: [node1]

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

[root@control ~]#

/etc/sysctl.d/10-test.confを確認すると、kernel.panicに1が設定されていることがわかります。

[root@node1 ~]# cat /etc/sysctl.d/10-test.conf
kernel.panic=1

7 atモジュールの使い方

atモジュールは、atコマンドを使ってコマンドやスクリプトファイルの実行をスケジュールするモジュールです。詳細は、ansible.posix.at module – Schedule the execution of a command or script file via the at command — Ansible Community Documentationを参照してください。

atモジュールを実行するためには、ターゲットノードにatコマンドがインストールされている必要があります。そのため、atパッケージを事前にインストールします。

[root@node1 ~]# dnf install at

playbookを作成します。

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: nodes
  tasks:
    - name: Get target node's time
      ansible.builtin.command:
        cmd: date
      register: node_time

    - name: Output target node's time to control node's stdout
      ansible.builtin.debug:
        msg: "Target node's time: {{ node_time.stdout }}"

    - name: Schedule a command using at module
      ansible.posix.at:
        command: echo "$(date)" > /tmp/time.txt
        count: 1
        units: minutes
      register: result

    - name:
      ansible.builtin.debug:
        msg: "Job scheduled with command: {{ result }}"

playbookを実行します。atモジュールを実行する直前のターゲットノードの時刻が21時38分13秒であることがわかります。

[root@control ~]# ansible-playbook -i hosts.ini test.yml

PLAY [Sample Playbook] ***********************************************************************

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

TASK [Get target node's time] ****************************************************************
changed: [node1]

TASK [Output target node's time to control node's stdout] ************************************
ok: [node1] => {
    "msg": "Target node's time: 2024年  4月 17日 水曜日 21:38:13 JST"
}

TASK [Schedule a command using at module] ****************************************************
changed: [node1]

TASK [ansible.builtin.debug] *****************************************************************
ok: [node1] => {
    "msg": "Job scheduled with command: {'changed': True, 'state': 'present', 'script_file': '/tmp/atyq_8mt9r', 'count': 1, 'units': 'minutes', 'failed': False}"
}

PLAY RECAP ***********************************************************************************
node1                      : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

[root@control ~]#

ターゲットノードでatqコマンドを実行します。echoコマンドが21時39分00秒に実行されることがわかります。

[root@node1 ~]# atq
22      Wed Apr 17 21:39:00 2024 a root

ファイルの中身を確認すると、echoコマンドが21時39分00秒に実行されたことがわかります。

[root@node1 ~]# cat /tmp/time.txt
2024年  4月 17日 水曜日 21:39:00 JST

8 selinuxモジュールの使い方

selinuxモジュールは、SELinuxのモードを変更するモジュールです。

ターゲットノードのSELinuxのモードをEnforcingに変更するPlaybookを作成します。

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: nodes
  tasks:
    - name: Enable SELinux
      ansible.posix.selinux:
        policy: targeted
        state: enforcing

Playbookを実行する前にターゲットノードでSELinuxのモードを確認すると、Permissiveであることがわかります。

[root@node1 ~]# getenforce
Permissive

playbookを実行します。

[root@control ~]# ansible-playbook -i hosts.ini test.yml

PLAY [Sample Playbook] ***********************************************************************

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

TASK [Enable SELinux] ************************************************************************
changed: [node1]

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

[root@control ~]#

Playbookを実行した後にターゲットノードでSELinuxのモードを確認すると、Enforcingに変更されたことがわかります。

[root@node1 ~]# getenforce
Enforcing