服务热线
135-6963-3175
开始配置Kubernetes集群的时候为了少出问题,都是在apiserver配置中去掉ServiceAccount采用非安全连接的方式,但在后面配置FEK日志的过程中,很多时候绕不开这个安全机制,但因为开始在centos上安装是通过yum的方式,所以那些ca.crt,server.crt,kubecfg.key等文件都是没有的。
Kubernetes需要PKI证书才能通过TLS进行身份验证。如果您使用kubeadm安装Kubernetes,则会自动生成集群所需的证书。您还可以生成自己的证书-例如,通过不将其存储在API服务器上来使私钥更加安全。
http方式连接到集群,http方式是不安全,如果内部使用还可以,若是部署到外部则需要使用https增加安全性。下面介绍如何在node2上采用https方式。介绍http方式是没有任何认证措施的,也就是说只要能访问master的主机都可以与其进行通信。特别说明:kubectl命令行工具既同时支持CA双向认证也支持简单认证(http base或者token)两种模式与apiserver进行通信,但其他组件只能配置成一种模式。
k8s中哪些组件需要进行tls证书认证,哪些不需要?
kube-scheduler、kube-controller-manager 一般和 kube-apiserver 部署在同一台机器上,它们使用非安全端口和 kube-apiserver通信,非安全端口默认为http的8080,可以使用--insecure-port指定,监听非安全端口的地址默认为127.0.0.1,可以使用--insecure-bind-address指定;
kubelet、kube-proxy、kubectl 部署在其它 Node 节点上,如果通过安全端口访问 kube-apiserver,则必须先通过 TLS 证书认证,再通过 RBAC 授权。安全端口默认为https的6443,可以使用--secure-port指定,监听安全端口的地址默认为0.0.0.0(监听所有接口),可以使用--bind-address指定。
在进行网络通信时,通信双方需要验证对方的身份,以避免恶意第三方伪造身份窃取信息或者对系统进行攻击。为了相互验证对方的身份,通信双方中的任何一方都需要做下面两件事情:
向对方提供标明自己身份的一个证书
验证对方提供的身份证书是否合法,是否伪造的?
在 Kubernetes 中使用了数字证书来提供身份证明。数字证书的验证是在协议层面通过 TLS 完成的,除了需要在建立通信时提供相关的证书和密钥外,在应用层面并不需要进行特殊处理。采用 TLS 进行验证有两种方式:
服务器单向认证:只需要服务器端提供证书,客户端通过服务器端证书验证服务的身份,但服务器并不验证客户端的身份。这种情况一般适用于对 Internet 开放的服务,例如搜索引擎网站,任何客户端都可以连接到服务器上进行访问,但客户端需要验证服务器的身份,以避免连接到伪造的恶意服务器。
双向 TLS 认证:除了客户端需要验证服务器的证书,服务器也要通过客户端证书验证客户端的身份。这种情况下服务器提供的是敏感信息,只允许特定身份的客户端访问。
在 Kubernetes 中,各个组件提供的接口中包含了集群的内部信息。如果这些接口被非法访问,将影响集群的安全,因此组件之间的通信需要采用双向 TLS 认证。即客户端和服务器端都需要验证对方的身份信息。在两个组件进行双向认证时,会涉及到下面这些证书相关的文件:
服务器端证书:服务器用于证明自身身份的数字证书,里面主要包含了服务器端的公钥以及服务器的身份信息。
服务器端私钥:服务器端证书中包含的公钥所对应的私钥。公钥和私钥是成对使用的,在进行 TLS 验证时,服务器使用该私钥来向客户端证明自己是服务器端证书的拥有者。
客户端证书:客户端用于证明自身身份的数字证书,里面主要包含了客户端的公钥以及客户端的身份信息。
客户端私钥:客户端证书中包含的公钥所对应的私钥,同理,客户端使用该私钥来向服务器端证明自己是客户端证书的拥有者。
服务器端 CA 根证书:签发服务器端证书的 CA 根证书,客户端使用该 CA 根证书来验证服务器端证书的合法性。
客户端端 CA 根证书:签发客户端证书的 CA 根证书,服务器端使用该 CA 根证书来验证客户端证书的合法性。
k8s证书的创建
一共有多少证书:
先从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证书
etcd | ca.pem server.pem server-key.pem |
flannel | ca.pem server.pem server-key.pem |
kube-apiserver | ca.pem server.pem server-key.pem |
kubelet | ca.pem ca-key.pem |
kube-proxy | ca.pem kube-proxy.pem kube-proxy-key.pem |
kubectl | ca.pem admin.pem admin-key.pem |
根据官方文档,生成k8s秘钥证书及相关管理证书有三种方式,其本质都是通过openssl:
cfssl
easyrsa
openssl
下面我们使用cfssl方式创建
curl -L https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o cfssl chmod +x cfssl curl -L https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -o cfssljson chmod +x cfssljson curl -L https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -o cfssl-certinfo chmod +x cfssl-certinfo
$ cp cfssl-certinfo /usr/local/bin/cfssl-certinfo $ cp cfssljson /usr/local/bin/cfssljson $ cp cfssl /usr/local/bin/cfssl
证书分四类
ca.pem - 私有CA根证书
server.pem(kubernetes.pem) - 与node通信的
kube-proxy.pem - k8s与容器通信的
admin.pem - kubectl管理用
生成证书请求
在生成证书过程中需要有四类文件
*.csr -证书请求文件,base64格式,有--BEGIN CERTICATE REQUEST---标识
*.csr.json - 证书请求文件,是上面格式的再封装 ,便于传给cfssl,json格式,大括号开始
*-key.pem - 私钥文件,base64格式,有----BEGIN RSA PRIVATE KEY---标识
*.pem -证书文件,base64格式,可以用cfssl certinfo -cert查看有效期,有---BEGIN CERTIFICATE---标识
前两类是中间产物,过后可以不保留,后两个需要配置到系统中(通常是主从节点的/etc/kubernetes/ssl目录下)
中间文件和生成的文件最好放在一起
1.创建证书配置文件ca-config.json
过期时间配置为10年
ca-config.json:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数,后续在签名证书时使用某个profile;
signing:表示该证书可用于签名其它证书,生成的ca.pem证书中CA=TRUE;
server auth:表示client可以用该CA对server提供的证书进行验证;
client auth:表示server可以用该CA对client提供的证书进行验证;
[root@localhost ssl]$ cat > ca-config.json <<EOF { "signing": { "default": { "expiry": "87600h" }, "profiles": { "kubernetes": { "expiry": "87600h", "usages": [ "signing", "key encipherment", "server auth", "client auth" ] } } } } EOF [root@localhost ssl]$ ls ca-config.json
2.创建CA证书
创建签名请求文件ca-csr.json
CN : Common Name,kube-apiserver从证书中提取该字段作为请求的用户名; 浏览器使用该字段验证网站是否合法;
O : Organization,kube-apiserver从证书中提取该字段作为请求用户所属的组;
[root@localhost ssl]$ cat > ca-csr.json <<EOF { "CN": "kubernetes", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "Beijing", "ST": "Beijing", "O": "k8s", "OU": "System" } ] } EOF [root@localhost ssl]# ls ca-config.json ca-csr.json
生成CA证书和秘钥
生成ca-key.pem,ca.pem
其中ca-key.pem是ca的私钥,ca.csr是一个签署请求,ca.pem是CA证书,是后面kubernetes组件会用到的RootCA。
[root@localhost ssl]$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca 2020/09/16 04:09:59 [INFO] generating a new CA key and certificate from CSR 2020/09/16 04:09:59 [INFO] generate received request 2020/09/16 04:09:59 [INFO] received CSR 2020/09/16 04:09:59 [INFO] generating key: rsa-2048 2020/09/16 04:09:59 [INFO] encoded CSR 2020/09/16 04:09:59 [INFO] signed certificate with serial number 441536260878779044361548687020338409598653447074
3、创建kubernetes server证书
生成server-csr.json文件
创建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 则配置 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也可以更换为主机名。
不过根据情况我们目前就一台,则是下面:
[root@localhost ssl]$ cat > server-csr.json <<EOF { "CN": "kubernetes", "hosts": [ "127.0.0.1", "192.168.1.104", "192.168.1.104", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster", "kubernetes.default.svc.cluster.local" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "BeiJing", "ST": "BeiJing", "O": "k8s", "OU": "System" } ] } EOF
生成kubernetes证书和私钥 server.pem,server-key.pem
[root@localhost ssl]$ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes server-csr.json | cfssljson -bare server 2020/09/16 04:29:39 [INFO] generate received request 2020/09/16 04:29:39 [INFO] received CSR 2020/09/16 04:29:39 [INFO] generating key: rsa-2048 2020/09/16 04:29:39 [INFO] encoded CSR 2020/09/16 04:29:39 [INFO] signed certificate with serial number 307169675858223955921526744614218631261100767335 2020/09/16 04:29:39 [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@localhost ssl]$
4 创建admin证书
创建admin证书签名请求文件admin-csr.json
[root@localhost ssl]$ cat > admin-csr.json <<EOF { "CN": "admin", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "BeiJing", "ST": "BeiJing", "O": "system:masters", "OU": "System" } ] } EOF
后续 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:masters,kubelet 使用该证书访问 kube-apiserver 时 ,由于证书被 CA 签名,所以认证通过,同时由于证书用户组为经过预授权的 system:masters,所以被授予访问所有 API 的权限;
注:这个admin 证书,是将来生成管理员用的kube config 配置文件用的,现在我们一般建议使用RBAC 来对kubernetes 进行角色权限控制, kubernetes 将证书中的CN 字段 作为User, O 字段作为 Group
生成admin-key.pem,admin.pem
[root@localhost ssl]$ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin 2020/09/16 04:39:47 [INFO] generate received request 2020/09/16 04:39:47 [INFO] received CSR 2020/09/16 04:39:47 [INFO] generating key: rsa-2048 2020/09/16 04:39:47 [INFO] encoded CSR 2020/09/16 04:39:47 [INFO] signed certificate with serial number 28725323334636465654720894944629328554654813559 2020/09/16 04:39:47 [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").
5 生成代理kube-proxy证书
创建kube-proxy证书签名请求文件
[root@localhost ssl]$ cat > kube-proxy-csr.json <<EOF { "CN": "system:kube-proxy", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "BeiJing", "ST": "BeiJing", "O": "k8s", "OU": "System" } ] } EOF
说明:
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证书和私钥 kube-proxy.pem,kube-proxy-key.pem
[root@localhost ssl]$ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy 2020/09/16 05:03:18 [INFO] generate received request 2020/09/16 05:03:18 [INFO] received CSR 2020/09/16 05:03:18 [INFO] generating key: rsa-2048 2020/09/16 05:03:18 [INFO] encoded CSR 2020/09/16 05:03:18 [INFO] signed certificate with serial number 142322461904216930340298836903855862742747426147 2020/09/16 05:03:18 [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").
//查看生成的证书#
ls | grep pem admin-key.pem admin.pem ca-key.pem ca.pem kube-proxy-key.pem kube-proxy.pem server-key.pem server.pem
附:kube-controller-manager、kube-scheduler证书的创建(可选,因可与kube-apiserver,etcd部署一台,所以可公用kube-apiserver的证书 )
创建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-manager,kubernetes 内置的 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-scheduler,kubernetes 内置的 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证书创建完毕