TL;DR;
EC2におけるインスタンスプロフィールによる権限付与の仕組み
EC2インスタンスにインスタンスプロフィールを設定しておくと、プロフィールに設定したIAMロールの権限が付与された一時クレデンシャルをmetadataサービス(169.254.169.254)から得ることができます。
各言語向けのAWS SDKや、aws-cliはこれを利用してAWS_ACCESS_KEY_IDやAWS_SECRET_ACCESS_KEYなしでAWS APIを呼ぶことを可能にしてます。
ECSのIAMロール対応
2016/8月のアップデート以後、AWS ECSはタスク毎にIAMロールを設定できるようになっています。この仕組は以下のとおりです。
- タスク内のコンテナの環境変数AWS_CONTAINER_CREDENTIALS_RELATIVE_URIにタスク毎にユニークなパスが設定される
-
169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
にアクセスすると、JSON形式でクレデンシャルが返ってくる - 既存バージョンのAWS SDKは169.254.169.254からクレデンシャルを得る想定なのでこのままだと意味がないけど…
- 各言語のAWS CLI、AWS SDK(2016/7/13にリリースされたバージョン以降)は
169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
も見るようになっている(http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html#task-iam-roles-minimum-sdk) - EC2インスタンスのOSレベルの設定で、
169.254.170.2
がローカルホストの127.0.0.1:51679
にDNATで変換されるようにしておく- ECS-optimized AMIを利用している場合、既にそうなっている
- 他のAMIを利用している場合、iptables等の設定をする http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html#enable_task_iam_roles
Kubernetesで同じことを実現する方法・仕組み
- 結局のところ、AWS SDKやAWS CLIを騙して、metadataサービスからEC2でインスタンスプロフィールが設定されているときと同じようにクレデンシャルが返ってくるように見せることができればよい
- iptablesのPREROUTING chainで、metadataサービスへの通信を変換(DNAT)
- Pod内のコンテナから
169.254.169.254
へのアクセスが、iptablesによってプロキシ用コンテナに送られるようにする - そこで、EC2におけるインスタンスプロフィールのような挙動を実現する
- 例えばjtblin/kube2iamはPodに付与しておいたannotationに書かれているIAMロールを取り出し、プロキシ内でAssumeRole、一時クレデンシャルを返す
- Pod内のコンテナから
2018.3アップデート
kube2iamよりkiamのほうが安定して動いてます。あと危険なオプション(default-arnがない)がないのもポイント。