この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
2021年9月30日にクラウドコントロールAPIがGA(一般提供開始)しました。
従来、各サービスごとにバラバラだったAPIの使い方を、一貫した方法で使えるようにしたAPIです。またAWSサービスのみならず CloudFormation Registry で利用可能なサードパーティー製ソリューションもこのAPIを通して利用可能です。
前回、このクラウドコントロールAPIをTerraformのaws provider経由で使ってみました。
今回はTerraform経由でのもう一つの使い方をご紹介します。クラウドコントロールAPI専用のprovider「awscc」がリリースされていますのでこれを使ってみます。
なおこのproviderは現在tech previewです。本番環境での利用はまだ控えておきましょう。
使ってみた
前回と同様、このproviderを使って2AZにそれぞれPublicとPrivateサブネットを持つような一般的なVPC構成を作ってみたいと思います。
Terraformとproviderの定義
terraform {
required_version = "1.0.10"
required_providers {
awscc = {
source = "hashicorp/awscc"
version = "0.4.0"
}
}
}
provider "awscc" {
region = "ap-northeast-1"
}
普通のproviderの設定ですね。
認証
認証はaws providerと同様、多様な方法で可能です。アクセスキー・シークレットキーを providerブロックのattributeで渡す、環境変数にセットする、profile attributeを使う、AWS_PROFILE環境変数を使うなど。 AWS SSO Profileも使えました。
まずはVPCだけ
こんな感じのコードです。
resource "awscc_ec2_vpc" "vpc" {
cidr_block = "192.168.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
instance_tenancy = "default"
tags = [{
key = "Name"
value = "basic-vpc"
}]
}
前回試したaws providerでクラウドコントロールAPIを使う例では、どんなリソースを作る場合でもaws_cloudcontrolapi_resource
を使い、そのtype_name
値を切り替えることでプロビジョニングするリソースを切り替えていました。が、この awscc providerはリソースごとにResourceが定義されています。
aws providerのaws_cloudcontrolapi_resourceでVPCをプロビジョニングする例1
resource "aws_cloudcontrolapi_resource" "vpc" {
type_name = "AWS::EC2::VPC"
desired_state = jsonencode({
CidrBlock = "192.168.0.0/16"
EnableDnsSupport = true
EnableDnsHostnames = true
InstanceTenancy = "default"
Tags = [{
Key = "Name"
Value = "plain-vpc"
}]
})
}
aws providerのaws_cloudcontrolapi_resourceでVPCをプロビジョニングする例2
resource "aws_cloudcontrolapi_resource" "vpc" {
type_name = "AWS::EC2::VPC"
desired_state = jsonencode(yamldecode(
<<-EOT
CidrBlock: "192.168.0.0/16"
EnableDnsSupport: true
EnableDnsHostnames: true
InstanceTenancy: default
Tags:
- Key: Name
Value: "plain-vpc"
EOT
))
}
aws_cloudcontrolapi_resource
はリソースのプロパティを desired_state
attribute以下にJSON型で押し込む形になっています。そのためjsonencode()
などを挟まないと書きにくいです。この点awsccはより簡潔に書けて良いと思います。
以下はaws providerのaws_vpc
リソースを使った、つまり一般的なTerraformでのVPCの書き方ですが、ほとんど前述のawsccのコードと同じですよね。
resource "aws_vpc" "vpc" {
cidr_block = "192.168.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
instance_tenancy = "default"
tags = {
Name = "plain-vpc"
}
}
他のリソースも
全体のコードは以下のようになりました。前回aws providerのaws_cloudcontrolapi_resource
でやったときと同様、一部リソースがクラウドコントロールAPIでは未対応だったのでその部分はaws providerを使っています。
terraform {
required_version = "1.0.10"
required_providers {
awscc = {
source = "hashicorp/awscc"
version = "0.4.0"
}
aws = {
source = "hashicorp/aws"
version = "3.63.0"
}
}
}
provider "awscc" {
region = "ap-northeast-1"
}
provider "aws" {
region = "ap-northeast-1"
}
resource "awscc_ec2_vpc" "vpc" {
cidr_block = "192.168.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
instance_tenancy = "default"
tags = [{
key = "Name"
value = "basic-vpc"
}]
}
# public subnet
resource "aws_internet_gateway" "igw" {
vpc_id = awscc_ec2_vpc.vpc.id
tags = {
Name = "basic-vpc-igw"
}
}
data "aws_availability_zones" "az" {}
resource "aws_subnet" "public" {
count = 2
vpc_id = awscc_ec2_vpc.vpc.id
cidr_block = cidrsubnet(awscc_ec2_vpc.vpc.cidr_block, 8, count.index)
availability_zone = data.aws_availability_zones.az.names[count.index]
map_public_ip_on_launch = true
tags = {
Name = "basic-vpc-public-subnet-${count.index + 1}"
}
}
resource "awscc_ec2_route_table" "public" {
vpc_id = awscc_ec2_vpc.vpc.id
tags = [{
key = "Name"
value = "basic-vpc-public-subnet-rtb"
}]
}
resource "aws_route" "public" {
route_table_id = awscc_ec2_route_table.public.id
gateway_id = aws_internet_gateway.igw.id
destination_cidr_block = "0.0.0.0/0"
}
resource "awscc_ec2_subnet_route_table_association" "public" {
count = 2
route_table_id = awscc_ec2_route_table.public.id
subnet_id = aws_subnet.public.*.id[count.index]
}
# private subnet
resource "aws_subnet" "private" {
count = 2
vpc_id = awscc_ec2_vpc.vpc.id
cidr_block = cidrsubnet(awscc_ec2_vpc.vpc.cidr_block, 8, count.index + 2)
availability_zone = data.aws_availability_zones.az.names[count.index]
map_public_ip_on_launch = false
tags = {
Name = "basic-vpc-private-subnet-${count.index + 1}"
}
}
resource "awscc_ec2_route_table" "private" {
vpc_id = awscc_ec2_vpc.vpc.id
tags = [{
key = "Name"
value = "basic-vpc-private-subnet-rtb"
}]
}
resource "awscc_ec2_subnet_route_table_association" "private" {
count = 2
route_table_id = awscc_ec2_route_table.private.id
subnet_id = aws_subnet.private.*.id[count.index]
}
使ってみた感想
先に書いたとおり、aws providerのaws_cloudcontrolapi_resource
よりは書きやすい、読みやすいと思います。が、クラウドコントロールAPIの一番のユースケースは、aws providerで未対応のリソースをプロビジョニングしたいとき、です。この観点で言うとaws_cloudcontrolapi_resource
に軍配が上がるかなと思います。aws_cloudcontrolapi_resource
は該当リソースがクラウドコントロールAPIに対応してさえいればすぐ使うことができます。対してこのawscc providerはproviderのバージョンアップで対応リソースが増えない限りは使うことができません。どんどん対応リソースは増えているようですが…
将来的に、awsccでプロビジョニングできるリソースの種類がaws providerと同じくらいになったら、awsccが覇権を握る未来が来るかもしれません。