前回の記事「Dockerコンテナで Ansible をテストする」で作成した Playbook を使用して EC2インスタンスを構築してみます。
新規のEC2インスタンス起動は、Terraform を使用し、OS設定変更、追加インストールは Ansible で実施します。
1. 既存のAWSリソースを Terraform で管理
Terraforming を使用すると、既存のAWSリソースを terraform の管理下に置けるようなので、試してみます。
既存の vpc とサブネットを Terraform の管理下に置いてみます。
最初は、既存の vpc です。
まず、既存のAWSリソースを参照して vpcのtf形式のファイルを作成します。 続けて、状態を管理する、terraform.tfstate を作成します。
[root@centos0702 terraform]# terraforming vpc > ./vpc.tf [root@centos0702 terraform]# terraforming vpc --tfstate > ./terraform.tfstate
次はサブネットです。
tf形式のファイルを作成後、terraform.tfstate にサブネットをマージします。
[root@centos0702 terraform]# terraforming sn > ./vpc_sn.tf [root@centos0702 terraform]# terraforming sn --tfstate --merge=./terraform.tfstate > ./work.tfstate [root@centos0702 terraform]# mv ./work.tfstate ./terraform.tfstate
terraform コマンドの refresh を実行して、既存の環境に合わせて、terraform.tfstate を最新化します。
[root@centos0702 terraform]# terraform refresh aws_subnet.subnet-f528a2ad-public-b: Refreshing state... (ID: subnet-f528a2ad) aws_vpc.dev: Refreshing state... (ID: vpc-d480c3b1) aws_subnet.subnet-ceb59087-public-a: Refreshing state... (ID: subnet-ceb59087)
terraform コマンドの plan を実行して Terraformと既存環境に差異があるかを確認します。
下記のように表示されたら差異はありません。
[root@centos0702 terraform]# terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. aws_vpc.dev: Refreshing state... (ID: vpc-d480c3b1) aws_subnet.subnet-ceb59087-public-a: Refreshing state... (ID: subnet-ceb59087) aws_subnet.subnet-f528a2ad-public-b: Refreshing state... (ID: subnet-f528a2ad) No changes. Infrastructure is up-to-date. This means that Terraform could not detect any differences between your configuration and the real physical resources that exist. As a result, Terraform doesn't need to do anything.
2. EC2インスタンスの作成
新規のEC2インスタンス用に tf形式のファイルを作成します。
内容は以下のとおり。
[root@centos0702 terraform]# cat ./ec2_centos6.tf resource "aws_instance" "centos6" { count = 1 ami = "ami-1c221e76" instance_type = "t2.micro" availability_zone = "us-east-1a" key_name = "virginia_key" iam_instance_profile = "admin" vpc_security_group_ids = [ "sg-bbf176df" ] subnet_id = "subnet-ceb59087" associate_public_ip_address = "true" root_block_device { volume_type = "gp2" volume_size = "8" delete_on_termination = "true" } tags { Name = "centos6" } }
plan を実行して変更箇所を確認します。
[root@centos0702 terraform]# terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. aws_subnet.subnet-f528a2ad-public-b: Refreshing state... (ID: subnet-f528a2ad) aws_vpc.dev: Refreshing state... (ID: vpc-d480c3b1) aws_subnet.subnet-ceb59087-public-a: Refreshing state... (ID: subnet-ceb59087) The Terraform execution plan has been generated and is shown below. Resources are shown in alphabetical order for quick scanning. Green resources will be created (or destroyed and then created if an existing resource exists), yellow resources are being changed in-place, and red resources will be destroyed. Cyan entries are data sources to be read. Note: You didn't specify an "-out" parameter to save this plan, so when "apply" is called, Terraform can't guarantee this is what will execute. + aws_instance.centos6 ami: "ami-1c221e76" associate_public_ip_address: "true" availability_zone: "us-east-1a" ebs_block_device.#: "<computed>" ephemeral_block_device.#: "<computed>" iam_instance_profile: "admin" instance_state: "<computed>" instance_type: "t2.micro" key_name: "virginia_key" network_interface_id: "<computed>" placement_group: "<computed>" private_dns: "<computed>" private_ip: "<computed>" public_dns: "<computed>" public_ip: "<computed>" root_block_device.#: "1" root_block_device.0.delete_on_termination: "true" root_block_device.0.iops: "<computed>" root_block_device.0.volume_size: "8" root_block_device.0.volume_type: "gp2" security_groups.#: "<computed>" source_dest_check: "true" subnet_id: "subnet-ceb59087" tags.%: "1" tags.Name: "centos6" tenancy: "<computed>" vpc_security_group_ids.#: "1" vpc_security_group_ids.1754483564: "sg-bbf176df" Plan: 1 to add, 0 to change, 0 to destroy.
apply でAWSリソースの変更を実施します。
[root@centos0702 terraform]# terraform apply aws_subnet.subnet-ceb59087-public-a: Refreshing state... (ID: subnet-ceb59087) aws_vpc.dev: Refreshing state... (ID: vpc-d480c3b1) aws_subnet.subnet-f528a2ad-public-b: Refreshing state... (ID: subnet-f528a2ad) aws_instance.centos6: Creating... ami: "" => "ami-1c221e76" associate_public_ip_address: "" => "true" availability_zone: "" => "us-east-1a" ebs_block_device.#: "" => "<computed>" ephemeral_block_device.#: "" => "<computed>" iam_instance_profile: "" => "admin" instance_state: "" => "<computed>" instance_type: "" => "t2.micro" key_name: "" => "virginia_key" network_interface_id: "" => "<computed>" placement_group: "" => "<computed>" private_dns: "" => "<computed>" private_ip: "" => "<computed>" public_dns: "" => "<computed>" public_ip: "" => "<computed>" root_block_device.#: "" => "1" root_block_device.0.delete_on_termination: "" => "true" root_block_device.0.iops: "" => "<computed>" root_block_device.0.volume_size: "" => "8" root_block_device.0.volume_type: "" => "gp2" security_groups.#: "" => "<computed>" source_dest_check: "" => "true" subnet_id: "" => "subnet-ceb59087" tags.%: "" => "1" tags.Name: "" => "centos6" tenancy: "" => "<computed>" vpc_security_group_ids.#: "" => "1" vpc_security_group_ids.1754483564: "" => "sg-bbf176df" aws_instance.centos6: Still creating... (10s elapsed) aws_instance.centos6: Still creating... (20s elapsed) aws_instance.centos6: Still creating... (30s elapsed) aws_instance.centos6: Still creating... (40s elapsed) aws_instance.centos6: Creation complete Apply complete! Resources: 1 added, 0 changed, 0 destroyed. The state of your infrastructure has been saved to the path below. This state is required to modify and destroy your infrastructure, so keep it safe. To inspect the complete state use the `terraform show` command. State path: terraform.tfstate
EC2 インスタンスのインスタンスID、パブリックIP、ステータスを確認します。
[root@centos0702 terraform]# terraform show aws_instance.centos6: id = i-06aa5902e65a0c49c ami = ami-1c221e76 associate_public_ip_address = true availability_zone = us-east-1a disable_api_termination = false ebs_block_device.# = 0 ebs_optimized = false ephemeral_block_device.# = 0 iam_instance_profile = admin instance_state = running instance_type = t2.micro key_name = virginia_key monitoring = false network_interface_id = eni-d78ba639 private_dns = ip-10-0-10-190.ec2.internal private_ip = 10.0.10.190 public_dns = ec2-52-90-3-23.compute-1.amazonaws.com public_ip = 52.90.3.23 root_block_device.# = 1 root_block_device.0.delete_on_termination = true root_block_device.0.iops = 100 root_block_device.0.volume_size = 8 root_block_device.0.volume_type = gp2 security_groups.# = 0 source_dest_check = true subnet_id = subnet-ceb59087 tags.% = 1 tags.Name = centos6 tenancy = default vpc_security_group_ids.# = 1 vpc_security_group_ids.1754483564 = sg-bbf176df aws_subnet.subnet-ceb59087-public-a: id = subnet-ceb59087 availability_zone = us-east-1a cidr_block = 10.0.10.0/24 map_public_ip_on_launch = true tags.% = 1 tags.Name = public-a vpc_id = vpc-d480c3b1 aws_subnet.subnet-f528a2ad-public-b: id = subnet-f528a2ad availability_zone = us-east-1b cidr_block = 10.0.11.0/24 map_public_ip_on_launch = true tags.% = 1 tags.Name = public-b vpc_id = vpc-d480c3b1 aws_vpc.dev: id = vpc-d480c3b1 cidr_block = 10.0.0.0/16 default_network_acl_id = acl-c67209a3 default_route_table_id = rtb-cdcc9ea8 default_security_group_id = sg-bbf176df dhcp_options_id = dopt-ffa5459a enable_classiclink = false enable_dns_hostnames = true enable_dns_support = true instance_tenancy = default main_route_table_id = rtb-cdcc9ea8 tags.% = 1 tags.Name = dev
試しに、awscli で EC2 インスタンスのステータスを確認してみます。
[root@centos0702 terraform]# aws ec2 describe-instances --instance-ids i-06aa5902e65a0c49c --query 'Reservations[].Instances[].{status:State.Name}' --output table ------------------- |DescribeInstances| +-----------------+ | status | +-----------------+ | running | +-----------------+
3. Ansibleの Playbook 実行
Ansible の Playbook を実行します。
パブリックIPと、キーペアの秘密鍵を指定します。
[root@centos0702 ansible]# env ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i ,52.90.3.23 --private-key ./virginia_key.pem ./centos6_basic.yml PLAY [all] ********************************************************************* TASK [setup] ******************************************************************* ok: [52.90.3.23] TASK [install libselinux-python] *********************************************** changed: [52.90.3.23] TASK [disable selinux] ********************************************************* changed: [52.90.3.23] TASK [disable ipv6] ************************************************************ changed: [52.90.3.23] TASK [set locale to /etc/sysconfig/i18n] *************************************** changed: [52.90.3.23] TASK [set zone to /etc/sysconfig/clock] **************************************** changed: [52.90.3.23] TASK [set localtime] *********************************************************** changed: [52.90.3.23] TASK [install ntp] ************************************************************* changed: [52.90.3.23] TASK [enable ntp service] ****************************************************** changed: [52.90.3.23] TASK [disable firewall] ******************************************************** changed: [52.90.3.23] => (item=iptables) changed: [52.90.3.23] => (item=ip6tables) TASK [awscli - epel] *********************************************************** changed: [52.90.3.23] TASK [awscli - python-pip] ***************************************************** changed: [52.90.3.23] TASK [awscli - pip install] **************************************************** changed: [52.90.3.23] TASK [codedeploy agent - yum] ************************************************** changed: [52.90.3.23] => (item=[u'git', u'gcc', u'openssl-devel', u'readline-devel', u'zlib-devel']) TASK [codedeploy agent - git clone rbenv] ************************************** changed: [52.90.3.23] TASK [codedeploy agent - git clone ruby_build] ********************************* changed: [52.90.3.23] TASK [codedeploy agent - /etc/profile.d/rbenv.sh] ****************************** changed: [52.90.3.23] => (item={u'lin': u'export RBENV_ROOT=/opt/rbenv', u'reg': u'^export RBENV_ROOT='}) changed: [52.90.3.23] => (item={u'lin': u'export PATH="${RBENV_ROOT}/bin:${PATH}"', u'reg': u'^export PATH='}) changed: [52.90.3.23] => (item={u'lin': u'eval "$(rbenv init -)"', u'reg': u'^eval '}) TASK [codedeploy agent - rbenv install 2.2.4] ********************************** changed: [52.90.3.23] [WARNING]: Consider using 'become', 'become_method', and 'become_user' rather than running sudo TASK [codedeploy agent - rbenv grobal 2.2.4] *********************************** changed: [52.90.3.23] TASK [codedeploy agent - /usr/bin/ruby] **************************************** changed: [52.90.3.23] TASK [codedeploy agent - wget (N.Virginia)] ************************************ changed: [52.90.3.23] TASK [codedeploy agent - script chmod] ***************************************** changed: [52.90.3.23] TASK [codedeploy agent - install auto] ***************************************** changed: [52.90.3.23] TASK [ssm agent - wget (N.Virginia)] ******************************************* changed: [52.90.3.23] TASK [ssm agent - rpm] ********************************************************* changed: [52.90.3.23] PLAY RECAP ********************************************************************* 52.90.3.23 : ok=25 changed=24 unreachable=0 failed=0
これで構築は完了です。
[root@centos0702 ansible]# aws ec2 stop-instances --instance-ids i-06aa5902e65a0c49c { "StoppingInstances": [ { "InstanceId": "i-06aa5902e65a0c49c", "CurrentState": { "Code": 64, "Name": "stopping" }, "PreviousState": { "Code": 16, "Name": "running" } } ] } [root@centos0702 ansible]# aws ec2 describe-instances --instance-ids i-06aa5902e65a0c49c --query 'Reservations[].Instances[].{status:State.Name}' --output table ------------------- |DescribeInstances| +-----------------+ | status | +-----------------+ | stopped | +-----------------+ [root@centos0702 ansible]# aws ec2 start-instances --instance-ids i-06aa5902e65a0c49c { "StartingInstances": [ { "InstanceId": "i-06aa5902e65a0c49c", "CurrentState": { "Code": 0, "Name": "pending" }, "PreviousState": { "Code": 80, "Name": "stopped" } } ] } [root@centos0702 ansible]# aws ec2 describe-instances --instance-ids i-06aa5902e65a0c49c --query 'Reservations[].Instances[].{status:State.Name}' --output table ------------------- |DescribeInstances| +-----------------+ | status | +-----------------+ | running | +-----------------+
[root@centos0702 terraform]# terraform refresh aws_instance.centos6: Refreshing state... (ID: i-06aa5902e65a0c49c) aws_subnet.subnet-f528a2ad-public-b: Refreshing state... (ID: subnet-f528a2ad) aws_vpc.dev: Refreshing state... (ID: vpc-d480c3b1) aws_subnet.subnet-ceb59087-public-a: Refreshing state... (ID: subnet-ceb59087) [root@centos0702 terraform]# terraform show | grep public_ip associate_public_ip_address = true public_ip = 52.90.228.249 map_public_ip_on_launch = true map_public_ip_on_launch = true
EC2インスタンスにログインできるか確認します。
[root@centos0702 ansible]# ssh -l centos -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ./virginia_key.pem 52.90.228.249 Last login: Tue Jan 17 18:06:38 2017 from 153.212.112.174 [centos@ip-10-0-10-190 ~]$ exit logout Connection to 52.90.228.249 closed.
4. EC2インスタンスの破棄
不要になったEC2インスタンスを terraform で破棄します。
破棄するEC2インスタンスを指定して 実行計画を ec2_destory.plan ファイルに保存します。
[root@centos0702 terraform]# ./terraform plan -destroy -target=aws_instance.centos6 -out ./ec2_destory.plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. aws_instance.centos6: Refreshing state... (ID: i-06aa5902e65a0c49c) The Terraform execution plan has been generated and is shown below. Resources are shown in alphabetical order for quick scanning. Green resources will be created (or destroyed and then created if an existing resource exists), yellow resources are being changed in-place, and red resources will be destroyed. Cyan entries are data sources to be read. Your plan was also saved to the path below. Call the "apply" subcommand with this plan file and Terraform will exactly execute this execution plan. Path: ./ec2_destory.plan - aws_instance.centos6 Plan: 0 to add, 0 to change, 1 to destroy.
実行計画をAWSリソースに適用して、EC2インスタンスをターミネートします。
[root@centos0702 terraform]# terraform apply ./ec2_destory.plan aws_instance.centos6: Destroying... aws_instance.centos6: Still destroying... (10s elapsed) aws_instance.centos6: Still destroying... (20s elapsed) aws_instance.centos6: Still destroying... (30s elapsed) aws_instance.centos6: Still destroying... (40s elapsed) aws_instance.centos6: Still destroying... (50s elapsed) aws_instance.centos6: Still destroying... (1m0s elapsed) aws_instance.centos6: Still destroying... (1m10s elapsed) aws_instance.centos6: Destruction complete Apply complete! Resources: 0 added, 0 changed, 1 destroyed.
awscli でステータスを確認します。
[root@centos0702 terraform]# aws ec2 describe-instances --instance-ids i-06aa5902e65a0c49c --query 'Reservations[].Instances[].{status:State.Name}' --output table ------------------- |DescribeInstances| +-----------------+ | status | +-----------------+ | terminated | +-----------------+