VTRyo Blog

一歩ずつ前に進むブログ

AnsibleでEC2を作成するときに冪等性を維持する方法

f:id:vtryo:20180714235526p:plain AnsibleのAWSモジュールをいじってる中、一番謎だったのが冪等性を担保する方法だった。

というのも、EC2のplaybookをそのまま適用すると同じ設定の別のEC2インスタンスが立ち上がってきた

playbook内にあるinstance_idを同名にしてみたりした(動的ではないので本来このやり方もおかしい)が、それでも別のEC2インスタンスが立ち上がっていた。

f:id:vtryo:20180714235839j:plain

※以下は別EC2インスタンスが立ち上がってくるplaybook

- name: create ec2 instance
  ec2:
    state: present
    aws_access_key: "{{ aws_access_key_id }}"
    aws_secret_key: "{{ aws_secret_access_key }}"
    region: "{{ aws_region }}"
    key_name: id_rsa
    instance_type: t2.micro
    #image: ami-4af5022c
    count: 1
    instance_tags:
      Name: "{{ instance_name }}"
    volumes:
      - device_name: /dev/xvda
        volume_type: gp2
        volume_size: 8
  register: ec2

Ansible AWSモジュールの立ち位置

正直、Ansibleでインフラの土台となる部分を構築&操作するのは気が進まない。

Terraformというツールの開発が爆速でされている以上、Terraformを使ったほうが建設的だった。

プラス、AnsibleはProvisioningに特化したツールであると認識していたため、AWSの操作に不備があっても何ら不思議ではないと勝手に思い込んでいた。

だから、EC2インスタンスの構築で冪等性が担保できなくても「仕様」であると諦めていた。

公式を読め。見落としているだけだ

count_tag, exact_count

しかし、何度も検証しているうちに見落としていることに気づいた。これは本当に恥ずかしい。

もちろん公式にはバッチリ書いてある。

http://docs.ansible.com/ansible/latest/ec2_module.html

以下に冪等性を担保するplaybookを載せる。

ポイントは、count: 1を削除すること。

- name: create ec2 instance
  ec2:
    aws_access_key: "{{ aws_access_key_id }}"
    aws_secret_key: "{{ aws_secret_access_key }}"
    region: "{{ aws_region }}"
    key_name: id_rsa
    instance_type: t2.micro
    #image: ami-4af5022c
    instance_tags:
      Name: "{{ instance_name }}"
    count_tag:
      Name: "{{ instance_name }}"
    exact_count: 1
    volumes:
      - device_name: /dev/xvda
        volume_type: gp2
        volume_size: 8
  register: ec2

以上を実行する。

一度目の実行では、EC2インスタンスが作成されるため「changed」が吐かれる。

f:id:vtryo:20180715000136j:plain

そしてそのまま二度目。普段は再び「changed」が吐かれ、二台目のEC2インスタンスが作成された。

しかし、さきほどのplaybookによって、「ok」が吐かれた。

f:id:vtryo:20180715000201j:plain

コンソールを確認しても、二台目はもちろん作成されていない。

冪等性の担保ができた。

感想

冪等性の担保は可能とわかったが、EC2インスタンスを立ち上げるまでにvpc関連のplaybookを書かなくてはならない。

しかもこれがかなり大変。動的にIDを取得する必要があるため、Ansibleのモジュールを駆使する。

TerraformのID取得の方が圧倒的に簡単だし便利だよ(笑)

参考

http://docs.ansible.com/ansible/latest/ec2_module.html

http://dev.classmethod.jp/server-side/ansible/ec2_using_ansible/