👻

AWS ECS Exec 周りの OSS のごくごく一部に寄与できた話

2021/08/25に公開

AWS ECS はマネージドなランタイムで Service, Task という独自のコンテキストでコンテナをサービスとして提供できるサービスです。
https://aws.amazon.com/jp/ecs/

ECS Fargate だとコンピューティングリソースもマネージドでインフラ管理コストが総合的に抑えられる点が利点です。

定義上で S3 から環境変数を直接読み込めるような定義ができたり、CloudFormation サポートや CodeDeploy による B/G デプロイへの対応など他 AWS リソースとの紐付きが強い点が EKS(kubernetes) との大きな差分になるかなと思います。(独自の定義なので、標準化されつつある k8s deployment 定義とのズレがあったり対応するアプリケーションが限定されたりといった悩みはあるにはありますが今回は別の話。。。)

今回はそんな AWS ECS のいち機能である ECS Exec 周辺のツールに対する貢献を行えた記事になります。この記事を通して OSS 怖くないじゃん!とか思っていただければ幸いです。

ECS Exec は kubectl exec, docker compose exec のようにコンテナの中に対して直接コマンドを叩ける機能となっていて、bash だと実行すればあたかも ssh したような振る舞いでコンテナに入ることもできる機能です。
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/ecs-exec.html

今回解決した問題は、「ECS Exec するにあたっての補助ツールで Exec できなくなる。」という問題です。問題が IAM 的な権限問題なのか、はたまた CLI 自体なのかというところの切り分けが難しい問題でした。

まずは権限の問題ではないというところに至る前に軽く ECS Exec の権限について説明します。

ECS には、タスクロールおよびタスク実行ロールという2つのロールを指定することができます。タスク実行ロールは、コンテナランタイムそのものを管理するロールで、タスクロールはコンテナの中からの API 操作権限になります。

ECR からイメージを pull する。といった操作はタスク実行ロールに必要で、コンテナの中で S3 に接続したいといった操作はタスク実行ロールに持たせる必要があるという感じです。

タスク実行ロールには AmazonECSTaskExecutionRolePolicy というものが既存で用意されていてこれをアタッチするのが通例です。
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_execution_IAM_role.html

タスクロールの方は独自に付与する形になります。
具体的な設定方法は「デバッグに Amazon ECS Exec を使用する」のドキュメントの通りではあります。
ECS exec 自体は、AWS が EC2 (など)とインタラクティブを開始できるセッションマネージャーという機能を利用して実現されています。コンテナエージェントが SSM 操作する権限が必要なため、各種 ssm 権限が必要になります。また、監査ログを有効にしたい場合に kms, s3 ... etc の権限がそれぞれ必要になるという形です。今回の問題は、この監査ログと暗号化を有効にした場合に発生しました。

ちなみに権限周り足りているか?などのチェックをできる補助ツールとして amazon-ecs-exec-checker というものもあります。awscli から describe-* を叩いて権限の整合性などをチェックしてくれるツールです。
https://github.com/aws-containers/amazon-ecs-exec-checker

この checker で通る状態だと exec するための権限は揃っていて実際に exec することができます。監査ログが実際に送れる状態か?とかまではまだ対応してない模様です。

一点実際そこでハマり点があり、「 exec できるけど監査ログが送られていない」といったことが権限が足りない問題で発生したこともありました。ログは agent 経由で /var/log/amazon/ssm/*.log に吐かれていてそこの error.log から推測することが可能でした。(似た問題があるか分からないですが、ECS Exec でなにか発生したときはココを見るとよさそうです。)

ここまでで exec 出来る環境は整い awscli では exec できるが、他ツールだとできない。という状態となり問題は権限的なところではなさそうとなりました。

実際に発生したエラーについては以下のようなものです。

...... Please upgrade to latest version of AWS CLI

awscli では exec できていて問題がないはずなのに、upgrade を求められるという内容です。さすがに混乱しましたが、順番に見ていくことで原因を見つけることができました。

まず awscli では ecs exec をどのように実現しているのかというのを確認すると、session-manager-plugin を直接叩いている事がわかります。
https://github.com/aws/aws-cli/blob/45b0063b2d0b245b17a57fd9eebd9fcc87c4426a/awscli/customizations/ecs/executecommand.py#L105

session-plugin-manager は SSM を利用するにあたって求められるプラグインです。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html

コードはしばらく公開されていなかったんですが、ごく最近公開されたようでこちらの中を確認すると upgrade awscli の謎が解けました。session-manager-plugin の方では awscli からのみ呼び出される前提の実装ともともとなっていて、渡す引数が少ない場合に「古い AWSCLI からのアクセス」という判定となっていて、結果として upgrade awscli を促していたという流れでした。本件については、session-manager-plugin の方に Issue を投げまして、コメントを改修してもらえました。
https://github.com/aws/session-manager-plugin/issues/8

変更後を確認すると、「お使いのCLIは暗号化に対応してないよ。」となっていて圧倒的に分かりやすくなってますね。ありがたいです!(上みたいな感じで割とラフな Issue でも対応してもらえるのが OSS のオモシロイところかもしれないです。)
https://github.com/aws/session-manager-plugin/blob/mainline/src/datachannel/streaming.go#L832

実際問題は「渡している引数が少ない」であることが判明したため、あとは利用ツールに対してコミットしたという流れになります。
https://github.com/kayac/ecspresso/issues/320
https://github.com/yukiarrr/ecsk/pull/1

ちなみに aws 公式の copilot-cli も引数が少ない前提の実装となっていたため一応 Issue を投げてみましたが、copilot-cli のポリシーとしてはひとまず標準を提供してそのあとユースケースに従って拡張させていくから単に今は対応してないだけだよみたいな感じだそうです。(長めの英語のやりとりが発生したので google 翻訳をフル活動させました。)
https://github.com/aws/copilot-cli/issues/2711

以上となります。ふとした問題でも諦めず追ってみると OSS 貢献に繋がるというのはこの世界のオモシロイところですね。続けることと順を追うこと、何よりやっぱりちゃんと(いろんな)ドキュメントを読むということが大事なんだなと改めて再認識しました。

OSS 怖くないです!楽しい:)

Discussion