在 linux 系统中可能会包含很多用户,且不同用户有不同的权限,若需要为不同的用户设置不同的操作K8s的权限,就需要用到 K8s 的 rbac 机制。下面以创建一个 user 用户,为其设置在 default namespace 下的只读权限。
我们执行 kubectl 命令时会需要 kube-apiserver 的认证和授权,即利用用户的证书和 rbac 机制,因此若对系统用户进行权限控制,首先需要为用户创建证书。
证书创建
首先创建一个用户组和普通用户
groupadd usergroup
useradd user -g usergroup -m
为用户创建证书有两种方式,可以使用 K8s 推荐的 cfssl,也可以用 openssl。
openssl 创建证书
我们默认 K8s 部署时所创建的认证相关的密钥和证书都保存在/etc/kubernetes/ssl/
中。
- 生成私钥
openssl genrsa -out user.key 2048
- 生成签名
export CA_DNAME="/CN=user/OU=Sysem/O=group:view/L=Beijing/ST=Beijing/C=CN"
openssl req -new -key user.key -subj $CA_DNAME -out user.csr
其中 CA_DNAME 显示签名的所有者,CN 为名字, 3. 生成证书
openssl x509 -req -CA /etc/kubernetes/ssl/ca.crt -CA /etc/kubernetes/ssl/ca.key -CAcreateserial -in user.csr -out user.crt -day 365
cfssl 创建证书
配置 K8s 上下文
切换到 user 用户后,配置访问的集群
kubectl config set-cluster <yourCluster> \
--certificate-authority=/etc/kubernetes/ssl/ca.crt \
--embed-certs=true \
--server=<your apiserver>
其中 certificate-authority 使用的是 K8s 生成的证书
cluster name 可以通过
kubectl config get-clusters
获取 apiserver 通过kubectl cluster-info
获取
配置认证证书
kubectl config set-credentials user\
--client-certificate=user.crt \
--client-key=user.key \
--embed-cert=true
注意,此处的 user 并非系统用户名,而是 CA_DNAME 中的用户名,即在K8s的 rbac 中认证的名字。OU为组,同样关联 K8s rbac 认证的组
配置上下文
kubectl config set-context contextName \
--cluster=<your clustername> \
--user=user # 此处user 仍是 CA_DNAME 中的用户名
这样就配置好 user 用户的 kubectl 访问的上下文了。上下文信息默认保存在了 $HOME/.kube/config
中。
这几步中其实可以看出 K8s 的认证与系统用户名及其所在组毫无关系,K8s 只关心用户通过 kubectl 访问时所携带的证书,即 config 文件中所包含的认证信息。因此如果用户有权指定 root 用户下的 .kube/config
作为上下文配置,则可以拥有所有权限。
K8s rbac 配置
K8s 中使用 RBAC 授权器为用户授权,相关资源有 Role
ClusterRole
RoleBinding
ClusterRoleBinding
Role & ClusterRole
Role
和ClusterRole
用于描述角色权限的,即配置角色对于资源的可操作权限,Role
可只属于某个namespace, ClusterRole
隶属于全局。
一个 Role
对象只能用于授予对某一单一命名空间中资源的访问权限。 以下示例描述了”default”命名空间中的一个Role对象的定义,用于授予对pod的读访问权限:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # 空字符串""表明使用core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
ClusterRole
对象可以授予与Role对象相同的权限,但由于它们属于集群范围对象, 也可以使用它们授予对以下几种资源的访问权限:
- 集群范围资源(例如节点,即node)
- 非资源类型endpoint(例如”/healthz”)
- 跨所有命名空间的命名空间范围资源(例如pod,需要运行命令kubectl get pods --all-namespaces来查询集群中所有的pod)
在本例中,若使用
ClusterRole
,则如下所示:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: global-pod-reader
rules:
- apiGroups: [""] # 空字符串""表明使用core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
RoleBinding & ClusterRoleBinding
角色绑定将一个角色中定义的各种权限授予一个或者一组用户。 角色绑定包含了一组相关主体(即subject, 包括用户——User、用户组——Group、或者服务账户——Service Account)以及对被授予角色的引用。 在命名空间中可以通过RoleBinding
对象授予权限,而集群范围的权限授予则通过ClusterRoleBinding
对象完成。
RoleBinding
可以引用在同一命名空间内定义的Role
对象。 下面我们定义RoleBinding
对象在”default”命名空间中将”pod-reader”角色授予用户”user”。 这一授权将允许用户”user”从”default”命名空间中读取pod。
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
若使用 ClusterRoleBinding
,则如下所示:
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-pod-global
namespace: default # 这里表明的是权限的作用域,而非所属哪个namespace,若没有这个字段,则表明作用域为全局。
subjects:
- kind: User # 此处也可以更换为 Group ,对应之前 CA_DNAME 中的 OU
name: user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: global-pod-reader
apiGroup: rbac.authorization.k8s.io
在K8s中,系统包含默认的用户,如下
ClusterRole | ClusterRoleBinding | info |
---|---|---|
cluster-admin | system:masters group | 超级用户权限,允许对任何资源执行任何操作。 在ClusterRoleBinding中使用时,可以完全控制集群和所有命名空间中的所有资源。 在RoleBinding中使用时,可以完全控制RoleBinding所在命名空间中的所有资源,包括命名空间自己。 |
admin | None | 管理员权限,利用RoleBinding在某一命名空间内部授予。 在RoleBinding中使用时,允许针对命名空间内大部分资源的读写访问, 包括在命名空间内创建角色与角色绑定的能力。 但不允许对资源配额(resource quota)或者命名空间本身的写访问。 |
edit | None | 允许对某一个命名空间内大部分对象的读写访问,但不允许查看或者修改角色或者角色绑定。 |
view | None | 允许对某一个命名空间内大部分对象的只读访问。 不允许查看角色或者角色绑定。 由于可扩散性等原因,不允许查看secret资源。 |
参考自https://jimmysong.io/kubernetes-handbook/concepts/rbac.html
总结
至此我们已经实现了通过 rbac 对系统用户的权限控制,对于用户的权限,可以使用 kubectl auth can-i <verbs> <resource>
的命令进行验证。
此处个人推荐一本 ebook,kubernetes handbook。