はじめに
AWS Lambda関数をCodeDeployでデプロイすることができたので、ここにまとめておきます。
AWSのドキュメントが以下にあるのですが、試してみたところ動かなかったのでゼロから実装してみました。
言語は慣れていてサクッと動かせるRubyにしてみました。
関連ファイルの作成
まずは関連ファイルを作成します。SAMのテンプレートファイルを作成します。Hookを使わず単純なものにしました。
AWSTemplateFormatVersion : '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: A sample SAM template for deploying Lambda functions. Resources: # Details about the mainFunction Lambda function mainFunction: Type: AWS::Serverless::Function Properties: Handler: handler.handler Runtime: ruby3.2 AutoPublishAlias: live DeploymentPreference: Type: Linear10PercentEvery1Minute # 1分間に10%ずつ更新
アプリはhandler.rb
に以下のように実装します。とりあえずの適当に作った関数です。
# frozen_string_literal: true require "json" require "date" # event には {"command": コマンド名, "option": オプション値}という # Hashで出力される def handler(event:, context:) status_code = 200 case event["command"] when "date" result = { date: JSON.generate(Date.today) } when "time" result = { time: JSON.generate(Time.now) } else status_code = 400 result = { "error" => "Must specify 'date' or 'time'" } end { statusCode: status_code, body: result, message: "message v1" } end
デプロイ
必要なファイルが作成できたらsam package
とsam deploy
を使ってデプロイします。これだけでCodeDeployでAWS Lambda関数がデプロイされます。DeploymentPreference
にLinear10PercentEvery1Minute
と指定したので、1分ごとに更新されることが確認できます。
AWS Lambda関数をaws lambda invoke
で実行してみます。
--function-name
に指定するARN文字列にAlias(ここではlive
)を付与して実行すると、タイミングによってはExecutedVersion
の値が変わることが確認できます。
Hookを実装する
Hookを実装します。こんな感じで実装します。まずはbefore_allow_traffic.rb
です。
# frozen_string_literal: true require 'aws-sdk-codedeploy' require 'logger' class BeforeAllowTraffic @logger = Logger.new(STDOUT) @codedeploy_client = Aws::CodeDeploy::Client.new def self.notify_execution_status(event:, status:) deployment_id = event['DeploymentId'] execution_id = event['LifecycleEventHookExecutionId'] @codedeploy_client.put_lifecycle_event_hook_execution_status( { deployment_id: deployment_id, lifecycle_event_hook_execution_id: execution_id, status: status }) end def self.handler(event: , context:) @logger.info(event) status = "Succeeded" begin notify_response = notify_execution_status(event: event, status: status) rescue => e @logger.fatal(e) status = "Failed" notify_response = notify_execution_status(event: event, status: status) ensure @logger.info("notify_response=[#{notify_response}]") end end end
次にafter_allow_traffic.rb
です。
# frozen_string_literal: true require 'aws-sdk-codedeploy' require 'logger' class AfterAllowTraffic @logger = Logger.new(STDOUT) @codedeploy_client = Aws::CodeDeploy::Client.new def self.notify_execution_status(event:, status:) deployment_id = event['DeploymentId'] execution_id = event['LifecycleEventHookExecutionId'] @codedeploy_client.put_lifecycle_event_hook_execution_status( { deployment_id: deployment_id, lifecycle_event_hook_execution_id: execution_id, status: status }) end def self.handler(event: , context:) @logger.info(event) status = "Succeeded" begin notify_response = notify_execution_status(event: event, status: status) rescue => e @logger.fatal(e) status = "Failed" notify_response = notify_execution_status(event: event, status: status) ensure @logger.info(notify_response) end end end
CodeDeployのput_lifecycle_event_hook_execution_status
に必要な引数の値はhandlerのeventにHashとして入っているのでそれを読み取ります。
SAMのtemplate.ymlも更新します。
AWSTemplateFormatVersion : '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: A sample SAM template for deploying Lambda functions. Resources: # Details about the mainFunction Lambda function mainFunction: Type: AWS::Serverless::Function Properties: Handler: handler.handler Runtime: ruby3.2 AutoPublishAlias: live DeploymentPreference: # Type: AllAtOnce # 一度に全部更新する Type: Linear10PercentEvery1Minute # 1分間に10%ずつ更新 Hooks: PreTraffic: !Ref BeforeTrafficFunction PostTraffic: !Ref AfterTrafficFunction BeforeTrafficFunction: Type: AWS::Serverless::Function Properties: Handler: before_allow_traffic.BeforeAllowTraffic.handler Runtime: ruby3.2 Policies: - Version: 2012-10-17 Statement: - Effect: Allow Action: - codedeploy:PutLifecycleEventHookExecutionStatus Resource: "*" AfterTrafficFunction: Type: AWS::Serverless::Function Properties: Handler: after_allow_traffic.AfterAllowTraffic.handler Runtime: ruby3.2 Policies: - Version: 2012-10-17 Statement: - Effect: Allow Action: - codedeploy:PutLifecycleEventHookExecutionStatus Resource: "*"
この段階で、sam deploy
したときに権限不足でエラーが出ましたのでCodeDeployのIAMロールにAWSLambdaRole
を付与してあげたら動きました。
これで当初の目的は実装することができました。