はじめに
はじめまして、多田です。
最近は環境構築にAnsibleを利用することが多くなりましたが、調べているとAWSのようなクラウド環境の構築についてもAnsibleはその多くを標準モジュールとして備えているようですので、いくつか試してみました。
どこまでやるか
標準モジュールを利用したPlaybookを作成し、以下の内容の構築・設定を行えるようにする。
- セキュリティグループの作成
- EC2インスタンスの作成
- AMIの作成
- CloudWatchの設定(オートリカバリ)
前提
- AWSマネジメントコンソールで、サーバー構築に使用するIAMユーザが作成されていること
- AWSマネジメントコンソールで、キーペアを登録してあること
準備
Pythonインストール
pyenv でpythonをインストールします。
1 2 3 4 5 6 7 8 9 10 11 |
[vagrant@ansible ~]$ sudo yum install git [vagrant@ansible ~]$ curl -L https://raw.githubusercontent.com/yyuu/pyenv-installer/master/bin/pyenv-installer | bash [vagrant@ansible ~]$ echo 'export PATH="$HOME/.pyenv/bin:$PATH"' >> ~/.bashrc [vagrant@ansible ~]$ echo 'eval "$(pyenv init -)"' >> ~/.bashrc [vagrant@ansible ~]$ echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc [vagrant@ansible ~]$ source ~/.bashrc [vagrant@ansible ~]$ pyenv install 2.7.10 [vagrant@ansible ~]$ pyenv rehash [vagrant@ansible ~]$ pyenv global 2.7.10 [vagrant@ansible ~]$ python --version Python 2.7.10 |
Ansibleインストール
pipでAnsibleをインストールします。
1 2 3 |
[vagrant@ansible ~]$ pip install ansible [vagrant@ansible ~]$ ansible --version ansible 1.9.1 |
botoインストール
pipで boto をインストールします(AnsibleのAWS関連モジュールを利用するのに必要)。
1 2 3 |
[vagrant@ansible ~]$ pip install boto [vagrant@ansible ~]$ pip list | grep "boto" boto (2.38.0) |
API接続情報設定
IAMユーザ作成時に設定したAPIの接続情報を、環境変数に設定します。
1 2 3 4 5 |
[vagrant@ansible ~]$ export AWS_ACCESS_KEY_ID=アクセスキー [vagrant@ansible ~]$ export AWS_SECRET_ACCESS_KEY=シークレットアクセスキー [vagrant@ansible ~]$ env | grep "AWS_" AWS_ACCESS_KEY_ID=アクセスキー AWS_SECRET_ACCESS_KEY=シークレットアクセスキー |
Dynamic Inventoryファイルダウンロード
Ansibleのリポジトリから
ec2.ini と
ec2.py をダウンロードしておく。
Playbookの構成
├─ansible-playbook
├─development.yml
├─hosts
│ └─development
│ └─ec2.ini(準備段階でダウンロードした ec2.ini を設置する)
│ └─ec2.py(準備段階でダウンロードした ec2.py を設置する。実行権限を付与しておく)
├─roles
│ ├─ami
│ │ └─tasks
│ │ └─main.yml
│ ├─cloud_watch
│ │ └─tasks
│ │ └─main.yml
│ ├─ec2
│ │ └─tasks
│ │ └─main.yml
│ ├─security_group
│ │ └─tasks
│ │ └─main.yml
Playbookの中身
development.yml
master playbookです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
--- - hosts: localhost connection: local gather_facts: no roles: - role: security_group - role: ec2 vars: ami_image: ami-cbf90ecb key_name: ec2-key # AWSに登録したキーペア名を入力 my_ip: xxx.xxx.xxx.xxx/32 # アクセス元のIPアドレス group_name: "development" instance_type: "t2.micro" device_name: "/dev/xvda" device_type: "gp2" volume_size: 20 # EBSのディスクサイズ(GB) - hosts: tag_Name_development remote_user: ec2-user gather_facts: no roles: - role: ami - role: cloud_watch |
roles/security_group/tasks/main.yml
ec2_group モジュールを使って、セキュリティグループを作成します。
インバウンドはsshのみを許可し、アウトバウンドは全ての通信を許可します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
--- - name: セキュリティグループを作成 ec2_group: name: "{{ group_name }}" description: "{{ group_name }} server security group" region: ap-northeast-1 rules: - proto: tcp from_port: 22 to_port: 22 cidr_ip: "{{ my_ip }}" rules_egress: - proto: all from_port: 0 to_port: 65535 cidr_ip: 0.0.0.0/0 |
roles/ec2/tasks/main.yml
ec2 モジュールを使って、EC2インスタンスを作成します。
EC2インスタンスにはdevelopmentというタグを付けます。
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 |
--- - name: EC2インスタンスを作成 ec2: image: "{{ ami_image }}" instance_type: "{{ instance_type }}" region: ap-northeast-1 key_name: "{{ key_name }}" group: "{{ group_name }}" instance_tags: Name: "{{ group_name }}" wait: yes wait_timeout: 300 volumes: - device_name: "{{ device_name }}" device_type: "{{ device_type }}" volume_size: "{{ volume_size }}" delete_on_termination: yes register: ec2 - name: SSHで接続できるようになるまで待機 wait_for: port=22 host="{{ item.public_ip }}" timeout=300 state=started with_items: ec2.instances - name: 作成したEC2インスタンスをインベントリに追加 add_host: hostname="{{ item.public_ip }}" groupname="tag_Name_{{ group_name }}" with_items: ec2.instances |
roles/ami/tasks/main.yml
ec2_ami モジュールを使って、AMIを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
--- - name: EC2インスタンスの情報を取得 ec2_facts: - name: AMIを作成 local_action: module: ec2_ami delete_snapshot: "yes" description: "{{ ansible_ec2_security_groups }} server AMI" instance_id: "{{ ansible_ec2_instance_id }}" name: "{{ ansible_ec2_security_groups }}" no_reboot: "no" region: "ap-northeast-1" state: "present" wait: "yes" wait_timeout: 600 |
roles/cloud_watch/tasks/main.yml
ec2_metric_alarm モジュールを使って、CloudWatchの設定を行います。
Amazon Web Services ブログを参考に、オートリカバリを設定してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
--- - name: EC2インスタンスの情報を取得 ec2_facts: - name: オートリカバリを設定 local_action: module: ec2_metric_alarm alarm_actions: ["arn:aws:automate:ap-northeast-1:ec2:recover"] comparison: ">=" description: "Created from Ansible Playbook" dimensions: "{'InstanceId':'{{ ansible_ec2_instance_id }}'}" evaluation_periods: 3 metric: "StatusCheckFailed_System" name: "awsec2-{{ ansible_ec2_instance_id }}-High-Status-Check-Failed-System-" namespace: "AWS/EC2" period: 60 region: "ap-northeast-1" state: "present" statistic: "Minimum" threshold: 1.0 |
Playbookの実行
以下のようにしてPlaybookを実行すると、環境構築が行われます。
1 |
[vagrant@ansible ~]$ ansible-playbook -i hosts/development/ec2.py development.yml --private-key=EC2の秘密鍵 |
ポイント
role のうち、
ami と
cloud_watch
の実行には、対象EC2インスタンスのインスタンスIDが必要となります。
インスタンスIDは、ec2_facts モジュールで取得できますが、その前に対象ホストを特定する必要があります。
対象ホストのIPアドレスを直接指定することもできますが、Ansibleには dynamic_inventory という仕組みが用意されているので、こちらを利用して対象ホストを指定します。
嬉しい事に、AnsibleにはEC2用のdynamic_inventoryが標準で用意されています。
※準備段階でダウンロードした
ec2.ini と
ec2.py です。
development.yml(master playbook) で
hosts: tag_Name_development
という形で対象ホストを指定していますが、この場合は development というタグを付けたEC2インスタンスが対象ホストとなります。
ダウンロードしたec2.pyを直接実行してみるとわかりますが、タグ以外にもリージョンやインスタンスタイプ等で対象ホストを指定することもできるようです。
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 |
{ "_meta": { "hostvars": { "52.68.9.18": { } } }, "ami-cbf90ecb": [ "52.68.9.18" ], "ap-northeast-1": [ "52.68.9.18" ], "ap-northeast-1a": [ "52.68.9.18" ], "ec2": [ "52.68.9.18" ], "i-d2d3f721": [ "52.68.9.18" ], "security_group_manage": [ "52.68.9.18" ], "tag_Name_manage": [ "52.68.9.18" ], "type_t2_micro": [ "52.68.9.18" ], "vpc_id_vpc-b04d44d2": [ "52.68.9.18" ] } |