日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無先后,達者為師

網(wǎng)站首頁 編程語言 正文

Kubernetes?權(quán)限管理認證鑒權(quán)詳解_云其它

作者:運維開發(fā)故事 ? 更新時間: 2022-12-23 編程語言

正文

Kubernetes 主要通過 API Server 對外提供服務(wù),對于這樣的系統(tǒng)來說,如果不加以安全限制,那么可能導(dǎo)致請求被濫用,甚至導(dǎo)致整個集群崩塌。

鑒于此,Kubernetes 對于訪問 API 的用戶提供了相應(yīng)的安全控制:認證和授權(quán)。認證解決用戶是誰的問題,授權(quán)解決用戶能做什么的問題。只有通過合理的權(quán)限控制,才能夠保證整個集群系統(tǒng)的安全可靠。

下圖是 API 訪問需要經(jīng)過的三個步驟,它們分別是:認證、授權(quán)和準入,準入不在這章節(jié)討論,它更多專注的是資源的管理。

認證

認證(Authentication)是指用戶是否可以登錄 Kubernetes,即是否可以向 API Server 發(fā)送請求。

在 Kubernetes 中,有兩類用戶:

  • Normal Users:外部用戶
  • Service Accounts:內(nèi)部用戶

認證用戶

Normal Users

Normal Users 獨立于 Kubernetes,不歸其管理,這類用戶可以是:

  • 可以分發(fā) private keys 的管理員(真人)
  • 提供用戶服務(wù)的第三方廠商,比如 Google Accounts
  • 保存用戶名和密碼的列表文件

如果用戶都不在 Kubernetes 中,都不歸它管,那它是如何進行認證的呢?

對于一般的應(yīng)用系統(tǒng)來說,用戶提供用戶名和密碼,服務(wù)端收到過后會在數(shù)據(jù)庫中進行檢查是否存在并有效,如果有就表示鑒權(quán)成功,反之失敗。

那對于 Kubernetes 來說,是如何實現(xiàn)的呢?

盡管無法通過 API 調(diào)用來添加普通用戶,Kubernetes 巧妙的通過證書來進行用戶認證。也就是說,不管任何用戶,只要能提供有效的證書就能通過 Kubernetes 用戶認證。

通過用戶認證過后,Kubernetes 會把證書中的 CN 作為用戶名(比如證書中”/CN=joker“,則用戶名就是 Joker),把 Organization 作為用戶組,然后由用戶名和用戶組綁定的 Role 來決定用戶的權(quán)限。

Service Accounts

Service Accounts 由 Kubernetes 管理,它們被綁定到特定的 namespace,其可以通過 API Server 自己創(chuàng)建,也可以通過調(diào)用 API 來創(chuàng)建,比如使用 kubectl 客戶端工具。

與 Normal Users 不同,Service Accounts 存在對應(yīng)的 Kubernetes 對象,當創(chuàng)建 Service Accounts,會創(chuàng)建相應(yīng)的 Secret,里面保存對應(yīng)的密碼信息(在 1.24.x 版本中,不會創(chuàng)建對應(yīng)的 secret)。當創(chuàng)建的 Pod 指定了一個 Service Account,其 Secret 會被 Mount 到 Pod 中,Pod 中的進程就可以訪問 Kubernetes API 了。

認證策略

Kubernetes 有以下幾種鑒權(quán)方法:

  • 客戶端證書
  • 不記名令牌
  • 身份認證代理
  • 通過鑒權(quán)插件的 HTTP 基本認證機制

當 HTTP 請求發(fā)送到 API Server 時,Kubernetes 會從 Request 中關(guān)聯(lián)以下信息:

  • Username:用戶名,用來辨識最終用戶的字符串,比如 kube-admin 或jane@example.com
  • UID:用戶 ID,代表用戶的唯一 ID
  • Groups:用戶組,代表邏輯相關(guān)的一組用戶,
  • Extra Fields,擴展字段,鑒權(quán)可能需要的其他信息

需要注意的是,當多種鑒權(quán)方法同時啟用時,第一個鑒權(quán)方法鑒權(quán)成功即通過驗證,其它方法不再鑒權(quán),同時 api-server 也不保證鑒權(quán)方法的順序。所有鑒權(quán)成功的用戶都會加到 group “system:authenticated”中。

