RBAC(Role-Based Access Control,基于角色的访问控制),允许通过 Kubernetes API 动态配置策略。
概念理解
角色(权限的集合)
- Role:授权特定命名空间的访问权限
- ClusterRole:授权所有命名空间的访问权限(集群角色)
角色绑定
- RoleBinding:将角色(Role)绑定到主体(即subject)
- ClusterRoleBinding:将集群角色(ClusterRole)绑定到主体
主体(subject)
- User:用户
- Group:用户组
- ServiceAccount:服务账号
以上三个概念按照以下可以通俗的理解
Role ---> RoleBinding ---> User/Group/ServiceAccount
ClusterRole ---> ClusterRoleBinding ---> User/Group/ServiceAccount
将准备要设置赋予的权限,放到角色(Role/ClusterRole)里,通过角色绑定(RoleBinding/ClusterRoleBinding)将权限放在绑定到主体(User/Group/ServiceAccount)上
理解示例:比如上班使用的工卡,工卡上具有进入大厦以及公司的权限,然后给员工发卡时,就要知道是普通员工还是领导身份,普通员工则有进入工作场所的权限,而领导的还具有进入 “闲人免进” 字样的场所。工卡的权限就是角色,通过人事部将工卡发送给员工,此时人事部就是角色绑定,员工就是主体。
RBAC 案例
背景:新人上岗,让新人快速熟悉 k8s 环境,为了减少风险,担心误操作,决定给他一个很小的权限让他先熟悉项目。
为 FeiYi 用户授权 nginx 命名空间的 Pod 读取权限
签发证书
用 k8s 的 CA 签发一个客户端证书,k8s 使用 cfssl 工具用来生成证书,需要注意的是必须用 K8S 的 CA 来签发
安装cfssl工具
# cfssl:证书签发的主要工具
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O /usr/bin/cfssl
# cfssl-json:将cfssl生成的整数(json格式)变为文件承载式证书
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -O /usr/bin/cfssljson
# cfssl-certinfo:验证证书的信息
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -O /usr/bin/cfssl-certinfo
# 授权cfssl工具可执行
chmod +x /usr/bin/cfssl*
创建CA:用来签发证书
cat > ca-config.json << EOF
{
"signing": {
"default": {
"expiry": "438000h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "438000h"
}
}
}
}
EOF
# signing:表示该证书可用于签名其它证书;生成的 .pem 证书文件中 CA=TRUE
# expiry:默认的证书到期时间为50年,87600h为10年
# profiles:包含了server auth和client auth,所以可以签发三种不同类型证书;expiry 证书有效期,默认50年,可以定义多个profile
# kubernetes:kubernetes这个名字可以自定义,后续指定profiles时要一致,这就是一个单个的profile
# server auth:表示client可以用该 CA 对server提供的证书进行验证
# client auth:表示server可以用该CA对client提供的证书进行验证
创建CA证书签名请求文件
cat > ca-csr.json << EOF
{
"CN": "feiyi",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
# "CN: feiyi": Common Name,feiyi作为之后要授权的用户
# C: 国家 ST: 州/省 L: 地区/城市
# O: Organization,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group),也就是feiyi用户所属的组,之后也可给该组授权
# OU: 组织单位名称,公司部门
使用 k8s 的 CA 签发证书
cfssl gencert \
-ca=/etc/kubernetes/pki/ca.crt \
-ca-key=/etc/kubernetes/pki/ca.key \
-config=ca-config.json \
-profile=kubernetes ca-csr.json | cfssljson -bare feiyi
# -ca: 指定k8s的ca文件所在位置
# -ca-key: 指定k8s的ca密钥文件所在位置
# -config: 指定刚刚创建好的CA-config.json文件
# -profile: 指定ca-config.json中的profile---kubernetes
# cfssljson -bare feiyi:将以上信息解析,生成以feiyi为前缀的证书文件
当前目录会新增三个文件
feiyi-key.pem # ca的私钥
feiyi.pem # ca证书
feiyi.csr # 签署请求
生成 kubeconfig 授权文件
在创建完集群后,会让你执行如下命令
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
其中的 admin.conf
,就和要准备生成的 kubeconfig文件结构是一样的,只不过使用的 admin.conf
类似 Linux 系统的 root 用户,可以随意查看 K8S 集群里面的任何内容,具有最高权限
集群信息写入 kubeconfig
# 因为创建的kubeconfig也将作用于K8S集群,所以需要指定K8S的API信息
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--embed-certs=true \
--server=https://192.168.1.11:6443 \
--kubeconfig=feiyi.kubeconfig
# --certificate-authority:ca证书
# --server:apiserver地址
# --kubeconfig:根据给定的信息生成的kubeconfig名字
# --embed-certs:为true时,将证书信息写入kubeconfig文件;为false时,在kubeconfig文件中引用证书所在路径
################################################################
# 这一步主要生成了以下信息
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0t
...
ejhKYld1OHY3WmI4TVR2MG9GVQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
server: https://172.16.182.193:6443
name: kubernetes
客户端信息写入 kubeconfig
kubectl config set-credentials feiyi \
--client-key=feiyi-key.pem \
--client-certificate=feiyi.pem \
--embed-certs=true \
--kubeconfig=feiyi.kubeconfig
# set-credentials: 在 kubeconfig 中设置用户条目
# --client-key: 指定刚才生成私钥
# --client-certificate=feiyi.pem: 指定生成的数字证书
# --kubeconfig: 将客户端信息加入刚才生成的kubeconfig文件中
################################################################
# 这一步主要生成了以下信息
users:
- name: feiyi
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0
...
Si8rbHRhdXM4UWFRVmhCOHlndz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
client-key-data: LS0tLS1CRUdJTi BSU0EgUFJJVkFURSBLRVktLS0tLQp
...
ck9xK0pFdDJDNGpidmh0Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
上下文信息写入 kubeconfig
设置默认上下文加入 kubeconfig:如果存在多套集群,通过设置上下文可以在多套集群间切换
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=feiyi \
--kubeconfig=feiyi.kubeconfig
# set-context: 设置上下文,默认在名为kubernetes的集群
# --user=feiyi: 使用客户端用户为feiyi
# --cluster=kubernetes: 用户作用到名为kubernetes的集群
# --kubeconfig:将上下文信息加入刚才生成的kubeconfig文件中
################################################################
# 这一步主要生成了以下信息,表示使用feiyi用户访问集群kubernetes
contexts:
- context:
cluster: kubernetes
user: feiyi
name: kubernetes
感兴趣的话,可以将 admin.conf 和刚生成的 kubeconfig 对比一下,结构是一样的。
初始验证
使用刚生成的 kubeconfig 来查看集群信息
$ kubectl get node -n nginx --kubeconfig=feiyi.kubeconfig
Error from server (Forbidden): pods is forbidden: User "feiyi" cannot list resource "pods" in API group "" in the namespace "nginx"
这是因为现在生成的 kubeconfig 还没有任何权限,所以任何资源还无法访问
创建 RBAC 权限策略
仅给予查看 nginx 命名空间的 pod 资源
$ vim rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: nginx # 将权限给到nginx命名空间
name: rbac-test
rules:
- apiGroups: [""] # 如果为空,则代表核心组(一般不指定),可以指定多个
resources: ["pods"] # 仅允许该role对pod操作,可以指定多个
verbs: ["get", "watch", "list"] # 对pod 所作的操作
---
# 将role绑定到user
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: nginx
name: rbac-test-binding
subjects:
- kind: User
name: feiyi # 该名为生成证书时的CN名字
apiGroup: rbac.authorization.k8s.io
roleRef: # 指定上面创建的Role与feiyi绑定
kind: Role
name: rbac-test
apiGroup: rbac.authorization.k8s.io
创建 RBAC 权限策略
kubectl apply -f rbac.yaml
再次使用 kubeconfig 查看
kubectl get pods -n nginx --kubeconfig=./cfssl/kubeconfig/feiyi.kubeconfig
NAME READY STATUS RESTARTS AGE
nginx-deployment-c94f957b8-4t4f8 1/1 Running 0 17d
nginx-deployment-c94f957b8-gj4j7 1/1 Running 0 17d
可以尝试查看其它资源是都看不了的,和没授权的报错是一样的。
总结
最后创建完成后的访问流程
kubectl(客户端)通过使用创建好的 kubeconfig 中的User访问到 api,api 通过提取证书中的 CN 字段作为 Uesr ,然后去查看是否在创建好的 RABC 中有对应用户的策略权限,来判断该不该执行这个操作。这个过程就经历了,鉴权和授权