kiam で Kubernetes の Pod に IAM role を割り当てる
概要
- uswitch/kiam で Kubernetes Pod に対して IAM role を割り当て、動作を確認する
- Kubernetes cluster は kops で AWS 上に構築したものを使う
- 検証用の S3 bucket を使い Pod に割り当てた role の有無で参照可能/不可能になることを確認する
前回検証した kube2iam と同様に、 IAM role を Pod に対して割り当てられるようにしてくれるやーつ。
kube2iamの記事:
検証
以下をやってみる:
- 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 で通信を行う
- Pod からのメタデータ API に対するクレデンシャル要求の HTTP リクエストを受け付ける
- Server
- Agent から利用される gRPC サーバとして動作する
- Pod に必要な role を決定しクレデンシャルを取得する
kops で構築したクラスタの場合、 kiam-server のマニフェストに以下の変更を加える必要があった。
参考:
@@ -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
Agent - Server 間でのみ通信を可能にするために TLS 相互認証が使われる。 必要な証明書は自動的には作成されないため、証明書を作成して Server と Agent のプロセスだけがアクセス可能な secrets に保存する必要がある。
ドキュメントに記載の方法でセットアップすればおk。cfssl をインストールして証明書を生成、 secrets として Kubernetes クラスタに配置する。
IAM
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 を付与する
- Role を割り当てるには namespace にも annotation 付与が必要
参考
Previous Post
Next Post