- Terraform – Lambda + CodeDeployのサンプルコード紹介記事
- LambdaのBlue/Green、Canary(カナリア)デプロイを実現しています
作ったもの
- TerraformでLambda、CodeDeployをプロビジョニング
- Lambdaに何らかの変更が加わった場合のみ、追加でCodeDeployを利用してBlue/Greenor Canary(カナリア)デプロイをする
を実現するミニマルなサンプルコードです。
図で表すと、まずLambdaとCodeDeployの作成 or 更新が走り、
完了後に、Lambdaが更新されていれば、追加でCodeDeployのデプロイメントをトリガーします。
ポイント
TerraformでCodeDeployを起動する方法
Terraform本体には、CodeDeployのデプロイメントを起動する仕組みが存在しないため、自前で実装する必要があります。
今回は、null_resource中のlocal-execで、aws cliを呼び出して実現しています。
# ----------------------------------------------------------
# Trigger of deployment
# ----------------------------------------------------------
resource "null_resource" "run_codedeploy" {
・・・
provisioner "local-exec" {
# Only trigger deploy when lambda version is updated (=lambda version is not 1)
command = "if [ ${var.lambda_version} -ne 1 ] ;then aws deploy create-deployment --application-name ${aws_codedeploy_app.sample.name} --deployment-group-name ${aws_codedeploy_deployment_group.sample.deployment_group_name} --revision '{\"revisionType\":\"AppSpecContent\",\"appSpecContent\":{\"content\":\"{\\\"version\\\":0,\\\"Resources\\\":[{\\\"${var.lambda_function_name}\\\":{\\\"Type\\\":\\\"AWS::Lambda::Function\\\",\\\"Properties\\\":{\\\"Name\\\":\\\"${var.lambda_function_name}\\\",\\\"Alias\\\":\\\"${var.lambda_alias_name}\\\",\\\"CurrentVersion\\\":\\\"${var.lambda_alias_version}\\\",\\\"TargetVersion\\\":\\\"${var.lambda_version}\\\"}}}]}\"}}';fi"
}
}
かなり見づらいですが、使っているのは、
$ aws deploy create-deployment
です。
今回は、できるだけ外部ファイルへの参照をなくした実装としたかったため、ワンライナーで書いていますが、オプションの
--cli-input-yaml or --cli-input-json
を使って、外部ファイルからの読み込みとすることも可能です。
ただし、aws deploy create-deploymentに少しクセがあって、読み込むファイルはCodeDeployといえば、な「appspec.yml」ではないため注意しましょう。
CodeDeployのトリガータイミング
デプロイを発火するタイミングは、Lambdaのバージョンが上がったタイミングとしています。
先程のnull_resource内にtriggersを設定して実現しています。
resource "null_resource" "run_codedeploy" {
triggers = {
# Run codedeploy when lambda version is updated
lambda_version = var.lambda_version
}
provisioner "local-exec" {
# Only trigger deploy when lambda version is updated (=lambda version is not 1)
command = "if [ ${var.lambda_version} -ne 1 ] ;then aws deploy create-deployment --application-name ${aws_codedeploy_app.sample.name} --deployment-group-name ${aws_codedeploy_deployment_group.sample.deployment_group_name} --revision '{\"revisionType\":\"AppSpecContent\",\"appSpecContent\":{\"content\":\"{\\\"version\\\":0,\\\"Resources\\\":[{\\\"${var.lambda_function_name}\\\":{\\\"Type\\\":\\\"AWS::Lambda::Function\\\",\\\"Properties\\\":{\\\"Name\\\":\\\"${var.lambda_function_name}\\\",\\\"Alias\\\":\\\"${var.lambda_alias_name}\\\",\\\"CurrentVersion\\\":\\\"${var.lambda_alias_version}\\\",\\\"TargetVersion\\\":\\\"${var.lambda_version}\\\"}}}]}\"}}';fi"
}
}
デプロイ戦略を変えたい場合
デフォルトの実装では、「2分ごとに10%ずつ新バージョンにトラフィックを向けるBlue/Greenデプロイ」になっています。
こちらは、aws_codedeploy_appで設定しているので、デプロイ戦略を変えたい場合はこちらをカスタムしましょう。
resource "aws_codedeploy_deployment_group" "sample" {
app_name = aws_codedeploy_app.sample.name
deployment_group_name = "SampleDeploymentGroup"
service_role_arn = aws_iam_role.codedeploy_deployment_group_sample.arn
deployment_config_name = "CodeDeployDefault.LambdaLinear10PercentEvery2Minutes"
deployment_style {
deployment_option = "WITH_TRAFFIC_CONTROL"
deployment_type = "BLUE_GREEN"
}
}
注意点
デプロイをCodeDeployに任せることになるので、terraformコードでlambdaのaliasとversionを管理することはできなくなります。
Blue/Green、Canary(カナリア)デプロイできるメリットとのトレードオフになりますので、ケースによって使い分けてください。
あとがき
最後までご覧いただきありがとうございました。
Jimon(@jimon_s)でした。