玩转 K8s 权限控制:RBAC + kubeconfig 搞定 kubectl 权限管理那些事
1. 先拋需求
當一個 K8s 集群需要被多個租戶共享時,就涉及到了權限問題,比如你是管理員,這時候你會面臨著“給每個用戶分配一個 Namespace”類似的需求。
更進一步,可能你需要限制特定用戶只能夠對集群進行特定的操作,比如不能讓“張三”有機會執行 kubectl delete node <NODE_NAME> 這種 sao 命令。
在上一篇文章《通過 VS Code 優雅地編輯 Pod 內的代碼(非 NodePort)》中我們講到怎樣在不暴露一堆 NodePort 的前提下,通過 VS Code 更新 Pod 內的代碼。VS Code 里去 Attach Pod 其實也是用的本地 kubeconfig 來和 apiserver 通信,進而操作到 Pod。換言之,要實現“多租戶通過 VS Code 連接自己的 Pod”這個需求,也涉及到給不同租戶創建合適的“最小權限 kubeconfig”。行,今天就來解決這個問題。
2. RBAC 配置
整體就兩步,先倒騰 RBAC,然后倒騰 kubeconfig。我們先來看 RBAC吧。
2.1. K8s 里的 RBAC 機制介紹
先復習下 K8s 里的 RBAC 機制。
(這時候需要用到 GPT 了。)
- 
我:Hello ChatGPT,用中文總結下 K8s 里的 RBAC 是個啥。
 - 
ChatGPT:
 
在 Kubernetes 中,RBAC 是一種強大的訪問控制機制,用于管理對集群資源的訪問權限。RBAC 可以幫助管理員精確地控制用戶、ServiceAccount 或其他實體對 Kubernetes API 中資源的操作權限。RBAC 基于角色的授權模型使得管理員可以定義角色和角色綁定,從而實現對不同用戶或實體的訪問權限控制。
RBAC 由四個基本概念組成:
- 角色(Role):角色定義了一組操作權限,例如對某個命名空間下資源的讀取、創建或刪除等操作。
 - 角色綁定(RoleBinding):角色綁定將特定的角色授予 User、Group 或者 ServiceAccount,從而賦予它們相應的權限。
 - 集群角色(ClusterRole):類似于角色,但作用范圍更廣,可以授權對整個集群中資源的操作權限。
 - 集群角色綁定(ClusterRoleBinding):將集群角色綁定給 User、Group 或者 ServiceAccount,授予它們在整個集群范圍內的權限。
 通過 RBAC,管理員可以根據需求精確控制不同用戶或實體在集群中的權限范圍,避免了不必要的權限泄露或誤操作,提高了集群的安全性和管理靈活性。
行,就總結到這里,接著我們要實操了。
2.2 創建 ServiceAccount、Role、RoleBinding 和 Secret
- ServiceAccount:以用戶 user1 為例,來一個 user1-account
 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: user1-account
  namespace: default
- Role:繼續來一個 user1-role
 
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: user1-role
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods", "pods/exec"]
  verbs: ["get", "list", "watch", "create", "delete", "update", "patch"]
這里就可以在 rules 下精細地控制這個角色所能夠訪問的資源、執行的操作了。如果需要集群維度資源的控制,比如 Node,那就得用到 ClusterRole 了,玩法類似,不贅述。
- RoleBinding:把用戶和角色綁起來
 
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: user1-access-default-namespace
  namespace: default
subjects:
- kind: ServiceAccount
  name: user1-account
  namespace: default
roleRef:
  kind: Role
  name: user1-role
  apiGroup: rbac.authorization.k8s.io
- Secret:在 K8s 1.24 版本之后,ServiceAccount 對于的 Secret 就不會自動創建了。哎,手動搞吧
 
apiVersion: v1
kind: Secret
metadata:
  name: user1-account-secret
  annotations:
    kubernetes.io/service-account.name: "user1-account"
type: kubernetes.io/service-account-token
這個 Secret 創建出來之后,K8s 會自動將 ServiceAccount 對應的 token 寫進這個 Secret。
一頓 apply 操作之后,RBAC 相關的幾個資源就都有了。前幾個沒啥好說的,Secret 的關鍵字段貼一下,大家感受下 K8s 在背地里偷偷干了些啥:
kgsec user1-account-secret -o yaml
apiVersion: v1
data:
  ca.crt: LS0t……==
  namespace: ZGVmYXVsdA==
  token: ZXlKa……=
kind: Secret
metadata:
  annotations:
    kubernetes.io/service-account.name: user1-account
  name: user1-account-secret
  namespace: default
type: kubernetes.io/service-account-token
data 部分,發現了嗎,ca.crt 和 token 信息被填進去了。這兩段配置在后面要用到。
3. 配置 kubeconfig 文件
user1 的權限配置已經 OK 了,下一步就是將 token 搞到 kubeconfig 里。
3.1 kubeconfig 文件介紹
呵呵,老規矩,我這么懶的人,怎么可能自己總結。
- ChatGPT:
 
