AnsibleのインストールからPlaybookの実行まで

# はじめに
この記事は、Ansibleを使ったことがない方や初心者の方向けに、AnsibleのインストールからPlaybook実行までの流れが把握できるようシンプルな手順を説明しています(手順はOSがRed Hat Enterprise Linux (RHEL)8.8前提で記載しています)。

# 環境準備
VMを2台、以下の表の通り用意します。
コントロールノードでは管理対象ノードのホスト名`managed_node01`の名前解決ができるようになっています。

|  役割  |  ホスト名  |  OS  |
| ---- | ---- | ---- |
|コントロールノード|  control_node  |  Red Hat Enterprise Linux (RHEL) 8.8 |
|管理対象ノード|  managed_node01  |  Red Hat Enterprise Linux (RHEL) 8.8  |

# SSH接続
SSHでコントロールノードから管理対象ノードへ接続できる必要があります。
今回はSSHの認証方式として公開鍵認証を使用します。

コントロールノードで公開鍵と秘密鍵を生成します。

``` shell-session
[root@control_node ~]# ssh-keygen -h
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): /root/.ssh/id_rsa_ansible
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa_ansible.
Your public key has been saved in /root/.ssh/id_rsa_ansible.pub.
The key fingerprint is:
SHA256:Ps7Kf9hLltIBJCYaUMAoYPKRQc8qLOhvgbRkNtg2k30 root@control_node
The key's randomart image is:
+---[RSA 3072]----+
|O**o. o .        |
|=o.* o o         |
|o.ooo   .        |
|+**.. E  .       |
|Oo=o .  S .      |
|o+ .   . . o     |
| .  .   +o=      |
|  .. . o.=o      |
|  ..  oo+...     |
+----[SHA256]-----+
```

そして管理対象ノードへSSH公開鍵の登録を行います。
`-i`オプションで生成された公開鍵を指定します。

``` shell-session
[root@control_node ~]# ssh-copy-id -i /root/.ssh/id_rsa_ansible.pub  root@managed_node01
```

# Ansible インストール
コントロールノードにAnsibleをインストールしていきます。
2024年3月時点のドキュメント最新版で記載されているインストール方法の1つであるpipを用いたインストールを行います。
https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#installing-and-upgrading-ansible-with-pip

まずPythonのインストールをします。
``` shell-session
[root@control_node ~]# dnf install python3.11
```

以下のコマンドで、デフォルトで使用するPythonを設定します。
今回インストールしたpython 3.11を使用するよう該当の番号を入力します。

``` shell-session
[root@control_node ~]# alternatives --config python

There are 3 programs which provide 'python'.

  Selection    Command
-----------------------------------------------
*+ 1           /usr/libexec/no-python
   2           /usr/bin/python3
   3           /usr/bin/python3.11

Enter to keep the current selection[+], or type selection number: 3
```

pythonコマンドが使用できることを確認します。

``` shell-session
[root@control_node ~]# python -V
Python 3.11.5
```

次にpipをインストールします。

``` shell-session
[root@control_node ~]# dnf install python3.11-pip
```

pipコマンドが使用できることを確認します。

``` shell-session
[root@control_node ~]# python -m pip -V
pip 22.3.1 from /usr/lib/python3.11/site-packages/pip (python 3.11)
```

Ansibleを以下のコマンドでインストールします。

``` shell-session
[root@control_node ~]# python -m pip install --user ansible
```

以下のコマンドを実行し、ansibleのコマンドが使えるようにパスを通します。(または`~/.bash_profile`等に記載して環境変数を永続化してください)

``` shell-session
[root@control_node ~]# export PATH=$PATH:/root/.local/bin
```

ansibleコマンドが実行できることを確認します。

``` shell-session
[root@control_node ~]# ansible --version
ansible [core 2.16.3]
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /root/.local/lib/python3.11/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /root/.local/bin/ansible
  python version = 3.11.5 (main, Sep 22 2023, 15:34:29) [GCC 8.5.0 20210514 (Red Hat 8.5.0-20)] (/usr/bin/python)
  jinja version = 3.1.3
  libyaml = True
  ```

Ansibleのインストールは以上です。


# Playbookの実行
これから作成する`inventory`、`ansible.cfg`、`Playbook.yaml`は同じ任意のディレクトリに配置します。

