一. 基础知识:
- K8s默认采用RBAC鉴权方式,包含4个顶级资源对象,Role/ClusterRole/RoleBinding/ClusterRoleBinding
- Role/ClusterRole:角色和集群角色,角色/集群角色 = 一组对K8s资源对象操作权限的集合(如get pod,delete deployment等操作均需要权限)
- RoleBinding/ClusterRoleBinding:角色绑定和集群角色绑定,通过这两种资源对象,可以将Role/ClusterRole与集群中对象进行绑定,包括User/Group/Service Account
- 上述集群中对象User/Group/service Account与宿主机无直接关系,如此处User为k8s集群内用户,而/etc/passwd中的为Linux系统用户
- 通过kubeconfig可以将系统用户和K8s集群用户关联,如:
[root@test ~]# kubectl --kubeconfig=readonly.conf get pods
(执行该命令需要先切换kubeconfig中当前的上下文,配置过程中会详细说明)
# root用户执行kubectl并指定kubeconfig配置文件,该文件中保存有名为readonly的K8s集群用户的证书信息和秘钥信息,
# 这样root用户就可使用K8s集群中readonly用户具有的相应权限来对集群资源对象进行操作,
# 而readonly用户具有的权限是通过RoleBinding/ClusterRoleBinding将K8s集群用户readonly与Role/ClusterRole(一组权限)进行绑定而得到的。
12345
二. 举例说明Linux系统用户、K8s集群User用户、Role/ClusterRole、RoleBinding/ClusterRoleBinding间的关系:
班级中的对应关系:
Linux系统用户:助教小明
K8s集群User用户:职务,如班长、学习委员...
Role/ClusterRole:责任或权利,如收作业,安排值日...
RoleBinding/ClusterRoleBinding:老师安排职务和权利对应关系
ca.pem/ca-key.pem或ca.crt/ca.key(集群CA根证书和CA私钥):班级公章,用于盖章生成集群证明
--kubeconfig指定的文件:印的写有某职务名的肩章,如“三年二班班长”肩章
运维工程师:班主任
12345678
- 绑定职务及权利(Role/ClusterRole与RoleBinding/ClusterRoleBinding原理) 三年二班中有很多日常工作要做,如收作业,安排值日,检查着装等;班主任为了便于管理,就设置了几个职务如班长、学习委员,并且规定,班长的权利有:安排值日,检查着装,学习委员的权利有:收作业。老师通过规定(RoleBinding/ClusterRoleBinding)将职务(User)与权利(Role/ClusterRole)进行绑定,这样同学们就知道班长(User)有什么权利能干什么(Role/ClusterRole)。当然,老师同样可以规定,班级中有班长和副班长,但是两人的权利完全相同,即多个User绑定同一个Role/ClusterRole。
- 制作肩章过程(生成kubeconfig文件) 班级通过一致决定(通过集群认证)将每个职位做成肩章,如带有“三年二班班长”字样的班长肩章(–kubeconfig对应的文件),并规定戴上肩章的人才有肩章对应的权利而忘戴则没有。肩章的制作过程首先需要班主任写好带有职务名(写有K8s集群用户readonly的readonly.json文件)和职务有效期等信息(写有过期时间的ca配置文件ca-config-readonly.json)的两个文件,之后班主任使用班级公章(ca根证书和私钥)和写好的两个文件(两个json)通过计算机算法得到用于证明肩章有效的文件(readonly.pem客户端证书,用于K8s的解密认证)和另一个文件(readonly-key.pem客户端私钥,实在编不出来了。。。)。之后将班级公章(ca.pem/ca-key.pem或ca.crt/ca.key:CA根证书和CA私钥)和证明肩章有效的两个文件(readonly.pem/readonly-key.pem:客户端证书和客户端私钥)提交至班级系统里,从而注册班长职务并备注过期时间等信息。学校获取到班长职务信息后,要求班主任提供肩章样式(context上下文),再根据职务名(K8s集群User用户名)和样式制作出肩章(–kubeconfig指定的文件)并返回给班主任
- (K8s RBAC权限控制) 班级中除班主任外还有一些助教,其中助教小明经班主任任命得到了“三年二班班长”肩章,只要他(Linux系统用户)戴着写有“三年二班班长”(K8s集群User用户)字样的肩章(kubectl时指定–kubeconfig),他就对班级中的同学(集群资源对象如pod)有权利检查着装(Role/ClusterRole)。某天助教小明忘戴了班长肩章(未指定–kubeconfig),则班级就不认可(认证失败)他的任何权利。若班主任(运维工程师)将助教小明的工作服上均印有“三年二班班长”字样的班长肩章(将kubeconfig文件cp为/home/xiaoming/.kube/config),则即使小明忘戴,依然有班长的默认权利(–kubeconfig默认路径为/home/$USER/.kube/config)
三. 具体操作:
- 安装cfssl和cfssljson工具用于生成证书
wget <https://pkg.cfssl.org/R1.2/cfssl_linux-amd64>
chmod +x cfssl_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl
wget <https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64>
chmod +x cfssljson_linux-amd64
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
1234567
- 使用集群CA自签名证书生成client证书和client私钥
mkdir /tmp/test && cd /tmp/test # 在master上操作
cp /etc/kubernetes/ssl/ca.pem ./ # 可以通过ps -ef |grep kube-apiserver |grep ca来获取--client-ca-file路径,ca.pem也可以是ca.crt
cp /etc/kubernetes/ssl/ca-key.pem ./ # 路径同上,ca-key.pem也可以是ca.key
123
- 新增用于生成Client证书的Json文件,其中声明了User相关信息
vim readonly.json # 可以基于已有用户如admin.json进行修改
{
"CN": "readonly", # 证书中记录的k8s集群User用户名,需要与后续集群添加用户(set-credentials)相同
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "HangZhou", # 随意填写
"L": "HangZhou", # 随意填写
"O": "develop:readonly", # 随意填写
"OU": "develop" # 随意填写
}
]
}
123456789101112131415161718
- 新增用于生成Client证书的Json文件,包含有效期等信息
vim ca-config-readonly.json
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
12345678910111213141516171819
- 创建readonly用户Client证书和Client私钥
sudo cfssl gencert --ca ca.pem --ca-key ca-key.pem --config ca-config-readonly.json --profile=kubernetes readonly.json | cfssljson --bare readonly
# 当前目录下会生成readonly.csr、readonly.pem证书和readonly-key.pem私钥文件用于添加K8s集群User用户
12
- 基于已有kubeconfig文件添加新K8s集群User及Context信息
cp /root/.kube/config ./readonly.kubeconfig # 也可以从之前获取到的目录找到当前集群中已有的conf,如admin.conf
1
- 新增环境准备脚本
vim kubeconfig.sh
#!/bin/bash
# 添加readonly至K8s集群User用户中,这里readonly必须跟制作证书阶段Json文件中的CN保持一致,否则最终kubectl将无任何权限
kubectl config set-credentials readonly \\
--certificate-authority=/tmp/test/ca.pem \\ # CA根证书
--embed-certs=true \\
--client-key=/tmp/test/readonly-key.pem \\ # Client私钥
--client-certificate=/etc/kubernetes/pki/test/readonly.pem \\ # Client证书
--kubeconfig=/etc/kubernetes/pki/test/readonly.kubeconfig # kubeconfig文件
kubectl config set-context readonly-context --cluster=kubernetes \\ # set-context后为新增上下文名,最好创建之前通过kubectl config get-contexts查看已有上下文避免冲突
--user=readonly \\ # 添加readonly用户的上下文并保存至readonly.kubeconfig中
--kubeconfig=readonly.kubeconfig
kubectl config use-context readonly-context --kubeconfig=readonly.kubeconfig # 切换kubeconfig证书中的上下文,由admin切换至readonly-context
sh kubeconfig.sh
1234567891011121314151617
- 创建ClusterRole,并通过ClusterroleBinding将名为readonly-clusterrole的ClusterRole与名为readonly的K8s集群User用户绑定(也可以使用已有clusterrole----view)
vim clusterrole_and_binding.yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: readonly-clusterrole #添加名为readonly-clusterrole的clusterrole资源对象
rules:
- apiGroups:
- ""
resources:
- pods
- pods/attach
- pods/exec
- pods/portforward
- pods/proxy
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- persistentvolumeclaims
- replicationcontrollers
- replicationcontrollers/scale
- secrets
- serviceaccounts
- services
- services/proxy
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- bindings
- events
- limitranges
- namespaces/status
- pods/log
- pods/status
- replicationcontrollers/status
- resourcequotas
- resourcequotas/status
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- namespaces
verbs:
- get
- list
- watch
- apiGroups:
- apps
resources:
- deployments
- deployments/rollback
- deployments/scale
- statefulsets
verbs:
- get
- list
- watch
- apiGroups:
- autoscaling
resources:
- horizontalpodautoscalers
verbs:
- get
- list
- watch
- apiGroups:
- batch
resources:
- cronjobs
- jobs
- scheduledjobs
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- daemonsets
- deployments
- ingresses
- replicasets
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: cluster-readonly # 添加名为cluster-readonly的clusterrolebinding资源对象
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: readonly-clusterrole # 将名为readonly-clusterrole的Clusterrole与名为readonly的K8s User进行绑定
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: readonly
kubectl apply -f clusterrole_and_binding.yaml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
- 验证通过指定存有readonly-context上下文和readonly集群用户的kubeconfig文件,能否访问node和pod
kubectl --kubeconfig=readonly.kubeconfig get nodes # 被拒绝,权限不够
kubectl --kubeconfig=readonly.kubeconfig get nodes -n kube-system # 可以获取
kubectl --kubeconfig=readonly.kubeconfig delete pods xxx -n kube-system # 被拒绝,权限不够
123
- Linux用户的权限限制