技术交流28群

服务热线

135-6963-3175

微信服务号

kubernetes证书的创建 更新时间 2020-9-22 浏览1863次

开始配置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证书创建完毕