k8s集群安全机制说明

k8s作为一个分布式集群的管理工具,保证集群的安全性是其一个重要的任务,apiserver是集群内部各个组件通信的中介,也是外部控制的入口,所以k8s的安全机制基本就是围绕保护apiserver来设计的。k8s使用了认证Authentication、鉴权Authorization、准入控制admissionControl三步来保证apiserver的安全。

用户通过kubectl、客户端库或者通过发送REST请求访问API。 用户和Kubernetes服务账户都可以被授权进行API访问。请求到达API服务器后会经过几个阶段,具体说明如图:

传输层安全
在典型的Kubernetes集群中,API通过443端口提供服务。API服务器会提供一份证书。该证书一般是自签名的,所以用户机器上的$USER/.kube/config目录通常包含该API服务器证书的根证书,用来代替系统默认根证书。

认证Authentication

认证的方式:
1)HTTP Token认证:通过一个Token来识别合法用户
HTTP Token的认证是用一个很长的特殊编码方式的并且难以被模仿的字符串——Token来表明客户身份的一种方式。
在通常情况下,Token是一个复杂的字符串,比如我们用私钥签名一个字符串的数据就可以作为一个Token。此外每个Token对应一个用户名,存储在API Server能访问的一个文件中。当客户端发起API调用请求时,需要在HTTP Header里放入Token,这样一来API Server就能够识别合法用户和非法用户了

2)HTTP Base认证:通过用户名+密码的方式认证
HTTP Base认证是把"用户名+冒号+密码"用BASE64算法进行编码后的字符串放在HTTP REQUEST中的Header Authorization域里发送给服务端。服务端收到后进行解码,获取用户名及密码,然后进行用户身份的鉴权过程。

3)最严格的HTTPS证书认证:基于CA根证书签名的双向数字证书认证方式
首先,需要一个CA证书。CA通过证书证实他人的公钥信息,而证书上有CA的签名。很多情况下,CA与用户是相互独立的实体,CA作为服务提供方,有可能因为服务质量问题而给用户带来损失。在证书中绑定了公钥数据和相应私钥拥有者的信息,并带有CA的数字签名。证书中也包含了CA的名称,以便于依赖方找到CA的公钥,验证证书上的数字签名。

CA认证涉及诸多概念,比如根证书、自签名证书、密钥、私钥、加密算法及HTTPS等。
下面通过大致讲述SSL协议的流程,帮助理解CA认证和Kubernetes CA认证的配置过程。
(1)HTTPS通信双方的务器端向CA机构申请证书,CA机构是可信的第三方机构,它可以是一个公认的权威的企业,也可以是企业自身。企业内部系统一般都使用企业自身的认证系统。CA机构下发根证书、服务端证书及私钥给申请者;
(2)HTTPS通信双方的客户端向CA机构申请证书,CA机构下发根证书、客户端证书及私钥给申请者;
(3)客户端向服务器端发起请求,服务端下发服务端证书给客户端。客户端接收到证书后,通过私钥解密证书,并利用服务器端证书中的公钥认证证书信息比较证书里的消息,例如域名和公钥与服务器刚刚发送的相关消息是否一致,如果一致,则客户端认可这个服务器的合法身份;
(4)客户端发送客户端证书给服务器端,服务端接收到证书后,通过私钥解密证书,获得客户端的证书公钥,并用该公钥认证证书信息,确认客户端是否合法;
(5)客户端通过随机秘钥加密信息,并发送加密后的信息给服务器端。服务器端和客户端协商好加密方案后,客户端会产生一个随机的秘钥,客户端通过协商好的加密方案,加密该随机秘钥,并发送该随机秘钥到服务器端。服务器端接收这个秘钥后,双方通信的所有内容都通过该随机秘钥加密。

上述是双向SSL协议的具体通信过程,这种情况要求服务器和用户双方都有证书。单向认证SSL协议不需要客户拥有CA证书,对应上面的步骤,只需将服务器端验证客户端证书的过程去掉,以及在协商对称密码方案和对称通话秘钥时,服务器端发送给客户端的是没有加过密的(这并不影响SSL过程的安全性)密码方案。

k8s需要认证的节点
两种类型:
1)k8s组件对apiserver的访问:kubectl、controller manager、scheduler、kubelet、kube-proxy
2)k8s管理的pod对容器的访问:Pod

安全性说明
controller manager、scheduler、apiserver在同一台机器,所以直接使用apiserver的非安全端口访问,--insecure-bind-address=127.0.0.1
kubectl、kubelet\kube-proxy访问apiserver就都需要证书进行HTTPS双向认证

证书颁发
手工签发:通过k8s集群跟ca进行签发HTTPS证书
自动签发:kubelet首次访问apiserver时,使用token做认证,通过后controller manager会为kubelet生成一个证书,以后的访问都是用证书做认证。

