kubernetes

AWS ECSのタスク同様に、KubernetesでもPod毎にIAMロールを設定する仕組みと方法

TL;DR;

https://github.com/kubernetes/kubernetes/issues/23580

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で変換されるようにしておく

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、一時クレデンシャルを返す

2018.3アップデート

kube2iamよりkiamのほうが安定して動いてます。あと危険なオプション(default-arnがない)がないのもポイント。

https://github.com/uswitch/kiam