Kubernetes访问控制之RBAC

眼前多少难甘事,自古男儿当自强。这篇文章主要讲述Kubernetes访问控制之RBAC相关的知识,希望能为你提供帮助。
kubernete中账户分为两种:

  • User Account (用户账户):kubernetes集群外部用户使用
  • Service Account (服务账号):用于集群内部使用
Kubernetes设计了一种Secret资源,分为两类,一种是用于 ServiceAccount,每创建一个SA,就会随之创建一个Secret;另一种就是用户自定义的保密信息Opaque
一、ServiceAccount中添加Image pull secrets
创建用于拉取镜像的secret
# kubectl create secret docker-registry harbor-registrykey \\
--docker-server=devops.harbor.com \\
--docker-username=admin \\
--docker-password=admin@123
创建sa并绑定secret
# cat imagepull-sa.yml
apiVersion: v1
kind: ServiceAccount
metadata:
name: imagepull-sa
namespace: devops
imagePullSecrets: #添加此字段
- name: harbor-registrykey

这个时候,只要是使用此 SA 的Pod,都可以在docker-registry拉取镜像了。
二、RBAC
RBAC介绍在Kubernetes中,所有资源对象都是通过API对象进行操作,他们保存在etcd里。而对etcd的操作我们需要通过访问 kube-apiserver 来实现,上面的Service Account其实就是APIServer的认证过程,而授权的机制是通过RBAC:基于角色的访问控制实现。RBAC使用rbac.authorization.k8s.io API Group 来实现授权决策,允许管理员通过 Kubernetes API 动态配置策略,要启用RBAC,需要在 apiserver 中添加参数--authorization-mode=RBAC
Role and ClusterRole在RBAC API中,Role表示一组规则权限,Role 是定义在一个 namespace 中,而 ClusterRole 是集群级别 下面定义一个Role
# cat test-role.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: test-role
namespace: devops
rules:
- apiGroups: [""]# 为空表示为默认的core api group
resources: ["pods"] # 数据源类型
verbs: ["get","watch","list"] #赋予的权限

以上策略表示对devops名称空间下的Pods有get,watch,list的权限
ClusterRole 具有与 Role 相同权限角色控制能力,不同的就是 Cluster Role是集群级别,主要用于:
  • 集群级别的资源控制(例如 node 访问权限)
  • 非资源型 endpoints(例如对某个目录或文件的访问:/healthz)
  • 所有命名空间资源控制(Pod、Deployment等)
# cat test-clusterrole.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: test-clusterrole
rules:
- apiGroups: [""]
resources: ["services"]
verbs: ["get","create","list"]

以上策略表示,有get,create,list整个集群service的权限
创建以上规则
kubectl apply -f test-role.yml
kubectl apply -f test-clusterrole.yml

RoleBinding 和 ClusterRoleBindingRoleBinding可以将角色中定义的权限授予用户或用户组,RoleBinding包含一组权限列表(Subjects),权限列表中包含有不同形式的待授予权限资源类型(users,groups, or Service Account)
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-rolebinding1
namespace: devops
subjects:
- kind: User# 权限资源类型
name: liheng# 名称
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role#要绑定的Role的类型(可以是Role或ClusterRole)
name: test-role # Role的名称
apiGroup: rbac.authorization.k8s.io

将名称为test-role的Role的权限资源赋予名为devops的用户,作用域为devops名称空间
【Kubernetes访问控制之RBAC】RoleBinding也可以引用ClusterRole来对当前 namespace 内用户、用户组或SA来进行授权,这种操作允许管理员在整个集群中定义一些通用的ClusterRole,然后在不同的namespace中使用RoleBinding绑定。
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-rolebinding2
namespace: devops
subjects:
- kind: User
name: devops
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: test-clusterrole
apiGroup: rbac.authorization.k8s.io

将名称为test-clusterrole的ClusterRole的资源权限赋予给了名称为devops的用户,但由于Role仅作用于单个namespace,所以此资源策略仅仅对devops名称空间下的资源有效
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: test-clusterrolebinding
subjects:
- kind: Group
name: devops
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: test-clusterrole
apiGroup: rbac.authorization.k8s.io

将名称为test-clusterrole的ClusterRole的资源权限赋予给groupname为devops的用户组,对此用户组下所有用户生效。
创建一个用户只能查看devops名称空间下的pod资源1、生成用户(liheng)私钥
# openssl genrsa -out liheng.key 2048

2、通过生成的私钥生成证书签名请求文件:liheng.csr,注意-subj中的CN表示用户名,O表示用户组。
# openssl req -new -key liheng.key -out liheng.csr -subj "/CN=liheng/O=yunweizhongxi"

3、通过kubernetes集群的CA证书为用户颁发签名证书
# openssl x509 -req -in liheng.csr -CA /opt/kubernetes/ssl/ca.pem \\
-CAkey /opt/kubernetes/ssl/ca-key.pem \\
-CAcreateserial -out liheng.crt -days 500

4、使用创建的证书文件和私钥创建用户(客户端)认证凭据
# kubectl config set-credentials liheng \\
--client-certificate=liheng.crt \\
--embed-certs=true \\
--client-key=liheng.key \\
--kubeconfig=liheng.kubeconfig

5、创建用户上下文(Context)
# kubectl config set-context liheng-context \\
--cluster=kubernetes \\
--namespace=kube-system \\
--user=liheng \\
--kubeconfig=liheng.kubeconfig

6、设置要访问的集群信息
# kubectl config set-cluster kubernetes \\
--certificate-authority=/opt/kubernetes/ssl/ca.pem \\
--embed-certs=true \\ #表示将--certificate-authority证书写入到kubeconfig中
--server=$KUBE_APISERVER \\
--kubeconfig=liheng.kubeconfig

