8 Kubernetes-集群安全机制
Kubernetes 一个分布式集群的管理工具
Kubernetes 的安全机制围绕着保护apiserver设计,使用了 3A 服务:
- 认证:(Authentication)判断是否为自己人
- 鉴权:(Authorization)判断是否有权限
- 准入控制:(Admission Control)有权限,判断操作是否合理
一、认证(Authentication)
-
HTTP Token 认证:通过一个 Token 来识别合法用户
客户端发起api调用请求时,在HTTP Header 里放入 Token
HTTP Token 的认证是用一个很长的特殊编码方式的并且难以被模仿的字符串 - Token 来表达客户的一种方式
Token 是一个很长的很复杂的字符串,每一个 Token 对应一个用户名存储在 API Server 能访问的文件中
-
HTTP Base 认证:通过 用户名+密码 的方式认证
用户名+:+密码 用 BASE64 算法进行编码后的字符串放在 HTTP Request 中的 Heather Authorization 域里发送给服务端,服务端收到后进行编码,获取用户名及密码
-
最严格的 HTTPS 证书认证:基于 CA 根证书签名的客户端身份认证方式 (√)
单向认证:客户端认证服务端是否合法
双向认证:客户端和服务端,相互认证是否合法(金融级认证,在Kubernetes集群中,采用此方式进行认证)
1)HTTPS 证书双向认证原理:

2)需要认证的节点
并非所有组件与 ApiServer 通讯都采用 HTTPS 双向认证:
若组件与 ApiServer 在同一个物理机,不采用 HTTPS 双向认证,比如 Controller Manager、Schedule
(排除用二进制安装集群的方式,二进制安装,有可能将所有组件都分布在不同物理机)
1、存储
HTTPS 双向认证。认证文件: /etc/kubernetes/pki/etcd/{ca.crt,ca.key}
服务端:ETCD
客户端:ApiServer
2、服务
Ⅰ、组件认证
认证文件:/etc/kubernetes/pki/{ca.crt,ca.key}
服务端:ApiServer
客户端:
需要加密:
手动颁发:若采用kubeadm安装集群(容器化安装),kubeadm组件帮助完成了手动颁发证书
kube-proxy
kubectl
自动颁发:节点加入集群时,用的kubeadm join ,使用了双向认证,能自动颁发
kubelet
无需加密:
Controller Manager、Scheduler
注意:客户端需要加密的手动颁发证书机制
采用kubeadm安装集群(容器化安装),kubeadm组件帮助完成了手动颁发证书
注意:客户端需要加密的自动颁发证书机制
节点加入集群时,用的kubeadm join ,使用了双向认证,能自动颁发
拓展:md5sum 命令
验证两个文件的md5值是否相同。(此处判断存储、服务使用的证书不同)
[root@k8s-master01 ~]# cd /etc/kubernetes/pki/
[root@k8s-master01 pki]# md5sum ca.crt
42eb20c11d98bcff8bc18c1199e8f668 ca.crt
[root@k8s-master01 pki]# md5sum etcd/ca.crt
8448c984c06a6893ff1f4d79558f9f5b etcd/ca.crt
kubeconfig
组件通过 kubeconfig 连接 ApiServer
Ⅱ、pod认证
使用 SA(Server Account)
1、token JWT 使用 ApiServer 私钥签发的,用于server认证pod是否合法
2、ca.crt 用于pod认证apiserver是否合法
3、namespace 标识当前pod的作用域
默认挂载目录: /run/secrets/kubernetes.io/serviceaccount
二、鉴权(Authorization)
- AlwaysDeny:都拒绝(一般用于测试)
- AlwaysAllow:都允许(一般用于测试)
- ABAC:基于属性的访问控制 (在K8S中需有一个pod作为授权的载体)
- WebHook:通过其他服务,进行授权操作
openstark中:使用keystone进行统一授权
openstartk和K8S结合时:使用keystone进行统一授权(目前还未使用)
- RBAC:基于角色的访问控制
1)RBAC授权模式
RBAC基于角色的访问控制,在K8S中引入,直连 ApiServer的接口进行授权
- 对集群中的资源和非资源,都拥有完整的覆盖
- RBAC完全由几个API对象完成
- 运行中可调整,无需重启ApiServer
2)RBAC的四个顶级资源对象
ROLE、ClusterRole、RoleBinding、ClusterRolebinding

在 Kubernetes 集群中,权限可以绑定给 用户/组/SA(默认无权限):
1.通过角色 或 集群角色与权限绑定
2.然后, 用户/组/SA 通过角色绑定 或 集群角色绑定,获取权限

角色 角色绑定 # 需要指定名称空间
集群角色 集群角色绑定 # 所有空间
集群角色 角色绑定 # 需要指定名称空间
角色绑定 与 集群角色绑定区别:

Kubernetes 集群中的 用户、组来源:证书信息
证书请求的模板文件:(json格式)( cfssl 工具:基于json文件,签发证书)
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "HangZhou",
"L": "XS",
"O": "system:masters",
"OU": "System"
}
]
}
# 重点选项
"CN": "admin", # 用户名
"hosts": [], # 证书能被使用的位置。[]表示任意位置可用
"O": "system:masters", # 组
Kubernetes 集群中的 Service Account: 通过命令
$ kubectl create sa
3)Role and ClusterRole
Role 例子:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # [""] 表示 core/v1
resources: ["pods"] # 指定资源
verbs: ["get", "watch", "list"] # 指定动作类型
ClusterRole:
- 集群级别的资源控制( 例如 node 访问权限 )
- 非资源型 endpoints( 例如
/health访问 ) - 所有命名空间资源控制(例如 pods )
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
#### 不能指定namespace
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
4)RoleBinding and ClusterRoleBinding
Rolebinding例子:( jane 用户,将 pod-reader 角色,进行绑定)
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: jane
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
( dave 用户,将 secret-reader 集群角色,进行绑定,在 dev 名字空间下)
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-secrets
namespace: dev
subjects:
- kind: User
name: dave
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
ClusterRolebinding 例子:
( manager 组,将 secret-reader 集群角色,进行绑定,在所有空间下)
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-secrets-global
subjects:
- kind: Group
name: manager
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
5)Resources(子资源)
资源下的子资源限制
# 格式:
GET /api/v1/namespaces/{namespace}/pods/{name}/log
# 例子:
/api/v1/namespaces/default/pods/pod-demo/log
6)to Subject
角色绑定、集群角色绑定,将角色绑定到 Subject
Subeject 命名随意:字符串表示,它可以是一个普通的名字字符串,也可以是 email 格式的邮箱地址,甚至是一组字符串形式的数字 ID(但不能是 system: 为前缀,system: 是系统保留的)
7)实践:创建一个用户只能管理 dev 空间
注意:此处仅能限制用户在名字空间下的操作,但每个名字空间默认能使用集群的最大资源(后续介绍资源限制)
1、创建证书描述文件
[root@k8s-master01 ~]# cd /etc/kubernetes/pki/
[root@k8s-master01 pki]# vim devuser.json
[root@k8s-master01 pki]# cat devuser.json
{
"CN": "devuser",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
2、安装 cfssl 工具包
# 下载证书生成工具
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl
coreOS json
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo
# 本地上传到 /usr/local/bin/
chmod a+x /usr/local/bin/*

3、签发证书
[root@k8s-master01 bin]# cd /etc/kubernetes/pki/
[root@k8s-master01 pki]# pwd
/etc/kubernetes/pki
[root@k8s-master01 pki]# cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes devuser.json | cfssljson -bare devuser
4、设置集群参数
export KUBE_APISERVER="https://192.168.20.201:6443"
kubectl config set-cluster kubernetes \
--certificate-authority=ca.crt \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=devuser.kubeconfig
5、设置客户端认证参数
kubectl config set-credentials devuser \
--client-certificate=devuser.pem \
--client-key=devuser-key.pem \
--embed-certs=true \
--kubeconfig=devuser.kubeconfig
6、设置上下文参数---context(将用户和集群关联)
kubectl create ns dev
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=devuser \
--namespace=dev \
--kubeconfig=devuser.kubeconfig
7、设置默认上下文(刷新)
kubectl config use-context kubernetes --kubeconfig=devuser.kubeconfig
8、角色绑定
本次使用命令进行角色绑定(也可以通过 yaml 文件进行绑定)
kubectl create rolebinding devuser-admin-binding --clusterrole=admin --user=devuser --namespace=dev
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
creationTimestamp: null
name: devuser-admin-binding
namespace: dev
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: devuser
9、测试
更改当前角色为 devuser,创建控制器进行测试
[root@k8s-master01 pki]# pwd
/etc/kubernetes/pki
[root@k8s-master01 pki]# useradd devuser && echo "123" |passwd --stdin devuser
[root@k8s-master01 pki]# mkdir /home/devuser/.kube
[root@k8s-master01 pki]# cp -a /etc/kubernetes/pki/devuser.kubeconfig /home/devuser/.kube/config
[root@k8s-master01 pki]# chown -R devuser:devuser /home/devuser/
[root@k8s-master01 pki]# su - devuser
[devuser@k8s-master01 ~]$ kubectl create deployment nginx --image=wangyanglinux/myapp:v1
[devuser@k8s-master01 ~]$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-74c68d8687-cvk52 1/1 Running 0 5s 172.100.2.3 k8s-node02 <none> <none>
[devuser@k8s-master01 ~]$ exit
登出
[root@k8s-master01 pki]# kubectl get pod
No resources found.
[root@k8s-master01 pki]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
nginx-74c68d8687-cvk52 1/1 Running 0 27s
三、准入控制---(插件集合)
1.有权限,但不合理操作的拒绝
2.一些特殊功能
列举几个插件的功能:
- NamespaceLifecycle: 防止在不存在的 namespace 上创建对象,防止删除系统预置 namespace,删除 namespace 时,连带删除它的所有资源对象。
- LimitRanger:确保请求的资源不会超过资源所在 Namespace 的 LimitRange 的限制。
- ServiceAccount: 实现了自动化添加 ServiceAccount。
- ResourceQuota:确保请求的资源不会超过资源的 ResourceQuota 限制。