Docs/CloudNative/Kubernetes/Base/k8s证书浅析
2022-10-18 16:59:37 +08:00

445 lines
No EOL
14 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

在进行二进制搭建K8S集群前我们需要梳理最磨人的一个点就是各种各样的证书。
官方文档参考https://kubernetes.io/docs/setup/certificates/
一共有多少证书:
先从Etcd算起
1、Etcd对外提供服务要有一套etcd server证书
2、Etcd各节点之间进行通信要有一套etcd peer证书
3、Kube-APIserver访问Etcd要有一套etcd client证书
再算kubernetes
4、Kube-APIserver对外提供服务要有一套kube-apiserver server证书
5、kube-scheduler、kube-controller-manager、kube-proxy、kubelet和其他可能用到的组件需要访问kube-APIserver要有一套kube-APIserver client证书
6、kube-controller-manager要生成服务的service account要有一对用来签署service account的证书(CA证书)
7、kubelet对外提供服务要有一套kubelet server证书
8、kube-APIserver需要访问kubelet要有一套kubelet client证书
加起来共8套但是这里的“套”的含义我们需要理解。
同一个套内的证书必须是用同一个CA签署的签署不同套里的证书的CA可以相同也可以不同。例如所有etcd server证书需要是同一个CA签署的所有的etcd peer证书也需要是同一个CA签署的而一个etcd server证书和一个etcd peer证书完全可以是两个CA机构签署的彼此没有任何关系。这算两套证书。
为什么同一个“套”内的证书必须是同一个CA签署的
原因在验证这些证书的一端。因为在要验证这些证书的一端通常只能指定一个Root CA。这样一来被验证的证书自然都需要是被这同一个Root CA对应的私钥签署不然不能通过认证。
其实实际上使用一套证书都使用一套CA来签署一样可以搭建出K8S一样可以上生产但是理清这些证书的关系在遇到因为证书错误请求被拒绝的现象的时候不至于无从下手而且如果没有搞清证书之间的关系在维护或者解决问题的时候贸然更换了证书弄不好会把整个系统搞瘫。
TLS bootstrapping 简化kubelet证书制作
Kubernetes1.4版本引入了一组签署证书用的API。这组API的引入使我们可以不用提前准备kubelet用到的证书。
官网地址https://kubernetes.io/docs/tasks/tls/certificate-rotation/
每个kubelet用到的证书都是独一无二的因为它要绑定各自的IP地址于是需要给每个kubelet单独制作证书如果业务量很大的情况下node节点会很多这样一来kubelet的数量也随之增加而且还会经常变动增减Nodekubelet的证书制作就成为一件很麻烦的事情。使用TLS bootstrapping就可以省事儿很多。
工作原理Kubelet第一次启动的时候先用同一个bootstrap token作为凭证。这个token已经被提前设置为隶属于用户组systembootstrappers并且这个用户组的权限也被限定为只能用来申请证书。 用这个bootstrap token通过认证后kubelet申请到属于自己的两套证书kubelet server、kube-apiserver client for kubelet申请成功后再用属于自己的证书做认证从而拥有了kubelet应有的权限。这样一来就去掉了手动为每个kubelet准备证书的过程并且kubelet的证书还可以自动轮替更新
参考文档:
https://mritd.me/2018/01/07/kubernetes-tls-bootstrapping-note/
https://www.jianshu.com/p/bb973ab1029b
kubelet证书为何不同
这样做是一个为了审计,另一个为了安全。 每个kubelet既是服务端kube-apiserver需要访问kubelet也是客户端kubelet需要访问kube-apiserver所以要有服务端和客户端两组证书。
服务端证书需要与服务器地址绑定每个kubelet的地址都不相同即使绑定域名也是绑定不同的域名故服务端地址不同
客户端证书也不应相同每个kubelet的认证证书与所在机器的IP绑定后可以防止一个kubelet的认证证书泄露以后使从另外的机器上伪造的请求通过验证。
安全方面如果每个node上保留了用于签署证书的bootstrap token那么bootstrap token泄漏以后是不是可以随意签署证书了安全隐患非常大。所以kubelet启动成功以后本地的bootstrap token需要被删除。
正式制作证书
虽然可以用多套证书但是维护多套CA实在过于繁杂这里还是用一个CA签署所有证书。
需要准备的证书:
admin.pem
ca.-key.pem
ca.pem
admin-key.pem
admin.pem
kube-scheduler-key.pem
kube-scheduler.pem
kube-controller-manager-key.pem
kube-controller-manager.pem
kube-proxy-key.pem
kube-proxy.pem
kubernetes-key.pem
kubernetes.pem
使用证书的组件如下:
etcd使用 ca.pem kubernetes-key.pem kubernetes.pem
kube-apiserver使用 ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem
kubelet使用 ca.pem
kube-proxy使用 ca.pem kube-proxy-key.pem kube-proxy.pem
kubectl使用 ca.pem admin-key.pem、admin.pem
kube-controller-manager使用 ca-key.pem ca.pem kube-controller-manager-key.pem kube-controller-manager.pem
kube-scheduler: 使用 kube-scheduler-key.pem kube-scheduler.pem
我们使用CFSSL来制作证书它是cloudflare开发的一个开源的PKI工具是一个完备的CA服务系统可以签署、撤销证书等覆盖了一个证书的整个生命周期后面只用到了它的命令行工具。
一般情况下K8S中证书只需要创建一次以后在向集群中添加新节点时只要将/etc/kubernetes/ssl目录下的证书拷贝到新节点上即可。
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo
创建CA证书
创建证书配置文件
vim ca-config.json
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
字段说明:
ca-config.json可以定义多个 profiles分别指定不同的过期时间、使用场景等参数后续在签名证书时使用某个 profile
signing表示该证书可以签名其他证书生成的ca.pem证书中 CA=TRUE
server auth表示client可以用该 CA 对server提供的证书进行验证
client auth表示server可以用该CA对client提供的证书进行验证
expiry过期时间
创建CA证书签名请求文件
vim ca-csr.json
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
],
"ca": {
"expiry": "87600h"
}
}
字段说明:
“CN”Common Namekube-apiserver 从证书中提取该字段作为请求的用户名 (User Name);浏览器使用该字段验证网站是否合法;
“O”Organizationkube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group)
生成CA证书和私钥
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
ls | grep ca
ca-config.json
ca.csr
ca-csr.json
ca-key.pem
ca.pem
其中ca-key.pem是ca的私钥ca.csr是一个签署请求ca.pem是CA证书是后面kubernetes组件会用到的RootCA。
创建kubernetes证书
在创建这个证书之前,先规划一下架构
k8s-master1 10.211.55.11
k8s-master2 10.211.55.12
k8s-master3 10.211.55.13
etcd01 10.211.55.11
etcd02 10.211.55.12
etcd03 10.211.55.13
VIP 10.211.55.8
创建kubernetes证书签名请求文件
vim kubernetes-csr.json
{
"CN": "kubernetes",
"hosts": [
"127.0.0.1",
"10.211.55.11",
"10.211.55.12",
"10.211.55.13",
"10.211.55.8",
"10.0.0.1",
"k8s-master1",
"k8s-master2",
"k8s-master3",
"etcd01",
"etcd02",
"etcd03",
"kubernetes",
"kube-api.wangdong.com",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
字段说明:
如果 hosts 字段不为空则需要指定授权使用该证书的 IP 或域名列表。
由于该证书后续被 etcd 集群和 kubernetes master 集群使用将etcd、master节点的IP都填上同时还有service网络的首IP。(一般是 kube-apiserver 指定的 service-cluster-ip-range 网段的第一个IP如 10.0.0.1)
三个etcd三个master以上物理节点的IP也可以更换为主机名。
生成kubernetes证书和私钥
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes
ls |grep kubernetes
kubernetes.csr
kubernetes-csr.json
kubernetes-key.pem
kubernetes.pem
创建admin证书
创建admin证书签名请求文件
vim admin-csr.json
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "system:masters",
"OU": "System"
}
]
}
说明:
后续 kube-apiserver 使用 RBAC 对客户端(如 kubelet、kube-proxy、Pod)请求进行授权;
kube-apiserver 预定义了一些 RBAC 使用的 RoleBindings如 cluster-admin 将 Group system:masters 与 Role cluster-admin 绑定,该 Role 授予了调用kube-apiserver 的所有 API的权限
O指定该证书的 Group 为 system:masterskubelet 使用该证书访问 kube-apiserver 时 ,由于证书被 CA 签名,所以认证通过,同时由于证书用户组为经过预授权的 system:masters所以被授予访问所有 API 的权限;
这个admin 证书是将来生成管理员用的kube config 配置文件用的现在我们一般建议使用RBAC 来对kubernetes 进行角色权限控制, kubernetes 将证书中的CN 字段 作为User O 字段作为 Group
相关权限认证可以参考下面文章
https://mp.weixin.qq.com/s/XIkQdh5gnr-KJhuFHboNag
生成admin证书和私钥
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin
ls | grep admin
admin.csr
admin-csr.json
admin-key.pem
admin.pem
创建kube-proxy证书
创建 kube-proxy 证书签名请求文件
vim kube-proxy-csr.json
{
"CN": "system:kube-proxy",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
说明:
CN 指定该证书的 User 为 system:kube-proxy
kube-apiserver 预定义的 RoleBinding system:node-proxier 将User system:kube-proxy 与 Role system:node-proxier 绑定,该 Role 授予了调用 kube-apiserver Proxy 相关 API 的权限;
该证书只会被 kubectl 当做 client 证书使用,所以 hosts 字段为空
生成kube-proxy证书和私钥
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
ls |grep kube-proxy
kube-proxy.csr
kube-proxy-csr.json
kube-proxy-key.pem
kube-proxy.pem
创建kube-controoler-manager证书
创建 kube-controoler-manager 证书签名请求文件
vim kube-controller-manager-csr.json
{
"CN": "system:kube-controller-manager",
"key": {
"algo": "rsa",
"size": 2048
},
"hosts": [
"127.0.0.1",
"10.211.55.11",
"10.211.55.12",
"10.211.55.13",
"k8s-master1",
"k8s-master2",
"k8s-master3"
],
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "system:kube-controller-manager",
"OU": "system"
}
]
}
说明:
hosts 列表包含所有 kube-controller-manager 节点 IP
CN 为 system:kube-controller-manager、O 为 system:kube-controller-managerkubernetes 内置的 ClusterRoleBindings system:kube-controller-manager 赋予 kube-controller-manager 工作所需的权限
生成kube-controoller-manager证书和私钥
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager
创建kube-scheduler证书
创建 kube-scheduler 证书签名请求文件
vim kube-scheduler-csr.json
{
"CN": "system:kube-scheduler",
"hosts": [
"127.0.0.1",
"10.211.55.11",
"10.211.55.12",
"10.211.55.13",
"k8s-master1",
"k8s-master2",
"k8s-master3",
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "system:kube-scheduler",
"OU": "4Paradigm"
}
]
}
说明:
hosts 列表包含所有 kube-scheduler 节点 IP
CN 为 system:kube-scheduler、O 为 system:kube-schedulerkubernetes 内置的 ClusterRoleBindings system:kube-scheduler 将赋予 kube-scheduler 工作所需的权限。
经过上述操作,我们会用到如下文件
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-scheduler-csr.json| cfssljson -bare kube-scheduler
ls | grep pem
admin-key.pem
admin.pem
ca-key.pem
ca.pem
kube-proxy-key.pem
kube-proxy.pem
kubernetes-key.pem
kubernetes.pem
kube-controller-manager-key.pem
kube-controller-manager.pem
kube-scheduler-key.pem
kube-scheduler.pem
查看证书信息:
cfssl-certinfo -cert kubernetes.pem
在搭建k8s集群的时候将这些文件分发到至此集群中其他节点机器中即可。至此TLS证书创建完毕
证书这块知道怎么生成、怎么用即可,建议暂时不必过多研究