食欲の秋に(体重的な意味で)危機感を覚える Coati開発チーム 沼野井です。
でも秋の味覚を食べないという選択肢はないですよね!
前回までのあらすじ
ansibleで、

VPCと、それに紐づく サブネット、ルートテーブル、セキュリティグループを作ったCoatiだった・・・

というわけで、前回に続いて、ansibleでEC2・VPC環境を構築していこうと思います。
今回は、
- 前回作成したSIOS VPC内に EC2インスタンスを作成
- 前回作成したSIOS VPCとお客様VPCをPeeringで接続
します。
Playbookの内容
Coatiチームで使用している、環境デプロイ用のPlaybookのディレクトリ構成と、変数定義をしているall.ymlの内容をもう一回掲載します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
├── ansible.cfg ├── group_vars │ └── all.yml # 変数定義 ├── hosts ├── roles │ ├── VPC │ │ └── tasks │ │ ├── main.yml # VPC.ymlの本体 │ │ ├── setup_ec2.yml # VPC.ymlの本体 │ │ └── setup_vpc.yml # VPC.ymlの本体 │ └── vpc_peering │ └── tasks │ ├── main.yml # VPC.ymlの本体 │ └── vpc_peering.yml # create_vpc_peering.ymlの本体 ├── create_vpc_peering.yml # 実行するplaybook └── VPC.yml # 実行するplaybook |
group_vars/all.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
PEERING_VPC_ID: vpc-XXXXXXXX # お客様のVPC ID PEERING_VPC_CIDR: XXX.XXX.XXX.XXX/XX # お客様のVPC CIDR CUSTOMER: Coati Coffee.break.fun # お客様名 EMAIL: COATI@coati.coffee_break_fun.com # お客様のEメールアドレス PREFIX: "CoatiManager_{{ CUSTOMER }}" # VPC, Subnet, ルートテーブル, インスタンス名のprefix REGION: ap-northeast-1 # リージョン(東京) OFFICE_IP: ZZZ.ZZZ.ZZZ.ZZZ # SIOSのオペレーション端末のIPアドレス OFFICE_IP_CIDR: "{{ OFFICE_IP }}/32" # SIOSのオペレーション端末のIPアドレスのCIDR VPC_NAME: "{{ PREFIX }}_VPC" # VPC名称 VPC_CIDR_LEFT: YYY.YYY.YYY # Coati ManagerのCIDRの左部分 VPC_CIDR_BLOCK: "{{ VPC_CIDR_LEFT }}.0/23" # VPCのCIDR Block SUBNET1_NAME: "{{ PREFIX }}_SUBNET1" # Subnet名 SUBNET1_CIDR_BLOCK: "{{ VPC_CIDR_LEFT }}.0/24" # SubnetのCIDR Block ROUTETABLE1_NAME: "{{ PREFIX }}_RT1" # ルートテーブル名 KEY_PAIR: XXXXXXXXXXXXXXXXXXXXXXXXXXX # Coati Managerインスタンスにアクセスするためのキーペア INSTANCE_TYPE: t2.small # Coati Managerインスタンスのインスタンス・タイプ EC2_NAME: "{{ PREFIX }}" # Coati Managerインスタンス名 EC2_PRIVATE_IP: "{{ VPC_CIDR_LEFT }}.10" # Coati ManagerインスタンスのプライベートIPアドレス IAM_ROLE: XXXXXXXXXXXX # Coati Managerインスタンスに割り当てるIAMロール SIOS_ACCOUNT_ID: 987654321098 # サイオスのAWSアカウントID |
インスタンス作成
作成したVPC内にEC2インスタンスを作成するplaybook, setup_ec2.ymlの中身を見ていきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
|
- ec2_remote_facts: region: "{{ REGION }}" filters: private-ip-address: "{{ EC2_PRIVATE_IP }}" subnet-id: "{{ SUBNET_ID }}" register: ec2 # Search for the AMI tagged "Role: CoatiManager" and "Version: Master" - ec2_ami_find: owner: self region: "{{ REGION }}" ami_tags: Role: CoatiManager Version: Master sort: creationDate sort_order: descending sort_end: 1 no_result_action: fail register: ami_find - name: Create AWS Instance ec2: key_name: "{{ KEY_PAIR }}" instance_type: "{{ INSTANCE_TYPE }}" image: "{{ ami_find.results[0].ami_id }}" region: "{{ REGION }}" vpc_subnet_id: "{{ SUBNET_ID }}" private_ip: "{{ EC2_PRIVATE_IP }}" instance_profile_name: "{{ IAM_ROLE }}" assign_public_ip: no wait: yes instance_tags: Name: "{{ EC2_NAME }}" Role: CoatiManager volumes: - device_name: /dev/sda1 volume_type: gp2 volume_size: 20 delete_on_termination: true when: not ec2.instances # refresh remote facts - ec2_remote_facts: region: "{{ REGION }}" filters: private-ip-address: "{{ EC2_PRIVATE_IP }}" subnet-id: "{{ SUBNET_ID }}" register: ec2 - name: Associate EIP for instance ec2_eip: region: "{{ REGION }}" device_id: "{{ ec2.instances[0].id }}" reuse_existing_ip_allowed: yes in_vpc: yes register: eip |
順にみていきます。
|
- ec2_remote_facts: region: "{{ REGION }}" filters: private-ip-address: "{{ EC2_PRIVATE_IP }}" subnet-id: "{{ SUBNET_ID }}" register: ec2 |
ec2_remote_factsはAWS内の(複数の)インスタンスの情報を集めるモジュールです。
IPアドレス・サブネット名など多種のFilterを設定して検索することができます。
今回は、SUBNET_IDのサブネット、EC2_PRIVATE_IPのIPアドレスのインスタンスが、環境内に既に存在しているかどうかをチェックしています。
|
なお、<span style="font-family: georgia, palatino, serif;"><strong>ec2_remote_facts</strong></span> は ansible 2.4 では<strong>非推奨</strong>モジュールとなっており、代わりに <strong><span style="font-family: georgia, palatino, serif;"><a href="http://docs.ansible.com/ansible/latest/ec2_instance_facts_module.html#ec2-instance-facts">ec2_instance_facts</a></span></strong> がリリースされています。 - ec2_ami_find: owner: self region: "{{ REGION }}" ami_tags: Role: CoatiManager Version: Master sort: creationDate sort_order: descending sort_end: 1 no_result_action: fail register: ami_find |
続いて、AMIの検索です。
Coati開発チームでは、Coati Manager用のAMIをあらかじめ用意していて、タグ Role=CoatiManager をつけています。ec2_ami_findモジュールを利用して、タグをキーにしてAMIのIDを取得します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
- name: Create AWS Instance ec2: key_name: "{{ KEY_PAIR }}" instance_type: "{{ INSTANCE_TYPE }}" image: "{{ ami_find.results[0].ami_id }}" region: "{{ REGION }}" vpc_subnet_id: "{{ SUBNET_ID }}" private_ip: "{{ EC2_PRIVATE_IP }}" instance_profile_name: "{{ IAM_ROLE }}" assign_public_ip: no wait: yes instance_tags: Name: "{{ EC2_NAME }}" Role: CoatiManager volumes: - device_name: /dev/sda1 volume_type: gp2 volume_size: 20 delete_on_termination: true when: not ec2.instances |
いよいよ、インスタンスの作成です。そのものズバリな ec2モジュールを使います。
パラメータはAWS Management ConsoleでEC2インスタンスを作成する際にお馴染みな面々を指定していきます。imageには、さきほど検索したAMIのIDを指定しています。
|
<span style="font-size: 12pt; font-family: arial, helvetica, sans-serif;"><code> image: "{{ ami_find.results[0].ami_id }}"</code></span> |
instance_tags: で Name=名前, Role=CoatiManager、というタグ付けもしています。
最後の
|
<span style="font-size: 12pt; font-family: arial, helvetica, sans-serif;"><code> when: not ec2.instances</code></span> |
は、ec2.instancesがある場合にはインスタンスの作成をしない、という条件判定です。
一番最初に ec2_remote_factモジュールで同じIPアドレスとサブネットのインスタンスを検索したときに、もし既に存在している場合には変数ec2.instancesなんらかの値が入っているはずですので、その場合にはインスタンスの作成は行わないようにしています。
VPCピアリング接続
VPCピアリングを行うplaybook, vpc_peering.ymlです。
|
--- - name: include vars include_vars: '/tmp/__temp_fact__.yml' - name: Setup VPC peering for customer ec2_vpc_peer: region: "{{ REGION }}" vpc_id: "{{ manager_vpc_id }}" peer_vpc_id: "{{ PEERING_VPC_ID }}" peer_owner_id: "{{ PEER_OWNER_ID }}" state: present tags: Name: Peering connection for "{{ CUSTOMER }}" register: vpc_peering_for_customer |
ec2_vpc_peerモジュールを使い、接続するVPCをそれぞれ指定して、VPCピアリング接続を行います。
このplaybookを実行したあと、お客様に接続を承認していただくと、晴れて両VPCがピアリング接続されることになります。
ここまでの結果
ついに、Coati環境が完成しました!

いかがでしたでしょうか?
今後も、役に立ちそうなplaybookを紹介していく予定ですので、よろしくお願いします。