目录
k8s安全框架
K8S安全控制框架主要由下面3个阶段进行控制,通过API Server配
置来启用插件:
1. Authentication(鉴权)
2. Authorization(授权)
3. Admission Control(准入控制)
整个k8s的操作流程如下
![](https://img-blog.csdnimg.cn/0f578db2bdc8499cbe57d4a32ecb21bf.png)
K8s Apiserver提供三种客户端身份认证:
• HTTPS 证书认证:基于CA证书签名的数字证书认证(kubeconfig)
• HTTP Token认证:通过一个Token来识别用户(serviceaccount)
• HTTP Base认证:用户名+密码的方式认证(1.19版本弃用)
授权(Authorization )
RBAC(Role-Based Access Control,基于角色的访问控制):负责完成授权(Authorization)工作。RBAC根据API请求属性,决定允许还是拒绝。
比较常见的授权维度:
• user:用户名
• group:用户分组
• 资源,例如pod、deployment
• 资源操作方法:get,list,create,update,patch,watch,delete
• 命名空间
• API组
准入控制(Admission Control)
Adminssion Control实际上是一个准入控制器插件列表,发送到API Server的请求都需要经过这个列表中的每个准入控制器插件的检查,检查不通过,则拒绝请求。
启用一个准入控制器:
kube-apiserver --enable-admission-plugins=NamespaceLifecycle,LimitRanger ...
关闭一个准入控制器:
kube-apiserver --disable-admission-plugins=PodNodeSelector,AlwaysDeny ...
查看默认启用:
kubectl exec kube-apiserver-k8s-master -n kube-system -- kube-apiserver -h | grep enable-admission-plugins
例如,通过这个命令我们可以查看,,
![](https://img-blog.csdnimg.cn/d706b6450cbd4c19ac9ddb537cfd7da8.png)
这里面包含已启用以及全部可启用
基于角色的权限访问控制:RBAC
RBAC(Role-Based Access Control,基于角色的访问控制),
是K8s默认授权策略,并且是动态配置策略(修改即时生效)。
主体(subject)
• User:用户
• Group:用户组
• ServiceAccount:服务账号
角色
• Role:授权特定命名空间的访问权限
• ClusterRole:授权所有命名空间的访问权限
角色绑定
• RoleBinding:将角色绑定到主体(即subject)
• ClusterRoleBinding:将集群角色绑定到主体
注:RoleBinding在指定命名空间中执行授权,ClusterRoleBinding在集群范围执行授权。
![](https://img-blog.csdnimg.cn/5b147a8f020e47f79a3d05c76cb88654.png)
案例
为指定用户授权访问不同命名空间权限,例如新入职一个小弟,希望让他先熟悉K8s集群,为了安全性,先不能给他太大权限,因此先给他授权访问default命名空间Pod读取权限。
实施大致步骤:
1. 用K8S CA签发客户端证书
2. 生成kubeconfig授权文件
3. 创建RBAC权限策略
4. 指定kubeconfig文件测试权限:
kubectl get pods --kubeconfig=./aliang.kubeconfig
操作示例
首先,我们要知道所有kubeadm安装的k8s所有配置文件存放地,在/etc/kubernetes下的pki中
![](https://img-blog.csdnimg.cn/27691d79e747450a839157df3cd4e399.png)
一般ca即是根证书
1、用cfssl来利用ca来生成客户端证书
先将rbac.zip传到master目录并解压
![](https://img-blog.csdnimg.cn/026126bc87cf4dd88559349fbc6b61cc.png)
将cfssl工具包也传入服务器,并直接解压到/usr/bin目录下
tar zxvf cfssl.tar.gz -C /usr/bin/
![](https://img-blog.csdnimg.cn/7c8cf913515d424ab19b95e50e86f98f.png)
进入rbac文件
cd rbac/
![](https://img-blog.csdnimg.cn/bee60f995a8d4e458320d10ed21d2b07.png)
进入cert进行修改
vi cert.sh
![](https://img-blog.csdnimg.cn/74a964abbbf34ef8ab78d46822cc6629.png)
这两个对应的是用户名和根证书
直接执行
bash cert.sh
![](https://img-blog.csdnimg.cn/4a7460d99a0b4bf78f51ebe5c0d1470e.png)
这两个即为生成的证书
![](https://img-blog.csdnimg.cn/53cdedb0bec741b7af69b9f6f8bbff8f.png)
接下来,生成kubectl授权文件
即,实际上我们使用kubectl命令时,是kubectl将请求发给了api,其中kubectl本身也需要配置文件。他的配置文件在/root/.kube
![](https://img-blog.csdnimg.cn/4bd9210b2fc948049e9264f6e446e6bb.png)
这里的config即是安全权限证书
![](https://img-blog.csdnimg.cn/da6424a9cb4343529709f937cc7393ca.png)
回到刚刚的rbac目录,修改生成config脚本
cd /root/rbac
vi kubeconfig.sh
kubectl config set-cluster kubernetes \--certificate-authority=/etc/kubernetes/pki/ca.crt \--embed-certs=true \--server=https://192.168.209.110:6443 \--kubeconfig=aliang.kubeconfig# 设置客户端认证kubectl config set-credentials aliang \--client-key=aliang-key.pem \--client-certificate=aliang.pem \--embed-certs=true \--kubeconfig=aliang.kubeconfig# 设置默认上下文kubectl config set-context kubernetes \--cluster=kubernetes \--user=aliang \--kubeconfig=aliang.kubeconfig
# 设置当前使用配置
kubectl config use-context kubernetes --kubeconfig=aliang.kubeconfig
集群ip需要改,证书名看需求
执行脚本生成证书
bash kubeconfig.sh
![](https://img-blog.csdnimg.cn/bedbda4d2da74399995d2119e1400afe.png)
可以看到生成的证书如下
![](https://img-blog.csdnimg.cn/2b42cf648aa54a53a187e2240ca3cbcb.png)
测试
我们在kubectl命令的时候引用我们刚刚生成的config
kubectl get pod --kubeconfig=aliang.kubeconfig
![](https://img-blog.csdnimg.cn/8948dd5ac2a34024bb49fb85c878f222.png)
这个是以新生成的config来执行kubectl命令,可以看到,他报没有权限,即还未授权
授权
vi rbac.yaml
![](https://img-blog.csdnimg.cn/933b9c916af248768016a367fc41c4e3.png)
其中,role即新建的角色,roleBinding是将角色与刚刚新建的主题绑定
执行
kubectl apply -f rbac.yaml
![](https://img-blog.csdnimg.cn/6666c28146b645608d586f1d8c3ed7f9.png)
再用之前生成的config执行get pod,发现这次就可以执行了
![](https://img-blog.csdnimg.cn/805a329cb6a94c81990834b0d53df129.png)
但deployment和svc还是不行,原因是刚刚只对pods进行了授权
![](https://img-blog.csdnimg.cn/9991375d4de54951ba2aab3ef06f2159.png)
案例:为指定用户授权访问不同命名空间权限
创建角色(权限集合):
apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata:namespace: defaultname: pod-readerrules:- apiGroups: [“”] # api组,例如apps组,空值表示是核心API组,像namespace、pod、service、pv、pvc都在里面resources: [“pods”] #资源名称(复数),例如pods、deployments、servicesverbs: [“get”, “watch”, “list”] # 资源操作方法
将用户与角色绑定:
apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata:name: read-podsnamespace: defaultsubjects:- kind: User # 主体name: aliang # 主体名称apiGroup: rbac.authorization.k8s.ioroleRef: # 绑定的角色kind: Rolename: pod-reader # 角色名称apiGroup: rbac.authorization.k8s.io
其中,使用
kubectl api-resources
可以查看所有的组对应的功能
![](https://img-blog.csdnimg.cn/5e402c97ed614eb88ed430b50e9e58ed.png)
授权deployment
例如,刚刚的congig只能访问pods,我现在要给刚刚生成的config授权访问deployment
使用
kubectl api-resources |grep deployment
找出deployment对应的组名
![](https://img-blog.csdnimg.cn/863444c1f7fc48c5a11ef54ed163a93c.png)
第三列斜杠左侧就是组名
例如pods他的组是空的。即他在k8s的核心组里面。在rbac中以“”为表达
![](https://img-blog.csdnimg.cn/411316abe9ff4f0eaad62c2f49d836e3.png)
加入deployment组名在刚刚的rbac规则yaml上,并在资源名上写明deployment
vi rbac.yaml
kind: RoleapiVersion: rbac.authorization.k8s.io/v1metadata:namespace: defaultname: pod-readerrules:- apiGroups: ["","apps"]resources: ["pods","deployments"]verbs: ["get", "watch", "list"]---kind: RoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata:name: read-podsnamespace: defaultsubjects:- kind: Username: aliangapiGroup: rbac.authorization.k8s.ioroleRef:kind: Rolename: pod-readerapiGroup: rbac.authorization.k8s.io
执行
kubectl apply -f rbac.yaml
可以看到,这次即可使用deployment,svc依旧不行
![](https://img-blog.csdnimg.cn/f15f431e77a84df49acfbd55fbce9d10.png)
授权service
授权service的方式通上,首先,先通过命令查询service在哪个组
![](https://img-blog.csdnimg.cn/bf29bda7d79741b9aeda467ee6fd70c7.png)
发现service本身就在核心组
这样只需要在资源名称中加入services即可
vi rbac.yaml
kind: RoleapiVersion: rbac.authorization.k8s.io/v1metadata:namespace: defaultname: pod-readerrules:- apiGroups: ["","apps"]resources: ["pods","deployments","services"]verbs: ["get", "watch", "list"]---kind: RoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata:name: read-podsnamespace: defaultsubjects:- kind: Username: aliangapiGroup: rbac.authorization.k8s.ioroleRef:kind: Rolename: pod-readerapiGroup: rbac.authorization.k8s.io
kubectl apply -f rbac.yaml
更新,然后再使用新建证书查看service
kubectl get svc --kubeconfig=aliang.kubeconfig
![](https://img-blog.csdnimg.cn/039f645e224d4babbf10ec9c929db256.png)
验证成功
![](https://img-blog.csdnimg.cn/926bb442cddd4cc79edb0e36ed3a4d74.png)
拓展
kubectl命令可以在集群网络通用内的任何服务器执行,只需要指定专门的证书,即刚刚生成的证书传到其他服务器。其他服务器也可以用此证书来操作k8s集群,
如例,将文件传到其他服务器
![](https://img-blog.csdnimg.cn/0b38230712d7460d9df006182e7851a4.png)
这样在其他服务器指定这个配置文件也可以操作集群
![](https://img-blog.csdnimg.cn/7297824413d14b74a54b2374029765de.png)
如果想不指定配置文件让他成为默认配置文件的话,将这个文件改名移动到kubectl默认访问路径就行
mv aliang.kubeconfig .kube/config
![](https://img-blog.csdnimg.cn/9e3d6a47ad8445e3a31785743f508b6a.png)
这样就不需要指定,默认使用
![](https://img-blog.csdnimg.cn/888c8a2017ba4d4d983f88185fa0b675.png)