こんにちは。 ディベロップメントサービス1課の山本です。
今回は API Gateway でカナリアリリース機能の使い方を説明したいと思います。
- この記事の対象者は?
- カナリアリリースについて
- API Gateway でのカナリアリリースの方法
- SAM テンプレートファイルの内容
- Lambda 関数の内容
- カナリアリリースの実施
- まとめ
- さいごに
この記事の対象者は?
- デプロイ時に変更の影響を最小限にしたい方
- カナリアリリースを検討されている方
カナリアリリースについて
カナリアリリースとは、ソフトウェアのデプロイ方法の一つです。
方法は以下の通りです。
- 現行のソフトウェアを維持したまま、新規のソフトウェアをデプロイ
- トラフィックの一部を新規ソフトウェアに向けて転送
- 新規ソフトウェアをテスト
- 問題なければ、全てのトラフィックを新規ソフトウェアに移行
- 問題がある場合は、現行のソフトウェアに切り戻す
API Gateway と AWS Lambda を例に説明すると、以下のよう形になります。
API Gateway でのカナリアリリースの方法
API Gateway では REST API のみ canary(カナリア)リリースでのデプロイがサポートされてます。
こちらを利用して、今回カナリアリリースを実施してみます。
API Gateway の Canary リリースデプロイの設定 - Amazon API Gateway
AWS Serverless Application Model (以降、SAM) を利用してデプロイしてみます。
SAM テンプレートファイルの内容
以下にテンプレートを記載します。
10 % の割合で新バージョンに流れるようにします。
着目点は以下の点です。
- Api のプロパティに
CanarySetting
を記載する。 - Function のプロパティに
AutoPublishAlias
を設定する。- カナリアリリースには API Gateway のステージ更新が必要。
- エイリアスを指定・変更しないと Lambda バージョンが
LATEST
で固定されるため、ステージが更新されない。
- Function に
DeletionPolicy: Retain
を追加する。- 追加しない場合、エイリアス更新の度に過去のエイリアスが削除されるのでカナリアリリースできない。
- Function に
UpdateReplacePolicy: Retain
を追加する。- 追加しない場合、エイリアス更新の度にリソースベースのポリシーが新規エイリアスに置き換わりカナリアリリースできない。
template.yaml
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: sam-app Globals: Function: Timeout: 3 MemorySize: 128 Resources: RestAPI: Type: AWS::Serverless::Api Properties: StageName: test CanarySetting: # カナリアリリースの設定を追加 PercentTraffic: 10 HelloWorldFunction: Type: AWS::Serverless::Function DeletionPolicy: Retain # 過去のエイリアスが削除されないように追加 UpdateReplacePolicy: Retain # リソースベースのポリシーが削除されないように追加 Properties: CodeUri: hello_world/ Handler: app.lambda_handler Runtime: python3.9 AutoPublishAlias: "step1" # Lambda 更新時に API Gateway のステージが更新されるように追加 Architectures: - x86_64 Events: HelloWorld: Type: Api Properties: Path: /hello Method: get RestApiId: Ref: RestAPI
Lambda 関数の内容
エイリアスを確認できるARNを返却する簡単なプログラムを作成しました。
app.py
import json def lambda_handler(event, context): arn = context.invoked_function_arn message = f"arn: {arn}" return { "statusCode": 200, "body": json.dumps(message), }
カナリアリリースの実施
初回デプロイ
それではカナリアリリースを実施してみたいと思います。
まず普通に初回デプロイします。
sam build sam deploy
カナリアリリース設定は問題無し。
Lambda のエイリアスも step1
に設定されております。
API の結果も エイリアスが step1
の Lambda が呼ばれてます。
"arn: arn:aws:lambda:ap-northeast-1:XXX:function:sam-app-HelloWorldFunction-QWELwhKuFQv3:step1"
2回目のデプロイ
Lambda のエイリアスを step2
に変更してデプロイします。
ここで、問題が発生しました。
step2 と step1のエイリアスを持つレスポンス両方返却されるのですが、想定と割合が逆です。step2 の方が多い!
step1 | step2 | |
---|---|---|
想定 | 90 % | 10 % |
実際 | 10 % | 90 % |
トラフィックの割合が反転した理由
どうも SAM からデプロイすると、カナリアリリースにはならず本番デプロイとして扱われ最新デプロイが Active
になる模様です。
初回デプロイ時は強制的にカナリアリリースも含まれるので、step1
が canary 、step2
が現行として扱われるので割合が反転しました。
コンソール上からのデプロイ
SAM から無理なら、コンソール上から試します。
リクエスト先の Lambda エイリアスを step 3
に変更後、コンソール上からデプロイします。
すると、デプロイは成功したのですが Active
状態にはならずカナリアリリース成功となります。
この状態で API をコールすると、想定通り 10 % のトラフィックのみ step3
に流すことができました。
step2 | step3 | |
---|---|---|
想定 | 90 % | 10 % |
実際 | 90 % | 10 % |
canary リリースを現行に昇格
Canary タブから canaryを昇格することが可能です。
昇格後は元々カナリアリリースしたデプロイが Active
状態になり、全てのトラフィックを受信することになります。
まとめ
- API Gateway の canary の設定を行うことで、カナリアデプロイが可能
- SAM からデプロイすると、常に最新デプロイ適用されるためカナリアデプロイはできない
- コンソール上から実施することでカナリアデプロイが実施可能
さいごに
よく試験で見かけた内容を試してみましたが、落とし穴だらけでした。
本ブログがどなかたのお役に立てれば幸いです。