kubeconfig
kubeconfig文件包含集群参数(ca证书、apiserver地址),客户端参数(生成的证书和私钥),集群context信息(集群名称、用户名)。k8s组件通过启动时指定不同的kubeconfig文件可以切换到不同的集群。
serviceAccount
pod中的容器访问apiserver,因为pod的创建、销毁是动态的,所以要为它手工生成证书就不行了。k8s使用service account解决pod访问apiserver的认证问题

secret与sa的关系
k8s涉及了一种资源对象叫做secret,分为两类,一种是用于serviceAccount的service-account-token,另一种是用于保存用户自定义保密信息的opaque。serviceAccount中
用到包含三个部分:Token、ca.crt、namespace
token是使用apiserver私钥签名的JWT,用于访问apiserver是server端认证。
ca.crt根证书,用于client端验证apiserver发送的证书
namespace标识这个service-account-token的作用域名空间
[root@k8smaster pod]# kubectl get secret --all-namespaces 
[root@k8smaster pod]# kubectl describe secrets default-token-rfxkf --namespace=kube-system 
默认情况下,每个namespace都会有一个ServiceAccount,如果pod在创建时没有指定ServiceAccount,就会使用pod所属的namespace的ServiceAccount

鉴权Authorization
上面认证过程,只是确认通信的双方都确认了对方是可信的,可以相互通信。而鉴权是确定请求方有哪些资源的权限。apiserver目前支持以下几种授权策略(通过apiserver的启动参数--authorization-mode设置)
alwaysDeny:表示拒绝所有的请求,一般用于测试
alwaysAllow:允许接收所有的请求,如果集群不需要授权流程,则可以采用该策略
ABAC(Attrilbute-Based Access Control):基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制
webbook:通过调用外部REST服务对用户进行授权
RBAC(Role-Based Access Control):基于角色的访问控制,现在默认规则

RBAC授权模式
RBAC(Role-Based Access Control)基于角色的访问控制,在k8s1.5中引入,现行版本成为默认标准,相对其他访问控制方式,拥有以下优势:
对集群中的资源和非资源均拥有完整的覆盖
整个RBAC完全由几个api对象完成,同其他api对象一样,可以用kubectl或api进行操作
可以在运行时进行调整,无需重启apiserver

RBAC的api资源对象说明
RBAC引入了4个新的顶级资源对象:Role、ClusterRole、RoleBinding、ClusterRoleBinding,4种对象类型均可以通过kubectl与api操作

Role and ClusterRole
在RBAC API中,Role表示一组规则权限,权限只会增加(累加权限),不存在一个资源一开始就有很多权限而通过RBAC对其进行减少的操作,Role可以定义在一个namespace中,如果想要跨namespace则可以创建ClusterRole。

ClusterRole具有与Role相同的权限角色控制能力,不同的是ClusterRole是集群级别的,ClusterRole可以用于:
集群级别的资源控制(例如node访问权限)
非资源型endpoints(例如/healthz访问)
所有命名空间资源控制(例如pods)

RoleBinding and ClusterRoleBinding 
RoleBinding可以将角色中定义的权限授予用户或用户组,RoleBinding包含一组权限列表(subjects)、权限列表中包含有不同形式的待授予权限资源类型(users、groups、service accounts),RoleBinding同样包含对Bind的Role引用。RoleBinding适用于某个命名空间内授权,而ClusterRoleBinding适用于集群范围内的授权。RoleBinding 同样可以引用ClusterRole来对当前namespace内用户、用户组或ServiceAccount进行授权,这种操作允许集群管理员在整个集群内定义一些通用的CLusterRole,然后在不同的namespace中使用RoleBinding来引用,使用ClusterRoleBinding可以对整个集群中的所有命名空间资源权限进行授权,

实战操作
[root@k8smaster user]# useradd devuser  #创建用户devuser
[root@k8smaster user]# passwd devuser #设置devuser密码
Changing password for user devuser.
New password: 
BAD PASSWORD: The password is shorter than 8 characters
Retype new password: 
passwd: all authentication tokens updated successfully.
[root@k8smaster user]# 

官网证书生成方式:https://kubernetes.io/zh/docs/concepts/cluster-administration/certificates/

链接:https://pan.baidu.com/s/1npkX5-KkBJg13mIDyjRMpg  证书生成工具
提取码:nrtc