7、为用户(liheng)设置RBAC权限
# cat test-role.yml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: test-role
namespace: devops
rules:
- apiGroups: [""]# 为空表示为默认的core api group
resources: ["pods"] # 数据源类型
verbs: ["get","watch","list"] #赋予的权限
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-rolebinding
namespace: devops
subjects:
- kind: User
name: liheng
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: test-role# 绑定上文中创建的名称为 test-rbac 的Role,具体权限,往上翻下哈
apiGroup: rbac.authorization.k8s.io
# kubectl apply -f test-role.yml

8、设置默认上下文
# kubectl config use-context liheng-context

9、测试
# [root@sl-k8s-master-01 devops]# kubectl get pod
NAMEREADYSTATUSRESTARTSAGE
jenkins-745596c48d-fjt591/1Running02d20h
# [root@sl-k8s-master-01 devops]# kubectl execjenkins-745596c48d-fjt59 -n devops -- sh
Error from server (Forbidden): pods "jenkins-745596c48d-fjt59" is forbidden: User "liheng" cannot create resource "pods/exec" in API group "" in the namespace "devops"
# [root@sl-k8s-master-01 devops]# kubectl get svc
Error from server (Forbidden): services is forbidden: User "liheng" cannot list resource "services" in API group "" in the namespace "devops"

可以看到liheng用户只有查看devops名称空间下pod的权限。
cfssl颁发签名证书方法
1、创建CA证书签名请求文件
# cat liheng-csr.json

"CN": "liheng",# 用户名,必填
"hosts": [],# 主机地址,不填表示所有主机都可使用
"key":
"algo": "rsa",
"size": 2048
,
"names": [

"C": "CN",
"L": "BeiJing",
"ST": "Beijing",
"O": "yunweizhongxin",
"OU": "System"

]

2、创建访问证书
# cfssl gencert -ca=/opt/kubernetes/ssl/ca.pem \\
-ca-key=/opt/kubernetes/ssl/ca-key.pem \\
-profile=kubernetes liheng-csr.json|cfssljson -bare liheng

3、为liheng用户生成集群配置文件
# kubectl config set-cluster kubernetes \\
--certificate-authority=/opt/kubernetes/ssl/ca.pem \\
--embed-certs=true \\
--server=$KUBE_APISERVER --kubeconfig=liheng.kubeconfig
# kubectl config set-credentials liheng \\
--client-certificate=liheng.pem \\
--client-key=liheng-key.pem \\
--embed-certs=true --kubeconfig=liheng.kubeconfig
# kubectl config set-context liheng-context \\
--cluster=kubernetes \\
--user=liheng \\
--namespace=devops \\
--kubeconfig=liheng.kubeconfig

4、切换上下文
# kubectl config use-context liheng-context --kubeconfig=liheng.kubeconfig

5、测试
# [root@sl-k8s-master-01 src]# kubectl get pod -n kube-system --kubeconfig=liheng.kubeconfig
Error from server (Forbidden): pods is forbidden: User "liheng" cannot list resource "pods" in API group "" in the namespace "kube-system"

配置具有操作整个集群的管理员用户(admin)1、生成用户(admin)私钥
# openssl genrsa -out admin.key 2048

2、通过生成的私钥生成证书签名请求文件:admin.csr.
# openssl req -new -key admin.key -out admin.csr \\
-subj "/CN=admin/O=system:masters"

使用config还需要注意用户已经经过授权(如RBAC授权),上述例子中用户的证书中O字段为system:masters,kube-apiserver预定义的ClusterRoleBinding cluster-admin默认将Group system:masters与ClusterRole cluster-admin进行了绑定,该ClusterRole授予了调用kube-apiserver相关API的权限;-subj中的CN表示用户名,O表示用户组
3、通过kubernetes集群的CA证书为用户颁发签名证书
# openssl x509 -req -in admin.csr -CA /opt/kubernetes/ssl/ca.pem \\
-CAkey /opt/kubernetes/ssl/ca-key.pem \\
-CAcreateserial -out admin.crt -days 500

4、使用创建的证书文件和私钥创建用户(客户端)认证凭据
# kubectl config set-credentials admin \\
--client-certificate=admin.crt \\
--embed-certs=true \\
--client-key=admin.key
--kubeconfig=admin.kubeconfig

5、创建用户上下文(Context)
# kubectl config set-context admin-context \\
--cluster=kubernetes \\
--user=admin
--kubeconfig=admin.kubeconfig

6、设置默认上下文
# kubectl config use-context admin-context

创建一个只能访问某个 namespace 的ServiceAccount接下来配置创建一个ServiceAccount来访问特定名称空间下资源的示例 1、创建名为liheng-sa的ServiceAccount
# kubectl create sa liheng-sa -n devops

2、新建一个 Role和RoleBinding 对象
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: liheng-sa-role
namespace: devops
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
# 将上面的 liheng-sa 和角色 liheng-sa-role 进行绑定
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: liheng-sa-rolebinding
namespace: devops
subjects:
- kind: ServiceAccount
name: liheng-sa
namespace: devops
roleRef:
kind: Role
name: liheng-sa-role
apiGroup: rbac.authorization.k8s.io

3、验证 每个ServiceAccount会生成一个Secret对象和它进行映射,这个Secret里面包含一个 token,我们可以利用这个token去登录Dashboard进行验证
# kubectl get secret -n devops |grep liheng-sa
# kubectl get secret liheng-sa-token-klju -o jsonpath=.data.token -n devops |base64 -d


    推荐阅读