この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
こんにちは、中山です。
Terraformのv0.6.16がリリースされました。本エントリではAWS関連の更新内容についてCHANGELOGをもとにまとめたいと思います。また、私が気になった部分をいくつかピックアップしてご紹介します。
新規追加Resource
リソース名 | 主な機能 | Issue | 参考URL |
---|---|---|---|
aws_api_gateway_account | API Gateway Accountを操作する | #6321 | Specify a Stage's Settings in API Gateway |
aws_api_gateway_authorizer | API Gateway Authorizerを設定する | #6320 | Enable Amazon API Gateway Custom Authorization |
aws_db_event_subscription | RDSのイベントを取得する | #6367 | 【AWS】RDS入門/イベントをメールで通知してみよう |
aws_db_option_group | RDSのオプショングループを設定する | #4401 | Amazon RDS MySQL 5.6と新機能を試してみた |
aws_eip_association | 既存EIPをAWSリソースに関連付ける | #6552 | N/A |
既存Resource/Provider/Backend改善点
リソース名 | 改善点 | Issue |
---|---|---|
aws_opswork_stack | agent_version オプションの追加 |
#6493 |
api_gateway_method api_gateway_integration |
request_parameters_in_json オプションの追加 |
#6501 |
api_gateway_integration_response api_gateway_integration_response |
response_parameters_in_json オプションの追加 |
#6344 |
aws_cloudfront_dirstribution | s3_origin_config と custom_origin_config が指定されていない場合、エラーとならないように origin_access_identity を空にする処理を追加 |
#6487 |
aws_iam_server_certificate | エラー処理の改善 | #6442 |
aws | allowed_account_ids または forbidden_account_ids オプションを利用する際、アカウント情報を取得する方法に sts:GetCallerIdentity を追加 |
#6385 |
aws_redshift_cluster | automated_snapshot_retention_period オプションのデフォルト値を1であると明示的に指定して、 内部的にエラーが発生する可能性を低減させる処理を追加 |
#6537 |
aws_cloudfront_dirstribution | hosted_zone_id の追加 |
#6530 |
S3 Backend | S3 Backend利用時にAWSクレデンシャルを取得する処理がaws providerと同じになった | #5270 |
ピックアップ
aws_cloudfront_dirstribution
のattributeに hosted_zone_id
が追加
aws_s3_bucket
や aws_elb
リソースにはALIASレコードを設定する際に利用する hosted_zone_id
というattributeがあります。今回のアップデートで aws_cloudfront_dirstribution
にもこのattributeが追加されました。今まででもCloudFrontのHosted Zone IdをハードコードしてあげればALIASレコードの作成はできたのですが、attributeとして追加されることでより簡単に利用することができるようになりました。
以下にCloudFrontのドメインに対してALIASレコードを設定するサンプルコードを記載します。ドメインは適当なものに読み替えてください。
variable "name" {
default = "ap-northeast-1-cloudfront-hosted-zone-id-demo"
}
variable "region" {
default = "ap-northeast-1"
}
variable "site_domain" {
default = "*********.**."
}
provider "aws" {
region = "${var.region}"
}
resource "template_file" "s3" {
template = <<EOT
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadForGetBucketObjets",
"Effect": "Allow",
"Principal": "*",
"Action": ["s3:GetObject"],
"Resource": ["arn:aws:s3:::${bucket_name}/*"]
}
]
}
EOT
vars {
bucket_name = "${var.name}"
}
}
resource "aws_s3_bucket" "s3" {
bucket = "${var.name}"
acl = "public-read"
force_destroy = true
policy = "${template_file.s3.rendered}"
website {
index_document = "index.html"
}
}
resource "aws_s3_bucket_object" "s3" {
bucket = "${aws_s3_bucket.s3.bucket}"
key = "index.html"
source = "${concat(path.module, "/", "index.html")}"
content_type = "text/html"
}
resource "aws_cloudfront_distribution" "cf" {
enabled = true
comment = "${var.name}"
default_root_object = "index.html"
price_class = "PriceClass_200"
retain_on_delete = true
origin {
domain_name = "${concat(aws_s3_bucket.s3.id, ".s3.amazonaws.com")}"
origin_id = "${var.name}"
}
default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "${aws_s3_bucket.s3.id}"
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
viewer_protocol_policy = "allow-all"
min_ttl = 0
default_ttl = 3600
max_ttl = 86400
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
viewer_certificate {
cloudfront_default_certificate = true
}
}
resource "aws_route53_zone" "dns" {
name = "${var.site_domain}"
}
resource "aws_route53_record" "dns" {
zone_id = "${aws_route53_zone.dns.zone_id}"
name = "${concat("cf.", var.site_domain)}"
type = "A"
alias {
name = "${aws_cloudfront_distribution.cf.domain_name}"
zone_id = "${aws_cloudfront_distribution.cf.hosted_zone_id}"
evaluate_target_health = true
}
}
output "website_endpoint" {
value = "${aws_s3_bucket.s3.website_endpoint}"
}
output "cloudfront_domain_name" {
value = "${aws_cloudfront_distribution.cf.domain_name}"
}
output "cloudfront_hosted_zone_id" {
value = "${aws_cloudfront_distribution.cf.hosted_zone_id}"
}
output "alias_record_fqdn" {
value = "${aws_route53_record.dns.fqdn}"
}
まずはテスト用にCloudFrontでキャッシュさせる index.html
を作成しておきます。
$ echo 'Hello, World!' > index.html
続いてTerraformを実行します。
$ terraform apply
<snip>
Outputs:
alias_record_fqdn = cf.*********.**
cloudfront_domain_name = d2t6keum07cvba.cloudfront.net
cloudfront_hosted_zone_id = Z2FDTNDATAQYW2
website_endpoint = ap-northeast-1-cloudfront-hosted-zone-id-demo.s3-website-ap-northeast-1.amazonaws.com
今回の例ではCloudFrontのドメイン名が d2t6keum07cvba.cloudfront.net
です。レコードセットの内容を確認してみましょう。
$ aws route53 list-resource-record-sets \
--hosted-zone-id "$(aws route53 list-hosted-zones --query 'HostedZones[].Id' --output text | cut -d/ -f3)" \
--query 'ResourceRecordSets[2]'
{
"AliasTarget": {
"HostedZoneId": "Z2FDTNDATAQYW2",
"EvaluateTargetHealth": true,
"DNSName": "d2t6keum07cvba.cloudfront.net."
},
"Type": "A",
"Name": "cf.*********.**."
}
正常に登録されているようですね。続いて実際にアクセスしてみましょう。
$ curl cf.*********.**.
Hello, World!
上記のように「Hello, World!」と表示されたら成功です。わざわざCloudFrontのHosted Zone IDを指定せずに済むのは地味に便利ですね。
aws_eip_association
により既存EIPの割当が可能になった
今まではTerraformでEIPを利用する場合 aws_eip
を使用し、新規にEIPを作成してからAWSリソースへ関連付けるという作業が必要でした。つまり、すでに作成済みのEIPを割り当てられないという問題がありました。しかし、 aws_eip_association
リソースの追加により既存EIPをAWSリソースに対して割り当てられるようになりました。実際に試してみましょう。
まずはテスト用のEIPを作成します。
$ aws ec2 allocate-address
{
"PublicIp": "52.69.11.29",
"Domain": "vpc",
"AllocationId": "eipalloc-b9bfdbdc"
}
一時的に利用しているのでEIPの情報出してますが、割り当てられたパブリックIPが 52.69.11.29
で、 AllocationId
が eipalloc-b9bfdbdc
です。このEIPをEC2インスタンスに割り当ててみたいと思います。
サンプルコードが以下になります。関連する部分をハイライトしています。
variable "name" {
default = "test"
}
variable "region" {
default = "ap-northeast-1"
}
variable "vpc_cidr" {
default = "172.16.0.0/16"
}
variable "az" {
default = "ap-northeast-1a"
}
variable "public_subnet" {
default = "172.16.0.0/24"
}
variable "web_instance_type" {
default = "t2.micro"
}
variable "web_instance_ami_id" {
default = "ami-29160d47"
}
variable "allocation_id" {
default = "eipalloc-b9bfdbdc"
}
variable "key_name" {
default = "*****"
}
provider "aws" {
region = "${var.region}"
}
resource "aws_vpc" "vpc" {
cidr_block = "${var.vpc_cidr}"
enable_dns_support = true
enable_dns_hostnames = true
}
resource "aws_internet_gateway" "public" {
vpc_id = "${aws_vpc.vpc.id}"
}
resource "aws_subnet" "public" {
vpc_id = "${aws_vpc.vpc.id}"
cidr_block = "${var.public_subnet}"
availability_zone = "${var.az}"
map_public_ip_on_launch = true
}
resource "aws_route_table" "public" {
vpc_id = "${aws_vpc.vpc.id}"
route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.public.id}"
}
}
resource "aws_route_table_association" "public" {
subnet_id = "${aws_subnet.public.id}"
route_table_id = "${aws_route_table.public.id}"
}
resource "aws_network_acl" "acl" {
vpc_id = "${aws_vpc.vpc.id}"
subnet_ids = ["${aws_subnet.public.id}"]
ingress {
protocol = "-1"
rule_no = 100
action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 0
to_port = 0
}
egress {
protocol = "-1"
rule_no = 100
action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 0
to_port = 0
}
}
resource "aws_security_group" "web" {
name = "${var.name}-web"
vpc_id = "${aws_vpc.vpc.id}"
description = "${var.name}-SG"
ingress {
from_port = 22
to_port = 22
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" "web" {
ami = "${var.web_instance_ami_id}"
instance_type = "${var.web_instance_type}"
vpc_security_group_ids = ["${aws_security_group.web.id}"]
subnet_id = "${aws_subnet.public.id}"
key_name = "${var.key_name}"
associate_public_ip_address = true
root_block_device {
volume_type = "gp2"
volume_size = 8
}
}
resource "aws_eip_association" "eip" {
instance_id = "${aws_instance.web.id}"
allocation_id = "${var.allocation_id}"
}
output "web_public_ip" {
value = "${aws_eip_association.eip.public_ip}"
}
実行してみましょう。
$ terraform apply
<snip>
Outputs:
web_public_ip = 52.69.11.29
該当のIPがEC2インスタンスに割り当てられたようです。SSHしてみましょう。
$ ssh -i path/to/keypair ec2-user@52.69.11.29
<snip>
__| __|_ )
_| ( / Amazon Linux AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-ami/2016.03-release-notes/
[ec2-user@ip-172-16-0-66 ~]$
ちゃんとEIPが関連付けられたようですね。
まとめ
いかがだったでしょうか。
Terraformはズッ友だよ。
本エントリがみなさんの参考になったら幸いに思います。