掃碼或搜索: 進擊的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 的限制,大功告成。

相關文章