
急遽帰省することになり、AWS Summit Japan 2024には関東に戻れるといいなと思っております。 AWS AppConfigがAWS PrivateLinkをサポートし始めたのが2023年12月のことで、まだ記憶に新しい出来事です。
本ブログ投稿では、Amazon ECS on Fargateを例として、AWS AppConfigのPrivateLinkのサポートを活用した具体的な設定方法と注意点をご紹介します。
- 読者の前提条件
- AWS AppConfigのAWS PrivateLinkサポートで何が変わるのか
- ECSを活用した閉域環境でのAppConfigの活用例
- AWS AppConfigのPrivateLinkをプロビジョニングしない場合はどうなるのか
- 注意点:AppConfigエージェントのコンテナイメージの取得について
- おわりに
読者の前提条件
- ✅ AWS AppConfig、VPCエンドポイント、Amazon ECSを概要レベルで理解している必要があります。
AWS AppConfigのAWS PrivateLinkサポートで何が変わるのか
これまでは、プライベートサブネットからAWS AppConfigを利用するためには、NATゲートウェイが必要でした。

AppConfigがPrivateLinkに対応したことで、AppConfigへのアクセスをVPC Interface Endpointを経由して行えるようになり、NATゲートウェイが不要になりました。

ECSを活用した閉域環境でのAppConfigの活用例
ここからは、Amazon ECSの例を用いて、AppConfigのPrivateLinkを利用する方法をご紹介します。
AWS構成図
この活用例では下図のような、よくある閉域環境でのAmazon ECSによるAPIサーバーのAWS構成図になっています。ですので、Amazon ECSに必要なVPC Interface Endpointも含まれています。ecr.api , ecr.dkr , logs のVPC Interface Endpointが該当します。

この活用例で利用したソースコードは、以下のGitHubリポジトリにありますので、ご参照いただければと思います。
1. IaCによるAmazon ECSとAWS AppConfigのセットアップ
この活用例では、インフラストラクチャのプロビジョニングにTerraform、コンテナのデプロイにecspressoというツールを用いて、インフラとアプリケーションの管理を分離しています。AWS AppConfigについては以下のコードの内容でPrivateLinkを利用するためのセットアップを行っています。
# VPC Endpoint resource "aws_vpc_endpoint" "vpce_appconfig" { vpc_id = var.vpc_id service_name = "com.amazonaws.ap-northeast-1.appconfig" vpc_endpoint_type = "Interface" subnet_ids = [ var.subnet_id_private_c ] security_group_ids = [ aws_security_group.yassan-fa-ac-vpce-sg.id, ] private_dns_enabled = true } resource "aws_vpc_endpoint" "vpce_appconfigdata" { vpc_id = var.vpc_id service_name = "com.amazonaws.ap-northeast-1.appconfigdata" vpc_endpoint_type = "Interface" subnet_ids = [ var.subnet_id_private_c ] security_group_ids = [ aws_security_group.yassan-fa-ac-vpce-sg.id, ] private_dns_enabled = true }
AWS AppConfigの機能フラグについては以下のコードでセットアップを行っています。
# AppConfig resource "aws_appconfig_application" "yassan-ac-app" { name = "yassan-ac-app" } resource "aws_appconfig_configuration_profile" "yassan-ac-c-profile" { application_id = aws_appconfig_application.yassan-ac-app.id location_uri = "hosted" name = "yassan-ac-cprofile" type = "AWS.AppConfig.FeatureFlags" } resource "aws_appconfig_hosted_configuration_version" "yassan-ac-hcv" { application_id = aws_appconfig_application.yassan-ac-app.id configuration_profile_id = aws_appconfig_configuration_profile.yassan-ac-c-profile.configuration_profile_id content = jsonencode({ flags : { featureA : { name : "featureA" } }, values : { featureA : { enabled : "false" } }, version : "1" }) content_type = "application/json" } resource "aws_appconfig_environment" "yassan-ac-env-dev" { application_id = aws_appconfig_application.yassan-ac-app.id name = "yassan-ac-env-dev" } resource "aws_appconfig_deployment_strategy" "yassan-ac-deploy-stg" { deployment_duration_in_minutes = 0 growth_factor = 100 final_bake_time_in_minutes = 0 name = "yassan-ac-deploy-stg" replicate_to = "NONE" } resource "aws_appconfig_deployment" "yassan-ac-deployment" { application_id = aws_appconfig_application.yassan-ac-app.id configuration_profile_id = aws_appconfig_configuration_profile.yassan-ac-c-profile.configuration_profile_id configuration_version = aws_appconfig_hosted_configuration_version.yassan-ac-hcv.version_number deployment_strategy_id = aws_appconfig_deployment_strategy.yassan-ac-deploy-stg.id environment_id = aws_appconfig_environment.yassan-ac-env-dev.environment_id }
2. AppConfigのVPCエンドポイントのプロビジョニング結果を確認する
上記のIaCをプロビジョニングしてAppConfigのVPCエンドポイントを追加します。AppConfigは2種類のエンドポイントがあり、「com.amazonaws.region.appconfig」と「com.amazonaws.region.appconfigdata」の両方のVPC Interface Endpointを設定してあげる必要があります。
VPC Interface Endpointの設定は、他のサービスと同様に、HTTPS(ポート443)に対するインバウンドを許可するセキュリティグループと、プライベートサブネットの指定が必要です。