客戶端證書

當我們使用客戶端證書進進行認證時,需要向 Kubernetes 提供有效的證書,這個證書可以是外部證書,也可以是 Kubernetes 自己審批的證書。

如果是外部證書,就需要在 API Server 啟動的時候用--client-ca-file=SOMEFILE參數(shù)引入外部證書的 CA 等信息,用來驗證客戶端證書的有效性。

當認證通過后,Kubernetes 會把證書的 Subject CN 作為用戶名,Organization 作為用戶組(Group)。

不記名令牌

當使用不記名令牌(Bearer token)來對某 HTTP 客戶端執(zhí)行身份認證時,API 服務(wù)器希望看到一個名為 Authorization 的 HTTP 頭,其值格式為 Bearer。不記名令牌(Bearer token)必須是一個可以放入 HTTP 頭部值字段的字符序列,至多可使用 HTTP 的編碼和引用機制。例如:如果持有者令牌為 31ada4fd-adec-460c-809a-9e56ceb75269,則其出現(xiàn)在 HTTP 頭部時如下所示:

Authorization: Bearer 31ada4fd-adec-460c-809a-9e56ceb75269

在 Kubernetes 中,主要有以下幾種使用不記名令牌(Bearer token)的方法:

  • Static Token File(靜態(tài)令牌)
  • Service Account Tokens(服務(wù)賬號令牌)
  • OpenID Connect Tokens(OIDC 令牌)

Static Token File

當使用靜態(tài)令牌的時候,API Server 會通過--token-auth-file=SOMEFILE從外部引入一個 CSV 文件,API Server 會從這個文件中讀取對應(yīng)的用戶名和用戶組。

當客戶端進行請求時,API Server 把請求 Header 中的 Bearer tokens 和文件中的 token 進行比較,然后判斷 Token 是否有效。

Service Account Tokens

當手動或者自動創(chuàng)建 Service Account 的時候,Kubernetes 會自動創(chuàng)建一個 Service Account Token,在 v1.24 版本之前,會對應(yīng)創(chuàng)建一個 secret 保存到對應(yīng)的 namespace 中,在 v1.24 版本之后不會再單獨創(chuàng)建 secret,而是在啟動 Pod 的時候,由 kubelet 通過 TokenRequest API 生成一個 Token 掛載到 Pod 中。

上文提到,Service Account 主要是為 Pods 提供訪問 API Server 的功能,當 Pod 創(chuàng)建過后,Service Account Token 就會被 Mount 到 Pod 中,此時 Pod 就擁有訪問 API Server 的能力。

當然,Service Account Token 除了用在 Pod 上,在外部也可以使用,在《Kubernetes 集群管理》中的集群安裝章節(jié),有介紹使用 Token 訪問 Kubernetes Dashboard,這時候使用的也是 Service Account Token。

OpenID Connect Tokens

OpenID Connect 是一種 OAuth3 認證方式,Kubernetes 可以利用 OAuth3 Token Response 中的 ID Token 作為 Bearer Token 進行認證訪問。

其流程如下:

  • 登錄到你的身份服務(wù)(Identity Provider)
  • 你的身份服務(wù)將為你提供 access_token、id_token 和 refresh_token
  • 在使用 kubectl 時,將 id_token 設(shè)置為 --token 標志值,或者將其直接添加到 kubeconfig 中
  • kubectl 將你的 id_token 放到一個稱作 Authorization 的頭部,發(fā)送給 API 服務(wù)器
  • API 服務(wù)器將負責(zé)通過檢查配置中引用的證書來確認 JWT 的簽名是合法的
  • 檢查確認 id_token 尚未過期
  • 確認用戶有權(quán)限執(zhí)行操作
  • 鑒權(quán)成功之后,API 服務(wù)器向 kubectl 返回響應(yīng)
  • kubectl 向用戶提供反饋信息

不管用戶通過哪種方式進行認證,認證通過并不代表就有操作權(quán)限,僅僅只是通過第一條防線而已,下一步就要進行鑒權(quán),用來決定用戶是否有具體的操作權(quán)限。

鑒權(quán)

鑒權(quán)流程

當請求通過認證(Authentication)過后,就會進入鑒權(quán)(Authorization)階段。在這個階段 Kubernetes 會檢查請求是否有權(quán)限訪問需要的資源,如果有權(quán)限則開始處理請求,反之則返回權(quán)限不足。

