创建TLS证书和秘钥

前言

注意:这一步是在安装配置kubernetes的所有步骤中最容易出错也最难于排查问题的一步,而这却刚好是第一步,万事开头难,不要因为这点困难就望而却步。

kubernetes系统的各组件需要使用 TLS证书对通信进行加密,本文档使用 CloudFlare的 PKI 工具集 cfssl 来生成 Certificate Authority (CA) 和其它证书;

生成的CA证书和密钥文件如下:

ca-key.pem

ca.pem

kubernetes-key.pem

kubernetes.pem

kube-proxy.pem

kube-proxy-key.pem

admin.pem

admin-key.pem

使用证书的组件如下:

etcd:使用 ca.pem、kubernetes-key.pem、kubernetes.pem;

 kube-apiserver:使用 ca.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

注意:以下操作都在 master 节点即 192.168.70.21 这台主机上执行,证书只需要创建一次即可,以后在向集群中添加新节点时只要将 /etc/kubernetes/ 目录下的证书拷贝到新节点上即可。

安装 CFSSL

直接使用二进制源码包安装

cd /opt
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
chmod +x cfssl_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl

wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
chmod +x cfssljson_linux-amd64
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson

wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x cfssl-certinfo_linux-amd64
mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo

创建 CA (Certificate Authority)

创建 CA 配置文件

 mkdir /root/ssl
 cd /root/ssl/
 cfssl print-defaults config > config.json
 cfssl print-defaults csr > csr.json
 # 根据config.json 文件的格式创建如下的ca-config.json文件
 #过期时间设置大点876000h 100年
 vim ca-config.json
 {
    "signing": {
        "default": {
            "expiry": "876000h"
        },
        "profiles": {
            "kubernetes": {
                "expiry": "876000h",
                "usages": [
                    "signing",
                    "key encipherment",
                    "server auth",
                    "client auth"
                ]
            }
        }
    }
}

字段说明

  • ca-config.json:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;后续在签名证书时使用某个 profile;

  • signing:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE

  • server auth:表示client可以用该 CA 对server提供的证书进行验证;

  • client auth:表示server可以用该CA对client提供的证书进行验证;

创建 CA 证书签名请求

mv csr.json ca-csr.json
vim ca-csr.json
{
    "CN": "kubernetes",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "BeiJing",
            "ST": "BeiJing",
            "O": "k8s",
            "OU": "System"
        }
    ],
        "ca": {
            "expiry": "876000h"
    }
}
  • "CN":Common Name,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name);浏览器使用该字段验证网站是否合法;
  • "O":Organization,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group);

生成 CA 证书和私钥

cfssl gencert -initca ca-csr.json | cfssljson -bare ca
ls  ca*
ca-config.json  ca.csr  ca-csr.json  ca-key.pem  ca.pem

创建 kubernetes 证书

创建 kubernetes 证书签名请求文件 kubernetes-csr.json

vim kubernetes-csr.json
{
    "CN": "kubernetes",
    "hosts": [
      "127.0.0.1",
      "192.168.76.10",
      "192.168.76.11",
      "192.168.76.14",
      "192.168.76.250",
      "10.7.1.45",
      "192.168.70.21",
      "10.7.4.17",
      "10.254.0.1",
      "kubernetes",
      "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为空配置
vim kubernetes-csr.json
{
    "CN": "kubernetes",
    "hosts": [],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "ST": "BeiJing",
            "L": "BeiJing",
            "O": "k8s",
            "OU": "System"
        }
    ]
}

如果 hosts 字段不为空则需要指定授权使用该证书的 IP 或域名列表,由于该证书后续被 etcd 集群和 kubernetes master

注意: 创建kubernete集群的时候hosts字段一定不能为空。里面需要加etcd 集群和kubernetes master节点的ip。

集群使用,所以上面分别指定了 etcd集群、kubernetes master集群的主机 IP 和 kubernetes服务的服务 IP(一般是 kube-apiserver指定的service-cluster-ip-range网段的第一个IP,如 10.254.0.1)。

