kiam で Kubernetes の Pod に IAM role を割り当てる

シェアする

  • このエントリーをはてなブックマークに追加

概要

kiam - Integrate AWS IAM with Kubernetes
  • uswitch/kiam で Kubernetes Pod に対して IAM role を割り当て、動作を確認する
  • Kubernetes cluster は kops で AWS 上に構築したものを使う
  • 検証用の S3 bucket を使い Pod に割り当てた role の有無で参照可能/不可能になることを確認する

前回検証した kube2iam と同様に、 IAM role を Pod に対して割り当てられるようにしてくれるやーつ。

kube2iamの記事:

概要 kube2iam で Kubernetes Pod に対して IAM role を割り当て、動作を確認する Kubernetes ...

検証

以下をやってみる:

  • kiam のインストール
  • S3 バケットを参照する IAM role を作成
  • Pod に role を割り当てたり外したりして挙動を確認してみる

kiam のインストール

git clone https://github.com/uswitch/kiam.git
cd kiam/deploy
kubectl create -f agent.yaml
kubectl create -f server-rbac.yaml
kubectl create -f server.yaml

kiam は2つのプロセスから成り立つ:

  • Agent
    • Pod からのメタデータ API に対するクレデンシャル要求の HTTP リクエストを受け付ける
    • それ以外のリクエストは AWS API に転送する
    • Server と gRPC で通信を行う
  • Server
    • Agent から利用される gRPC サーバとして動作する
    • Pod に必要な role を決定しクレデンシャルを取得する

kops で構築したクラスタの場合、 kiam-server のマニフェストに以下の変更を加える必要があった。

参考:

{"generation.metadata":0,"level":"error","msg":"error warming credentials: RequestError: send request failed\ncause...
When deploying kiam using the yaml files in /deploy, both DaemonSets are created, but only the kiam-agent DaemonSet actually has any pods. kiam-server has no po...
@@ -15,12 +19,16 @@ spec:
         role: server
     spec:
       serviceAccountName: kiam-server
+      tolerations:
+        - key: "node-role.kubernetes.io/master"
+          effect: "NoSchedule"
+          operator: "Exists"
       nodeSelector:
         kubernetes.io/role: master
       volumes:
         - name: ssl-certs
           hostPath:
-            path: /usr/share/ca-certificates
+            path: /etc/ssl/certs
         - name: tls
           secret:
             secretName: kiam-server-tls

インストール後、 Kubernetes node の iptables ルールには以下が追加された:

-A PREROUTING -d 169.254.169.254/32 -i cni0 -p tcp -m tcp --dport 80 -j DNAT --to-destination {{ Node IP }}:8181
-A PREROUTING -d 169.254.169.254/32 -i cali+ -p tcp -m tcp --dport 80 -j DNAT --to-destination {{ Node IP }}:8181

TLS

uswitch/kiam/docs/TLS.md

Agent – Server 間でのみ通信を可能にするために TLS 相互認証が使われる。
必要な証明書は自動的には作成されないため、証明書を作成して Server と Agent のプロセスだけがアクセス可能な secrets に保存する必要がある。

ドキュメントに記載の方法でセットアップすればおk。cfssl をインストールして証明書を生成、 secrets として Kubernetes クラスタに配置する。

IAM

uswitch/kiam/docs/IAM.md

Cluster Node Policy

サーバプロセスを実行するノードには sts:AssumeRole を呼び出す権限が必要。

今回は kops を使用しているため、 kops edit cluster で編集できる cluster 設定の spec.additionalPolicies.master に、以下の内容を追加した。

spec:
  additionalPolicies:
    master: |
      [
        {
          "Effect": "Allow",
          "Action": ["sts:AssumeRole"],
          "Resource": ["*"]
        }
      ]

Application Roles

Pod に割り当てる IAM Role には、その Role を実際に引き受けるノード (kiam のサーバプロセスを実行するノード) を信頼するための
ポリシー (AssumeRolePolicyDocument) を設定する必要がある。

今回は特定の S3 Bucket に対して s3:ListBucket するための Role を用意した。 Role とポリシーは Terraform で作った。

#
# variables
#
variable "test-kiam-bucket-name" {
  type    = "string"
  default = "test-kiam-bucket"
}

#
# test-kiam-bucket role & policy
#
## role
resource "aws_iam_role" "test-kiam-bucket" {
  name = "${var.test-kiam-bucket-name}"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    },
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:role/masters.test.k8s.example.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
}