API Server 會檢查所有 Policy 來檢查是否存在 Policy 允許請求中的動作,存在則允許請求執(zhí)行,否則會拒絕執(zhí)行并返回 403 錯誤。當配置了多個授權(quán)模塊的時候,請求會按順序校驗每一個模板,如果其中任一模塊校驗不通過,則請求會被拒絕,不再進行后續(xù)的校驗。

Kubernetes 在做鑒權(quán)時,主要檢查以下信息:

  • user:同鑒權(quán)中檢查的信息相同
  • group:同鑒權(quán)中檢查的信息相同
  • extra:同鑒權(quán)中檢查的信息相同
  • API:是否為 Api 資源
  • Request path:非資源(API 資源)endpoint,比如/healthz
  • API request verb:API 動作,比如 get, list, create, update, patch,對某個資源的具體動作,比如,列出所有的 pod
  • HTTP request verb:用于非資源的請求中的 HTTP 動作,比如 get, post, put
  • Resource:請求訪問的資源名字或 ID
  • Subresource:請求訪問的子資源名字或 ID
  • Namespace:資源所在的名字空間
  • API group:請求訪問的 API group,API group 指控制相關(guān)資源的一組 Api,如果未指定則代表 core API group

鑒權(quán)模塊

Kubernetes 提供了以下 4 種鑒權(quán)模式:

  • Node:一種特殊的授權(quán)模塊,基于 Node 上運行的 Pod 為 Kubelet 授權(quán)
  • ABAC:基于屬性的訪問控制
  • RBAC:基于角色的訪問控制
  • Webhook:HTTP 請求回調(diào),通過一個 WEB 應(yīng)用鑒定是否有權(quán)限進行某項操作

這里只會介紹 RBAC——基于角色的訪問控制。在實際中,這種模式使用的場景比較多。

RBAC

RBAC 是 Kubernetes 中常用的鑒權(quán)模式,其基本概念如下:

  • Rule:規(guī)則,一組屬于不同 API Group 的操作集合;
  • Role:角色,用于定義一組對 Kubernetes API 對象操作的一組規(guī)則,作用于當個 namespace;
  • ClusterRole:集群角色,該角色不受 namespace 的限制;
  • Subject:被作用者,也就是規(guī)則作用的對象;
  • RoleBinding:將角色和被作用者進行綁定,作用于當個 namespace;
  • ClusterRoleBinding:將集群角色和作用者進行綁定,不受 namespace 限制;

Role 和 ClusterRole

Role 和 ClusterRole 中定義一組相關(guān)權(quán)限的規(guī)則,這些權(quán)限是累加的(不存在拒絕某操作的規(guī)則)。其中 Role 是 Namespace 級別的,而 ClusterRole 是集群級別的。

Role 的定義如下:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: role-demo
  namespace: devops
rules:
- apiGroups: [""]
  resources: ["pods", "deployment"]
  verbs: ["creat", "delete", "watch", "list", "get"]

其含義是:它允許被作用者在 devops 的 namespace 中對 pod 和 deployment 有 creat,delete,watch,list,get 操作。由于 Role 是 Namespace 級別,所以上面的規(guī)則只對 devops 的 namespace 有效。

ClusterRole 的定義如下:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-role-demo
rules:
- apiGroups: [""]
  resources: [""]
  verbs: ["watch", "list", "get"]

其含義是對所有資源都有 watch、list、get 的操作權(quán)限。

如果要定義所有權(quán)限,可以將 verbs 字段定義如下:

verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

RoleBinding 和 ClusterRoleBinding

角色綁定將一個角色中定義的各種權(quán)限授予一個或者一組用戶。角色綁定包含了一組相關(guān)主體(即 subject, 包括用戶——User、用戶組——Group、或者服務(wù)賬戶——Service Account)以及對被授予角色的引用。在命名空間中可以通過 RoleBinding 對象授予權(quán)限,而集群范圍的權(quán)限授予則通過 ClusterRoleBinding 對象完成。

RoleBinding 可以引用在同一命名空間內(nèi)定義的 Role 對象。如下:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: joker-rolebinding
  namespace: devops
