Kubernetes 如何限制特定 namespace 的權限
掃碼或搜索: 進擊的Coder
發送
即可 立即永久 解鎖本站全部文章
最近遇到一個問題,那就是需要給別人共享一下 Kubernetes 的某個資源的使用和訪問權限,這個僅僅存在於某個 namespace 下,但是我又不能把管理員權限全都給它,我想只給他授予這一個 Namespace 下的權限,那應該怎麼辦呢?
比如我這邊是需要只想授予 postgresql 這個 Namespace 的權限,這裏我就需要利用到 Kubernetes 裏面的 RBAC 機制來實現了,下面記錄了我的操作流程。
創建 Namespace
kubectl create namespace postgresql
首先沒有 Namespace 的話需要創建一個 Namespace,這裏我創建的是 postgresql,大家可以自行修改。
創建 ServiceAccount
接下來需要創建一個 ServiceAccount,yaml 如下:
apiVersion: v1 kind: ServiceAccount metadata: name: postgresql namespace: postgresql
創建 Role
然後還要創建一個 Role,來控制相應的權限,yaml 如下:
kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: postgresql namespace: postgresql rules: - apiGroups: ["", "extensions", "apps"] resources: ["*"] verbs: ["*"] - apiGroups: ["batch"] resources: - jobs - cronjobs verbs: ["*"]
這裏由於 Role 是 Namespace 級別的,所以只能在特定 Namespace 下生效,這裏我要讓授予本 Namespace 下的所有權限,這裏 rules 就添加了所有的 API類型、資源類型和操作類型。
創建 RoleBinding
最後需要將 Role 和 ServiceAccount 綁定起來,yaml 如下:
kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: postgresql namespace: postgresql subjects: - kind: ServiceAccount name: postgresql namespace: postgresql roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: postgresql
創建 kubeconfig 文件
現在我們執行上述 yaml 文件之後,ServiceAccount 其實就已經創建好了,它會對應一個 secret,我們來看下詳情,執行:
kubectl get serviceaccount postgresql -n postgresql -o yaml
好,運行結果類似如下:
apiVersion: v1 kind: ServiceAccount metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"postgresql","namespace":"postgresql"}} creationTimestamp: "2020-07-30T16:10:38Z" name: postgresql namespace: postgresql resourceVersion: "17800240" selfLink: /api/v1/namespaces/postgresql/serviceaccounts/postgresql uid: 6327db1f-6a93-4f1e-b988-31842989bbbc secrets: - name: postgresql-token-v26k7
這裏它實際關聯了一個 secret,叫做 postgresql-token-v26k7,這裏面就隱藏了 ServiceAccount 的 token 和證書。
好,那麼我們就可以利用這個 secret 來製作 kubeconfig 文件了,命令如下:
server=https://your-server:443 name=postgresql-token-v26k7 namespace=postgresql ca=$(kubectl get secret/$name -n $namespace -o jsonpath='{.data.ca.crt}') token=$(kubectl get secret/$name -n $namespace -o jsonpath='{.data.token}' | base64 --decode) echo "apiVersion: v1 kind: Config clusters: - name: test cluster: certificate-authority-data: ${ca} server: ${server} contexts: - name: test context: cluster: test user: postgresql current-context: test users: - name: postgresql user: token: ${token} " > postgresql.kubeconfig
這裏我們需要指定三個變量:
- server:就是 Kubernetes Server API 的地址
- name:就是 ServiceAccount 對應的 secret
- namespace:就是當前操作的 Namespace
運行之後就會生成一個 portgresql.kubeconfig 文件。
使用
那麼怎麼使用呢?很簡單,設置下環境變量切換下就好了。
export KUBECONFIG=postgresql.kubeconfig
這裏我們就將 KUBECONFIG 設置了下,這樣再執行 kubectl 就會讀取到當前的 kubeconfig 文件,就會生效了。
這時候我們來測試下:
kubectl get nodes
運行結果如下:
Error from server (Forbidden): nodes is forbidden: User "system:serviceaccount:postgresql:postgresql" cannot list resource "nodes" in API group "" at the cluster scope
可以看到這裏就提示沒有列出節點的權限了。
然後我們操作下 postgresql 下的權限試試:
kubectl get svc -n postgresql
運行結果如下:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE postgresql ClusterIP 10.0.193.137 <none> 5432/TCP 9d postgresql-headless ClusterIP None <none> 5432/TCP 9d postgresql-metrics ClusterIP 10.0.60.88 <none> 9187/TCP 9d postgresql-read ClusterIP 10.0.236.184 <none> 5432/TCP 9d
這裏就可以看到對 postgresql 這個命名空間的操作就成功了。
到此爲止我們就成功實現了特定 Namespace 的限制,大功告成。