Kubernetes 如何只授予某一 Namespace 的访问权限

最近遇到一个问题,那就是需要给别人共享一下 Kubernetes 的某个资源的使用和访问权限,这个仅仅存在于某个 namespace 下,但是我又不能把管理员权限全都给它,我想只给他授予这一个 Namespace 下的权限,那应该怎么办呢?

比如我这边是需要只想授予 postgresql 这个 Namespace 的权限,这里我就需要利用到 Kubernetes 里面的 RBAC 机制来实现了,下面记录了我的操作流程。

创建 Namespace

kubectl create namespace postgresql

首先没有 Namespace 的话需要创建一个 Namespace,这里我创建的是 postgresql,大家可以自行修改。

创建 ServiceAccount

接下来需要创建一个 ServiceAccount,yaml 如下:

apiVersion: v1kind: ServiceAccountmetadata:  name: postgresql  namespace: postgresql

创建 Role

然后还要创建一个 Role,来控制相应的权限,yaml 如下:

kind: RoleapiVersion: rbac.authorization.k8s.io/v1beta1metadata:  name: postgresql  namespace: postgresqlrules:  - apiGroups: ["", "extensions", "apps"]    resources: ["*"]    verbs: ["*"]  - apiGroups: ["batch"]    resources:      - jobs      - cronjobs    verbs: ["*"]

这里由于 Role 是 Namespace 级别的,所以只能在特定 Namespace 下生效,这里我要让授予本 Namespace 下的所有权限,这里 rules 就添加了所有的 API类型、资源类型和操作类型。

创建 RoleBinding

最后需要将 Role 和 ServiceAccount 绑定起来,yaml 如下:

kind: RoleBindingapiVersion: rbac.authorization.k8s.io/v1beta1metadata:  name: postgresql  namespace: postgresqlsubjects:  - kind: ServiceAccount    name: postgresql    namespace: postgresqlroleRef:  apiGroup: rbac.authorization.k8s.io  kind: Role  name: postgresql

创建 kubeconfig 文件

现在我们执行上述 yaml 文件之后,ServiceAccount 其实就已经创建好了,它会对应一个 secret,我们来看下详情,执行:

 kubectl get serviceaccount postgresql -n postgresql -o yaml

好,运行结果类似如下:

apiVersion: v1kind: ServiceAccountmetadata:  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-31842989bbbcsecrets:- name: postgresql-token-v26k7

这里它实际关联了一个 secret,叫做 postgresql-token-v26k7,这里面就隐藏了 ServiceAccount 的 token 和证书。

好,那么我们就可以利用这个 secret 来制作 kubeconfig 文件了,命令如下:

server=https://your-server:443name=postgresql-token-v26k7namespace=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: v1kind: Configclusters:- name: test cluster: certificate-authority-data: ${ca} server: ${server}contexts:- name: test context: cluster: test user: postgresqlcurrent-context: testusers:- 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)    AGEpostgresql            ClusterIP   10.0.193.137   <none>        5432/TCP   9dpostgresql-headless   ClusterIP   None           <none>        5432/TCP   9dpostgresql-metrics    ClusterIP   10.0.60.88     <none>        9187/TCP   9dpostgresql-read       ClusterIP   10.0.236.184   <none>        5432/TCP   9d

这里就可以看到对 postgresql 这个命名空间的操作就成功了。

到此为止我们就成功实现了特定 Namespace 的限制,大功告成。

原文地址:https://www.cnblogs.com/cheyunhua/p/13426821.html