subjects:
  - kind: User
    name: joker
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: role-demo
  apiGroup: rbac.authorization.k8s.io

這就給 joker 用戶和 role-demo 的 Role 建立了綁定關(guān)系,其中 joker 這個 User 只是一個授權(quán)系統(tǒng)中的邏輯概念,它需要通過外部認證服務(wù),比如 Keystone,或者直接給 API Server 指定一個用戶名,密碼文件。

上面的 YAML 文件中其中一個重要的字段是 Subjects 字段,它定義"被作用者",其中的 kind 表示被作用者的類型,其有以下三種類型:

  • User:用戶,這是由外部獨立服務(wù)進行管理的,管理員進行私鑰的分配,用戶可以使用 KeyStone 或者 Goolge 帳號,甚至一個用戶名和密碼的文件列表,對于用戶的管理集群內(nèi)部沒有一個關(guān)聯(lián)的資源對象,所以用戶不能通過集群內(nèi)部的 API 來進行管理。
  • Group:組,這是用來關(guān)聯(lián)多個賬戶,集群中有一個默認的組,比如 cluster-admin。
  • ServiceAccount:服務(wù)帳號,通過 Kubernetes API 來管理的一些用戶帳號,和 namespace 進行關(guān)聯(lián)的,適用于集群內(nèi)部運行的應(yīng)用程序,需要通過 API 來完成權(quán)限認證,所以在集群內(nèi)部進行權(quán)限操作,我們都需要使用到 ServiceAccount。

另外一個重要字段是 roleRef,它定義 RoleBing 對象可以直接通過 Role 的名字來引用我們定義的 Role 對象,從而定義被作業(yè)者和角色之間的綁定關(guān)系。

RoleBinding 是 namespace 級別的,如果是集群級別則用 ClusterRoleBinding,如下:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: joker-clusterrolebinding
subjects:
  - kind: User
    name: joker
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-role-demo
  apiGroup: rbac.authorization.k8s.io

上面定義的就是 joker 這個用戶對所有 namespace 里的資源都有 watch,list,get 的操作權(quán)限。

Service Account

Service Account 也是一種賬號,但它并不是給 Kubernetes 集群的用戶(系統(tǒng)管理員、運維人員、租戶用戶等)用的,而是給運行在 Pod 里的進程用的,它為 Pod 里的進程提供了必要的身份證明。

我們通過一個例子來了解 ServiceAccount 的授權(quán)過程。

1、首先定義一個 ServiceAccount:

apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: devops
  name: sa-demo

一個簡單的 ServiceAccount 只需要簡單的 namespace 和 name 即可。

2、編寫 RoleBinding 的 YAML 文件來為這個 ServiceAccount 分配權(quán)限:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: role-demo
  namespace: devops
