AppConfigとLambda Extensionsを活用したデプロイの分離をしてみる

### AppConfigとは

AppConfigとは、下記のように説明されています。
もう少し簡単にいうと、AppConfigを使うことで、ソースコードとは別に構成管理情報(環境変数)を管理することができ、迅速なデプロイまでを行えるツールになります

> Use AWS AppConfig, a capability of AWS Systems Manager, to create, manage, and quickly deploy application configurations. You can use AWS AppConfig with applications hosted on Amazon Elastic Compute Cloud (Amazon EC2) instances, AWS Lambda, containers, mobile applications, or IoT devices.

> AWS Systems Managerの機能であるAWS AppConfigを使用して、アプリケーション構成の作成、管理、迅速なデプロイを行うことができます。AWS AppConfigは、Amazon Elastic Compute Cloud (Amazon EC2)インスタンス、AWS Lambda、コンテナ、モバイルアプリケーション、IoTデバイスでホストされているアプリケーションで使用できます。

[What is AWS AppConfig](https://docs.aws.amazon.com/appconfig/latest/userguide/what-is-appconfig.html)

### Lambda Extensionsとは

Lambda Extensionsは、10月末にプレビュー版がリリースされており、下記のように説明されています。
もっと簡単にいうと、ガバナンス用ツールなどに対して以前までは、lambdaからSDK経由でアクセスしていたが、その部分をExtensionsが肩代わりして、より簡単に実装することが可能になった機能になります

> Lambda Extensionsは、お好みのモニタリング、オブザーバビリティ、セキュリティ、ガバナンス用ツールとLambdaとの統合を簡単にする新しい方法です。

### この二つを使うとどうなるの？

では、説明した2つのツールを使うと何が嬉しいの？ということになります
嬉しいこととしては、4点あるかなと思います

- 構成管理情報を変更する度に、ソースコードのデプロイをしなくて良い
- 構成管理情報に不具合があった場合、迅速なロールバックが可能
- 構成管理情報のカナリアリリースが可能なので、lambda単体でもカナリア挙動が実現できる
- SSMのパラメータストアとは違い、Extensionsを使うことで構成管理情報をキャッシュすることができ、lambdaの実行時間をより高速化可能


デプロイ戦略に関しては、3つのパターンがあります
AWSとしての推奨は、AppConfig.Canary10Percent20Minutesのデプロイになるそうです
注意点などの詳細に関しては、[こちらのリンク](https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-creating-deployment-strategy.html)を確認してください

- AppConfig.AllAtOnce： 全てを直ちにデプロイする
- AppConfig.Linear50PercentEvery30Seconds： 30秒ごとに全ターゲットの半分に構成をデプロイし、1分間のデプロイを行います。
- AppConfig.Canary10Percent20Minutes： 20分かけて10%の成長因子を使用して指数関数的に展開を処理します。


### じゃあどう作れば良いの？

では、実際にどう作れば良いのか？となると思います
実際にlambdaを運用・管理していく場合だと、ServerlessApplicationModel(SAM)を使ってlambdaを管理するケースが一般的だと思うので、そちらを前提にお話ししたいと思います

すでにawsからAppConfigとLambda Extensionsを使った[デモ](https://github.com/aws-samples/aws-lambda-extensions/tree/main/awsappconfig-extension-demo)が公開されています

リポジトリをCloneして、README.md通り、sam deployを実行するとデモ環境が構築されてます
ここで気をつけないといけないこととして、Lambda ExtensionsのAppConfig機能は、リージョン毎にARNの指定先が違うので、使いたいリージョンのものを採用する必要があります
それぞれのリージョン毎のARNは、参照リンクに記載されてます

[詳細説明](https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-integration-lambda-extensions.html)

SAMのデプロイが完了すると、SSMのAppConfigのところに、DemoExtensionApplicationが構築されており、その中にProductionが構築されていると思います

![スクリーンショット 2020-12-10 0.15.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440378/b741dc4f-f7db-c531-efff-f63a44801455.png)

![スクリーンショット 2020-12-10 0.15.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440378/12a8fbb6-46a1-1c5f-ef59-d694f7c7090e.png)

そして、設定プロファイルというところにLoggingLevelというプロファイルが作成されていると思います

![スクリーンショット 2020-12-10 0.16.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440378/a178e694-6c8e-9228-4c21-c2ab50252109.png)

このアプリケーション名, 環境名, 設定プロファイルの3つのキーを使って、lambda側でAPIをコールすることで、LoggingLevelの中に記述された以下の情報を取得することができます

![スクリーンショット 2020-12-10 0.16.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440378/648060e7-185e-cfd7-89b1-1b2a2877d949.png)

取得するAPIのホストは、以下のようになります
このURLの先がLambda Extensionsの先になり、Lambda ExtensionsがSDKを使って代わりにAppConfigの情報を取得してレスポンスとして返却されます

`http://localhost:2772/applications/application_name/environments/environment_name/configurations/configuration_name`

少し違和感があるかと思いますが、イメージとしてはAWSのドキュメントにも書かれているこちらがわかりやすいと思います

![スクリーンショット 2020-12-10 0.25.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440378/3c78080f-4b42-7341-6f12-a2e3d0b6dbbb.png)

[参照元](https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-integration-lambda-extensions.html)

### まとめ

以上で、AppConfigとLambda Extensionsの簡単な説明と実際に作った時にどのようになるのかという情報でした
今回使ってみたところ、かなり簡単に導入が可能だなと言う印象を感じました
さらに、機密情報の場合、パラメータストアで暗号化したい要件もあるかと思いますが、そちらもAppConfigが透過的に参照できるので、問題ないかと思います


### おまけ

おまけですが、VPC Lambdaで使う場合やローカルPCでの開発でも使えるのかと言う点が疑問になるかと思います
そちらに関しては、両方とも問題なく使えます。
ただし、VPC Lambdaの場合はAppConfigに対してインターネット経由でのアクセスが必要になるので、NATゲートウェイ経由の経路を用意する必要があります。
また、ローカルPCに関しては、AppConfigに関する権限も必要になってきます