hana_shinのLinux技術ブログ

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

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



1 はじめに

本記事では、Ansibleのモジュールの使い方について説明します。モジュールとは、ターゲットノード(リモートホスト)で実行される操作を指します。モジュールを使用すると、ターゲットノード上でファイルの作成や削除などを行うことができます。なお、モジュールの一覧は以下を参照してください。
Ansible.Builtin — Ansible Core Documentation

2 検証環境

モジュールの動作検証をするための環境は以下のとおりです。

                 192.168.122.0/24
control ------------------------------------- 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

3 事前準備

3.1 Ansibleパッケージのインストール

Ansibleのパッケージはepel-releaseリポジトリにあるので、まずepel-releaseパッケージをインストールします。

[root@control ~]# dnf install epel-release

Ansibleパッケージをインストールします。

[root@control ~]# dnf install ansible

Ansibleの版数を確認します。

[root@control ~]# ansible --version
ansible [core 2.14.9]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.9/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.9.16 (main, Dec  8 2022, 00:00:00) [GCC 11.3.1 20221121 (Red Hat 11.3.1-4)] (/usr/bin/python3)
  jinja version = 3.1.2
  libyaml = True

3.2 公開鍵認証方法のセットアップ

Playbookを実行する際、コントロールノードからターゲットノードにSSHでログインします。ここでは、パスワード認証ではなく公開鍵認証を使用してログインします。以下では、公開鍵認証の設定方法を説明します。

コントロールノードで鍵ペアを作成します。秘密鍵が漏洩しても、秘密鍵が悪用されないようにするため、秘密鍵パスフレーズを設定します。なお、ssh-keygenコマンドの使い方は、ssh-keygenコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。

[root@control ~]# ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (/root/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_ed25519
Your public key has been saved in /root/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:CJCKkLdQN2qaLjyGsJEqp2LwVL7DI5148sKdnLq2yPo root@control
The key's randomart image is:
+--[ED25519 256]--+
| oo.o            |
|+ o+ .           |
|o+o..            |
|o=. .. .         |
|*  o  . S        |
|Bo. .            |
|BO.* =           |
|*=X &            |
|B+EX.o           |
+----[SHA256]-----+

ssh-keygenコマンドで作成した鍵ペアを確認します。公開鍵がid_ed25519.pub、秘密鍵がid_ed25519となります。

[root@control ~]# ls -l .ssh/id_ed25519*
-rw-------. 1 root root 444  2月 17 21:44 .ssh/id_ed25519
-rw-r--r--. 1 root root  94  2月 17 21:44 .ssh/id_ed25519.pub

ssh-copy-idコマンドを使って、公開鍵をターゲットノードの/root/.ssh/authorized_keysに追加します。

[root@control ~]# ssh-copy-id -i /root/.ssh/id_ed25519.pub root@192.168.122.220
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_ed25519.pub"
The authenticity of host '192.168.122.220 (192.168.122.220)' can't be established.
ED25519 key fingerprint is SHA256:qOFHEFGjbm/592tXQ75TCKUxXfHwTFx+wZisx5LN2uM.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.122.220's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.122.220'"
and check to make sure that only the key(s) you wanted were added.

authorized_keysファイルを確認します。公開鍵がauthorized_keysファイルに追記されたことがわかります。

[root@node1 ~]# cat .ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFlLtp0lJeI2sU28wTlCADMz4ol7iJZLNM0eciAS03dF root@control

3.3 パスフレーズ入力の省略

ターゲットノードにsshログインするたびにパスフレーズを入力するのは手間がかかります。そのため、SSHエージェントを使用して初回のみパスフレーズを入力し、その後はパスフレーズの入力を省略できるように設定します。

SSHエージェントを起動します。

[root@control ~]# eval "$(ssh-agent -s)"
Agent pid 1934

SSHエージェントが保持している秘密鍵のリストに新しい秘密鍵を追加します。パスフレーズを入力すると、これ以降のsshログインはパスワードなしでログインできるようになります。