rules:
  - apiGroups: [""]
    resources: ["pods", "deployment"]
    verbs: ["creat", "delete", "watch", "list", "get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: sa-rolebinding
  namespace: devops
subjects:
  - kind: ServiceAccount
    name: sa-demo
    namespace: devops
roleRef:
  kind: Role
  name: role-demo
  apiGroup: rbac.authorization.k8s.io

然后我們創(chuàng)建上面定義的 YAML 文件,查看創(chuàng)建完成后的信息:

$ kubectl get sa -n devops
NAME      SECRETS   AGE
default   0         6m25s
sa-demo   0         6m25s
$ kubectl get role -n devops
NAME        CREATED AT
role-demo   2022-07-06T04:27:02Z
$ kubectl get rolebinding -n devops
NAME             ROLE             AGE
sa-rolebinding   Role/role-demo   6m50s

現(xiàn)在創(chuàng)建一個 Pod 并使用 sa-demo Service Account。

apiVersion: v1
kind: Pod
metadata:
  name: pod-sa-demo
  namespace: devops
spec:
  serviceAccountName: sa-demo
  containers:
  - name: pod-sa-demo
    image: nginx
    imagePullPolicy: IfNotPresent

查看 Pod 信息如下:

$ kubectl get po -n devops pod-sa-demo -oyaml
apiVersion: v1
kind: Pod
metadata:
  annotations:
    cni.projectcalico.org/containerID: c0820de4319bb6915602c84132ff83a63f62abaa1e9c706bad04e64661455d30
    cni.projectcalico.org/podIP: 172.16.51.225/32
    cni.projectcalico.org/podIPs: 172.16.51.225/32
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"pod-sa-demo","namespace":"devops"},"spec":{"containers":[{"image":"nginx","imagePullPolicy":"IfNotPresent","name":"pod-sa-demo"}],"serviceAccountName":"sa-demo"}}
  creationTimestamp: "2022-07-06T04:30:13Z"
  name: pod-sa-demo
  namespace: devops
  resourceVersion: "192831"
  uid: 4f4c7c5a-53ca-45f7-94ad-63e546cfcc62
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: pod-sa-demo
    resources: {}
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: kube-api-access-vxrcd
      readOnly: true
  dnsPolicy: ClusterFirst
  enableServiceLinks: true
  nodeName: kk-node01
  preemptionPolicy: PreemptLowerPriority
  priority: 0
  restartPolicy: Always
  schedulerName: default-scheduler
  securityContext: {}
  serviceAccount: sa-demo
  serviceAccountName: sa-demo
  terminationGracePeriodSeconds: 30
  tolerations:
  - effect: NoExecute
    key: node.kubernetes.io/not-ready
    operator: Exists
    tolerationSeconds: 300
  - effect: NoExecute
    key: node.kubernetes.io/unreachable
    operator: Exists
    tolerationSeconds: 300
  volumes:
  - name: kube-api-access-vxrcd
    projected:
      defaultMode: 420
      sources:
      - serviceAccountToken:
          expirationSeconds: 3607
          path: token
      - configMap:
          items:
          - key: ca.crt
            path: ca.crt
          name: kube-root-ca.crt
      - downwardAPI:
          items:
          - fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
            path: namespace

從上面可以看到 Service Account Token 被掛載到 Pod 中了。

$ kubectl exec -it -n devops pod-sa-demo -- /bin/sh
# ls /var/run/secrets/kubernetes.io/serviceaccount
ca.crt  namespace  token

其中 ca,crt 就是用來訪問 API Server 的。

如果一個 Pod 在定義時沒有指定 spec.serviceAccountName 屬性,則系統(tǒng)會自動為其賦值為 default,即大家都使用同一個 Namespace 下的默認 Service Account。

Subjects 的 kind 類型除了 User,ServiceAccount 之外,還有一個 Group,就是一組用戶的意思。如果你為 Kubernetes 配置了外部認證服務(wù)的話,這個用戶組就由外部認證服務(wù)提供。而對于 Kubernetes 內(nèi)置用戶 ServiceAccount 來說,其也有用戶和用戶組的概念,其中對于一個 ServiceAccount,其在 Kubernetes 中對應(yīng)的用戶是:

system:serviceaccount:<ServiceAccount名字>

而對于其用戶組是:

system:serviceaccounts:<Namespace名字>

比如我們定義下面這個 RoleBinding:

subjects:
  - kind: Group
    name: system:serviceaccounts:devops
    apiGroup: rbac.authorization.k8s.io

這就意味著 Role 這個角色的權(quán)限規(guī)則作用與 devops 的 namespace 中的所有 ServiceAccount。

再比如:

subjects:
  - kind: Group
    name: system:serviceaccounts
    apiGroup: rbac.authorization.k8s.io

這就意味著 Role 這個角色規(guī)則作用與整個集群的所有 ServiceAccount。

kubernetes 已經(jīng)內(nèi)置了許多 ClusterRole,以 system:開頭,可以用 kubectl get clusterrole 查看。

另外,Kubernetes 還提供了四個預(yù)先定義好的 ClusterRole 來供用戶直接使用,它們是:

  • cluster-admin:超管
  • admin:普通管理權(quán)限
  • edit:修改權(quán)限
  • view:只讀權(quán)限

我們在定義 RoleBinding 或 ClusterRolebinding 的時候可以直接使用。

最后

Kubernetes 的權(quán)限管理就介紹到這里,本章節(jié)主要介紹了認證、授權(quán)的大概流程以及在 Kubernetes 中是如何實現(xiàn)認證、授權(quán)的。學(xué)完本章,你可以掌握認證用戶有哪些,有哪些認證策略,以及如何使用 RBAC 實現(xiàn)鑒權(quán)。

原文鏈接:https://juejin.cn/post/7132353316184391687

欄目分類
最近更新