aws-cdk-goでEC2インスタンスをたてる
Go版CDKが発表されて1年くらい経つが全く触れていなかったので、素振りとしてEC2インスタンスをたててみる。
ちなみにこれまでもCDKは使ってきたけど、全てTypeScriptで書いていた。
実行環境
- macOS Monterey 12.0.1
- cdk 2.19.0
- go1.18
雛形を作ろう
まずは cdk init
する。
$ mkdir cdk-go-example
$ cdk init --language=go
ファイルが自動生成される。
.
├── README.md
├── cdk-go-example.go
├── cdk-go-example_test.go
├── cdk.json
└── go.mod
go.modだけ作ってくれているので、go mod tidy
しておく。
$ go mod tidy
Stackを実装しよう
初期化時に作成されたファイルにスタックの雛型とかも作られる。
以下の通り。(コメントは削除済み)
package main
import (
"github.com/aws/aws-cdk-go/awscdk/v2"
"github.com/aws/constructs-go/constructs/v10"
)
type CdkGoExampleStackProps struct {
awscdk.StackProps
}
func NewCdkGoExampleStack(scope constructs.Construct, id string, props *CdkGoExampleStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
stack := awscdk.NewStack(scope, &id, &sprops)
return stack
}
func main() {
app := awscdk.NewApp(nil)
NewCdkGoExampleStack(app, "CdkGoExampleStack", &CdkGoExampleStackProps{
awscdk.StackProps{
Env: env(),
},
})
app.Synth(nil)
}
func env() *awscdk.Environment {
return nil
}
NewCdkGoExampleStack
に作成するリソースを定義していく感じみたい。
https://pkg.go.dev/github.com/aws/aws-cdk-go/awscdk/v2 を見ながら進める。
EC2インスタンスを定義しよう
awsec2.NewInstance
関数でインスタンスを作る。
今回はt3.micro
のAMAZON_LINUX_2
にする。
func NewCdkGoExampleStack(scope constructs.Construct, id string, props *CdkGoExampleStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
stack := awscdk.NewStack(scope, &id, &sprops)
// EC2インスタンスを作成
awsec2.NewInstance(scope, jsii.String("ExampleInstance"), &awsec2.InstanceProps{
InstanceType: awsec2.NewInstanceType(jsii.String("t3.micro")),
MachineImage: awsec2.NewAmazonLinuxImage(&awsec2.AmazonLinuxImageProps{
Generation: awsec2.AmazonLinuxGeneration_AMAZON_LINUX_2,
}),
})
return stack
}
VPCを設定しよう
前節のソースコードのままcdk deploy
コマンドを叩くと、panicとなりデプロイに失敗する。
panic: "Missing required properties for aws-cdk-lib.aws_ec2.InstanceProps: vpc"
VPCの指定が必須と仰っている。
確かにインスタンスを配置するVPCを自動で決定されると困る。
とりあえずやってみた記事なので、デフォルトのVPCを指定する。
awsec2.Vpc_FromLookup
関数で既に存在しているVPCをインポートできる。
今回はデフォルトVPCを使うので、awsec2.VpcLookupOptions
構造体のIsDefault
にbool値trueのポインタを渡す。
また、awsec2.VpcLookupOptions
構造体のフィールドにはVpcName
やVpcId
もあり、IDや名前でインポートすることもできる様だ。
func NewCdkGoExampleStack(scope constructs.Construct, id string, props *CdkGoExampleStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
stack := awscdk.NewStack(scope, &id, &sprops)
// デフォルトのVPCをインポート
defaultVpc := awsec2.Vpc_FromLookup(stack, jsii.String("DefaultVPC"), &awsec2.VpcLookupOptions{
IsDefault: jsii.Bool(true),
})
// EC2インスタンスを作成
awsec2.NewInstance(stack, jsii.String("ExampleInstance"), &awsec2.InstanceProps{
InstanceType: awsec2.NewInstanceType(jsii.String("t3.micro")),
MachineImage: awsec2.NewAmazonLinuxImage(&awsec2.AmazonLinuxImageProps{
Generation: awsec2.AmazonLinuxGeneration_AMAZON_LINUX_2,
}),
Vpc: defaultVpc,
})
return stack
}
環境値を設定しよう
スタック作成先のアカウントIDとリージョンを指定する。
雛形として自動で作られたenv
関数がアカウントIDとリージョンの情報を持った*awscdk.Environment
を返す様に実装する。
値は環境変数から取ることにする。
func env() *awscdk.Environment {
return &awscdk.Environment{
Account: jsii.String(os.Getenv("ACCOUNT_ID")),
Region: jsii.String(os.Getenv("REGION")),
}
}
完成ソースコード
package main
import (
"os"
"github.com/aws/aws-cdk-go/awscdk/v2"
"github.com/aws/aws-cdk-go/awscdk/v2/awsec2"
"github.com/aws/constructs-go/constructs/v10"
"github.com/aws/jsii-runtime-go"
)
type CdkGoExampleStackProps struct {
awscdk.StackProps
}
func NewCdkGoExampleStack(scope constructs.Construct, id string, props *CdkGoExampleStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
stack := awscdk.NewStack(scope, &id, &sprops)
// デフォルトのVPCをインポート
defaultVpc := awsec2.Vpc_FromLookup(stack, jsii.String("DefaultVPC"), &awsec2.VpcLookupOptions{
IsDefault: jsii.Bool(true),
})
// EC2インスタンスを作成
awsec2.NewInstance(stack, jsii.String("ExampleInstance"), &awsec2.InstanceProps{
InstanceType: awsec2.NewInstanceType(jsii.String("t3.micro")),
MachineImage: awsec2.NewAmazonLinuxImage(&awsec2.AmazonLinuxImageProps{
Generation: awsec2.AmazonLinuxGeneration_AMAZON_LINUX_2,
}),
Vpc: defaultVpc,
})
return stack
}
func main() {
app := awscdk.NewApp(nil)
NewCdkGoExampleStack(app, "CdkGoExampleStack", &CdkGoExampleStackProps{
awscdk.StackProps{
Env: env(),
},
})
app.Synth(nil)
}
func env() *awscdk.Environment {
return &awscdk.Environment{
Account: jsii.String(os.Getenv("ACCOUNT_ID")),
Region: jsii.String(os.Getenv("REGION")),
}
}
スタックをデプロイ
cdkコマンドを使ってスタックをデプロイする。
ここは他の言語を選択している時と変わらない。
$ cdk deploy
存在確認
雑だけどLaunchTime
とInstanceType
を取って存在確認する。
$ aws ec2 describe-instances --query 'Reservations[].Instances[].[LaunchTime, InstanceType]'
[
[
"2022-04-10T11:14:20.000Z",
"t3.micro"
]
]
できてた🆗
所感
今回は本当に触りくらいしか書いてない上に、TypeScriptで書くことに慣れているので、これからは全部Goで書こう!とまでは思わなかった。今まで作ったことあるリソースなら、TypeScriptの方が早く書ける筈。
ただテストコードに関しては、Goで書いてみたいという思いがあるので、GoでCDKのテストコード書いてみた的な記事も上げようと考えている。
Discussion