文章目录
一、K8s安全框架
K8s安全控制作用:
- 保证容器与其所在宿主机的隔离。
- 限制容器给基础设施或其他容器带来的干扰。
- 最小权限原则,即合理限制所有组件的权限,确保组件只执行它被授权的行为,通过限制单个组件的能力来限制它的权限范围。
- 明确组件间边界的划分。
- 划分普通用户和管理员的角色。
- 在必要时允许将管理员权限赋给普通用户。
- 允许拥有Secret数据(Keys、Certs、Passwords)的应用在集群中运行。
安全控制框架3个阶段:
- 3个阶段包括鉴权(验证用户身份)、授权(判断用户访问资源的权限)、准入控制(验证用户的额外权限)。
- 每个阶段都支持插件方式,通过API Server配置来启用插件。
第一阶段: Authentication(鉴权):判断你的身份是否是可靠的。
- 官方提供的验证方式很多,这里列举常见的:
- HTTPS 证书认证:基于CA证书签名的数字证书认证(kubeconfig),比如.kube/config文件就是这种认证。
- HTTP Token认证:通过一个Token来识别用户(serviceaccount),比如我们搭建K8s图形页面登录时就使用到Token认证,但是加入集群时也使用到Token,这个不属于该种认证,只是单纯的加入集群。
- HTTP Base认证:用户名+密码的方式认证,1.19版本弃用,安全系数低。
第二阶段:Authorization(授权):控制你的权限是否可以访问相对应的资源。
- 官方提供的验证方式很多,这里列举常见的:
- Node、ABAC、RBAC、Webhook。
第三阶段: Admission Control(准入控制):其实就是一张准入控制插件列表,根据需求把K8s的一些高级功能放入列表,哪个功能不用就把对应的控制器插件移除列表。
- Adminssion Control实际上是一个准入控制器插件列表,发送到API Server的请求都需要经过这个列表中的每个准入控制器插件的检查,检查不通过,则拒绝请求。
- 插件形式,方便用户实现检查准入控制,例如i当以操作等等。
1.1 鉴权
1.1.1 HTTPS证书认证
- CA机构是可信的第三方机构,具备让信任者有追究自己责任的能力,它可以是一个公认的权威企业,也可以是企业自身。企业内部系统一般都用企业自身的认证系统。
- CA通过证书证实他人的公钥信息,在证书上有CA的签名。在证书中绑定了公钥数据和相应私钥拥有者的身份信息,并带有CA的数字签名;在证书中也包含了CA的名称,以便于依赖方找到CA的公钥,验证证书上的数字签名。
双向CA认证工作流程:
- 服务端向CA机构申请证书,CA机构下发根证书、服务端证书、私钥给服务端。
- 客户端向CA机构申请证书,CA机构下发根证书、客户端证书、私钥给客户端。
- 客户端向服务端发起请求,服务端下发服务端证书给客户端。客户端在接收到服务端证书后,通过私钥解密证书,并利用服务端证书中的公钥认证证书信息比较证书里的消息。例如,比较域名和公钥与服务器刚刚发送的相关消息是否一致,如果一致,则客户端认可这个服务器的合法身份。
- 客户端发送客户端证书给服务端,服务端在接收到证书后通过私钥解密证书,获得客户端证书公钥,并用该公钥认证证书的信息,确认客户端是否合法。
- 客户端通过随机密钥加密信息,并发送加密后的信息给服务端。在服务端和客户端协商好加密方案后,客户端会产生一个随机的密钥,客户端通过协商好的加密方案加密该随机密钥,并发送该随机密钥到服务端。服务端接收这个密钥后,双方通信的所有内容都通过该随机密钥加密。
注意事项:
- 双向CA认证要求服务器和用户双方都拥有证书,而单向认证则不需要客户端拥有CA证书。
- 单项CA认证只需将服务端验证客户证书的过程去掉,之后协商对称密码方案和对称通话密钥时,服务端发送给客户端的密码没被加密即可。
1.1.2 HTTP Token认证
基本了解:
- 为验证使用者身份,需要客户端向服务端提供一个可靠的身份信息,称之为Token,这个Token被放在HTTP Header头里,在Token里有信息来表明客户身份。Token通常是一个有一定长度的难以被篡改的字符串,我们用私钥签名一个字符串后的数据也可被当作一个加密的Token。
- 在K8s中,每个Bearer Token都对应一个用户名,存储在API Server能访问的一个文件中(Static Token file)。客户端发起API调用请求时,需要在HTTPHeader里放入此Token,这样一来,API Server就能识别合法用户和非法用户了。
- sa认证方式也采用了与HTTP Bearer Token相同的实现方式。每个sa都对应一个Secret,在Secret中有一个加密的Token字段,这个Token字段就是Bearer Token。这个Token是用哪个私钥加密的,要取决于API Server的启动参数–service-account-key-file指定的文件,若没有指定该参数,则会采用API Server自己的私钥进行加密。为了方便Pod里的用户进程使用这个Token访问API Server,Secret Token里的内容会被映射到Pod中固定路径和名字的文件中。当API Server设置了启动参数–service-account-lookup=true,API Server就会验证Token是否在etcd中存在,若已从etcd中删除,则将注销容器中Token的有效性。
使用前提:
- 要使用这种认证方式,就需要为API Server服务设置一个保存用户信息和Token的文件,通过启动参数–token-auth-file=SOMEFILE指定文件路径。
- 该文件为CSV文本文件格式,每行内容都由以下字段组成
1.2 授权
- 当客户端发起API Server调用时,API Server内部会通过授权策略决定一个API调用是否合法。授权就是授予不同的用户或程序不同的访问权限。
授权策略:
- ABAC:基于属性的访问控制,表示使用用户配置的授权规则对用户的请求进行匹配和控制。硬伤多,已被RBAC替代。
- RBAC:基于角色的访问控制。
- Webhook:通过调用外部的REST服务对用户进行授权。若RBAC仍不满足特定需求,用户可以自行编写授权逻辑通过Webhook方式注册为K8s的授权服务,以实现更加复杂的授权规则。
- Node:是一种对kubelet进行授权的特殊模式。
- sa:是给应用程序授权的。
注意事项:
- 设置apiserver参数–authorization-mode,配置多种授权策略。
- 当设置授权策略为Node,RBAC,API Server在收到请求后,会读取该请求中的数据,生成一个访问策略对象,API Server会将这个访问策略对象和配置的授权模式逐条进行匹配,第一个被满足或拒绝的授权策略决定了该请求的授权结果,若匹配的结果是禁止访问,则API Server会终止API调用流程,并返回客户端的错误调用码。
- Node授权策略是限制每个Node访问自身运行的Pod等资源信息,与用户的应用授权无关。只能受限于修改自身Node的一些信息,比如Label,不能操作其他Node上的资源。之前用RBAC这种通用权限模型其实并不能满足Node这种特殊的安全要求,所以将其剥离出来定义为新的Node授权策略。
1.3 准入控制
基本了解:
- 客户端请求通过前面的鉴权、授权后,还要过一道门槛,Admission Control准入控制。
- 准入控制过程分为两个阶段。第一阶段,运行变更准入控制器。第二阶段,运行验证准入控制器。 某些控制器既是变更准入控制器又是验证准入控制器。
- 若两个阶段之一的任何一个控制器拒绝了某请求,则整个请求将立即被拒绝,并向最终用户返回错误。
概念:
- Admission Control配备了一个准入控制器的插件列表,发送给APIServer的任何请求都需要通过列表中每个准入控制器的检查,检查不通过,API Server就会拒绝此调用请求。
- 准入控制器插件能够修改请求参数以完成一些自动化任务,比如ServiceAccount这个控制器插件。
注意事项:
- 一般情况下不需要更改默认配置,需要二次开发时可根据自身需求来更改。
- 除了使用官方默认配置的准入控制器之外,还可以扩展独立开发,并以运行时所配置的 Webhook 的形式运行。Webhook方式更加灵活,能够在API Server运行时修改和配置动态更新控制策略,但实现步骤较为负责,需要开发一个Admission Webhook Server实现HTTP回调的逻辑程序,还需要创建一个对应的ValidatingWebhookConfiguration配置文件。
1.启用一个准入控制器,以下是启用NamespaceLifecycle 和 LimitRanger 准入控制插件。
kube-apiserver --enable-admission-plugins=NamespaceLifecycle,LimitRanger ...
2.关闭一个准入控制器。
kube-apiserver --disable-admission-plugins=PodNodeSelector,AlwaysDeny ...
3.查看默认启用插件。
kubectl exec kube-apiserver-k8s-master -n kube-system -- kube-apiserver -h | grep enable-admission-plugins
4.也可以进入apiserver配置文件查看更改。
1.4 集群四大角色
- k8s预定好了四个集群角色供用户使用。
内置集群角色 | 描述 |
---|---|
cluster-admin | 超级管理员,对集群所有权限。 |
admin | 主要用于授权命名空间所有读写权限。 |
edit | 允许对命名空间大多数对象读写操作,不允许查看或者修改角色、角色绑定。 |
view | 允许对命名空间大多数对象只读权限,不允许查看角色、角色绑定和Secre。 |
1.查看集群所有角色,systemd:开头的为系统内部使用不能删除修改。
2.查看对应角色所赋予的资源权限。
#查看view角色对应的权限。
[root@k8s-master1 manifests]# kubectl describe clusterrole view
二、RBAC给用户授权(TLS)
概念:
- RBAC(Role-Based Access Control,基于角色的访问控制),是K8s默认授权策略,并且是动态配置策略,修改即时生效。
- 很多访问控制系统也是用这个,比如Nacos。
主体(subject):
- User:用户
- Group:用户组
- ServiceAccount:服务账号
角色:
- Role:授权特定命名空间的访问权限
- ClusterRole:授权所有命名空间的访问权限
角色绑定:
- RoleBinding:将角色绑定到主体(即subject)
- ClusterRoleBinding:将集群角色绑定到主体
注意事项:
- RoleBinding在指定命名空间中执行授权,ClusterRoleBinding在集群范围执行授权。
概念图:
案例:
- 为指定用户授权访问不同命名空间权限,例如新入职一个小弟,希望让他先熟悉K8s集群,为了安全性,先不能给他太大权限,因此先给他授权访问default命名空间Pod读取权限。
实施思路:
- 用K8S CA签发客户端证书,也就是是用K8s根证书签发一个客户端证书。
- 生成kubeconfig授权文件
- 创建RBAC权限策略
- 把kubeconfig文件给小弟就可以使用了。
生成证书步骤:
- 客户端证书都是基于K8s根证书来生成的,根证书在搭建K8s集群时候就被创建了,且创建时生成的ca-config配置文件是被删除了,根证书位置在/etc/kubernetes/pki目录下,一个是在K8s层面上的根证书,一个是etcd是用的。
- 生成ca-config配置文件,里面记录的根证书的有效期等信息。因为最后生成客户端证书时需要指定该配置文件。
- 生成客户端证书配置文件,里面声明一个CN字段(标识),可信任IP,生成的算法,证书里的设计属性。
- 使用cfssl工具指定根证书、根证书的配置文件和指定该文件中使用哪块配置、客户端证书的请求文件来生成。
2.1 签发客户端证书
1.需要先准备好K8s的根证书,我们搭建集群时就已经生成了。
2.生成客户端证书。
[root@k8s-master rbac]# cat cert.sh
##生成K8s根证书配置文件
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
EOF
##生成客户端证书请求文件
cat > qingjun-csr.json <<EOF
{
"CN": "qingjun", ##指定标识,后面会用到
"hosts": [],
"key": {
"algo": "rsa", ##生成算法
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
##使用cfssl工具来生成客户端证书,再传入到cfssljson中,生成以qingjun为前缀的证书。
## -profile参数代表使用请求文件中的哪块配置。
cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key -config=ca-config.json -profile=kubernetes qingjun-csr.json | cfssljson -bare qingjun
2.2 生成kubeconfig授权文件
- 往kubeconfig文件填充内容,填充出来的内容和.kube/config文件格式一样,是一个yaml文件,上面是集群信息、客户端信息、上下文信息。我这里使用的脚本,也可以分步执行。
- 填充完后,可以指定生成出来的kubeconfig文件来查询资源测试效果,因为最后就是把这个文件给小弟用,让他指定这个文件来查询集群资源。
2.2.1 手动生成
第一步:填充集群相关信息。
[root@k8s-master rbac]# kubectl config set-cluster kubernetes \ ##set-cluster代表对授权文件中的集群部分内容进行填充。
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--embed-certs=true \
--server=https://192.168.130.145:6443 \
--kubeconfig=qingjun.kubeconfig
第二步:填充客户端相关信息。
[root@k8s-master rbac]# kubectl config set-credentials qingjun \ ##set-credentials代表对授权文件中的客户端部分内容进行填充。
--client-key=qingjun-key.pem \
--client-certificate=qingjun.pem \
--embed-certs=true \
--kubeconfig=qingjun.kubeconfig
第三步:关联上下文,将集群和客户端关联在一起。
[root@k8s-master rbac]# kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=qingjun \
--kubeconfig=qingjun.kubeconfig
第四步:设置当前使用配置,指定使用哪个集群。
##指定当前操作集群名为kubernetes的集群。
[root@k8s-master rbac]# kubectl config use-context kubernetes --kubeconfig=qingjun.kubeconfig
第五步:使用授权文件测试效果。
#使用授权文件查询资源,显示没权限,是因为这个授权文件只是你访问的方式是没问题的,但是没有相关权限去访问资源。
#所以要进行下一步,创建RBAC权限策略。
[root@k8s-master bck]# kubectl get po --kubeconfig=qingjun.kubeconfig
2.2.2 脚本生成
[root@k8s-master rbac]# cat kubeconfig.sh
# 设置集群信息
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/pki/ca.crt \ #指向K8s根证书。
--embed-certs=true \ #将根证书嵌套在这个授权文件里,若为flase,则只写根证书路径。
--server=https://192.168.130.145:6443 \ #指定API server所在的服务器地址。
--kubeconfig=aliang.kubeconfig #生成的文件名,是个json格式的。
# 设置客户端认证
kubectl config set-credentials qingjun \
--client-key=aliang-key.pem \
--client-certificate=qingjun.pem \
--embed-certs=true \
--kubeconfig=qingjun.kubeconfig
# 设置默认上下文
kubectl config set-context kubernetes \ ##“kubernetes”为集群名称
--cluster=kubernetes \ ##指定K8s集群名称
--user=qingjun \ ##指定客户端用户名,也就是我们上步生成的客户端证书配置文件中的CN字段内容。
--kubeconfig=qingjun.kubeconfig ##授权文件。
# 设置当前使用配置
kubectl config use-context kubernetes --kubeconfig=qingjun.kubeconfig
2.2.3 切换操作集群
- 上面第四步的命令是指定操作的当前集群,当有多个K8s集群时,一个授权文件要怎么操作呢?
- 可以生成第二套配置追加到刚刚生成的授权文件中。
- 将上面生成的kubeconfig授权文件先备份,再生成第二个授权文件,此时第二次生成的文件内容会追加到第一次生成的qingjun.kubeconfig文件中,也就是说这个授权文件里有两套集群配置,此时就可以通过第四步命令来切换集群。
[root@k8s-master rbac]# cat kubeconfig2.sh
kubectl config set-cluster baimu \ #修改成第2个集群名称。
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--embed-certs=true \
--server=https://192.168.10.11:6443 \ #第二个集群API server所在机器IP。
--kubeconfig=qingjun.kubeconfig
# 设置客户端认证
kubectl config set-credentials baimu \ #第二个集群客户端名。
--client-key=qingjun-key.pem \
--client-certificate=qingjun.pem \
--embed-certs=true \
--kubeconfig=qingjun.kubeconfig
# 设置默认上下文
kubectl config set-context baimu \ ##修改成第二个集群名称。
--cluster=baimu \ #第二个集群名称
--user=baimu \ #第二个客户端名。
--kubeconfig=qingjun.kubeconfig
# 设置当前使用配置
kubectl config use-context baimu --kubeconfig=qingjun.kubeconfig #指定使用第二个集群。
2.3 定义RBAC权限策略
2.3.1 创建角色、绑定角色
1.编辑yaml文件,创建角色和绑定角色。
[root@k8s-master rbac]# cat rbac.yaml
#创建角色,该角色具备什么操作权限。
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: qingjun-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
---
#绑定角色,和客户端用户绑定在一起,使客户端拥有该种角色的操作权限。
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: qingjun
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: qingjun-role
apiGroup: rbac.authorization.k8s.io
2.导入yaml文件,查看结果。
3.验证。使用生成的授权文件查看pod可以成功,但是查看service会失败是因为我们定义的权限规对该客户端只能查看、列出Pod资源信息。
2.3.2 给新员工授权文件
- 此时把生成的授权文件给新员工,新员工在自己的虚拟机上安装kubectl工具后,就可以查看我集群相关资源。
- 新员工的虚拟机是能和K8s集群网络相通的。
1.新员工主机配置阿里云的源,并安装kubelet工具。
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
[root@localhost ~]# yum install -y kubelet-1.27.0 kubeadm-1.27.0 kubectl-1.27.0
2.将授权文件给新员工,新员工拿着授权文件在自己的虚拟机上查看k8s资源。
2.4 RBAC权限定义法则
定义步骤:
- 查看要定义的资源属于哪个API组里。V1前面有值的话,则该值为组名;若V1前面没值,则属于核心组。
- 确定角色权限空间,对应管控该空间下的所有资源权限。
- 填写资源组,“”代表是核心组。
- 填写资源名称,要使用复数形式。
- 填写操作资源方法,比如get、create等等。
填写示例:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: pod-reader rules: - apiGroups: [“”] # api组,例如apps组,空值表示是核心API组,像namespace、pod、service、pv、pvc都在里面 resources: [“pods”] # 资源名称(复数),例如pods、deployments、services verbs: [“get”, “watch”, “list”] # 允许对资源操作方法 --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: read-pods namespace: default subjects: - kind: User # 主体。 name: jane # 主体名称。若是用户的话,则是客户端证书里的CN字段。 apiGroup: rbac.authorization.k8s.io roleRef: # 绑定的角色 kind: Role name: pod-reader # 角色名称 apiGroup: rbac.authorization.k8s.io
认证流程图:
1.先确定资源在哪个组。
- 斜杠前面有值,则代表在哪个组;若没有值,则代表在核心组。
[root@k8s-master rbac]# kubectl api-resources
2.编辑yaml文件,指定什么用户具备什么权限。比如我这里就添加了qingjun用户能查询pod和deployment资源,能创建deployment。
[root@k8s-master rbac]# cat rbac.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: text
rules:
- apiGroups: ["", "apps"]
resources: ["pods", "deployments"]
verbs: ["get", "watch", "list"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["create"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: rolebinding2
namespace: default
subjects:
- kind: User
name: qingjun
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: text
apiGroup: rbac.authorization.k8s.io
3.验证,可以查询pod,deploy资源,不能查看其他任何资源。
4.验证,可以创建deployment,不能创建其他任何资源。
5.现在我让小弟只能查看deployment资源的同时,还能查看service资源。
6.现在我让小弟只能查看service资源,同时还能查看、删除deployment资源。
三、RBAC给用户组授权(TLS)
基本了解:
- K8s本身没有组的概念,使用这个功能需要提前定义组,而k8s也就是读取客户端证书中的O字段。
- 用户组:用户组的好处是无需单独为某个用户创建权限,统一为这个组名进行授权,所有的用户都以组的身份访问资源。
使用思路:
- 生成客户端证书时,修改里面的O字段。
- 生成授权文件。
- 将O字段对应的某某用户组与角色绑定。
1.生成新客户端证书。修改组里的O字段,代表哪个组,CN字段不能少,代表组里哪个用户。
2.根据新客户端证书生成授权文件,需改脚本生成的授权文件名称为qingjun.kubeconfig。
[root@k8s-master1 RBAC2]# sh kubeconfig.sh
3.角色和组进行绑定,指定组名。
4.测试dev组的用户可以删除svc资源。
四、RBAC给程序授权(SA)
基本了解:
- ServiceAccount,简称SA,是一种用于让程序访问K8s API的服务账号。也就是后面在绑定角色时,不再写user、group,而是写SA。
- 当创建namespace时,会自动创建一个名为default的SA,这个SA没有绑定任何权限。
- 当这个default的SA创建时,会自动创建一个default-token-xxx的secret,并自动关联到SA。而在1.24版本之后token的保存机发生变化不再放在secret里保存,新增token命令可以获取token,所以这里并没有看到default-token-xxx的secret。
- 当创建Pod时,若没有指定SA,会自动为pod以volume方式挂载这个default SA,在容器目录:/var/run/secrets/kubernetes.io/serviceaccount,任何一个pod都会有这个路径文件。
- ca.crt文件:k8s根证书。
- namespace文件:该pod在哪个命名空间下。
- token文件:该pod拿此文件连接apiserver的凭据。
概念图:
4.1 命令创建
需求:
- 给一个服务账号分配只能创建deployment、daemonset、statefulset资源的权限。
1.创建服务账号。
#创建一个命名空间,名为app。
[root@k8s-master rbac]# kubectl create ns app
#在app命名空间里创建一个服务账号,名为qingjun。
[root@k8s-master rbac]# kubectl create serviceaccount qingjun -n app
2.创建集群角色,名为baimu,该角色具备创建deployments、daemonsets、statefulsets资源权限。
[root@k8s-master rbac]# kubectl create clusterrole baimu --verb=create --resource=deployments,daemonsets,statefulsets
3.账号将app命名空间下的qingjun账号和baimu集群角色绑定,名为text。
[root@k8s-master rbac]# kubectl create rolebinding text --serviceaccount=app:qingjun --clusterrole=baimu -n app
4.测试服务账号权限,创建deployment成功,而查看资源失败,正好印证我们只给了创建deployment资源权限。
[root@k8s-master rbac]# kubectl --as=system:serviceaccount:app:qingjun create deployment nginx --image=nginx -n app
4.2 yaml文件创建
1.编辑yaml文件
[root@k8s-master rbac]# cat rbac1.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: qingjun
namespace: app
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: baimu
rules:
- apiGroups: ["apps"]
resources: ["deployments","daemonsets","statefulsets"]
verbs: ["create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: text
namespace: app
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: baimu
subjects:
- kind: ServiceAccount
name: qingjun
namespace: app
2.创建deploy资源,验证查看。
4.3 例一
需求:
- 授权SA只能查看test命名空间控制器的权限。
1.创建role,定义资源操作权限。
[root@k8s-master1 RBAC]# kubectl create role test-role --verb=get,list --resource=deployments,daemonsets,statefulsets -n test
2.创建SA。
[root@k8s-master1 RBAC]# kubectl create sa test-sa -n test
3.SA和角色绑定。
[root@k8s-master1 RBAC]# kubectl create rolebinding test-rolebinding --serviceaccount=test:test-sa --role=test-role -n test
4.测试效果,可以查看deploy资源,查看pod资源失败。
4.4 例二
需求:
- 授权容器中Python程序对K8s API访问权限。
思路步骤:
- 创建Role,定义资源操作权限。
- 创建ServiceAccount。
- 将ServiceAccount与Role绑定。
- 创建Pod时,指定自定义的SA,也就拥有了对应绑定的角色权限。
- 进入pod容器里,执行Python程序测试操作K8s API权限。
1.写了一个python程序去访问apiserver,查看deploy和pod资源权限。
[root@k8s-master1 RBAC]# cat k8s-api-test.py
from kubernetes import client, config
with open('/var/run/secrets/kubernetes.io/serviceaccount/token') as f:
token = f.read()
configuration = client.Configuration()
configuration.host = "https://kubernetes" # APISERVER地址
configuration.ssl_ca_cert="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" # CA证书
configuration.verify_ssl = True # 启用证书验证
configuration.api_key = {"authorization": "Bearer " + token} # 指定Token字符串
client.Configuration.set_default(configuration)
apps_api = client.AppsV1Api()
core_api = client.CoreV1Api()
try:
print("###### Deployment列表 ######")
#列出default命名空间所有deployment名称
for dp in apps_api.list_namespaced_deployment("default").items:
print(dp.metadata.name)
except:
print("没有权限访问Deployment资源!")
try:
#列出default命名空间所有pod名称
print("###### Pod列表 ######")
for po in core_api.list_namespaced_pod("default").items:
print(po.metadata.name)
except:
print("没有权限访问Pod资源!")
2.使用python镜像创建一个pod,把上面这个程序文件放在容器里测试效果,可以看到此时没有访问资源权限,因为使用的是/var/run/secrets/kubernetes.io/serviceaccount/token下的token,默认没有任何权限,所以接下来我们需要手动授权。
#创建一个python环境。
[root@k8s-master1 RBAC]# kubectl run py3 --image=python:3 -- sleep 24h
#把python程序放进python环境里测试连接apiserver,验证是否具备查看deploy和pod资源权限。
[root@k8s-master1 RBAC]# kubectl cp k8s-api-test.py py3:/
#进入容器测试。
[root@k8s-master1 RBAC]# kubectl exec -it py3 -- /bin/bash
root@py3:/# pip3 install kubernetes -i https://mirrors.aliyun.com/pypi/simple/ ##指定阿里云的源安装kubernetes模块,测试命令依赖该模块。
3.创建一个sa和角色,两者绑定一起。
1、创建一个SA,名为qingjun。
[root@k8s-master1 ~]# kubectl create sa qingjun
2、创建一个角色pod-reader2具备查看deploy资源权限,并将qingjun和角色绑定在一起。
[root@k8s-master1 RBAC]# cat rbac.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader2
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "watch", "list"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods2
namespace: default
subjects:
- kind: ServiceAccount
name: qingjun
# apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader2
apiGroup: rbac.authorization.k8s.io
[root@k8s-master1 RBAC]# kubectl apply -f rbac.yaml
4.使用命令测试效果,可以查看deploy资源,不能查看Pod资源,测试无误。
[root@k8s-master1 RBAC]# kubectl --as=system:serviceaccount:default:qingjun get deploy
5.更换默认挂载的default serviceaccount,改成我们创建具有操作权限的qingjun serviceaccount,在创建pod时指定sa。
[root@k8s-master1 RBAC]# cat py3.yaml
apiVersion: v1
kind: Pod
metadata:
name: py3
spec:
containers:
- args:
- sleep
- 24h
image: python:3
name: py3
serviceAccountName: qingjun ##指定SA。
[root@k8s-master1 RBAC]# kubectl apply -f py3.yaml
6.容器被重建,需要再安装依赖模块。
[root@k8s-master1 RBAC]# kubectl cp k8s-api-test.py py3:/
[root@k8s-master1 RBAC]# kubectl exec -it py3 -- /bin/bash
root@py3:/# pip3 install kubernetes -i https://mirrors.aliyun.com/pypi/simple/
7.测试效果,可以访问到deploy资源,不能访问pod资源,测试无误。
8.外面创建一个deploy,进入容器再测试可以列出刚创建的deploy,测试无误。
9.增加查看pod权限,再次测试,可以查看到deploy、pod资源,测试无误。