CDK for Terraform で適当にEC2インスタンスをデプロイしてみた
はじめに
CDK for Terraformが7/17にリリースされましたね。
まだGAではないので、検証がてら遊んでみようと思います。
環境準備
今回の環境は以下の通りです。
$ cat /etc/issue Amazon Linux AMI release 2018.03 $ node --version v12.18.2 $ npm --version 6.14.5 $ yarn version yarn version v1.22.4 $ terraform version Terraform v0.12.28 $ yarn -s cdktf --version 0.0.12
それでは、上述のサービスのインストール及び、アップグレードの方法から紹介していきます。
node.js / npm
まずはnode.jsとnpmです。
Cloud9のAMI使用していますが、デフォルト入っているnodeのバージョンが0.10だったので、アップグレードしていきます。
// リポジトリの追加 $ sudo su - > curl -sL https://rpm.nodesource.com/setup_12.x | bash - // node.jsのアップグレード > yum update nodejs // バージョン確認 > node --version > nom --version
yarn
yarnはインストールされていなかったようなので、インストールしていきます。
// リポジトリの追加 > wget https://dl.yarnpkg.com/rpm/yarn.repo -O /etc/yum.repos.d/yarn.repo // yarnのインストール > yum install yarn // バージョン確認 > yarn version
terraform
Terraformのインストールです。
上述の参考サイトにある通り、terraformがインストールされていない状態で、CDK for Terraform(cdktf-cli)をインストールしようとすると怒られます。
なお、Terraformがインストールされていない環境で実行すると # Terraform CLI not present - Please install a current version https://learn.hashicorp.com/terraform/getting-started/install.html とエラーが表示されます、事前にインストールしておいてください。
AWS CDKでプロバイダーとしてTerraformが使える!!CDK for Terraformが発表されました!! #awscdk | Developers.IO
インストール手順は以下の通りです。
// terraform用のディレクトリを用意 > mkdir /opt/terra_0_12_28/ // zipファイルのダウンロード > wget https://releases.hashicorp.com/terraform/0.12.28/terraform_0.12.28_linux_amd64.zip // zipを先に作成したディレクトリに解凍 > unzip -d /opt/terra_0_12_28/ /home/ec2-user/environment/terraform_0.12.28_linux_amd64.zip // 後ほど/opt/terraformにパスを通すので、シンボリックリンクを作成 > ln -sfn /opt/terra_0_12_28 /opt/terraform // パスを通す > vi /etc/profile (以下を追記) export PATH=$PATH:/opt/terraform/ // /etc/profile読み込み > source /etc/profile // 一般ユーザーでもパスが通っていることを確認 > exit $ which terraform // バージョン確認 $ terraform version
EC2インスタンスのデプロイ
早速以下の通り、EC2インスタンスをデプロイするように、main.tsファイルを編集してみました。
main.ts
import { Construct } from 'constructs'; import { App, TerraformStack, Token } from 'cdktf'; import { AwsProvider } from './.gen/providers/aws'; import { Vpc } from './.gen/providers/aws/vpc'; import { Subnet } from './.gen/providers/aws/subnet'; import { RouteTable } from './.gen/providers/aws/route-table'; import { RouteTableAssociation } from './.gen/providers/aws/route-table-association'; import { InternetGateway } from './.gen/providers/aws/internet-gateway'; import { Instance } from './.gen/providers/aws/instance'; class MyStack extends TerraformStack { constructor(scope: Construct, name: string) { super(scope, name); new AwsProvider(this, 'Aws', { region: 'us-east-1', }) const vpc = new Vpc(this, 'Vpc', { cidrBlock: '10.0.0.0/16' }); const igw = new InternetGateway(this, 'InternetGateway', { vpcId: Token.asString(vpc.id) }); const rt = new RouteTable(this, 'RouteTable', { vpcId: Token.asString(vpc.id), route: [ { cidrBlock: '0.0.0.0/0', gatewayId: Token.asString(igw.id), egressOnlyGatewayId: '', instanceId: '', ipv6CidrBlock: '', natGatewayId: '', networkInterfaceId: '', transitGatewayId: '', vpcPeeringConnectionId: '' } ] }); const sbn = new Subnet(this, 'Subnet', { vpcId: Token.asString(vpc.id), availabilityZone: 'us-east-1a', cidrBlock: '10.0.0.0/24' }); new RouteTableAssociation(this, 'RouteTableAssociation', { routeTableId: Token.asString(rt.id), subnetId: Token.asString(sbn.id) }); new Instance(this, 'Instance', { ami: 'ami-08f3d892de259504d', instanceType: 't2.micro', subnetId: Token.asString(sbn.id) }); } } const app = new App(); new MyStack(app, 'terraform-cdk'); app.synth();
ほとんど参考サイトの記載と同じですね。
少し違うところといえば、IGWや、ルートテーブルの作成をしているところですかね。
ルートテーブルのところについては、地味に詰まってしまいました。
IGWしかルーティングしないため、gatewayId
のみ書いていましたが、以下のようなエラーが出ました。
Inappropriate value for attribute "route": element 0: attributes "egress_only_gateway_id", "instance_id", "ipv6_cidr_block", "nat_gateway_id", "network_interface_id", "transit_gateway_id", and "vpc_peering_connection_id" are required.
解決方法としては上述の通り、今回のルーティング設定には関係ないegressOnlyGatewayId
や、instanceId
などについても書いてあげる必要がありました。
./.gen/providers/aws/route.ts を確認しても、required じゃないのに何故...
また、各種リソースに指定できるオプションは、./.gen/providers/aws/<リソース名>.ts
のexport interface <リソース名>Config
を見れば確認できます。
e.g.) ./.gen/providers/aws/route.ts
export interface RouteConfig extends TerraformMetaArguments { readonly destinationCidrBlock?: string; readonly destinationIpv6CidrBlock?: string; readonly egressOnlyGatewayId?: string; readonly gatewayId?: string; readonly instanceId?: string; readonly natGatewayId?: string; readonly networkInterfaceId?: string; readonly routeTableId: string; readonly transitGatewayId?: string; readonly vpcPeeringConnectionId?: string; /** timeouts block */ readonly timeouts?: RouteTimeouts; }
順番が少し前後しましたが、デプロイなどの基本的な操作は以下の通りです。
cdktf synth
: cdktf.outにcdk.tf.jsonというJSON形式のTerraformのテンプレートファイルを出力する。
e.g.)
$ yarn -s cdktf synth Generated Terraform code in the output directory: cdktf.out
cdktf deploy
: CDKで記載したリソースをTerraformテンプレートに変換してデプロイする。
e.g.)
$ yarn -s cdktf deploy Deploying Stack: terraform-cdk Resources ✔ AWS_INSTANCE Instance aws_instance.terraformcdk_Instance_D75D061F ✔ AWS_INTERNET_GATEWAY InternetGateway aws_internet_gateway.terraformcdk_InternetGateway_12383DC6 ✔ AWS_ROUTE_TABLE RouteTable aws_route_table.terraformcdk_RouteTable_FE93546D ✔ AWS_ROUTE_TABLE_ASSO RouteTableAssociati aws_route_table_association.terraformcdk_RouteTableAssociation_6D40008E ✔ AWS_SUBNET Subnet aws_subnet.terraformcdk_Subnet_D427F1FE ✔ AWS_VPC Vpc aws_vpc.terraformcdk_Vpc_DF4745BC Summary: 6 created, 0 updated, 0 destroyed.
cdktf synth
: cdktf deploy
でデプロイしたリソースを削除する。
e.g.)
$ yarn -s cdktf destroy Destroying Stack: terraform-cdk Resources ✔ AWS_INSTANCE Instance aws_instance.terraformcdk_Instance_D75D061F ✔ AWS_INTERNET_GATEWAY InternetGateway aws_internet_gateway.terraformcdk_InternetGateway_12383DC6 ✔ AWS_ROUTE_TABLE RouteTable aws_route_table.terraformcdk_RouteTable_FE93546D ✔ AWS_ROUTE_TABLE_ASSO RouteTableAssociati aws_route_table_association.terraformcdk_RouteTableAssociation_6D40008E ✔ AWS_SUBNET Subnet aws_subnet.terraformcdk_Subnet_D427F1FE ✔ AWS_VPC Vpc aws_vpc.terraformcdk_Vpc_DF4745BC Summary: 6 destroyed.
まとめ・感想
今まではCDK はCloudFormationを介して操作できるものしか触れませんでしたが、Terraformにも対応したことで、クラウドのリソース管理をするならまずCDKを検討してから のように一気に可能性が広がったような気がします。
感想としては、私自身Terraformに触れるのは初めてでしたが、思ったよりも簡単に操作することができ、面白かったです。
これも、コードがTypescriptで記述されており、なんとなく見たことあるような構文が並んでいるからだと思います。
また、書いている途中ですが、Cloud9の補完がかなり効いててスムーズに編集することができました。素のTerraformのテンプレートファイルの.jsonや、.tf ファイルと比べるとそういった利便性の向上も期待できそうだと感じました。