[アップデート] AWS AppConfig Agent が EC2 でもサポートされるようになりました

2023.07.23

いわさです。

AWS AppConfig ではアプリケーション上で使用する構成値や機能フラグを定義し、アプリケーションや環境ごとにデプロイ管理することが出来るサービスです。

通常アプリケーションから利用する際には AppConfig の API へアクセスして値を取得するか、あるいは取得した値を頻繁に参照する場合は独自にキャッシュ管理を行う必要があります。
しかし、そのあたりの管理を簡素化するために Lambda Extension やサイドカーコンテナ向けに、定期的に AppConfig リソースをポーリングしてローカルキャッシュ管理してくれるエージェント AppConfig Agent というものが提供されていました。

これまでは EC2 ではエージェントを利用することが出来なかったのですが、先日のアップデートでサポートされるようになりました。

今回ドキュメントに従って Amazon Linux 2023 にセットアップして使ってみたのですが、うまく起動せずにトラブルシュートが必要だったので試したことなどを残しておきたいと思います。

事前準備 AppConfig 構成

今回エージェントからリモートの AppConfig 構成を取得するので適当なフィーチャーフラグを定義しておきます。

定義した構成は環境を指定してデプロイする必要があるので、環境も定義します。

導入してみる

今回 EC2 でサポートされた環境は以下です。

  • カーネル バージョン 4.15 以降を実行している Linux ベースの EC2 インスタンスで利用可能
  • x86_64 および ARM64 アーキテクチャをサポート

導入手順ですが、次の公式ドキュメント手順を参考にしています。

ドキュメントから少しコマンドの置き換えなどをしていますが、Amazon Linux 2023 (x86) で試してみたいと思います。

失敗した

次のようにユーザーデータを定義し、自動でインストールと起動を行ってみましょう。公式ドキュメントによるとこれでデフォルト設定で動作するはず。

#!/bin/bash
dnf install -y https://s3.amazonaws.com/aws-appconfig-downloads/aws-appconfig-agent/linux/x86_64/latest/aws-appconfig-agent.rpm
systemctl start aws-appconfig-agent

セッションマネージャーでアクセスしてみます。
アクセス後、ローカルホストの2772ポートへ HTTP リクエストを送信することでエージェントからキャッシュされた値を取得することが出来ます。
初回はリモートアクセスするので遅いとか、オプションでプリフェッチさせるとか色々あるのですが、今回はデフォルトでいきます。

sh-5.2$ curl "http://localhost:2772/applications/hoge0723appconfig/environments/hoge0723env1/configurations/hoge0723feature"
curl: (7) Failed to connect to localhost port 2772 after 0 ms: Couldn't connect to server

アクセスしてみたところ上記のように 2772 ポートへのリクエスト送信に失敗してしまいました。
ステータスなど確認してみると実行されたエージェントが失敗しています。

root@ip-172-31-33-199 bin]# systemctl status aws-appconfig-agent
● aws-appconfig-agent.service - aws-appconfig-agent
     Loaded: loaded (/etc/systemd/system/aws-appconfig-agent.service; enabled; preset: disabled)
     Active: activating (auto-restart) (Result: exit-code) since Sat 2023-07-22 23:29:01 UTC; 13s ago
    Process: 2962 ExecStart=/opt/aws/aws-appconfig-agent/bin/aws-appconfig-agent (code=exited, status=1/FAILURE)
   Main PID: 2962 (code=exited, status=1/FAILURE)
        CPU: 4ms

Jul 22 23:29:01 ip-172-31-33-199.ap-northeast-1.compute.internal systemd[1]: aws-appconfig-agent.service: Main process exited, code=exited, status=1/FAILURE
Jul 22 23:29:01 ip-172-31-33-199.ap-northeast-1.compute.internal systemd[1]: aws-appconfig-agent.service: Failed with result 'exit-code'.

オプションで環境変数を使うことでエージェントの動作をカスタマイズさせることが出来ると公式ドキュメントには記載されていますが、エージェント(/opt/aws/aws-appconfig-agent/bin/aws-appconfig-agent)を直接実行したところリージョンの指定がない場合にエラーとなることがわかりました。

[root@ip-172-31-33-199 system]# /opt/aws/aws-appconfig-agent/bin/aws-appconfig-agent
[appconfig agent] 2023/07/22 23:34:34 INFO AppConfig Agent 2.0.580
[appconfig agent] 2023/07/22 23:34:34 FATAL agent initialization failed for multiple reasons:
[appconfig agent] 2023/07/22 23:34:34 FATAL     an AWS region is required, but was not found
[appconfig agent] 2023/07/22 23:34:34 FATAL     an AWS region is required, but was not found
[root@ip-172-31-33-199 system]# /opt/aws/aws-appconfig-agent/bin/aws-appconfig-agent --help
Usage:
  -P, --prefetch_list string                           configurations to fetch immediately on startup (default "[]")
  -p, --poll_interval duration                         duration, in seconds, between checks for a configuration update (default 45s)
      --max_connections int                            maximum connections per host used by the agent (default 3)
  -t, --request_timeout duration                       duration, in milliseconds, the agent will wait for a service response (default 3000ms)
  -r, --service_region string                          AWS region to use for service calls
      --proxy_url string                               the url for a configured proxy (http or https)
      --proxy_headers string                           headers to be passed to the configured proxy (default "[]")
      --role_arn string                                IAM role the agent should assume when making service calls
      --role_external_id string                        the external id to set when the agent assumes a role
      --role_session_name string                       the session name to set when the agent assumes a role
      --http_port int                                  port number (1-65535) to use for the localhost proxy (default 2772)
      --access_token string                            if specified, the bearer token value required to retrieve configuration data
      --evidently_event_batch_size int                 events per project to batch before sending to Evidently (1-50) (default 40)
      --evidently_batch_collection_duration duration   duration to wait for events before sending to Evidently (default 30s)
      --evidently_configurations string                AppConfig configuration path(s) for Evidently projects (default "[]")
  -l, --log_level string                               the verbosity of output logs (debug, info, warn, error, none) (default "info")
      --log_path string                                the disk location where logs are written (if unset, logs are written to stderr)

