AWS
Table of Contents
Reference
Resources
awseip
resource "aws_eip" "main" {
count = "${var.num_hosts_eip}"
instance = "${aws_instance.main.*.id}"
# terraform tries to modify all eips when `count` changes.
# This is a workaround for this.
# SEE: https://github.com/hashicorp/terraform/issues/4944#issuecomment-248884637
lifecycle {
ignore_changes = ["instance"]
}
}
awselasticsearchdomain
resource "aws_elasticsearch_domain" "main" {
domain_name = "my-domain"
elasticsearch_version = "5.1"
cluster_config {
instance_type = "m3.medium.elasticsearch"
instance_count = 3
}
ebs_options {
ebs_enabled = true
volume_type = "gp2"
volume_size = "30" # in GBs per data instance
}
}
awselb
resource "aws_elb" "endpoint" {
name = "my-elb"
subnets = ["${var.subnet_ids}"]
security_groups = ["${var.security_groups}"]
instances = ["${aws_instance.cluster.*.id}"]
internal = true
listener {
instance_port = 8080
instance_protocol = "http"
lb_port = 80
lb_protocol = "http"
}
health_check {
target = "HTTP:8080/"
timeout = 5
interval = 30
unhealthy_threshold = 2
healthy_threshold = 10
}
tags {
Cluster = "${var.cluster}"
}
}
awsiamrole
resource "aws_iam_role" "main" {
name = "${var.name}"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
resource "aws_iam_role_policy" "kinesis" {
name = "${aws_iam_role.main.name}-kinesis"
role = "${aws_iam_role.main.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"kinesis:DescribeStream",
"kinesis:GetRecords",
"kinesis:GetShardIterator",
"kinesis:ListStreams",
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "${var.kinesis_arn}"
}
]
}
EOF
}
resource "aws_iam_role_policy" "cloudwatch" {
name = "${aws_iam_role.main.name}-cloudwatch"
role = "${aws_iam_role.main.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
EOF
}
# Needs a few seconds to replicate your new role through all regions.
# SEE: http://stackoverflow.com/questions/37503075/invalidparametervalueexception-the-role-defined-for-the-function-cannot-be-assu
resource "null_resource" "sleep" {
triggers {
role = "${aws_iam_role.main.arn}"
}
provisioner "local-exec" {
command = "sleep 15"
}
}
awslambdafunction
data "archive_file" "code" {
type = "zip"
source_file = "${path.module}/main.py"
output_path = "${path.module}/lambda.zip"
}
resource "aws_lambda_function" "main" {
function_name = "lambda-kinesis"
filename = "${data.archive_file.code.output_path}"
source_code_hash = "${data.archive_file.code.output_base64sha256}"
handler = "main.handle"
runtime = "python2.7"
role = "${var.role_arn}"
memory_size = 128
timeout = 10
environment {
variables {
MY_ENV = "test"
}
}
}
resource "aws_lambda_event_source_mapping" "kinesis" {
function_name = "${aws_lambda_function.main.arn}"
event_source_arn = "${var.kinesis_arn}"
batch_size = 1000
starting_position = "LATEST"
}
awsrdscluster
awsrdsclusterinstance
resource "aws_rds_cluster" "cluster" {
db_cluster_parameter_group_name = "default.aurora5.6"
cluster_identifier = "mydb"
db_subnet_group_name = "default-vpc-abcd1234"
vpc_security_group_ids = ["${data.terraform_remote_state.vpc.sg_default}"]
availability_zones = ["ap-northeast-1a", "ap-northeast-1c"]
skip_final_snapshot = true
database_name = "mydb"
master_username = "root"
master_password = "1234"
}
resource "aws_rds_cluster_instance" "node" {
count = 2
instance_class = "db.t2.medium"
identifier = "mydb-${count.index}"
cluster_identifier = "${aws_rds_cluster.cluster.id}"
db_subnet_group_name = "default-vpc-abcd1234"
}
awsdefaultsecuritygroups
When creating a VPC
, AWS automatically creates a default
security group that can not be deleted To manage it with Terraform, Terraform provides a dedicated resource type. Before you make any changes, be sure to read the link below.
resource "aws_default_security_group" "default" {
vpc_id = "${aws_vpc.main.id}"
ingress {
from_port = 0
to_port = 0
protocol = "-1"
security_groups = []
self = true
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
}
awssecuritygroup
resource "aws_security_group" "default" {
name = "${var.project}-default"
vpc_id = "${aws_vpc.main.id}"
ingress {
from_port = 0
to_port = 0
protocol = "-1" # all
security_groups = []
self = true
}
egress {
from_port = 0
to_port = 0
protocol = "-1" # all
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_security_group" "icmp" {
name = "${var.project}-icmp"
vpc_id = "${aws_vpc.main.id}"
ingress {
from_port = -1 # all
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_security_group" "ping" {
name = "${var.project}-ping"
vpc_id = "${aws_vpc.main.id}"
ingress {
from_port = 8 # echo
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_security_group" "ssh" {
name = "${var.project}-ssh"
vpc_id = "${aws_vpc.main.id}"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
Data Sources
awsami
data "aws_ami" "ubuntu1604" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}
data "aws_ami" "my_image1" {
most_recent = true
filter {
name = "state"
values = ["available"]
}
filter {
name = "tag:Name"
values = ["My Image"]
}
}
data "aws_ami" "my_image2" {
most_recent = true
filter {
name = "state"
values = ["available"]
}
filter {
name = "name"
values = ["my-image-*"]
}
}
How-to
Set up a VPC
terrafrom
will hang when destroying subnets if there are running instances on them.
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags {
Name = "main"
}
}
resource "aws_subnet" "main_public_a" {
vpc_id = "${aws_vpc.main.id}"
cidr_block = "10.0.0.0/20"
availability_zone = "eu-west-1a"
tags {
Name = "main-public-a"
}
}
resource "aws_internet_gateway" "main" {
vpc_id = "${aws_vpc.main.id}"
tags {
Name = "main"
}
}
resource "aws_route_table" "main" {
vpc_id = "${aws_vpc.main.id}"
route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.main.id}"
}
tags {
Name = "main"
}
}
resource "aws_main_route_table_association" "main" {
vpc_id = "${aws_vpc.main.id}"
route_table_id = "${aws_route_table.main.id}"
}
Create an instance
data "aws_ami" "ubuntu1404" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}
resource "aws_instance" "main" {
ami = "${data.aws_ami.ubuntu1404.id}"
instance_type = "t2.micro"
# Even though there's aws_key_pair,
# it's better to create a new one on web console manually.
key_name = "${var.key_name}"
subnet_id = "${data.terraform_remote_state.vpc.main_public_a}"
}
resource "aws_eip" "main" {
instance = "${aws_instance.main.id}"
}
Create an instance profile
resource "aws_iam_instance_profile" "main" {
name = "my-profile"
role = "${aws_iam_role.main.name}"
}
resource "aws_iam_role" "main" {
name = "my-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy" "main" {
name = "my-role-allow-s3"
role = "${aws_iam_role.main.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"${aws_s3_bucket.main.arn}"
]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": [
"${aws_s3_bucket.main.arn}/*"
]
}
]
}
EOF
}
Set up static website with S3
resource "aws_s3_bucket" "main" {
bucket = "${var.bucket}"
policy = <<EOF
{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Principal": "*",
"Action": ["s3:GetObject"],
"Resource": ["arn:aws:s3:::${var.bucket}/*"]
}
]
}
EOF
website {
index_document = "index.html"
error_document = "index.html" # SPA
}
}