[root@control ~]# ssh-add /root/.ssh/id_ed25519
Enter passphrase for /root/.ssh/id_ed25519:
Identity added: /root/.ssh/id_ed25519 (root@control)

コントロールノードにsshログインします。パスフレーズ入力せずに、ログインできることがわかります。

[root@control ~]# ssh 192.168.122.220
Last login: Thu Feb 22 21:11:54 2024 from 192.168.122.87

4 インベントリファイルの作成

管理対象となるサーバの一覧を記述したインベントリファイルを作成します。この後のモジュールの動作確認でも、このインベントリファイルを使用します。node1 はターゲットノードのホスト名であり、ansible_host はターゲットノードのIPアドレスを定義しています。

[root@control ~]# vi hosts.ini
[root@control ~]# cat hosts.ini
[nodes]
node1 ansible_host=192.168.122.220

5 fileモジュールの使い方

fileは、ファイルの作成、削除等を行うモジュールです。詳細は、ansible.builtin.file module -- Manage files and file properties — Ansible Core Documentationを参照してください。

5.1 ファイルを作成する方法

ファイルを作成するplaybookファイルを作成します。fileモジュールに対して、以下のパラメータを渡します。
・ファイル名(path: /tmp/test.txt)
・ファイル作成(state: touch)

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: nodes
  tasks:
    - name: Create file
      ansible.builtin.file:
        path: /tmp/test.txt
        state: touch

playbookを実行します。

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

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

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

TASK [Create file] *******************************************************************************************************
changed: [node1]

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

作成したファイルを確認します。

[root@node1 ~]# ls -l /tmp/test.txt
-rw-r--r--. 1 root root 0  2月 21 19:26 /tmp/test.txt

なお、モジュールに渡すパラメータは、以下のようにansible-docコマンドを使って調べることができます。