[root@ip-172-31-33-199 system]# /opt/aws/aws-appconfig-agent/bin/aws-appconfig-agent -r ap-northeast-1
[appconfig agent] 2023/07/22 23:35:58 INFO AppConfig Agent 2.0.580
[appconfig agent] 2023/07/22 23:35:58 INFO serving on localhost:2772

次のように記載があったので省略した場合もうまく実行リージョンくらいは取得してくれるのかと思ってました。IMDS 周りだろうか?

If left undefined, the agent attempts to determine the current Region. If it can't, the agent fails to start.

リージョン指定が必須という前提と解釈し指定してみる

構成ファイルの内容を見てみると、プリフェッチやログなどデフォルトからほぼ変えたほうが良いだろうというものが多かったので構成ファイルでリージョン指定する方向で対処してみます。
公式ドキュメントだと次のような指定方法が紹介されていました。

[Service]
Environment=LOG_LEVEL=DEBUG

ただ、この形式だと環境変数が認識されなかったのでユニットファイルの設定はこちらを参考に設定しました。
最終的にユーザーデータで次のように指定しています。

#!/bin/bash
dnf install -y https://s3.amazonaws.com/aws-appconfig-downloads/aws-appconfig-agent/linux/x86_64/latest/aws-appconfig-agent.rpm
mkdir /etc/systemd/system/aws-appconfig-agent.service.d
cat << 'EOF' > /etc/systemd/system/aws-appconfig-agent.service.d/overrides.conf
[Service]
Environment="SERVICE_REGION=ap-northeast-1"
EOF
systemctl daemon-reload
systemctl start aws-appconfig-agent

起動後にセッションマネージャーでアクセスしてみると、おっ良さそうです。

sh-5.2$ systemctl status aws-appconfig-agent
● aws-appconfig-agent.service - aws-appconfig-agent
     Loaded: loaded (/etc/systemd/system/aws-appconfig-agent.service; enabled; preset: disabled)
    Drop-In: /etc/systemd/system/aws-appconfig-agent.service.d
             └─overrides.conf
     Active: active (running) since Sun 2023-07-23 01:07:28 UTC; 1min 42s ago
   Main PID: 2197 (aws-appconfig-a)
      Tasks: 5 (limit: 1114)
     Memory: 7.6M
        CPU: 43ms
     CGroup: /system.slice/aws-appconfig-agent.service
             └─2197 /opt/aws/aws-appconfig-agent/bin/aws-appconfig-agent

リクエストも送信してみましょう。

sh-5.2$ curl "http://localhost:2772/applications/hoge0723appconfig/environments/hoge0723env1/configurations/hoge0723feature" | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    51  100    51    0     0    188      0 --:--:-- --:--:-- --:--:--   189
{
  "flag1": {
    "enabled": true
  },
  "flag2": {
    "enabled": true
  }
}

フラグを更新しデプロイする

では AppConfig の設定をエージェントから取得出来るようになったので、値の更新とデプロイを行ってみます。
次のようにフラグをひとつ変更してみます。

更新した構成バージョンを EC2 がリクエストしようとしている環境にデプロイします。

デプロイが完了したら、先程と同様にエージェント経由で取得してみましょう。
エージェントオプションでカスタマイズ出来ますが、デフォルトでは 45 秒でポーリングしていますので少しだけタイムラグがあるはず。
何度かアクセスしてみます。

sh-5.2$ curl "http://localhost:2772/applications/hoge0723appconfig/environments/hoge0723env1/configurations/hoge0723feature" | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    51  100    51    0     0  16042      0 --:--:-- --:--:-- --:--:-- 17000
{
  "flag1": {
    "enabled": true
  },
  "flag2": {
    "enabled": true
  }
}
sh-5.2$ curl "http://localhost:2772/applications/hoge0723appconfig/environments/hoge0723env1/configurations/hoge0723feature" | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    52  100    52    0     0   6134      0 --:--:-- --:--:-- --:--:--  6500
{
  "flag1": {
    "enabled": false
  },
  "flag2": {
    "enabled": true
  }
}

おっ、変更が反映されましたね。良さそうです。

さいごに

本日は AWS AppConfig Agent が EC2 でもサポートされるようになったので使ってみました。
これまで自前でポーリングやキャッシュを管理していた方は、エージェントをぜひ試してみてください。

なお、Systems Manager のパラメータストアと AppConfig の使い分けにたまに悩むときがあったのですが、環境やデプロイ管理出来る点は改めて AppConfig のおもしろいところだなと再認識しました。エージェントと併せてうまく使えると便利ですね。