Ansible を使って AWS の CloudFormation のスタックを作成および削除する方法のメモです。シンプルなスタックの管理は aws
コマンドをシェルスクリプトでラップすれば良いのですが、テンプレートへの入力パラメータの管理と出力内容の再利用性を高めるために Ansible を使います。
Ansible の cloudformation モジュールのドキュメントはこちら。
作成するスタックは AWS の Quick Start にある VPC と Bastion を使います。
Bastion スタックには DependsOn を利用して新規に VPC スタックを構成するマスターテンプレートもありますが、ここではスタックの出力を Ansible の変数として受け渡すことを示すため、個別にテンプレートを呼び出します。
準備
まずは Ansible をインストールし、AWS の API を実行できるように Boto を追加します。
Ansible のインストールは Ubuntu だと以下のような作業になりますが、他のディストリビューションおよび macOS でもだいたい一緒です。利用環境に合わせて調整してください。
$ sudo apt-get install -y python-pip
$ sudo pip install -U pip
$ sudo pip install ansible==2.4.0
続いて Boto をインストールし、アクセスキーの情報を設定ファイル (~/.boto
) に記載します。
$ sudo pip install boto3
アクセスキーの情報は利用するアカウントに合わせてください。CloudFormation の作成や削除の権限以外に、スタックの中で管理するリソースに関する権限が必要になります。Bastion スタックでは IAM の Role 関係の権限が必要です。
[Credentials]
aws_access_key_id = xxxxxxxxxxxxxxx
aws_secret_access_key = xxxxxxxxxxxxxxx
Ansible の変数ファイルを group_vars/all.yml
として用意します。踏み台ホスト (bastion) へのアクセスを許可する IP アドレスを remote_global_ip_addr と定義していますが、実行環境のネットワークに応じて値を変更してください。また、リージョンやAZ、キーペア、スタック名なども調整してください。
---
remote_global_ip_addr: "aaa.bbb.ccc.ddd/32"
aws_region: ap-northeast-1
aws_ec2_keypair_bastion:
name: bastion
private_key_file: ~/.ssh/keys/aws_bastion.pem
aws_cfn_stack_name: "Example"
aws_cfn_vpc_stack_name: "{{ aws_cfn_stack_name }}VPC"
aws_cfn_vpc_availability_zones: "ap-northeast-1b,ap-northeast-1c"
aws_cfn_vpc_qs_template_url: "https://s3.amazonaws.com/quickstart-reference/aws/vpc/latest/templates/aws-vpc.template"
aws_cfn_vpc_qs_keypair: "{{ aws_ec2_keypair_bastion.name }}"
aws_cfn_bastion_stack_name: "{{ aws_cfn_stack_name }}Bastion"
aws_cfn_bastion_qs_template_url: "https://s3.amazonaws.com/quickstart-reference/linux/bastion/latest/templates/linux-bastion.template"
例示のために all.yml
としていますが、インベントリごとに読み込みを変えたい場合はファイル配置とプレイブックを適宜調整してください。インベントリファイルの配置については Ansible のドキュメントを参照してください。
スタックの作成
site.yml
としてプレイブックを用意します。
---
- name: Create VPC and Bastion stack
hosts: localhost
connection: local
gather_facts: no
tasks:
- name: Launch VPC network with NAT gateway
cloudformation:
region: "{{ aws_region }}"
stack_name: "{{ aws_cfn_vpc_stack_name }}"
state: "present"
template_url: "{{ aws_cfn_vpc_qs_template_url }}"
template_parameters:
AvailabilityZones: "{{ aws_cfn_vpc_availability_zones }}"
KeyPairName: "{{ aws_cfn_vpc_qs_keypair }}"
register: _vpc
- name: Launch bastion stack
cloudformation:
region: "{{ aws_region }}"
stack_name: "{{ aws_cfn_bastion_stack_name }}"
state: "present"
template_url: "{{ aws_cfn_bastion_qs_template_url }}"
template_parameters:
VPCID: "{{ _vpc.stack_outputs.VPCID }}"
PublicSubnet1ID: "{{ _vpc.stack_outputs.PublicSubnet1ID }}"
PublicSubnet2ID: "{{ _vpc.stack_outputs.PublicSubnet2ID }}"
RemoteAccessCIDR: "{{ remote_global_ip_addr }}"
EnableTCPForwarding: "true"
KeyPairName: "{{ aws_ec2_keypair_bastion.name }}"
register: _bastion
- name: Show bastion EIP
local_action: shell echo {{ _bastion.stack_outputs.EIP1 }} > bastion
プレイブックを実行します。正常に処理が終了すると bastion ファイルに踏み台ホストの IP アドレスが出力されます。
$ ansible-playbook site.yml
スタックの削除
halt.yml
としてプレイブックを用意します。
---
- name: Delete all stacks
hosts: localhost
connection: local
gather_facts: no
tasks:
- name: Delete bastion stack
cloudformation:
region: "{{ aws_region }}"
stack_name: "{{ aws_cfn_bastion_stack_name }}"
state: "absent"
- name: Delete VPC stack
cloudformation:
region: "{{ aws_region }}"
stack_name: "{{ aws_cfn_vpc_stack_name }}"
state: "absent"
プレイブックを実行します。
$ ansible-playbook halt.yml
まとめ
Ansible を使って AWS の CloudFormation のスタックを作成および削除しました。入力パラメータを Ansible のインベントリに沿って管理でき、スタックの出力結果をプレイブックの中で変数として利用できますので、その他にもいくつかの処理が必要な場合には便利です。例えば、踏み台ホストの EIP を ~/.ssh/config
に追記することが考えられます。
シェルスクリプトだと書き方が人によってばらつきがあったり、条件による変数の使い分けが難しいことがありますので、Ansible のような構成管理ツールにまとめておくと便利な場面はあることでしょう。
環境補足
Vagrant を使って Ansible および Boto をインストールする場合は以下のようになります。
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "bento/ubuntu-16.04"
config.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y python-pip
pip install -U pip
pip install ansible==2.4.0
pip install boto3
SHELL
end
プレイブックの実行には Ansible Local を使っても良いでしょう。