Ansible ダイナミックインベントリの構成と ECS インスタンスとの統合

この記事では、**Ansible**のダイナミックインベントリを設定してECSインスタンスと統合する方法を学び、自動化によってサーバーを管理できるようにします。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/managing-ecs-instances-with-ansible-dynamic-inventory_594718)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

[Alibaba Cloud Tech Share](https://www.alibabacloud.com/campaign/techshare?spm=a2c65.11461447.0.0.63bf10ec8s0b65) 執筆者、Anish Nath、 [Tech Share](https://www.alibabacloud.com/campaign/techshare?spm=a2c65.11461447.0.0.63bf10ec8s0b65)は、技術的な知識やベストプラクティスをクラウドコミュニティ内で共有することを奨励するAlibaba Cloudのインセンティブプログラムです。

Alibaba Cloud [Elastic Compute Service](https://www.alibabacloud.com/product/ecs?spm=a2c65.11461447.0.0.63bf10ec8s0b65) (ECS)のインベントリが時間の経過とともに変動し、ビジネス需要に応じてホストがスピンアップしたりシャットダウンしたりする場合、静的なインベントリソリューションではニーズを満たすことができません。CMDBのような複数のソースからホストを追跡する必要があるかもしれませんし、手動のクエリとコンパイル、その他すべての面倒な作業が必要になるかもしれません。

Ansible では、Ansible Alicloud モジュールのインベントリスクリプトを使用して動的な外部インベントリシステムを介してこれらのオプションをすべて統合しています。
[https://raw.githubusercontent.com/alibaba/ansible-provider/master/contrib/inventory/alicloud.py](https://raw.githubusercontent.com/alibaba/ansible-provider/master/contrib/inventory/alicloud.py?spm=a2c65.11461447.0.0.63bf10ec8s0b65&file=alicloud.py)

この記事では、以下の方法を学びます。

- ECSダイナミックスクリプトの構成
- ECS ホストに問い合わせ
- ECSとAnsibleのダイナミックインベントリを統合
- インスタンスフィルタの使用
- ECSダイナミックスクリプトを使用してセキュリティコンプライアンスを実現

#前提条件
Alicloud providerをインストールする方法は2つあります。ただし、インストールする前に、Ansibleがサーバーにインストールされていることを確認してください。インストールされていない場合は、インストールしてください。

Alibaba Cloud ECSコントローラノードまたはマネージドノードにログインし、以下のコンポーネントをインストールします。

```
$ ssh root@47.254.17.249 root@47.254.17.249's password:
Welcome to Alibaba Cloud Elastic Compute Service !
$ sudo pip install ansible
$ sudo pip install ansible_alicloud
```

注意: NTP が同期していることを確認してください。そうしないと API コールの失敗が表示されます。

Alibaba Cloudを初めて利用する場合は、私の[紹介リンク]()から10ドル分のクレジットを取得してECSインスタンスを開始することができます。

#認証
Alibaba Cloudの認証資格情報(アクセスキーとシークレットキー)は、環境変数として渡すか、varsファイルに格納することで指定できます。

認証資格情報を環境変数として渡すには：

```
export ALICLOUD_ACCESS_KEY='XXXXXXXXXXXXX' 
export ALICLOUD_SECRET_KEY='YYYYYYYYYYYYYZZZZZZZZZZZZ'
```

このアカウントに関連付けられた RAM キーは、Alibaba クラウドリソースを照会するための適切な権限を持っている必要があります。システムセキュリティの専門家が決定する粒度は、最低でも[AliyunECSReadOnlyAccess](https://ram.console.aliyun.com/policies/AliyunECSReadOnlyAccess/System?spm=a2c65.11461447.0.0.63bf10ec8s0b65)を持っている必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/1a34a2e3-2a9b-5698-05c3-5691f134afd2.png)


#インベントリスクリプト
アリババクラウドの動的インベントリスクリプトalicloud.pyの最新版をダウンロードして実行可能な状態にします。

```
$wget https://raw.githubusercontent.com/alibaba/ansible-provider/master/contrib/inventory/alicloud.py 
$chmod +x alicloud.py 
$sudo cp alicloud.py /etc/ansible/hosts
```

Ansible Alibaba Cloud ECS ダイナミックインベントリのサンプルをダウンロードして、必要に応じて修正し、/etc/ansible/alicloud.iniにコピーします。

```
$ wget https://raw.githubusercontent.com/alibaba/ansible-provider/master/contrib/inventory/alicloud.ini  
$vi alicloud.ini  
$sudo cp alicloud.ini /etc/ansible/
```

Alibaba Cloudダイナミックインベントリスクリプトを手動でテストして、期待通りに動作していることを確認することができます。

```
$ ./alicloud.py --list
```

しばらくすると、ECSインスタンスに関する情報を含むJSON出力が表示されるはずです。

```
[Instance:i-rj9djh1xn7tava07qtam]
{
  "_meta": {
    "hostvars": {
      "i_rj9djh1xn7tava07qtam": {
        "ansible_ssh_host": "47.254.17.249", 
        "auto_release_time": "", 
        "availability_zone": "us-west-1b", 
        "block_device_mapping": [
          {
            "attach_time": "2019-01-04T04:43:26Z", 
            "delete_on_termination": true, 
            "device_name": "/dev/xvda", 
            "status": "in_use", 
            "volume_id": "d-rj9euf5u1ph9l348lre8"
          }
        ], 
        "cpu": 1, 
        "creation_time": "2019-01-04T04:43Z", 
        "credit_specification": "Standard", 
        "deletion_protection": false, 
        "deployment_set_id": "", 
        "description": "demo", 
        "eip": {
          "allocation_id": "", 
          "internet_charge_type": "", 
          "ip_address": ""
        }, 
        "expired_time": "2099-12-31T15:59Z", 
        "gpu": {
          "amount": 0, 
          "spec": "", 
          "specification": ""
        }, 
        "host_name": "demo", 
        "id": "i-rj9djh1xn7tava07qtam", 
        "image_id": "alinux_17_01_64_20G_cloudinit_20171222.vhd", 
        "instance_charge_type": "PostPaid", 
        "instance_id": "i-rj9djh1xn7tava07qtam", 
        "instance_name": "demo", 
        "instance_type": "ecs.t5-lc2m1.nano", 
        "internet_charge_type": "PayByTraffic", 
        "internet_max_bandwidth_in": 100, 
        "internet_max_bandwidth_out": 5, 
        "io_optimized": true, 
        "memory": 512, 
        "network_interfaces": [
          {
            "mac_address": "00:16:3e:00:46:ea", 
            "network_interface_id": "eni-rj99fi72su03d5iqpv26", 
            "primary_ip_address": "172.20.240.111"
          }
        ], 
        "osname": "Aliyun Linux  17.1 64\u4f4d", 
        "ostype": "linux", 
        "private_ip_address": "172.20.240.111", 
        "public_ip_address": "47.254.17.249", 
        "resource_group_id": "", 
        "state": "running", 
        "tags": {
          "tool": "ansible"
        }, 
        "user_data": "", 
        "vpc_id": "vpc-rj9mhs1pv5tbc31khpssv", 
        "vswitch_id": "vsw-rj9bt4ec9zqauhr8vig9q"
      }
    }
  }, 
  "alicloud": {
    "children": [
      "i_rj9djh1xn7tava07qtam"
    ]
  }, 
  "alinux_17_01_64_20G_cloudinit_20171222.vhd": [
    "i_rj9djh1xn7tava07qtam"
  ], 
  "i-rj9djh1xn7tava07qtam": [
    "i_rj9djh1xn7tava07qtam"
  ], 
  "i_rj9djh1xn7tava07qtam": [
    "47.254.17.249"
  ], 
  "security_group_security_group_id": [
    "i_rj9djh1xn7tava07qtam"
  ], 
  "subnet_vsw_rj9bt4ec9zqauhr8vig9q": [
    "i_rj9djh1xn7tava07qtam"
  ], 
  "tag_tool_ansible": [
    "i_rj9djh1xn7tava07qtam"
  ], 
  "type_ecs_t5_lc2m1_nano": [
    "i_rj9djh1xn7tava07qtam"
  ], 
  "us-west-1": [
    "i_rj9djh1xn7tava07qtam"
  ], 
  "us-west-1b": [
    "i_rj9djh1xn7tava07qtam"
  ], 
  "vpc_id_vpc_rj9mhs1pv5tbc31khpssv": [
    "i_rj9djh1xn7tava07qtam"
  ]
}
```

#Cacheの更新
Alibabaクラウドのダイナミックインベントリスクリプトは、APIコールの繰り返しを避けるために結果をキャッシュすることに注意してください。キャッシュを明示的にクリアするには、alicloud.py (またはhosts) スクリプトを -refresh パラメータを指定して実行します。

```
$ /alicloud.py --refresh-cache
```

インスタンスで使用可能な変数の完全なリストを確認するには、スクリプトを単独で実行します。

動的インベントリスクリプトが期待通りに動作していることを確認したら、次の図のように、Ansible に alicloud.py スクリプトをインベントリファイルとして使用するように指示します。

```
[root@demo ~]# ansible -i alicloud.py all -m ping -k -u root 
SSH password: 
 [WARNING]: Found both group and host with same name: i_rj9djh1xn7tava07qtam
i_rj9djh1xn7tava07qtam | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname i_rj9djh1xn7tava07qtam: Name or service not known\r\n", 
    "unreachable": true
}
47.254.17.249 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
```

#ECSダイナミックインベントリスクリプトの構成
上記の例では、インベントリを生成する際にアクセスできないホストが 1 つありました。Ansible は ECS インスタンスをアドレスする方法を知る必要があり、これらは複数のグループからのインスタンスへのマッピングを提供する ECS 動的インベントリスクリプト設定ファイル ansible.ini で制御されます。

- リージョン：ECS リージョン内のすべてのインスタンスのグループ、例えば cn-beijing,eu-central-1,ap-southeast-1,us-east-1 など。
- タグ：各インスタンスは、タグと呼ばれるそれに関連付けられた様々なキー/値のペアを持つことができます。それぞれのキー/値のペアは、特殊文字をアンダースコアに変換した独自のインスタンスのグループであり、tag_TAGNAMEのフォーマットになっています。
- HOST VAR：クエリ対象のVMの種類
alicloud.iniファイルを編集し、hostname_variableを変更します。

```
from
hostname_variable = instance_id
to
hostname_variable = instance_name
```

スクリプトをもう一度実行します。

```
[root@demo ~]# ansible -i alicloud.py all -m ping -k -u root 
SSH password: 
 [WARNING]: Found both group and host with same name: demo demo | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
47.254.17.249 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
```

パブリックアドレスを持たないプライベートVMについてはどうでしょうか、それらのVMを管理する方法は？

```
destination_variable=private_ip_address
```

以下の ansible クエリでは、ECS のプライベートアドレスを使用して VM を管理します。

```
[root@demo ~]# ansible -i alicloud.py all -m ping -k -u root 
SSH password: 
 [WARNING]: Found both group and host with same name: demo
demo | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
172.20.240.111 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
```

**instance_states**

ECS VMに関連付けられた5つのECSインスタンスの状態があります['pending', 'running', 'starting', 'stopping', 'stopped']。デフォルトでは、実行中の状態のECSインスタンスのみが返されますが、これらのオプションを制御するためにalicloud.iniファイルを修正し、必要に応じて設定を調整してください。

```
all_instances = True
# instance_states = pending, running, starting, stopping, stopped
```

#セキュリティ・コンプライアンス
Ansible ECSの動的インベントリスクリプトは、動的なクラウド環境のセキュリティコンプライアンスを達成するための正しい方法です。静的なインベントリを維持することなく、設定を動的にプッシュすることができます。例えば、以下の cron ジョブの設定では、30 分ごとに実行中の ECS サーバに [SSH](https://www.alibabacloud.com/blog/managing-system-users-using-ansible_593861?spm=a2c65.11461447.0.0.63bf10ec8s0b65) プロファイルをプッシュします。

```
*/30 * * * *  ansible-playbook ssh.yml -i alicloud.py
```

そして、4時間ごとにキャッシュを更新するためにcronジョブを使って在庫リストを更新し、必要に応じて調整します。

```
**0 0 */4 ? * ***   alicloud.py --refresh-cache
```

#結論
- ECS CMDB (Configuration Management Database) が動的で頻繁に変更される場合は、ダイナミックインベントリの使用を推奨します。(VMが急激にスケールアップ/スケールダウンしたり、巨大なサーバを管理している場合)
- Alibaba Cloud ECSダイナミックスクリプトは、手動で変更された場合、常に正しいIPアドレスを持っています(別のVMに割り当てられたEIP)
- alicloud.iniにAlibaba Cloudの資格情報を入れないことは推奨されませんが、環境変数を使用することを強く推奨します。

*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*