其中192.168.76.250 是master节点高可用 keepalive的虚拟ip。如果不加,mater高可用的时候使用vip的时候报证书错误。

生成 kubernetes 证书和私钥

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes
ls kubernetes*
kubernetes.csr  kubernetes-csr.json  kubernetes-key.pem  kubernetes.pem

注意:这里有个坑,服务器装的时候默认装成中文编码,编辑kubernetes-csr.json后,生成kubernetes证书和私钥的时候报错 "code":5200,"message":"failed to unmarshal configuration: invalid character。最后吧服务器编码改后 ,重新从第一步开始就没有报错了。

创建 admin 证书

创建 admin 证书签名请求文件 admin-csr.json

vim admin-csr.json 
{
    "CN": "admin",
    "hosts": [],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "BeiJing",
            "ST": "BeiJing",
            "O": "system:masters",
            "OU": "System"
        }
    ]
}
  • 后续 kube-apiserver使用 RBAC对客户端(如 kubeletkube-proxyPod)请求进行授权;
  • 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中 X509 Client Certs 一段)。

在搭建完 kubernetes 集群后,我们可以通过命令: kubectl get clusterrolebinding cluster-admin -o yaml,查看到 clusterrolebinding cluster-admin 的 subjects 的 kind 是 Group,name 是 system:mastersroleRef对象是 ClusterRole cluster-admin。 意思是凡是 system:masters Group的 user 或者 serviceAccount都拥有 cluster-admin的角色。 因此我们在使用 kubectl 命令时候,才拥有整个集群的管理权限。可以使用 kubectl get clusterrolebinding cluster-admin -o yaml来查看。

生成 admin 证书和私钥:

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin
ls admin*
admin.csr  admin-csr.json  admin-key.pem  admin.pem

创建 kube-proxy 证书

创建 kube-proxy 证书签名请求文件 kube-proxy-csr.json

vim kube-proxy-csr.json
{
    "CN": "system:kube-proxy",
    "hosts": [],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "BeiJing",
            "ST": "BeiJing",
            "O": "k8s",
            "OU": "System"
        }
    ]
}
  • CN 指定该证书的 User 为 system:kube-proxy
  • kube-apiserver预定义的 RoleBinding cluster-admin将User system:kube-proxy与 Role system:node-proxier绑定,该 Role 授予了调用 kube-apiserverProxy 相关 API 的权限;

    生成 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 kube-proxy*
kube-proxy.csr  kube-proxy-csr.json  kube-proxy-key.pem  kube-proxy.pem

校验证书

以 kubernetes 证书为例

使用 opsnssl 命令

