IAM是AWS的實際的受權方法。大部分針對AWS的Kubernetes的「快速入門」指南並無充分覆蓋如何在你的Pod中管理IAM訪問的相關內容。本系列文章講探討Kubernetes環境的AWS IAM特有的安全性問題,而後對比不一樣方案,並最終詳細介紹如何選擇一種方案來設置集羣。node
在以前的文章中,咱們在生產kubernetes集羣中安裝了kiam。在本文中,咱們將介紹在成產環境快速安裝kube2iam的過程.git
本文將包含你在身纏環境部署kube2iamd的如下4步:github
瀏覽kube2iam概況及特性,請查看 Github Page。docker
使用kubeiam的第一步是爲你的Pod建立IAM roles。kube2iam的工做方式是須要一個IAM策略附加到集羣中每一個節點以容許其爲Pod委派roles。json
建立爲你的節點一個IAM策略而且附加到你的kubernetes節點的role上。api
策略:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "sts:AssumeRole" ], "Resource": "*" } ] }
接下來爲每一個pod建立role。每一個role將須要一個策略,擁有Pod功能所需的最小權限,例如:列出S3對象,寫入DynamoDB, 讀取SQS等。你須要爲每一個所建立的role更新委派角色策略,以便使你的節點能夠委派這些role。用kubernetes節點所附加role的arn
替換YOUR_NODE_ROLE
。安全
委派角色策略:
{ "Version": "2012-10-17", "Statement": [ { "Action": "sts:AssumeRole", "Principal": { "Service": "ec2.amazonaws.com" }, "Effect": "Allow", "Sid": "" }, { "Sid": "", "Effect": "Allow", "Principal": { "AWS": "YOUR_NODE_ROLE" }, "Action": "sts:AssumeRole" } ] }
pod
增長Annotations
下一步將你的pod將用的role註釋到Pod。增長一個annotation
到pod 的metadata.spec
便可,kube2iam使用IAM對Pod進行身份認證時將使用這個role。如此配置後,kube2iam將爲該role自動檢查基礎arn
,可是若是你須要委派角色給其餘AWS帳號也能夠指定一個完整的arn
(以arn:aws:iam
開始)。kube2iam文檔有一些不一樣pod控制器的例子。網絡
annotations: iam.amazonaws.com/role: MY_ROLE_NAME
如今能夠部署kube2iam。你能夠參考kube2iam github repo 獲取EKS和OpenShift的例子,可是這裏也也會介紹一些通用deployment方法。第一步時配置RBAC:app
--- apiVersion: v1 kind: ServiceAccount metadata: name: kube2iam namespace: kube-system --- apiVersion: v1 items: - apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: kube2iam rules: - apiGroups: [""] resources: ["namespaces","pods"] verbs: ["get","watch","list"] - apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: kube2iam subjects: - kind: ServiceAccount name: kube2iam namespace: kube-system roleRef: kind: ClusterRole name: kube2iam apiGroup: rbac.authorization.k8s.io kind: List
由於kube2iam修改了kubernetes節點上的iptables規則來劫持到EC2 metadata服務的流量,我建議增長一個tainted
的新節點到集羣,這樣你能夠在確保不影響你生產環境Pod的前提下測試控制器來配置正確。爲集羣增長一個節點而後爲其打上五點鐘,這樣其餘Pod就不會被調度到該節點。tcp
export ALICLOUD_ACCOUNT="" export ALICLOUD_ACCESS_KEY="your-access-key" export ALICLOUD_SECRET_KEY="your-secret-key" export ALICLOUD_REGION="cn-qingdao"
kubectl taint nodes NODE_NAME kube2iam=kube2iam:NoSchedule
接下來咱們能夠在該節點上配置agent。增長nodeName: NEW_NODE_NAME
到Pod.spec
,而後增長tolerations
這樣它就能夠被調度到該節點。設置鏡像版本爲標記過的發佈版本而非latest
。還須要設置--host-interface
命令參數來適配你的CNI
。kube2iam頁面有完整的支持列表。我也建議設置 --auto-discover-base-arn
和 --auto-discover-default-role
參數來時配置和遷移更容易。若是你的集羣再單個可用區--use-regional-sts-endpoint
會頗有用,可是你必須爲其設置 AWS_REGION
環境變量。綜上所述,配置大體以下:
apiVersion: apps/v1 kind: DaemonSet metadata: name: kube2iam namespace: kube-system labels: app: kube2iam spec: selector: matchLabels: name: kube2iam template: metadata: labels: name: kube2iam spec: nodeName: NEW_NODE_NAME tolerations: - key: kube2iam value: kube2iam effect: NoSchedule serviceAccountName: kube2iam hostNetwork: true containers: - image: jtblin/kube2iam:0.10.6 imagePullPolicy: Always name: kube2iam args: - "--app-port=8181" - "--auto-discover-base-arn" - "--iptables=true" - "--host-ip=$(HOST_IP)" - "--host-interface=weave" - "--use-regional-sts-endpoint" - "--auto-discover-default-role" - "--log-level=info" env: - name: HOST_IP valueFrom: fieldRef: fieldPath: status.podIP - name: AWS_REGION value: "us-east-1" ports: - containerPort: 8181 hostPort: 8181 name: http securityContext: privileged: true
接下來你能夠建立agent並確認該agent運行於你的新節點上。你其餘節點上的Pod不會有變動。
在這一步,開始測試以指望一切正常。你能夠經過在該隔離節點部署一個Pod,而後在該POD中使用AWS CLI訪問資源進行測試。當你作這些時,請檢查kube2iam agent的日誌來debug你遇到的的問題。這裏有個deployment實例,你能夠指定一個role而後用它進行訪問測試。
apiVersion: apps/v1beta2 kind: Deployment metadata: name: aws-iam-tester labels: app: aws-iam-tester spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: aws-iam-tester template: metadata: labels: app: aws-iam-tester annotations: iam.amazonaws.com/role: TEST_ROLE_NAME spec: nodeSelector: kubernetes.io/role: node nodeName: NEW_NODE_NAME tolerations: - key: kube2iam value: kube2iam effect: NoSchedule containers: - name: aws-iam-tester image: garland/aws-cli-docker:latest imagePullPolicy: Always command: - /bin/sleep args: - "3600" env: - name: AWS_DEFAULT_REGION value: us-east-1
Pod將會在一個小時後退出,你可使用kubectl獲取一個TTY到Pod。
kubectl exec -ti POD_NAME /bin/sh
一旦你確認你的role能夠正常工做,而且kube2iam agent配置正常,你就能夠部署agent到每一個節點。
從kube2iam Daemonset刪除nodeName
和kub2iam:kub2iam
以容許它運行到每一個節點。 在每一個節點安裝完成之後,應該對關鍵pod進行更新,以這些Pod當即使用kube2iam進行驗證。其餘曾經使用node role進行認證的的Pod當其臨時憑據過時後將開始使用kube2iam進行認證(一般是一個小時)。若IAM認證有錯,請檢查你的應用及kubeiam日誌。
當一切運行正常,你就能夠刪除再次以前添加的隔離節點。
遇到問題時,你能夠刪除全部節點上的agent,可是它不會自動清理它建立的iptable規則。這將致使全部發往EC2 metada的請求不起做用。你須要分別登陸到每一個節點並手動移除這些iptables規則。
首先列出iptable規則,找出kube2iam所建立的部分
sudo iptables -t nat -S PREROUTING | grep 169.254.169.254
輸出大概以下:
-A PREROUTING -d 169.254.169.254/32 -i weave -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.101.101:8181
若是你意外的使用不一樣的--host-interface
選項部署agent你可能會看到多個結果。你能夠一次刪除他們。刪除一條規則使用iptables的-D
選項並指定-A
選項輸出的具體行號,例如:
sudo iptables -t nat -D PREROUTING -d 169.254.169.254/32 -i weave -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.101.101:8181
當每一個節點上都執行事後,EC2 metadta請求將不在發往kube2iam.
如今有kube2iam運行於你的生產集羣以及,併爲POD建立獨立的角色。
若是你的對其餘阿方案看興趣,請查看我以前寫的[kiam安裝]()一文。它更加複雜,而且使用不一樣的方法解決IAM的問題。我也在關注 kube-aws-iam-controller做爲替代方案,可是該項目一直不太成熟不適合生產環境。你可也能夠查看本系列第一,第二篇文章來了解kubernetes中使用AWS IAM的問題,以及對kiam和kube2iam做爲解決方案的深刻比較。
因在下英文太爛,若是能夠您閱讀英文,強烈建議 查看原文
Question: Add support for Instance Metadata Service Version 2 (IMDSv2)Question: 注意你的集羣所使用的網絡方案,好比:文中例子爲
weave
,個人集羣爲Calico
,因此應該修改成cali+
。不然會報以下錯誤:
$ k logs kube2iam-ltm7f -n kube-system ... time="2020-07-17T10:47:30Z" level=fatal msg="route ip+net: no such network interface"
Question 2: 默認狀況下kube2iam使用8181端口,由於個人worker node使用了8181端口,須要增長2個參數
--app-port=8182 --metrics-port=8183
,不然會報以下錯誤:
$ k logs kube2iam-bk59z -n kube-system time="2020-07-18T03:42:04Z" level=info msg="Listening on port 8181" time="2020-07-18T03:42:04Z" level=fatal msg="Error creating kube2iam http server: listen tcp :8181: bind: address already in use"
Question 3: 使用文中命令未找到相應的iptables規則
$ sudo iptables -t nat -S PREFOUTING | grep 169.254.169.254 iptables: No chain/target/match by that name. # 嘗試以下命令 sudo iptables -t nat -L | grep 169.254.169.254