まずは管理対象サーバーを記載するインベントリーを作成します。
今回、`managed_node01`のグループは`servers`としました。
`servers`グループの変数として、管理対象ノードでのansibleの実行ユーザーとssh接続時の秘密鍵を設定しています。

```config:inventory
[servers]
managed_node01
[servers:vars]
ansible_user=root
ansible_ssh_private_key_file="/root/.ssh/id_rsa_ansible"
```

この構成ファイルによって全てのホストが特定できることを確認します。

``` shell-session
[root@control_node ~]# ansible all --list-hosts -i inventory
  hosts (1):
    managed_node01
```

以下のコマンドでは、`servers`グループにあるホストを表示します。

```
[root@control_node ~]# ansible servers --list-hosts -i inventory
  hosts (1):
    managed_node01
```
こちらの設定は任意ですが、`ansible.cfg`を作成し、ホストキーチェック無効を記載することで、新しいホストが「known_hosts」にない場合でも鍵の確認が求められなくなります。

```config:ansible.cfg
[defaults]
host_key_checking=false
```

以下のコマンドで、利用可能なモジュールの一覧を確認できます。
次の手順で使用するpingモジュールもここで見れます。

``` shell-session
[root@control_node ~]# ansible-doc -l
```

ping モジュールを使用するアドホックコマンドで、全てのホストが稼働していることを確認します。
SUCCESSが返ってきたことがわかります。

``` shell-session
[root@control_node ~]# ansible all -m ping -i inventory
managed_node01 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
```

今回は、httpdをインストールして起動するPlaybookを以下の通り記述します。
`hosts`には実行対象のグループである`servers`を指定します。
`tasks`にはhttpdのインストールと起動をするタスクをそれぞれ記載しています。

```config:playbook.yaml
---
- hosts: servers
  tasks:
  - name: install httpd
    dnf:
      name: httpd
      state: latest

  - name: run httpd
    service:
      name: httpd
      state: started
      enabled: yes
```

以下のコマンドで、Playbookを実行します。
`PLAY RECAP`には実行結果のサマリーが表示され、問題なく実行できたことがわかります。

``` shell-session
[root@control_node ~]# ansible-playbook playbook.yaml -i inventory

PLAY [servers] ************************************************************************************************************************************************************************************************************************************************************************************

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

TASK [install httpd] ******************************************************************************************************************************************************************************************************************************************************************************
changed: [managed_node01]

TASK [run httpd] **********************************************************************************************************************************************************************************************************************************************************************************
changed: [managed_node01]

PLAY RECAP ****************************************************************************************************************************************************************************************************************************************************************************************
managed_node01      : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```

管理対象ノードを見るとhttpdのプロセスがたしかに存在することがわかります。

``` shell-session
[root@managed_node01 ~]# ps -ef | grep httpd |  grep -v grep
root       12687       1  0 01:37 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache     12782   12687  0 01:37 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache     12802   12687  0 01:37 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache     12803   12687  0 01:37 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache     12804   12687  0 01:37 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
```

以下のコマンドで、httpdがサービスとして起動していることを確認できます。

``` shell-session
[root@managed_node01 ~]# systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Wed 2024-02-14 01:37:33 PST; 2min 11s ago
     Docs: man:httpd.service(8)
 Main PID: 12687 (httpd)
   Status: "Running, listening on: port 80"
    Tasks: 213 (limit: 23221)
   Memory: 34.2M
   CGroup: /system.slice/httpd.service
           ├─12687 /usr/sbin/httpd -DFOREGROUND
           ├─12782 /usr/sbin/httpd -DFOREGROUND
           ├─12802 /usr/sbin/httpd -DFOREGROUND
           ├─12803 /usr/sbin/httpd -DFOREGROUND
           └─12804 /usr/sbin/httpd -DFOREGROUND

Feb 14 01:37:33 managed_node01 systemd[1]: Starting The Apache HTTP Server...
Feb 14 01:37:33 managed_node01 systemd[1]: Started The Apache HTTP Server.
Feb 14 01:37:33 managed_node01 httpd[12687]: Server configured, listening on: port 80
```

以上の流れでPlaybook実行までを試してみることができます。