## role policy
resource "aws_iam_role_policy" "test-kiam-bucket" {
  name = "${var.test-kiam-bucket-name}"
  role = "${aws_iam_role.test-kiam-bucket.id}"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::${var.test-kiam-bucket-name}"
      ]
    }
  ]
}
EOF
}

動作確認

aws-cli の使える適当な Pod を配置して、 Pod に IAM ロールを割り当てた場合/割り当てない場合の挙動の違いを確認する。

apiVersion: v1
kind: Pod
metadata:
  name: mypod
  labels:
    name: mypod 
spec:
  containers:
  - image: debian
    command: [ "/bin/bash", "-c", "--" ]
    args: [ "while true; do sleep 30; done;" ]
    name: mypod
$ kubectl create -f mypod.yml
pod "mypod" created

## aws-cli のインストール
$ kubectl exec -it mypod /bin/bash
root@mypod:/# apt-get update && apt-get install -y curl
root@mypod:/# apt-get install -y python && curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py" && python get-pip.py && pip install awscli
root@mypod:/# mkdir ~/.aws
root@mypod:/# cat > ~/.aws/config <<EOF
> [default]
> region = ap-northeast-1
> EOF

Pod に IAM ロールを付与し S3 バケットの内容が取得できるか確認

IAM Role は Pod に annotation を付与することで割り当てることができる。

annotation 付与前
## security-credentials 配下は empty
root@mypod:/# curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
empty role

## S3 bucket の中身は見ることができない
root@mypod:/# aws s3 ls s3://test-kiam-bucket
Unable to locate credentials. You can configure credentials by running "aws configure".
annotation 付与後
## Pod に用意した role 名で annotation をつける
% kubectl annotate pods mypod iam.amazonaws.com/role='test-kiam-bucket'
pod "mypod" annotated

## namespace にも利用できる role の許可設定を annotation で入れる
% kubectl annotate namespace default iam.amazonaws.com/permitted='.*'
namespace "default" annotated

## S3 バケットの中身が見られるか確認してみる
root@mypod:/# aws s3 ls s3://test-kube2iam-bucket
2018-02-26 12:31:57        306 chart.txt

Pod, namespase への annotation 付与後、 S3 bucket の中身が見えることが確認できた。

annotation を外せば bucket 内は再び見えなくなる。

% kubectl annotate pods mypod iam.amazonaws.com/role-
pod "mypod" annotated

root@mypod:/# aws s3 ls s3://test-kiam-bucket
Unable to locate credentials. You can configure credentials by running "aws configure".

Pod に付与する annotation は role の ARN でも指定可能。

kubectl annotate pods mypod iam.amazonaws.com/role='arn:aws:iam::111111111111:role/test-kiam-bucket'

また、 namespace に付与する annotation には正規表現が使用可能。

kubectl annotate namespace default iam.amazonaws.com/permitted='test-kiam-*'

まとめ

  • kiam を kops で構築した AWS 上の k8s cluster にインストールした
    • Agent と Server の2つのプロセスが必要
    • kops の場合 (現状は) Server の yaml manifest に変更を加える必要がある
  • 実際にクレデンシャルを取得するのは kiam-server プロセス
    • sts:AssumeRole は master node 側に必要
  • Pod に対して IAM role を付与することで S3 bucket の参照が可能になることを確認した
    • Role を割り当てるには namespace にも annotation 付与が必要
    • kube2iam は Pod に対してのみ annotation を付与する

参考

Developers.IOは、AWS、iOS/Androidアプリ、ビッグデータ、Alexa等の最新技術情報からリモートワークや働き方に関する記事まで多彩なトピックを紹介するクラスメソッドのオウンドメディアです。
この記事は1年以上前に書かれたものです。内容が古い可能性がありますのでご注意ください。  こんにちは。CS課の...

シェアする

  • このエントリーをはてなブックマークに追加

フォローする