やったこと
ちょっとしたWebアプリをAWSに気軽にデプロイできるようにしたかったので、Terraformを使ってECRのDockerイメージをEC2にささっとデプロイしてみたメモ。
ちょっとしたものを気軽にデプロイしたいだけなので、以下のようなかなり手抜きな内容です。
- VPCを適当に構築
- IAMロールでEC2からECRへのアクセスを許可
- 80番ポートのみアクセスを許可したEC2を起動
- User DataでDockerのインストールからECR上のコンテナのデプロイまで実施
作ったもの
- シェルスクリプト
- userdata.sh
- Terraformのテンプレート
- main.tf
- variables.tf
- outputs.tf
各種ファイルの内容
userdata.sh
Dockerのインストールと指定したイメージの起動を行います。
IMAGE_NAMEの部分は適宜修正します。
userdata.sh
#!/bin/bash -eux
IMAGE_NAME=xxx.dkr.ecr.ap-northeast-1.amazonaws.com/my-nginx
sudo yum install -y docker
sudo systemctl enable docker
sudo systemctl start docker
aws ecr get-login --no-include-email --region ap-northeast-1 | sudo sh
sudo docker run -d -p 80:80 $IMAGE_NAME
BASE64にエンコードして、あとでmain.tfに貼り付けます。
$ cat userdata.sh | base64
IyEvYmluL2Jhc2ggLWV1eAoKSU1BR0VfTkFNRT14eHguZGtyLmVjci5hcC1ub3J0aGVhc3QtMS5hbWF6b25hd3MuY29tL215LW5naW54CgpzdWRvIHl1bSBpbnN0YWxsIC15IGRvY2tlcgpzdWRvIHN5c3RlbWN0bCBlbmFibGUgZG9ja2VyCnN1ZG8gc3lzdGVtY3RsIHN0YXJ0IGRvY2tlcgoKYXdzIGVjciBnZXQtbG9naW4gLS1uby1pbmNsdWRlLWVtYWlsIC0tcmVnaW9uIGFwLW5vcnRoZWFzdC0xIHwgc3VkbyBzaApzdWRvIGRvY2tlciBydW4gLWQgLXAgODA6ODAgJElNQUdFX05BTUUK
main.tf
長いファイルなので、Provider、VPC、IAM、EC2に分けて掲載します。
全体的にBasic Two-Tier AWS Architectureを参考にしています。
Provider
# ######## #
# Provider #
# ######## #
provider "aws" {
version = "~> 1.3"
region = "${var.aws_region}"
}
VPC
# ### #
# VPC #
# ### #
resource "aws_vpc" "default" {
cidr_block = "10.0.0.0/16"
}
resource "aws_internet_gateway" "default" {
vpc_id = "${aws_vpc.default.id}"
}
resource "aws_route" "internet_access" {
route_table_id = "${aws_vpc.default.main_route_table_id}"
destination_cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.default.id}"
}
resource "aws_subnet" "default" {
vpc_id = "${aws_vpc.default.id}"
cidr_block = "10.0.0.0/24"
map_public_ip_on_launch = true
}
IAM
# ### #
# IAM #
# ### #
resource "aws_iam_role" "instance_role" {
name = "instance_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
resource "aws_iam_policy_attachment" "ecs-role-attach" {
name = "ecs-role-attach"
roles = ["${aws_iam_role.instance_role.name}"]
policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
}
resource "aws_iam_instance_profile" "instance_role" {
name = "instance_role"
role = "${aws_iam_role.instance_role.name}"
}
EC2へのIAMロールの割り当てについては、以下を参考にしました。
- https://cross-black777.hatenablog.com/entry/2015/12/04/233206
- https://inokara.hateblo.jp/entry/2015/12/25/092605
EC2
# ### #
# EC2 #
# ### #
resource "aws_security_group" "default" {
description = "Used in the terraform"
vpc_id = "${aws_vpc.default.id}"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "instance" {
instance_type = "t2.micro"
ami = "${lookup(var.aws_amis, var.aws_region)}"
vpc_security_group_ids = ["${aws_security_group.default.id}"]
subnet_id = "${aws_subnet.default.id}"
iam_instance_profile = "instance_role"
user_data = "IyEvYmluL2Jhc2ggLWV1eAoKSU1BR0VfTkFNRT14eHguZGtyLmVjci5hcC1ub3J0aGVhc3QtMS5hbWF6b25hd3MuY29tL215LW5naW54CgpzdWRvIHl1bSBpbnN0YWxsIC15IGRvY2tlcgpzdWRvIHN5c3RlbWN0bCBlbmFibGUgZG9ja2VyCnN1ZG8gc3lzdGVtY3RsIHN0YXJ0IGRvY2tlcgoKYXdzIGVjciBnZXQtbG9naW4gLS1uby1pbmNsdWRlLWVtYWlsIC0tcmVnaW9uIGFwLW5vcnRoZWFzdC0xIHwgc3VkbyBzaApzdWRvIGRvY2tlciBydW4gLWQgLXAgODA6ODAgJElNQUdFX05BTUUK"
}
user_dataには、先ほどBase64でエンコードしたものを貼り付けています。
variables.tf
# ####### #
# Overall #
# ####### #
variable "aws_region" {
description = "AWS region to launch servers."
default = "ap-northeast-1"
}
# ### #
# EC2 #
# ### #
# Amazon Linux 2
variable "aws_amis" {
default = {
us-east-1 = "ami-b70554c8"
ap-northeast-1 = "ami-e99f4896"
}
}
outputs.tf
output "address" {
value = "http://${aws_instance.instance.public_ip}"
}
実行
$ terraform init
:
:
:
$ terraform apply
:
:
:
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
Outputs:
address = http://xxx.xxx.xxx.xxx
Outputsに表示されているURLにアクセスすると、無事Nginxのページが表示されました。
片付け
terraform destroy