3. APIにアクセスしてAppConfigの機能フラグの状態を確認する
Web APIのエンドポイントをブラウザから呼び出して、APIがAppConfigから機能フラグを取得する動作を確認します。以下の画像のように、レスポンスにはconfig情報を含むJSONが返され、AppConfigから設定内容を適切に取得できていることが確認できます。

4. AppConfigの機能フラグを切り替えて動作確認する
次に、AppConfigの設定を更新しても正しく動作するか確認します。ここでは機能フラグを切り替えます。以下の画像のように、フラグをオンに変更してデプロイします。

デプロイ後にもう一度Web APIのエンドポイントをブラウザから呼び出すと、config情報のJSONの値が変更されていることがわかります。機能フラグの切り替えが適切に反映されていました。

AWS AppConfigのPrivateLinkをプロビジョニングしない場合はどうなるのか
AWS AppConfigのPrivateLinkをプロビジョニングしない場合はどうなるのか確認してみました。以下のCloudWatchLogsの内容から、タイムアウトエラーが発生しており、ECSタスクのAppConfigサイドカーコンテナでエラーが発生していることを確認できました。

注意点:AppConfigエージェントのコンテナイメージの取得について
AppConfigエージェントのコンテナイメージはECR Publicで公開されています。閉域環境でAWS PrivateLinkを利用する場合はECR Publicに接続できなくなります。その結果としてコンテナイメージを取得できず、ECSサービスが起動できない問題が発生します。この問題を解決するための有効な方法として、Pull through cacheの設定を行うことができます。
Pull through cacheを利用したAppConfigエージェントのコンテナイメージの取得方法
Pull through cacheを利用したAppConfigエージェントのコンテナイメージの取得方法を解説します。 まず、以下の画像のように、Pull through cacheを設定します。

次にAWS CLIを利用してECRにログインします。
# ログインコマンド例 $ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/ecr-public
ECR Publicにあるコンテナイメージを取得するには、ecr-publicのnamespaceを指定する必要があります。
# ECR Publicからコンテナイメージpullの例 $ docker image pull xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/ecr-public/aws-appconfig/aws-appconfig-agent:2.x
すると、自動的にプライベートリポジトリにPull through cacheとして保存されます。

あとは、ECSのタスク定義に、キャッシュされたコンテナイメージのURIを指定するだけでOKです。

おわりに
AppConfigのPrivateLinkを活用して、セキュアなアプリケーション設定を実現する方法をご紹介しました。今回はECSの事例でしたが、機会があればVPC Lambdaにおけるプライベートサブネットでの利用例も紹介できればと考えています。AppConfigは漸進的なアプリケーション構築に必須であり、積極的に活用していきたいと考えております。参考になれば幸いです。