AnsibleでAWS CLIコマンドを実行する


実現したいこと

Ansibleで以下の処理を実行します。また、AnsibleはDockerコンテナ上で実行します。
①AWS CLIを使用してターゲットとなるEC2をELBから切り離す
②切り離し完了後、yum updateを実行
③インスタンスをリブート
④再度ELBに登録する

1. Docker環境準備

1-1. Docker用のディレクトリとDockerfile作成
  ディレクトリとDockerfileを作成します。

$ sudo mkdir docker-demo
$ cd docker-demo
$ sudo vim Dockerfile

1-2. Dockerfileの編集
  AnsibleにPythonが必要なため、Docker公式のPythonイメージで軽量のslim-busterを使用します。
  WORKDIRは後ほど作成するAnsibleのファイルを置くディレクトリを指定します。
  ansibleとsshをインストールします。(ターゲットノードにパスワードでssh接続する場合は、sshpassもインストールが必要)

Dockerfile
FROM python:3.9.0-slim-buster

WORKDIR /usr/src/app

RUN pip install ansible
RUN apt-get update && apt-get install -y \
vim \
ssh

2. Ansible環境準備

2-1. ファイル作成
  Ansibleで使用するファイルを作成します。

$ cd /usr/src/app
$ sudo touch inventory main.yml ansible.cfg

2-2. inventoryファイルの編集
  ターゲットノードのIPアドレスを指定します。
  また、SSHで接続するのでユーザ名と秘密鍵のパスを記載します。

inventory
[targets]
10.0.1.100

[targets:vars]
ansible_connection=ssh
ansible_user=ec2-user
ansible_ssh_private_key_file=/usr/src/app/.ssh/秘密鍵ファイル

2-3. main.ymlの編集
  今回はmain.ymlに処理をすべて記載します。
  (shellでaws cliのコマンドを書いて、arnもmain.ymlの中で指定していますが、もっといい書き方があると思っています…)
  yumとreboot、wait_for_connectionはAnsibleモジュールを使用します。
  wait_for_connectionで再起動後も処理を続けられるようにします。

main.yml
- hosts: targets
  become: yes
  gather_facts: no
  tasks:
    ##################################################
    # deregister instances from elb
    ##################################################
    - name: deregistering instances from elb
      become: yes
      shell: >
        aws elbv2 deregister-targets
        --target-group-arn arn:aws:elasticloadbalancing:ap-northeast-1:0123456789:targetgroup/target-group-name/abc123456789
        --targets Id=i-0123456789,Port=80
        --region ap-northeast-1
      async: 600
      poll: 300

    ##################################################
    # yum update
    ##################################################
    - name: upgrade all packages
      yum:
        name: "*"
        state: latest
      async: 180
      poll: 60

    ##################################################
    # reboot
    ##################################################
    - reboot:

    ##################################################
    # wait for connection
    ##################################################
    - wait_for_connection:

    ##################################################
    # register instances with elb
    ##################################################
    - name: registering instances with elb
      become: yes
      shell: >
        aws elbv2 register-targets
        --target-group-arn arn:aws:elasticloadbalancing:ap-northeast-1:0123456789:targetgroup/target-group-name/abc123456789
        --targets Id=i-0123456789,Port=80
        --region ap-northeast-1
      async: 180
      poll: 60

2-4. ansible.cfgの編集
  設定オプションを指定します。
  known_inventoryにフィンガープリントを記録する処理の無効化のため、host_key_checking=Falseを設定。

ansible.cfg
[defaults]
host_key_checking=False

3. Dockerコンテナ作成

3-1. docker buildの実行
  Dockerfileのあるディレクトリでコマンドを実行します。
  docker imagesで作成されたことを確認できます。

$ docker build -t ansible-demo .
$ docker images
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
ansible-demo           latest              abc123456789        21 seconds ago      603MB

4. Ansibleコマンド実行

4-1. コンテナ起動
  WORKDIRで指定したディレクトリに移動し、docker runでコンテナを起動します。
  オプションの説明は以下の通りです。
   -it:コンテナ上で擬似ターミナルを割り当て、標準入力を開き続ける
   -v:ホストのディレクトリをコンテナにマウントする
   -rm:コンテナ終了時にコンテナを自動的に削除

$ cd /usr/src/app
$ docker run -it --rm -v $(pwd):/usr/src/app ansible-demo /bin/bash

4-2. Ansibleコマンド実行
  以下のようにコマンドを実行します。
  AWSコンソールからターゲットグループのステータスがdrainingになっていることが確認できます。
  最終的には再度ELBに登録され、healthyになっていることが確認できました。

root@abc012345:/usr/src/app# ansible-playbook -i ./inventory ./main.yml

PLAY [targets] ************************************************************************************

TASK [deregistering instances from elb] ***********************************************************
changed: [10.0.1.100]

TASK [upgrade all packages] ***********************************************************************
ok: [10.0.1.100]

TASK [reboot] *************************************************************************************
changed: [10.0.1.100]

TASK [wait_for_connection] ************************************************************************
ok: [10.0.1.100]

TASK [registering instances with elb]**************************************************************
changed: [10.0.1.100]

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