先日、DynamoDBにアクセスするAPIをLambdaからEKS上への再実装・載せ替えを行いました。その際、IAM Role for Service Account(IRSA)を使用した一時クレデンシャル取得時のレイテンシが大きく高まる事象に遭遇しました。
原因と解決策を調査から解決に至るまでの過程とともにご紹介します。
TL;DR
IRSAを使用する際は一時クレデンシャル取得時にSTSにリージョナルエンドポイントを使用させるためAWS_STS_REGIONAL_ENDPOINTS=regional
という環境変数を設定することを検討すること。
経緯
現在転職会議ではECS or Lambdaで実装された既存のサービスを順次EKS上に載せ替えていっています。
先日、私がLambdaで実装されていたAPIをGoで再実装しEKS上に載せ替えました。このAPIはDynamoDBの中身をレスポンスとして返すという極めてシンプルなAPIです。
リプレース後、レイテンシの平均をとってみると以前のLambdaでの実装よりも速くはなっていたのですが、1時間おきにレスポンスが2s程度まで跳ねあがる現象が発生しました。
Datadog APMでレイテンシ急増時のフレームグラフを見てみると、2秒かかっているうちDynamoDBへのアクセスにかかっているのはリクエスト処理時間のうち最後の方の0.2秒程度だけであることが分かりました。
ここまでのことから、DynamoDBにアクセスする前に必要な処理でありかつ1時間おき発生する処理が原因と考えられ、その両方に当てはまるIAM Role for Service Accounts(IRSA)による一時クレデンシャルの取得処理が疑わしいと考えました。
そこで、行われている動作をもう少し詳しく調べるため、ステージング環境でtcpdumpで調べてみることにしました。具体的な手順としては以下です。
kubectl exec
でAPIサーバのコンテナに入る- tcpdumpをコンテナにインストール
- tcpdumpでダンプを取得
- ダンプファイルをkubectl cpでローカルにコピー
- Wiresharkでダンプファイルを見る
ダンプファイルを見てみると、STSとの通信ログからSTSへのアクセスに1.5s程度時間がかかっていることがわかりました。どうやら、Kubernetesの発行したトークンで一時クレデンシャルを取得するSTSのAssumeRoleWebIdentity
で時間がかかっているようです。
ダンプの中身を詳しく見てみると、DNSの通信ログからそのSTSへのアクセスにグローバルエンドポイント(sts.amazonaws.com
)が使用されていることがわかります。
STSでは可能な場合はリージョナルエンドポイント(sts.<region名>.amazonaws.com
)を使用することが推奨されています。そこで、AWS_STS_REGIONAL_ENDPOINTS=regional
という環境変数を設定してリージョナルエンドポイントが使用されるように設定しました。
すると、デプロイ直後と1時間毎に発生している一時クレデンシャル取得時のAPIのレイテンシが2秒から0.4秒程度まで大きく改善しました!
念の為ダンプファイルをとってみると、変更後は一時クレデンシャル取得時にはちゃんとSTSのリージョナルエンドポイントと通信していました。
まとめ
IRSAにより一時クレデンシャルを取得してAWSのAPIへアクセスするときはAWS_STS_REGIONAL_ENDPOINTS=regional
という環境変数を設定することを検討してください。この環境変数は最近のバージョンのAWS SDKおよびAWS CLIであれば使用できるようです。(ほかにSTSのリージョナルエンドポイントを使用させるもっとよい方法があればこっそり教えて下さい)
問題調査をするときには必要とあれば抽象化の皮を剥がして調査する能力が大事だと強く感じる事件でした。