Ansible入門①：環境準備編

## 概要
CloudFormationテンプレートを利用してAnsibleの検証環境を構築し、Ansible Masterサーバから各ターゲットサーバ（Ansible_Dev_Target1、Ansible_Dev_Target2、Ansible_Test_Target1、Ansible_Test_Target2）に対してpingモジュールで疎通確認を行うまでの手順を作成しました。


---

## 1. CloudFormationテンプレートの構成

### 1.1 ネットワーク構成

```
# VPC設定
VPC: 10.0.0.0/16 (Ansible-VPC)
  └── PublicSubnet: 10.0.1.0/24 (eu-west-2の最初のAZ)
        ├── Ansible_Master (10.0.1.100, Public IPあり)
        ├── Ansible_Dev_Target1 (10.0.1.101, Public IPあり)
        ├── Ansible_Dev_Target2 (10.0.1.102, Public IPあり)
        ├── Ansible_Test_Target1 (10.0.1.103, Public IPあり)
        └── Ansible_Test_Target2 (10.0.1.104, Public IPあり)
```
- すべてのインスタンスは同じパブリックサブネット（10.0.1.0/24）に配置され、パブリックIPが割り当てられます
- インターネットゲートウェイとルートテーブルにより、インターネットアクセスが可能です

### 1.2 セキュリティ設定
- **AnsibleTargetSG**: ターゲットサーバ専用セキュリティグループ
  - SSH (TCP:22): 10.0.1.100/32（Ansible_Masterからのみ許可）
  - ICMP: 10.0.1.100/32（ping疎通確認用）
- **AnsibleMasterSG**: Masterサーバ専用セキュリティグループ
  - すべてのアウトバウンド通信を許可（インターネットアクセスやSSM通信用）
  - インバウンド通信はデフォルトで許可されていません（外部からの直接アクセスはできません）
### 1.3 IAM設定
- **AnsibleMasterSSMRole**: Masterサーバ用IAMロール
  - 管理ポリシー: `AmazonSSMManagedInstanceCore`をMasterサーバからssm接続するためにアタッチしています

### 1.4 EC2インスタンス構成

| インスタンス名           | プライベートIP   | 用途             | サブネット         | セキュリティグループ   | Public IP |
|--------------------------|------------------|------------------|--------------------|------------------------|-----------|
| Ansible_Master           | 10.0.1.100       | Ansibleコントローラ | PublicSubnet        | AnsibleMasterSG        | あり      |
| Ansible_Dev_Target1      | 10.0.1.101       | 開発環境1         | PublicSubnet        | AnsibleTargetSG        | あり      |
| Ansible_Dev_Target2      | 10.0.1.102       | 開発環境2         | PublicSubnet        | AnsibleTargetSG        | あり      |
| Ansible_Test_Target1     | 10.0.1.103       | テスト環境1       | PublicSubnet        | AnsibleTargetSG        | あり      |
| Ansible_Test_Target2     | 10.0.1.104       | テスト環境2       | PublicSubnet        | AnsibleTargetSG        | あり      |

- すべてのインスタンスはRed Hat Enterprise Linux 10（例: ami-05f861f26432a5eed）を利用します
- MasterサーバにはSSM Agentのインストール・有効化をUserDataで自動実行します
- すべてのインスタンスにKeyPairNameパラメータで指定したキーペアが割り当てられます(別途マネコンでキーペアを作成します。)
- MasterサーバのみにIAMロール（SSM用）がアタッチされます

---

## 2. 環境構築手順

### 2.1 CloudFormationスタックのデプロイ