kubeconfig 是 Kubernetes 的一個配置文件,它包含了訪問 Kubernetes 集群所需的所有信息。這些信息包括集群的地址、用戶證書、用戶名和命名空間等。kubeconfig 文件使得用戶和 CI/CD 工具可以方便地與 Kubernetes 集群進行交互。
kubeconfig 文件通常位于用戶的主目錄下的
.kube目錄中,文件名為config。然而,用戶也可以通過設置KUBECONFIG環境變量來指定其他位置的 kubeconfig 文件。kubeconfig 文件主要由以下三部分組成:
集群(clusters):定義了要連接的 Kubernetes 集群的信息,包括集群的名稱、服務器的地址和 CA 證書。
用戶(users):定義了用戶的認證信息,包括用戶的名稱、客戶端證書和密鑰。
上下文(contexts):定義了用戶和集群之間的關系。一個上下文包含了一個用戶和一個集群,以及用戶在該集群中的默認命名空間。
通過在 kubeconfig 文件中定義不同的上下文,用戶可以輕松地在不同的 Kubernetes 集群和命名空間之間切換。
稍顯稚嫩,不過將就吧。關于 kubeconfig 是個啥的資料太多了,我就不過多啰嗦了。
貼一個 minikube 默認創建的 kubeconfig 文件:
apiVersion: v1
clusters:
- cluster:
    certificate-authority: /Users/danielhu/.minikube/ca.crt
    extensions:
    - extension:
        last-update: Wed, 13 Dec 2023 15:28:46 CST
        provider: minikube.sigs.k8s.io
        version: v1.32.0
      name: cluster_info
    server: https://127.0.0.1:60719
  name: minikube
contexts:
- context:
    cluster: minikube
    extensions:
    - extension:
        last-update: Wed, 13 Dec 2023 15:28:46 CST
        provider: minikube.sigs.k8s.io
        version: v1.32.0
      name: context_info
    namespace: default
    user: minikube
  name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
- name: minikube
  user:
    client-certificate: /Users/danielhu/.minikube/profiles/minikube/client.crt
    client-key: /Users/danielhu/.minikube/profiles/minikube/client.key
總之就是 clusters 里定義一堆可用的集群信息,users 里定義一堆用戶信息,然后在 contexts 里將 user 和 cluster 關聯起來;最后通過切換 context 就可以實現切換“用戶/集群”了。
3.2 具體的 kubeconfig 配置
前面創建的 Secret 里有一個 token,將其復制出來備用。(這里要注意,別拿 base64 轉碼后的結果。kubectl get -o yaml 拿到的是 base64 編碼的;kubectl describe 拿到的是原始的,你可以直接拿原始的,也可以拿編碼后的自己 echo "xxx" | base64 -d 解碼一下。
此外 Secret 里有一個 ca.crt,這個 ca 的內容是集群維度統一的,你在其他地方復制也行,不過這里有,順手拿一個也不打緊。這里需要是 base64 編碼后的內容,注意這個細節。
然后準備這樣一個 kubeconfig 文件:
apiVersion: v1
kind: Config
clusters:
- name: minikube1
  cluster:
    server: https://127.0.0.1:60719
    certificate-authority-data: <ca.crt, base64>
users:
- name: user1-account
  user:
    token: <token>
contexts:
- name: user1-context
  context:
    cluster: minikube1
    namespace: default
    user: user1-account
注意幾個細節:
- clusters 下面的 name 記得不要和你系統內默認 config 中的 clusters 重名;
 - server 地址可以抄你的默認 config 里的配置;
 - ca 配置其實也是一樣的,你的系統內有,復用配置也行;我這里選擇貼一個 base64 版本的內容,為了不引入“外部文件”,方便分發;
 - token 填寫前面準備的 token,非 base64。
 
3.3 kubeconfig 切換測試
最簡單粗暴的辦法,你可以直接備份 $HOME/.kube/config,然后將這個新文件替換進去,這樣就能測試新的 kubeconfig 是不是正常工作了。
或者,你可以配置上 KUBECONFIG 環境變量,將新的 kubeconfig 保存路徑追加進去。比如 mac 可以這樣:
export KUBECONFIG=/Users/danielhu/.kube/config:/Users/danielhu/Work/test/kubeconfig
Windows 系統得用分號(;)。
這時候你再執行 kubectl config view 就可以看到一個 merge 之后的 kubeconfig 配置,也就是新的舊的 kubeconfig 都在一起了。
下一步,我推薦你用 kubectx 來切換 context:
kubectx
minikube
user1-context
kubectx user1-context
OK,這時候就能切換到新的 context 了。接著可以試下是不是只有 pods 能被操作到:
4. 總結
打完收工。沒啥好總結的。See you next day.
總結
以上是生活随笔為你收集整理的玩转 K8s 权限控制:RBAC + kubeconfig 搞定 kubectl 权限管理那些事的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: x86指令格式
 - 下一篇: 【案例教程】LoadRunner订票系统