openssl x509 -noout -text -in kubernetes.pem 
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            07:a0:70:d7:cb:7b:2b:13:25:05:c6:42:31:0b:ad:af:41:a2:16:2d
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=CN, ST=BeiJing, L=BeiJing, O=k8s, OU=System, CN=kubernetes
        Validity
            Not Before: Apr 24 07:34:00 2018 GMT
            Not After : Mar 31 07:34:00 2118 GMT
        Subject: C=CN, ST=BeiJing, L=BeiJing, O=k8s, OU=System, CN=kubernetes
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:e3:6d:bc:0f:78:fe:23:ed:fc:0c:09:49:51:bb:
                    59:cc:5c:36:75:10:93:38:f4:6c:9e:b7:2f:fd:69:
                    59:de:07:31:a5:fa:19:1f:70:b1:c8:87:8d:dc:c8:
                    40:1d:dc:7b:5e:e4:af:3f:0a:ef:99:86:e6:e3:2a:
                    4c:dd:64:51:3b:b6:4e:c5:e2:d8:88:ba:f2:b2:5e:
                    58:63:6d:1c:2e:3c:e3:29:d6:40:8d:e7:3a:7f:a7:
                    18:20:60:c7:91:9d:b8:4f:bf:aa:83:52:e4:a6:5f:
                    db:7b:2e:c3:02:9e:4b:ba:df:b1:cd:3d:7b:f8:5a:
                    25:99:6e:70:36:da:34:f4:dc:bb:a1:42:e2:c6:ed:
                    91:34:1c:e9:cc:d2:42:ff:c6:ae:ee:0e:51:d0:e2:
                    15:13:5f:11:3b:90:56:b5:1a:e1:5d:a2:6c:0d:f5:
                    87:ec:d5:f1:3b:72:f4:59:b0:71:43:51:85:d3:cb:
                    f7:26:fc:3e:6f:c3:a0:ea:5b:a7:07:cc:9c:56:88:
                    93:bf:84:af:3b:71:6a:20:40:c6:46:5b:24:2e:2c:
                    8d:74:18:f8:88:f1:29:02:ab:ae:fe:0a:93:fe:8d:
                    7d:79:75:b7:24:ad:eb:36:24:07:d8:84:c0:4b:37:
                    1c:17:5c:72:47:a6:df:c4:06:e3:9d:13:0b:e5:b2:
                    2e:0f
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Key Identifier: 
                1A:44:CA:AA:8A:D7:8A:4B:DA:1F:35:D4:91:2A:3E:94:86:B4:FF:27
            X509v3 Authority Key Identifier: 
                keyid:38:1B:C7:93:3F:50:F8:24:BB:57:68:48:17:45:C5:45:C5:F0:52:8F

    Signature Algorithm: sha256WithRSAEncryption
         75:2e:20:9b:24:d1:f9:07:11:a5:51:7f:0e:e3:71:66:a4:fc:
         b5:cc:7f:62:92:63:c2:73:3f:a1:8e:1a:2c:78:d1:33:cf:d9:
         42:85:32:0e:99:de:54:84:82:a8:b7:ad:a7:74:ba:88:c7:f8:
         81:f5:46:b8:d7:4c:e1:3d:0f:2f:53:07:7a:88:ba:df:b1:14:
         0b:34:3c:89:ff:74:4d:16:27:7b:e0:c9:08:2f:e4:48:30:80:
         de:c1:ed:76:df:71:c4:c4:8a:a6:0e:54:fa:9f:6c:cd:de:9a:
         c8:89:42:15:3a:07:b3:53:53:6f:c4:4c:2e:ad:bc:27:60:a4:
         e7:b6:60:3b:0f:d1:e4:bd:b4:1f:b7:b3:6c:5e:2c:dc:cd:70:
         7f:e3:22:d3:02:52:9b:bb:c0:9e:36:b4:bb:8c:d8:07:0f:ec:
         f5:45:86:4c:65:c1:37:90:7a:24:c2:52:56:b8:16:60:93:25:
         fd:07:a6:fb:58:01:98:47:58:bf:ca:82:b7:39:85:bf:79:da:
         39:a9:42:17:9f:72:3e:1c:4c:24:41:d5:c0:b2:98:01:db:5d:
         6f:76:16:86:84:37:af:f0:47:1e:a7:a2:6d:26:b6:9b:0f:c6:
         f3:3d:b6:ff:1b:6f:75:2f:2b:39:93:55:6d:7c:26:f6:6f:d9:
         b3:e2:11:a0
  • 确认Issuer字段的内容和 ca-csr.json一致;
  • 确认 Subject字段的内容和 kubernetes-csr.json一致;
  • 确认 X509v3 Subject Alternative Name字段的内容和 kubernetes-csr.json一致;(hosts为空的话此字段不存在)
  • 确认 X509v3 Key Usage、Extended Key Usage字段的内容和 ca-config.jsonkubernetesprofile 一致;

使用 cfssl-certinfo 命令

