在Kubernetes中訪問IAM:如何安裝Kube2iam

IAM是AWS的實際的受權方法。大部分針對AWS的Kubernetes的「快速入門」指南並無充分覆蓋如何在你的Pod中管理IAM訪問的相關內容。本系列文章講探討Kubernetes環境的AWS IAM特有的安全性問題,而後對比不一樣方案,並最終詳細介紹如何選擇一種方案來設置集羣。node

在以前的文章中,咱們在生產kubernetes集羣中安裝了kiam。在本文中,咱們將介紹在成產環境快速安裝kube2iam的過程.git

概述

本文將包含你在身纏環境部署kube2iamd的如下4步:github

  1. 建立 IAM roles
  2. 增長Annotation到Pod
  3. 部署kube2iam
  4. 測試
  5. 所有部署kube2iam

瀏覽kube2iam概況及特性,請查看 Github Pagedocker

1. 建立IAM Roles

使用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"
    }
  ]
}

2. 爲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

3. 部署kubeiam

如今能夠部署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_NAMEPod.spec,而後增長tolerations這樣它就能夠被調度到該節點。設置鏡像版本爲標記過的發佈版本而非latest。還須要設置--host-interface命令參數來適配你的CNIkube2iam頁面有完整的支持列表。我也建議設置 --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不會有變動。

4. 測試

在這一步,開始測試以指望一切正常。你能夠經過在該隔離節點部署一個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到每一個節點。

5. 全量部署kube2iam

從kube2iam Daemonset刪除nodeNamekub2iam: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做爲解決方案的深刻比較。

因在下英文太爛,若是能夠您閱讀英文,強烈建議 查看原文

FAQ & Checklist

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
相關文章
相關標籤/搜索