[root@k8smaster cfssl]# curl -L https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o cfss  #下载生成秘钥的工具
[root@k8smaster cfssl]# curl -L https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -o cfssljson
[root@k8smaster cfssl]# curl -L https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -o cfssl-certinfo
[root@k8smaster cfssl]# chmod a+x *  #工具设置为可执行权限
[root@k8smaster pki]# pwd
/etc/kubernetes/pki
[root@k8smaster pki]# /root/user/cfssl/cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes /root/user/devuser-csr.json | /root/user/cfssl/cfssljson -bare devuser  
#生成密钥和证书,生成的秘钥和证书分别默认保存在文件 devuser-key.pem 和 devuser.pem 中
2020/02/23 04:22:01 [INFO] generate received request
2020/02/23 04:22:01 [INFO] received CSR
2020/02/23 04:22:01 [INFO] generating key: rsa-2048
2020/02/23 04:22:01 [INFO] encoded CSR
2020/02/23 04:22:01 [INFO] signed certificate with serial number 341072919289017469746252089406121038060622110111
2020/02/23 04:22:01 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
[root@k8smaster pki]# 
-rw-r--r-- 1 root root 1237 Feb 23 04:22 devuser.pem
-rw------- 1 root root 1679 Feb 23 04:22 devuser-key.pem
-rw-r--r-- 1 root root  997 Feb 23 04:22 devuser.csr

[root@k8smaster user]# pwd
/root/user
[root@k8smaster user]# export KUBE_APISERVER="https://192.168.23.100:6443" #设置apiserver访问地址
[root@k8smaster user]# kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --server=${KUBE_APISERVER} --kubeconfig=devuser.kubeconfig  #设置集群参数
Cluster "kubernetes" set.
[root@k8smaster user]# 
[root@k8smaster user]# kubectl config set-credentials devuser \
> --client-certificate=/etc/kubernetes/pki/devuser.pem \
> --client-key=/etc/kubernetes/pki/devuser-key.pem \
> --embed-certs=true \
> --kubeconfig=devuser.kubeconfig  #设置客户端认证参数

User "devuser" set.
[root@k8smaster user]#
[root@k8smaster user]# ls -lrt
total 8
-rw-r--r-- 1 root root  206 Feb 23 03:20 devuser-csr.json
drwxr-xr-x 2 root root   55 Feb 23 03:34 cfssl
-rw------- 1 root root 4065 Feb 23 04:28 devuser.kubeconfig
[root@k8smaster user]# 
[root@k8smaster user]# kubectl create namespace dev #创建命名空间
namespace/dev created 
[root@k8smaster user]# kubectl  config set-context kubernetes \
> --cluster=kubernetes \
> --user=devuser \
> --namespace=dev \
> --kubeconfig=devuser.kubeconfig   #设置上下文参数

Context "kubernetes" created.
[root@k8smaster user]# 

[root@k8smaster user]# kubectl create rolebinding devuser-admin-binding --clusterrole=admin --user=devuser --namespace=dev #给devuser绑定dev命名空间的admin角色
rolebinding.rbac.authorization.k8s.io/devuser-admin-binding created
[root@k8smaster user]# 

[devuser@k8smaster ~]$ mkdir .kube
[devuser@k8smaster ~]$ 

[root@k8smaster user]# cp devuser.kubeconfig /home/devuser/.kube/
[root@k8smaster user]# chown devuser:devuser /home/devuser/.kube/devuser.kubeconfig  #为devuser配置kube环境变量

[devuser@k8smaster .kube]$ ls -lrt
total 8
-rw------- 1 devuser devuser 4153 Feb 23 04:40 devuser.kubeconfig
[devuser@k8smaster .kube]$ mv devuser.kubeconfig config
[devuser@k8smaster .kube]$ kubectl config use-context kubernetes --kubeconfig=config #切换用户上下文
Switched to context "kubernetes".
[devuser@k8smaster .kube]$ kubectl get pod
No resources found.
[devuser@k8smaster .kube]$ 
[devuser@k8smaster .kube]$ kubectl run tomcat --image=192.168.23.100:5000/tomcat:v2 --port=8080  --replicas=1 #运行tomcat
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/tomcat created
[devuser@k8smaster .kube]$ kube

[root@k8smaster user]# kubectl get pod --all-namespaces -o wide |grep tomcat #tomcat运行在dev命名空间
dev             tomcat-bb9f46cfc-gzmgr                     1/1     Running   0          2m39s   10.244.2.37      k8snode02   <none>           <none>
[root@k8smaster user]# 
[devuser@k8smaster .kube]$ kubectl get pod -n default #devuser无法查看其他命名空间,比如default
Error from server (Forbidden): pods is forbidden: User "devuser" cannot list resource "pods" in API group "" in the namespace "default"
[devuser@k8smaster .kube]$ 

准入控制
准入控制是apiserver的插件集合,通过添加不同的插件,实现额外的准入控制规则。甚至于apiserver的一些主要的功能都要通过admission Controllers实现,比如serviceAccount

发布了60 篇原创文章 · 获赞 20 · 访问量 4599

猜你喜欢

转载自blog.csdn.net/zhaikaiyun/article/details/104538141