cfssl-certinfo -cert kubernetes.pem
{
  "subject": {
    "common_name": "kubernetes",
    "country": "CN",
    "organization": "k8s",
    "organizational_unit": "System",
    "locality": "BeiJing",
    "province": "BeiJing",
    "names": [
      "CN",
      "BeiJing",
      "BeiJing",
      "k8s",
      "System",
      "kubernetes"
    ]
  },
  "issuer": {
    "common_name": "kubernetes",
    "country": "CN",
    "organization": "k8s",
    "organizational_unit": "System",
    "locality": "BeiJing",
    "province": "BeiJing",
    "names": [
      "CN",
      "BeiJing",
      "BeiJing",
      "k8s",
      "System",
      "kubernetes"
    ]
  },
  "serial_number": "43540884634737830840015465603197878486649935405",
  "not_before": "2018-04-24T07:34:00Z",
  "not_after": "2118-03-31T07:34:00Z",
  "sigalg": "SHA256WithRSA",
  "authority_key_id": "38:1B:C7:93:3F:50:F8:24:BB:57:68:48:17:45:C5:45:C5:F0:52:8F",
  "subject_key_id": "1A:44:CA:AA:8A:D7:8A:4B:DA:1F:35:D4:91:2A:3E:94:86:B4:FF:27",
  "pem": "-----BEGIN CERTIFICATE-----\nMIID2TCCAsGgAwIBAgIUB6Bw18t7KxMlBcZCMQutr0GiFi0wDQYJKoZIhvcNAQEL\nBQAwZTELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB0JlaUppbmcxEDAOBgNVBAcTB0Jl\naUppbmcxDDAKBgNVBAoTA2s4czEPMA0GA1UECxMGU3lzdGVtMRMwEQYDVQQDEwpr\ndWJlcm5ldGVzMCAXDTE4MDQyNDA3MzQwMFoYDzIxMTgwMzMxMDczNDAwWjBlMQsw\nCQYDVQQGEwJDTjEQMA4GA1UECBMHQmVpSmluZzEQMA4GA1UEBxMHQmVpSmluZzEM\nMAoGA1UEChMDazhzMQ8wDQYDVQQLEwZTeXN0ZW0xEzARBgNVBAMTCmt1YmVybmV0\nZXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDjbbwPeP4j7fwMCUlR\nu1nMXDZ1EJM49Gyety/9aVneBzGl+hkfcLHIh43cyEAd3Hte5K8/Cu+ZhubjKkzd\nZFE7tk7F4tiIuvKyXlhjbRwuPOMp1kCN5zp/pxggYMeRnbhPv6qDUuSmX9t7LsMC\nnku637HNPXv4WiWZbnA22jT03LuhQuLG7ZE0HOnM0kL/xq7uDlHQ4hUTXxE7kFa1\nGuFdomwN9Yfs1fE7cvRZsHFDUYXTy/cm/D5vw6DqW6cHzJxWiJO/hK87cWogQMZG\nWyQuLI10GPiI8SkCq67+CpP+jX15dbckres2JAfYhMBLNxwXXHJHpt/EBuOdEwvl\nsi4PAgMBAAGjfzB9MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcD\nAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUGkTKqorXikvaHzXU\nkSo+lIa0/ycwHwYDVR0jBBgwFoAUOBvHkz9Q+CS7V2hIF0XFRcXwUo8wDQYJKoZI\nhvcNAQELBQADggEBAHUuIJsk0fkHEaVRfw7jcWak/LXMf2KSY8JzP6GOGix40TPP\n2UKFMg6Z3lSEgqi3rad0uojH+IH1RrjXTOE9Dy9TB3qIut+xFAs0PIn/dE0WJ3vg\nyQgv5EgwgN7B7XbfccTEiqYOVPqfbM3emsiJQhU6B7NTU2/ETC6tvCdgpOe2YDsP\n0eS9tB+3s2xeLNzNcH/jItMCUpu7wJ42tLuM2AcP7PVFhkxlwTeQeiTCUla4FmCT\nJf0HpvtYAZhHWL/Kgrc5hb952jmpQhefcj4cTCRB1cCymAHbXW92FoaEN6/wRx6n\nom0mtpsPxvM9tv8bb3UvKzmTVW18JvZv2bPiEaA=\n-----END CERTIFICATE-----\n"
}

分发证书

将生成的证书和秘钥文件(后缀名为.pem)拷贝到所有机器的 /etc/kubernetes/ssl目录下备用;

results matching ""

    No results matching ""