1. **GitHubからテンプレートをダウンロード**  
   [ansible_gakusyuu_Cfn_ssm.yaml](https://github.com/super-masaya/ansible-gakusyuu/blob/main/ansible_gakusyuu_Cfn_ssm.yaml) をダウンロードし、ローカルPCに保存します。

2. **AWSマネジメントコンソールでCloudFormationスタックを作成**
   1. AWSマネジメントコンソールにログインし、リージョンをロンドン:eu-west-2 に切り替えてください　(筆者の気まぐれでロンドンリージョン用にCfnテンプレートを作成したため)
   2. EC２サービスを開き、左側メニューの「キーペア」をクリックし、「キーペアの作成」を選択します。
   3. 以下の情報を入力して「キーペアの作成」をクリックします。
   3. - 名前: ansible-test(任意の名前)
      - キーペアのタイプ: RSA
      - プライベートキーファイルの形式: .pem
      ※pemファイルは後ほど使用するので大切に保管してください。
![ansible02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4077172/57abc8c9-ab32-4089-bb24-f9e8e9b25e75.png)
![ansible03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4077172/199f9694-bb67-40fe-9914-d42e620aaf66.png)



   4. CloudFormationサービスを開きます。
   5. 「スタック」→「スタックの作成」を選択します。

![ansible04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4077172/118640d4-cf90-44c5-b682-9e1087bedf02.png)


   6. 「既存のテンプレートを選択」を選び、「テンプレートファイルのアップロード」を選択します。

   7. 「ファイルの選択」ボタンで `ansible_gakusyuu_Cfn_ssm.yaml` を選択します。
![ansible06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4077172/6a3562bd-19be-4ab9-bd88-961792fe0daa.png)


   8. 「次へ」をクリックし、スタック名（例: Ansible）とKeyPairName（例: ansible-test）を選択して「次へ」。
![ansible07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4077172/ef3350e7-13fc-4bb4-b893-1b68e977f164.png)



   9. オプション設定（タグや権限など）は必要に応じて設定し（今回はスキップ）、
      「AWS CloudFormationがIAMリソースを作成することを承認します」にチェックを入れて「次へ」。


      ![ansible08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4077172/9a420d7f-3c3a-4665-8305-154f55ff96b8.png)

  10. 確認画面が表示されるので、問題がなければ「送信」をクリックします。


### 2.2 デプロイ後の確認

1. **スタックの進捗状況を確認**
   - CloudFormationの「スタック」一覧から、作成したスタックの進捗状況（`CREATE_IN_PROGRESS` → `CREATE_COMPLETE`）を確認します。

![ansible09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4077172/8c0a6e16-552b-4667-bfa1-b6294aa5bccd.png)



2. **作成されたリソースの確認**
   - 「リソース」タブで作成されたリソース（EC2, VPC, サブネット, セキュリティグループなど）を確認できます。

---

## 3. Ansible Masterサーバのセットアップ

### 3.1 SSM Session Manager経由での接続

 Ansible_Master にチェックを入れ「接続」タブから「接続」をクリックし、SSM経由で接続してください。

![ansible10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4077172/105cb169-561c-4cea-ad4f-c59f9ef51c28.png)


#### 接続後、ルートユーザに切り替え
```bash
sudo su -
```

#### RHELのバージョンを確認（OSの種類とバージョンを確認）
```bash
cat /etc/redhat-release
```

**~出力結果~**
```
Red Hat Enterprise Linux release 10.0 (Coughlan)
```

#### ansibleをインストールする

Ansibleの自動化ツールであるansible-coreをインストールします。Red Hat Enterprise Linux 8以降では、従来の「ansible」パッケージではなく「ansible-core」が推奨されています。

```bash
dnf install ansible-core
```

**~出力結果~**
```
This system is not registered with an entitlement server. You can use "rhc" or "subscription-manager" to register.

Last metadata expiration check: 0:15:20 ago on Fri May 30 14:35:40 2025.

Dependencies resolved.

==================================================================================================================================================================================================================

 Package                                              Architecture                           Version                                            Repository                                                   Size

==================================================================================================================================================================================================================

Installing:

 ansible-core                                         noarch                                 1:2.16.14-1.el10                                   rhel-10-appstream-rhui-rpms                                 2.9 M

 Installing dependencies:

 git-core                                             x86_64                                 2.47.1-2.el10_0                                    rhel-10-appstream-rhui-rpms                                 4.9 M

 python3-cffi                                         x86_64                                 1.16.0-7.el10                                      rhel-10-baseos-rhui-rpms                                    312 k

 python3-cryptography                                 x86_64                                 43.0.0-4.el10                                      rhel-10-baseos-rhui-rpms                                    1.4 M

 python3-packaging                                    noarch                                 24.2-2.el10                                        rhel-10-baseos-rhui-rpms                                    157 k

 python3-ply                                          noarch                                 3.11-25.el10                                       rhel-10-baseos-rhui-rpms                                    139 k

 python3-pycparser                                    noarch                                 2.20-16.el10                                       rhel-10-baseos-rhui-rpms                                    162 k

 python3-resolvelib                                   noarch                                 1.0.1-6.el10                                       rhel-10-appstream-rhui-rpms                                  49 k

 Transaction Summary

==================================================================================================================================================================================================================

 Install  8 Packages

 Total download size: 9.9 M

 Installed size: 41 M

 Is this ok [y/N]:
```

`Is this ok [y/N]:` と表示されたら `y` を入力してエンターを押してください。

#### インストール確認（Ansibleが正常にインストールされたかバージョン情報で確認）
```bash
ansible --version
```

**~出力結果~**
```
ansible [core 2.16.14]
  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.12/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.12.9 (main, Mar 31 2025, 00:00:00) [GCC 14.2.1 20250110 (Red Hat 14.2.1-7)] (/usr/bin/python3)
  jinja version = 3.1.5
  libyaml = True
```

主に以下の内容が確認できます：
- Ansible本体（core）のバージョン
- 利用されている設定ファイルのパス（config file）
- モジュール検索パス（configured module search path）
- Ansible Pythonモジュールのインストール場所（ansible python module location）
- コレクションの検索パス（ansible collection location）
- ansibleコマンドの実行ファイルパス（executable location）
- 利用されているPythonのバージョンとパス（python version）
- Jinja2テンプレートエンジンのバージョン（jinja version）
- libyamlライブラリの有無（libyaml）

### 3.2 秘密鍵の配置

Ansible Masterサーバから各ターゲットサーバへSSHで安全に接続するためには、事前に対応する秘密鍵をサーバ上に配置しておく必要があります。これにより、Ansibleがターゲットサーバへ自動的に認証・接続できるようになります。

今回は、AWSでキーペア作成時にダウンロードしたpemファイル（秘密鍵）を使用します。

#### 秘密鍵ファイル作成（ターゲットサーバへのSSH接続用の秘密鍵を配置）
```bash
vi ~/.ssh/ansible-test.pem
```

# 保管していたpemファイルの内容を貼り付けてください
# 貼り付けたら「:wq」で保存してください

#### 権限を600に変更（秘密鍵ファイルのセキュリティを強化）
```bash
chmod 600 ~/.ssh/ansible-test.pem
```

#### 権限が変わったことを確認（ファイルの権限設定を確認）
```bash
ls -l ~/.ssh/ansible-test.pem
```

**~出力結果~**
```
-rw-------. 1 root root 1679 May 30 15:21 /root/.ssh/ansible-test.pem
```

---

## 4. Ansibleインベントリファイルを作成

インベントリファイルには、Ansibleで管理・操作する対象サーバ（ホスト）の一覧やグループ分け、各サーバへの接続方法（IPアドレス、ユーザー名、接続方式など）を記述します。これを作成することで、Ansibleがどのサーバにどのように接続し、どのグループに対して操作を行うかを明示的に指定できます。

#### Ansible用ディレクトリ作成（設定ファイル格納用のディレクトリを作成）
```bash
mkdir -p ~/ansible
```

#### インベントリファイル作成（管理対象サーバの一覧を定義するファイルを作成）

```bash
vi ~/ansible/inventory.ini
```

以下の内容を貼り付けて保存してください：


```ini
[dev_servers]
ansible-dev-target1 ansible_host=10.0.1.101 ansible_connection=ssh ansible_user=ec2-user
ansible-dev-target2 ansible_host=10.0.1.102 ansible_connection=ssh ansible_user=ec2-user

[test_servers]
ansible-test-target1 ansible_host=10.0.1.103 ansible_connection=ssh ansible_user=ec2-user
ansible-test-target2 ansible_host=10.0.1.104 ansible_connection=ssh ansible_user=ec2-user

[all_targets:children]
dev_servers
test_servers
```

貼り付けたら「:wq」で保存してください。

内容の補足説明

- `[dev_servers]` と `[test_servers]` は、管理対象のサーバーをグループ分けしています。
    - `dev_servers` グループには、開発環境用のサーバーが2台定義されています。
    - `test_servers` グループには、テスト環境用のサーバーが2台定義されています。
- このようにグループ化することで、特定のグループ全体に対して一括でAnsibleの操作を実行できます。
`ansible-dev-target1`: Ansibleがこのサーバーを認識するための名前（ホスト名）です。
`ansible_host=10.0.1.101`: このサーバーの実際のIPアドレスです。AnsibleはこのIPアドレスに対して接続を試みます。
`ansible_connection=ssh`: Ansibleがこのサーバーへ接続する際の接続方法を指定しています。ここではSSHを使用します。
`ansible_user=ec2-user`: SSH接続時に使用するユーザー名です。

- `[all_targets:children]` は、さらに別のグループを定義しています。
- `children` というキーワードは、この `all_targets` グループが、その下に記述された `dev_servers` グループと `test_servers` グループを子要素として含むことを意味します。
- これにより、`all_targets` グループを指定することで、開発環境とテスト環境の全てのサーバー（合計4台）に対して一度に操作を実行できるようになります。

#### ファイルが正常に作成されたか確認（インベントリファイルの存在確認）
```bash
ls -l ~/ansible/inventory.ini
```

---

## 5. 疎通確認の実行

疎通確認は、Ansible Masterサーバから各ターゲットサーバへ正しく接続できるかどうか、またインベントリやSSH認証などの設定に問題がないかを事前に確認するために行います。これにより、後続の自動化処理やプレイブック実行時のトラブルを未然に防ぐことができます。

### 5.1 事前確認

#### インベントリファイルの構文確認
インベントリファイルの内容をJSON形式で表示し、設定内容を確認します。
```bash
ansible-inventory -i ~/ansible/inventory.ini --list
```

**~出力結果~**
```json
{
    "_meta": {
        "hostvars": {
            "ansible-dev-target1": {
                "ansible_connection": "ssh",
                "ansible_host": "10.0.2.101",
                "ansible_user": "ec2-user"
            },
            "ansible-dev-target2": {
                "ansible_connection": "ssh",
                "ansible_host": "10.0.2.102",
                "ansible_user": "ec2-user"
            },
            "ansible-test-target1": {
                "ansible_connection": "ssh",
                "ansible_host": "10.0.2.103",
                "ansible_user": "ec2-user"
            },
            "ansible-test-target2": {
                "ansible_connection": "ssh",
                "ansible_host": "10.0.2.104",
                "ansible_user": "ec2-user"
            }
        }
    },
    "all": {
        "children": [
            "ungrouped",
            "all_targets"
        ]
    },
    "all_targets": {
        "children": [
            "dev_servers",
            "test_servers"
        ]
    },
    "dev_servers": {
        "hosts": [
            "ansible-dev-target1",
            "ansible-dev-target2"
        ]
    },
    "test_servers": {
        "hosts": [
            "ansible-test-target1",
            "ansible-test-target2"
        ]
    }
}
```

#### インベントリのグラフ表示

このコマンドでは、インベントリファイルで定義したサーバのグループ構成や、各サーバがどのグループに所属しているかをツリー状に視覚的に確認できます。グループ分けや階層構造が意図通りになっているかをチェックするのに便利です。

```bash
ansible-inventory -i ~/ansible/inventory.ini --graph
```

**~出力結果~**
```
@all:
  |--@ungrouped:
  |--@all_targets:
  |  |--@dev_servers:
  |  |  |--ansible-dev-target1
  |  |  |--ansible-dev-target2
  |  |  |--ansible-test-target1
  |  |  |--ansible-test-target2
  |  |--@test_servers:
  |  |  |--ansible-test-target1
  |  |  |--ansible-test-target2
```

#### ターゲットホスト一覧表示
```bash
ansible -i ~/ansible/inventory.ini all --list-hosts
```

**~出力結果~**
```
hosts (4):
  ansible-dev-target1
  ansible-dev-target2
  ansible-test-target1
  ansible-test-target2
```

### 5.2 個別サーバへの疎通確認

#### 開発サーバ1への疎通確認（特定のサーバに対してpingモジュールで接続テスト）
```bash
ansible -i ~/ansible/inventory.ini ansible-dev-target1 -m ping
```

以下のようなエラーが表示される場合があります。
秘密鍵がSSHエージェントに登録されていない、または認証情報が正しく設定されていない場合に発生）

**エラー例**
```
The authenticity of host '10.0.2.101 (10.0.2.101)' can't be established.
ED25519 key fingerprint is SHA256:Wgn4aWve8KMDrCOy1YPExjZvlmyG1nxMvHgk8Yu41GE.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
ansible-dev-target1 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: Warning: Permanently added '10.0.2.101' (ED25519) to the list of known hosts.\rec2-user@10.0.2.101: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).",
    "unreachable": true
}
```

#### 対処法

1. **SSHエージェントに秘密鍵を追加**（SSH認証用の秘密鍵をメモリに登録）
    ```bash
    ssh-add ~/.ssh/ansible-test.pem
    ```
2. **エージェントが起動していない場合のエラー例:**
    ```
    Could not open a connection to your authentication agent.
    ```
3. **エージェントを起動**（SSH認証エージェントサービスを開始）
    ```bash
    eval $(ssh-agent)
    ```
4. **再度追加**（秘密鍵をSSHエージェントに登録）
    ```bash
    ssh-add ~/.ssh/ansible-test.pem
    ```

**~出力結果~**
```
Agent pid 2610
Identity added: /root/.ssh/ansible-test.pem (/root/.ssh/ansible-test.pem)
```

##### 開発サーバ1への疎通確認（再実行）
```bash
ansible -i ~/ansible/inventory.ini ansible-dev-target1 -m ping
```

**~出力結果~**
```
ansible-dev-target1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
```

##### 開発サーバ2への疎通確認
```bash
ansible -i ~/ansible/inventory.ini ansible-dev-target2 -m ping
```

##### テストサーバ1への疎通確認
```bash
ansible -i ~/ansible/inventory.ini ansible-test-target1 -m ping
```

##### テストサーバ2への疎通確認
```bash
ansible -i ~/ansible/inventory.ini ansible-test-target2 -m ping
```

### 5.3 グループ単位での疎通確認

#### 開発環境グループ
```bash
ansible -i ~/ansible/inventory.ini dev_servers -m ping
```

**~出力結果~**
```
ansible-dev-target2 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
ansible-dev-target1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
```

#### テスト環境グループ
```bash
ansible -i ~/ansible/inventory.ini test_servers -m ping
```

**~出力結果~**
```
ansible-test-target2 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
ansible-test-target1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
```

#### 全ターゲットサーバ
```bash
ansible -i ~/ansible/inventory.ini all_targets -m ping
```

**~出力結果~**
```
ansible-test-target2 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
ansible-test-target1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
ansible-dev-target2 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
ansible-dev-target1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
```

---

## 6. CloudFormationテンプレートで作成したリソースの削除手順

AWS環境をクリーンアップする場合は、CloudFormationスタックを削除することで関連リソース（EC2インスタンス、VPC、サブネット、セキュリティグループなど）をまとめて削除できます。

### 削除手順
1. AWSマネジメントコンソールにログインし、CloudFormationサービスを開きます。
2. 削除したいスタック（例: Ansible）を選択します。
3. 「削除」ボタンをクリックします。

![ansible11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4077172/d28d6415-c176-46c1-95d4-7fcc4b8dbe7a.png)



4. スタックのステータスが `DELETE_IN_PROGRESS` から `DELETE_COMPLETE` になるまで待ちます。

> **注意:**
> - スタックを削除すると、テンプレートで作成されたすべてのリソースが削除されます。
> - 削除保護が有効なリソースは手動で削除が必要な場合があります。※今回のテンプレートをご使用の場合はすべて削除されます。

---

## 7. まとめ

CloudFormationを使用してAnsibleの検証環境を構築し、Ansible Masterサーバから複数のターゲットサーバへの疎通確認を行いました。

今後は作成した環境でAnsibleプレイブックの実行や様々なモジュールのを試す記事を投稿していきます！！