[root@control ~]# ansible-doc file
> ANSIBLE.BUILTIN.FILE    (/usr/lib/python3.9/site-packages/ansible/modules/file.py)

        Set attributes of files, directories, or symlinks and their targets.
        Alternatively, remove files, symlinks or directories. Many other modules
        support the same options as the `file' module - including
        [ansible.builtin.copy], [ansible.builtin.template], and
        [ansible.builtin.assemble]. For Windows targets, use the
        [ansible.windows.win_file] module instead.
-snip-

5.2 ファイルを削除する方法

ファイルを削除するplaybookファイルを作成します。fileモジュールに対して、以下のパラメータを渡します。
・ファイル名(path: /tmp/test.txt)
・ファイル削除(state: absent)

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Delete file
  hosts: nodes
  tasks:
    - name: Remove file
      ansible.builtin.file:
        path: /tmp/test.txt
        state: absent

playbookを実行します。

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

PLAY [Delete file] *******************************************************************************************************

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

TASK [Remove file] *******************************************************************************************************
changed: [node1]

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

[root@control ~]#

ファイルを確認します。ファイルが削除されたことがわかります。

[root@node1 ~]# ls -l /tmp/test.txt
ls: '/tmp/test.txt' にアクセスできません: そのようなファイルやディレクトリはありません

5.3 ディレクトリを作成する方法

ディレクトリを作成するplaybookファイルを作成します。fileモジュールに対して、以下のパラメータを渡します。
・作成するディレクトリのパス名(path: /tmp/test)
ディレクトリ作成(state: directory)
・アクセスモード(mode: '0600')

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: nodes
  tasks:
    - name: Create a directory if it does not exist
      ansible.builtin.file:
        path: /tmp/test
        state: directory
        mode: '0600'

playbook実行前に、ターゲットノードに/tmp/testディレクトリが存在しないことを確認します。

[root@node1 ~]# ls -ld /tmp/test
ls: '/tmp/test' にアクセスできません: そのようなファイルやディレクトリはありません

playbookを実行します。

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

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

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

TASK [Create a directory if it does not exist] ***************************************************************************
ok: [node1]

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

[root@control ~]#

playbookを実行すると、/tmp/testディレクトリが作成されたことがわかります。

[root@node1 ~]# ls -ld /tmp/test
drw-------. 2 root root 6  2月 18 20:27 /tmp/test

6 statモジュールの使い方

statは、ファイルやディレクトリの状態に関する情報を取得するためのモジュールです。
詳細は、ansible.builtin.stat module -- Retrieve file or file system status — Ansible Core Documentationを参照してください。

(1) 全ての情報を取得する方法
/etc/chrony.confの状態を取得するplaybookを作成します。

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: nodes
  tasks:
    - name: Check the status of /etc/chrony.conf
      ansible.builtin.stat:
        path: /etc/chrony.conf
      register: result

    - name: Display file information
      ansible.builtin.debug:
        var: result

playbookを実行します。ターゲットノードの/etc/chrony.confに関する様々な状態が取得できることがわかります。

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

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

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

TASK [Check the status of /etc/chrony.conf] *******************************************************
ok: [node1]

TASK [Display file information] *******************************************************************
ok: [node1] => {
    "result": {
        "changed": false,
        "failed": false,
        "stat": {
            "atime": 1709638065.1771483,
            "attr_flags": "",
            "attributes": [],
            "block_size": 4096,
            "blocks": 8,
            "charset": "us-ascii",
            "checksum": "4acaa3c2b1957b7fee0d60a5c9d9137ed4ef85fc",
            "ctime": 1703065758.2565594,
            "dev": 64771,
            "device_type": 0,
            "executable": false,
            "exists": true,
            "gid": 0,
            "gr_name": "root",
            "inode": 34489641,
            "isblk": false,
            "ischr": false,
            "isdir": false,
            "isfifo": false,
            "isgid": false,
            "islnk": false,
            "isreg": true,
            "issock": false,
            "isuid": false,
            "mimetype": "text/plain",
            "mode": "0644",
            "mtime": 1661778273.0,
            "nlink": 1,
            "path": "/etc/chrony.conf",
            "pw_name": "root",
            "readable": true,
            "rgrp": true,
            "roth": true,
            "rusr": true,
            "size": 1374,
            "uid": 0,
            "version": "1460430642",
            "wgrp": false,
            "woth": false,
            "writeable": true,
            "wusr": true,
            "xgrp": false,
            "xoth": false,
            "xusr": false
        }
    }
}

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

[root@control ~]#

(2) 特定の情報を取得する方法
次は、/etc/chrony.confの実行権限を取得するplaybookを作成します。

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: nodes
  tasks:
    - name: Check the status of /etc/chrony.conf
      ansible.builtin.stat:
        path: /etc/chrony.conf
      register: result

    - name: Display file information
      ansible.builtin.debug:
        var: result.stat.mode

playbookを実行すると、/etc/chrony.confの実行権限が0644であることがわかります。

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

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

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

TASK [Check the status of /etc/chrony.conf] *******************************************************
ok: [node1]

TASK [Display file information] *******************************************************************
ok: [node1] => {
    "result.stat.mode": "0644"
}

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

[root@control ~]#

ターゲットノードでstatコマンドを実行します。/etc/chrony.confの実行権限が0644であることがわかります。

[root@node1 ~]# stat /etc/chrony.conf
  File: /etc/chrony.conf
  Size: 1374            Blocks: 8          IO Block: 4096   通常ファイル
Device: fd03h/64771d    Inode: 34489641    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: system_u:object_r:etc_t:s0
Access: 2024-02-25 20:44:07.805680323 +0900
Modify: 2022-08-29 22:04:33.000000000 +0900
Change: 2023-12-20 18:49:18.256559259 +0900
 Birth: 2023-12-20 18:49:18.255559249 +0900

7 copyモジュールの使い方

copyは、ローカルマシンからリモートマシンにファイルを転送したり(デフォルトの動作)、リモートマシン内でファイルをコピーするモジュールです。ここでは、remote_srcパラメータの動作確認をしてみます。詳細は、ansible.builtin.copy module -- Copy files to remote locations — Ansible Core Documentationを参照してください。

(1) 事前準備
ローカルマシン(コントロールノード)でテスト用のファイルを作成します。

[root@control ~]# vi /root/test.txt
[root@control ~]# cat /root/test.txt
This is a control node.

リモートマシン(ターゲットノード)でテスト用のファイルを作成します。

[root@node1 ~]# vi /root/test.txt
[root@node1 ~]# cat /root/test.txt
This is a managed node.

(2) 動作確認(ローカルマシンからリモートマシンにファイルの転送を確認する)
ファイルを転送するplaybookファイルを作成します。copyモジュールに対して、以下のパラメータを渡します。remote_srcパラメータはplaybookファイルに記載していないので、デフォルトのfalseとして動作します。わかりやすくするため、明にremote_src: falseと記載してもよいです。
・ファイルのコピー元(src: /root/test.txt)
・ファイルのコピー先(dest: /tmp/)

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: node1
  tasks:
    - name: Copy file with permissions
      ansible.builtin.copy:
        src: /root/test.txt
        dest: /tmp/

playbookを実行します。

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

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

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

TASK [Copy file with permissions] ******************************************************************************************
ok: [192.168.122.220]

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

[root@control ~]#

リモートマシン(ターゲットノード)でファイルの内容を確認します。デフォルトは、ローカルマシンからリモートマシンにファイルを転送するので、test.txtファイルの内容が"This is a control node."となっていることがわかります。

[root@node1 ~]# cat /tmp/test.txt
This is a control node.

(3) 動作確認(リモートマシン内でファイルのコピーを確認する)
ファイルを転送するplaybookファイルを作成します。copyモジュールに対して、以下のパラメータを渡します。remote_srcパラメータにtrueと指定したので、ファイルのコピー元は、リモートマシンとなります。
・ファイルのコピー元(src: /root/test.txt)
・ファイルのコピー先(dest: /tmp/)
・ファイルのコピー元の指定(remote_src: true)

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: node1
  tasks:
    - name: Copy file with permissions
      ansible.builtin.copy:
        src: /root/test.txt
        dest: /tmp/
        remote_src: true

playbookを実行します。

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

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

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

TASK [Copy file with permissions] ******************************************************************************************
changed: [192.168.122.220]

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

[root@control ~]#

リモートマシン(ターゲットノード)でファイルの内容を確認します。リモートマシン内でファイルを転送するので、test.txtファイルの内容が"This is a managed node."となっていることがわかります。

[root@node1 ~]# cat /tmp/test.txt
This is a managed node.

8 unarchiveモジュールの使い方

unarchiveは、アーカイブファイルを展開するモジュールです。詳細は、
ansible.builtin.unarchive module -- Unpacks an archive after (optionally) copying it from the local machine — Ansible Core Documentationを参照してください。

アーカイブの展開方法として次の2つの動作確認をします。

方法 内容
その1 ローカルマシン(コントロールノード)にアーカイブファイルをダウンロード。それをリモートマシン(ターゲットノード)に転送して展開
その2 リモートマシン(ターゲットノード)にアーカイブファイルをダウンロードして展開

8.1 その1

事前準備として、ローカルマシン(コントロールノード)にhttpd-2.4.58.tar.gzをダウンロードします。

[root@control ~]# wget -P /root https://dlcdn.apache.org/httpd/httpd-2.4.58.tar.gz

ダウンロードしたファイルを確認します。

[root@control ~]# ls -l httpd-2.4.58.tar.gz
-rw-r--r--. 1 root root 9825177 10月 19 18:09 httpd-2.4.58.tar.gz

アーカイブファイルを展開するplaybookファイルを作成します。unarchiveモジュールに対して、以下のパラメータを渡します。
アーカイブファイルの格納ディレクトリ(/root/httpd-2.4.58.tar.gz)
アーカイブファイルの展開先ディレクトリ(dest: /tmp)

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: node1
  tasks:
    - name: Unarchive httpd-2.4.58.tar.gz to /tmp
      ansible.builtin.unarchive:
        src: /root/httpd-2.4.58.tar.gz
        dest: /tmp
        remote_src: false

playbookを実行する前に、リモートマシン(ターゲットノード)にhttpdディレクトリが存在しないことを確認します。

[root@node1 ~]# ls -ld /tmp/httpd*
ls: '/tmp/httpd*' にアクセスできません: そのようなファイルやディレクトリはありません

playbookを実行します。

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

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

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

TASK [Unarchive httpd-2.4.58.tar.gz to /tmp] *******************************************************************************
changed: [192.168.122.220]

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

[root@control ~]#

playbookを実行したあと、/tmp配下を確認すると、httpd-2.4.58ディレクトリが作成されたことがわかります。

[root@node1 ~]# ls -ld /tmp/httpd*
drwxr-xr-x. 13 504 games 4096 10月 17 00:06 /tmp/httpd-2.4.58

次の動作検証をするため、作成したディレクトリを削除します。

[root@node1 ~]# rm -fr /tmp/httpd-2.4.58/
[root@node1 ~]# ls -ld /tmp/httpd*
ls: '/tmp/httpd*' にアクセスできません: そのようなファイルやディレクトリはありません

8.2 その2

リモートマシン(ターゲットノード)でアーカイブファイルを展開するplaybookファイルを作成します。unarchiveモジュールに対して、以下のパラメータを渡します。
アーカイブの格納ディレクトリ(src: https://dlcdn.apache.org/httpd/httpd-2.4.58.tar.gz)
アーカイブの展開先ディレクトリ(dest: /tmp)
アーカイブファイルの展開場所(emote_src: true)

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: node1
  tasks:
    - name: Unarchive httpd-2.4.58.tar.gz to /tmp
      ansible.builtin.unarchive:
        src: https://dlcdn.apache.org/httpd/httpd-2.4.58.tar.gz
        dest: /tmp
        remote_src: true

playbookを実行します。

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

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

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

TASK [Unarchive httpd-2.4.58.tar.gz to /tmp] *******************************************************************************
changed: [192.168.122.220]

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

[root@control ~]#

playbookを実行したあと、リモートマシン(ターゲットノード)で/tmp配下を確認すると、httpd-2.4.58ディレクトリが作成されたことがわかります。

[root@node1 ~]# ls -ld /tmp/httpd*
drwxr-xr-x. 13 504 games 4096 10月 17 00:06 /tmp/httpd-2.4.58

9 userモジュールの使い方

userは、ユーザの追加・削除等を行うモジュールです。詳細は、ansible.builtin.user module -- Manage user accounts — Ansible Core Documentation

9.1 ユーザを追加する方法

UID=2000のユーザ(user1)を追加するplaybookファイルを作成します。
userモジュールに対して、以下のパラメータを渡します。
・ユーザ名(name: user1)
・passwdファイルに記載するコメント(comment: test)
・ユーザID(uid: 2000)

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: node1
  tasks:
    - name: Add the user 'user1' with a specific uid.
      ansible.builtin.user:
        name: user1
        comment: test comment
        uid: 2000

playbookを実行します。

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

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

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

TASK [Add the user 'user1' with a specific uid.] *****************************************************************
ok: [192.168.122.220]

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

[root@control ~]#

ターゲットノードでユーザを確認します。UID=2000のuser1が追加されたことがわかります。

[root@node1 ~]# grep user1 /etc/passwd
user1:x:2000:2000:test comment:/home/user1:/bin/bash

9.2 ユーザを削除する方法

ユーザ(user1)を削除するplaybookファイルを作成します。
userモジュールに対して、以下のパラメータを渡します。
・ユーザ名(name: user1)
・ユーザの削除(state: absent)

[root@control ~]# vi test.yml
[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: node1
  tasks:
    - name: Remove the user 'user1'.
      ansible.builtin.user:
        name: user1
        state: absent

playbookを実行します。

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

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

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

TASK [Remove the user 'user1'.] **********************************************************************************
ok: [192.168.122.220]

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

[root@control ~]#

ターゲットノードでユーザを確認します。user1が削除されたことがわかります。

[root@node1 ~]# grep user1 /etc/passwd
[root@node1 ~]#

10 dnfモジュールの使い方

dnfは、パッケージのインストールやアンインストールをするモジュールです。詳細は、ansible.builtin.dnf module -- Manages packages with the dnf package manager — Ansible Core Documentationを参照してください。

10.1 パッケージをインストールする方法

最新のhttpdパッケージをインストールするplaybookファイルを作成します。
dnfモジュールに対して、以下のパラメータを渡します。
・パッケージ名(name: httpd)
・最新パッケージのインストール(state: latest)

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: node1
  tasks:
    - name: Install the latest version of Apache
      ansible.builtin.dnf:
        name: httpd
        state: latest

playbookを実行します。

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

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

TASK [Gathering Facts] **************************************************************************************************
Enter passphrase for key '/root/.ssh/id_ed25519':
ok: [192.168.122.220]

TASK [Install the latest version of Apache] *****************************************************************************
changed: [192.168.122.220]

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

[root@control ~]#

ターゲットノードでパッケージを確認します。httpdパッケージがインストールされたことが確認できます。

[root@node1 ~]# rpm -qa|grep httpd-2
httpd-2.4.57-5.el9.x86_64

10.2 パッケージをアンインストールする方法

httpdパッケージをアンインストールするplaybookファイルを作成します。
dnfモジュールに対して、以下のパラメータを渡します。
・パッケージ名(name: httpd)
・パッケージの削除(state: absent)

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: node1
  tasks:
    - name: Remove the Apache package
      ansible.builtin.dnf:
        name: httpd
        state: absent

playbookを実行します。

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

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

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

TASK [Remove the Apache package] ****************************************************************************************
changed: [192.168.122.220]

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

[root@control ~]#

ターゲットノードでパッケージを確認します。httpdパッケージが削除されたことがわかります。

[root@node1 ~]# rpm -qa|grep httpd-2
[root@node1 ~]#

11 serviceモジュールの使い方

serviceは、サービスの起動・停止等をおこなうモジュールです。詳細は、ansible.builtin.service module -- Manage services — Ansible Core Documentationを参照してください。

11.1 サービスを起動・停止する方法

httpdパッケージをインストールしたあと、httpdサービスを起動するplaybookファイルを作成します。
serviceモジュールに対して、以下のパラメータを渡します。
・パッケージ名(name: httpd)
・サービスの状態(state: started)

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: node1
  tasks:
    - name: Install httpd package
      ansible.builtin.dnf:
        name: httpd
        state: latest

    - name: Start service httpd, if not started
      ansible.builtin.service:
        name: httpd
        state: started

playbookを実行します。

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

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

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

TASK [Install httpd package] *************************************************************************************
ok: [192.168.122.220]

TASK [Start service httpd, if not started] ***********************************************************************
ok: [192.168.122.220]

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

ターゲットノードでhttpdサービスの状態を確認すると、active になっていることがわかります。

[root@node1 ~]# systemctl status httpd
● httpd.service - The Apache HTTP Server
     Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; preset: disabled)
     Active: active (running) since Tue 2024-02-20 20:32:26 JST; 12min ago
       Docs: man:httpd.service(8)
   Main PID: 3874 (httpd)
     Status: "Total requests: 0; Idle/Busy workers 100/0;Requests/sec: 0; Bytes served/sec:   0 B/sec"
      Tasks: 213 (limit: 23186)
     Memory: 29.2M
        CPU: 1.489s
     CGroup: /system.slice/httpd.service
             tq3874 /usr/sbin/httpd -DFOREGROUND
             tq3875 /usr/sbin/httpd -DFOREGROUND
             tq3876 /usr/sbin/httpd -DFOREGROUND
             tq3877 /usr/sbin/httpd -DFOREGROUND
             mq3878 /usr/sbin/httpd -DFOREGROUND

 2月 20 20:32:26 node1 systemd[1]: Starting The Apache HTTP Server...
 2月 20 20:32:26 node1 httpd[3874]: AH00558: httpd: Could not reliably determine the server's fully qualif>
 2月 20 20:32:26 node1 httpd[3874]: Server configured, listening on: port 80
 2月 20 20:32:26 node1 systemd[1]: Started The Apache HTTP Server.

11.2 サービスの自動起動を有効/無効にする方法

ターゲットノードでhttpdサービスの自動起動の状態を確認します。自動起動は無効になっていることがわかります。

[root@node1 ~]# systemctl is-enabled httpd
disabled

httpdサービスの自動起動を有効にするplaybookファイルを作成します。
serviceモジュールに対して、以下のパラメータを渡します。
・パッケージ名(name: httpd)
自動起動の指定(enabled: true)

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: node1
  tasks:
    - name: Enable auto-start
      ansible.builtin.service:
        name: httpd
        enabled: true

playbookを実行します。

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

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

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

TASK [Enable auto-start] *****************************************************************************************
changed: [192.168.122.220]

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

[root@control ~]#

ターゲットノードでhttpdサービスの自動起動が有効になったことがわかります。

[root@node1 ~]# systemctl is-enabled httpd
enabled

12 get_urlモジュールの使い方

get_urlは、リモートサーバから、HTTP, HTTPS, FTPを使ってファイルをダウンロードするモジュールです。詳細は、ansible.builtin.get_url module -- Downloads files from HTTP, HTTPS, or FTP to node — Ansible Core Documentationを参照してください。

12.1 ファイルをダウンロードする方法

Apache のWebサーバからhttpd-2.4.58.tar.gzをダウンロードするplaybookファイルを作成します。
https://httpd.apache.org/download.cgi#apache24

get_urlモジュールに対して、以下のパラメータを渡します。
・URL(url: https://dlcdn.apache.org/httpd/httpd-2.4.58.tar.gz)
・ダウンロードするファイルを格納するパス(dest: /tmp/)
・ダウンロードしたファイルに付与する実行権(mode: '0444')

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: node1
  tasks:
    - name: Download httpd-2.4.58.tar.gz from Apache web server.
      ansible.builtin.get_url:
        url: https://dlcdn.apache.org/httpd/httpd-2.4.58.tar.gz
        dest: /tmp/
        mode: '0444'

playbookを実行します。

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

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

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

TASK [Download httpd-2.4.58.tar.gz from Apache web server.] *************************************************************
changed: [192.168.122.220]

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

[root@control ~]#

ターゲットノードでダウンロードしたファイル名、実行権を確認します。

[root@node1 ~]# ls -l /tmp/httpd-2.4.58.tar.gz
-r--r--r--. 1 root root 9825177  2月 19 21:28 /tmp/httpd-2.4.58.tar.gz

12.2 ダウンロードするファイルのチェックサムを実行する方法

12.2.1 正しいチェックサムファイルを指定した場合
[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: node1
  tasks:
    - name: Download file with checksum url (sha256)
      ansible.builtin.get_url:
        url: https://dlcdn.apache.org/httpd/httpd-2.4.58.tar.gz
        dest: /tmp/
        checksum: sha256:https://downloads.apache.org/httpd/httpd-2.4.58.tar.gz.sha256

playbookを実行します。

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

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

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

TASK [Download file with checksum url (sha256)] *************************************************************************
ok: [192.168.122.220]

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

[root@control ~]#
12.2.2 誤ったチェックサムファイルを指定した場合

checksumパラメータに対して、誤ったチェックサムを指定したplaybookを作成します。

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: node1
  tasks:
    - name: Download file with checksum url (sha256)
      ansible.builtin.get_url:
        url: https://dlcdn.apache.org/httpd/httpd-2.4.58.tar.gz
        dest: /tmp/
        checksum: sha256:https://downloads.apache.org/httpd/httpd-2.4.58.tar.gz.sha512

誤ったチェックサムファイルを指定すると、以下のようにエラー(failed=1)となります。

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

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

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

TASK [Download file with checksum url (sha256)] *************************************************************************
fatal: [192.168.122.220]: FAILED! => {"changed": true, "checksum_dest": null, "checksum_src": "cd04721a2d9abfc634c895853cd555ac659b81e8", "dest": "/tmp/httpd-2.4.58.tar.gz", "elapsed": 1, "msg": "The checksum for /tmp/httpd-2.4.58.tar.gz did not match 5c11faf0572035ef67b27775d975999411c689cb774553175299a9e99b63d3d7138b0c7f15048ec28038494d8513689f916202c2289d557947d8b190d46ca9f3; it was 503a7da4a4a27fd496037998b17078dc9fe004db32c657c96cce8356b8aa2eb6.", "src": "/root/.ansible/tmp/ansible-tmp-1708347415.2509441-1783-155710284696734/tmpvfp67ljr", "url": "https://dlcdn.apache.org/httpd/httpd-2.4.58.tar.gz"}

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

[root@control ~]#

13 commandモジュールの使い方

commandは、対象ホストでコマンドを実行するモジュールです。詳細は、ansible.builtin.command module -- Execute commands on targets — Ansible Core Documentationを参照してください。

次の内容のplaybookファイルを作成します。commandモジュールに対してhostnameコマンドをパラメータとして渡し、registerディレクティブを使ってhostnameコマンドの実行結果をvar_hostname変数に格納します。そして、debugモジュールを使って、var_hostname変数に保存されている内容を標準出力に出力します。

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: node1
  tasks:
    - name: Execute the hostname command
      ansible.builtin.command:
        cmd: hostname
      register: var_hostname
    - name: Display hostname command result
      ansible.builtin.debug:
        var: var_hostname.stdout

playbookを実行すると、ターゲットノードのホスト名(node1)が表示されていることがわかります。

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

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

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

TASK [Execute the hostname command] *******************************************************
changed: [192.168.122.220]

TASK [Display hostname command result] ****************************************************
ok: [192.168.122.220] => {
    "var_hostname.stdout": "node1"
}

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

[root@control ~]#

14 scriptモジュールの使い方

scriptは、ローカルマシン(コントロールノード)のスクリプトをリモートマシン(ターゲットノード)に転送して実行するモジュールです。詳細は、ansible.builtin.script module -- Runs a local script on a remote node after transferring it — Ansible Core Documentationを参照してください。

(1) 事前準備
ホスト名を表示するスクリプトをローカルマシン(コントロールノード)で作成します。

[root@control ~]# vi /tmp/test.sh
[root@control ~]# cat /tmp/test.sh
#!/usr/bin/bash
hostname

(2) 動作確認
playbookファイルを作成します。

[root@control ~]# vi test.yml
[root@control ~]# cat test.yml
- name: Sample Playbook
  hosts: node1
  tasks:
    - name: Run a script
      ansible.builtin.script:
        cmd: /tmp/test.sh
      register: var_hostname
    - name: Display hostname command result
      ansible.builtin.debug:
        var: var_hostname.stdout

playbookを実行すると、ターゲットノードのホスト名(node1)が表示されていることがわかります。

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

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

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

TASK [Run a script] ***********************************************************************
changed: [192.168.122.220]

TASK [Display hostname command result] ****************************************************
ok: [192.168.122.220] => {
    "var_hostname.stdout": "node1\r\n"
}

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

[root@control ~]#