k8s 集群搭建-02-二进制安装-生成证书

一、生成证书

0. 安装cfssl

cfssl是非常好用的CA工具,我们用它来生成证书和秘钥文件,在node-1节点执行如下安装命令:
安装过程比较简单,如下:

# 下载
$ wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O /usr/local/bin/cfssl
$ wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -O /usr/local/bin/cfssljson

# 修改为可执行权限
$ chmod +x /usr/local/bin/cfssl /usr/local/bin/cfssljson

# 验证
[root@hombd03 softwards]# cfssl version
Version: 1.2.0
Revision: dev
Runtime: go1.6

1. 根证书

根证书是集群所有节点共享的,只需要创建一个 CA 证书,后续创建的所有证书都由它签名。
在任意节点(可以免密登录到其他节点,这里选择node1节点)创建一个单独的证书目录,如:mkdir pki && cd pki

cd ~
mkdir pki && cd pki

[root@hombd03 pki]# pwd
/root/pki

根证书配置文件

$ cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "876000h"
    },
    "profiles": {
      "kubernetes": {
        "usages": ["signing", "key encipherment", "server auth", "client auth"],
        "expiry": "876000h"
      }
    }
  }
}
EOF

$ cat > ca-csr.json <<EOF
{
  "CN": "Kubernetes",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "US",
      "L": "Portland",
      "O": "Kubernetes",
      "OU": "CA",
      "ST": "Oregon"
    }
  ]
}
EOF

生成证书和私钥

# 生成证书和私钥
$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca
# 生成完成后会有以下文件(我们最终想要的就是ca-key.pem和ca.pem,一个秘钥,一个证书)

[root@hombd03 pki]# ls -l
total 20
-rw-r--r--. 1 root root  236 Jun  4 00:31 ca-config.json
-rw-r--r--. 1 root root 1005 Jun  4 00:33 ca.csr
-rw-r--r--. 1 root root  211 Jun  4 00:31 ca-csr.json
-rw-------. 1 root root 1679 Jun  4 00:33 ca-key.pem
-rw-r--r--. 1 root root 1367 Jun  4 00:33 ca.pem
[root@homaybd03 pki]# 

2. admin客户端证书

admin客户端证书配置文件

$ cat > admin-csr.json <<EOF
{
  "CN": "admin",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "system:masters",
      "OU": "seven"
    }
  ]
}
EOF

生成admin客户端证书和私钥

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

3. kubelet客户端证书

Kubernetes使用一种称为Node Authorizer的专用授权模式来授权Kubelets发出的API请求。 Kubelet使用将其标识为system:nodes组中的凭据,其用户名为system:node:nodeName,接下里就给每个工作节点生成证书。

生成kubelet客户端证书和私钥

# 设置你的worker节点列表
$ WORKERS=(node-2 node-3)
$ WORKER_IPS=(10.155.19.64 10.155.19.147)
# 生成所有worker节点的证书配置
$ for ((i=0;i<${#WORKERS[@]};i++)); do
cat > ${WORKERS[$i]}-csr.json <<EOF
{
  "CN": "system:node:${WORKERS[$i]}",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "Beijing",
      "O": "system:nodes",
      "OU": "seven",
      "ST": "Beijing"
    }
  ]
}
EOF
cfssl gencert \
  -ca=ca.pem \
  -ca-key=ca-key.pem \
  -config=ca-config.json \
  -hostname=${WORKERS[$i]},${WORKER_IPS[$i]} \
  -profile=kubernetes \
  ${WORKERS[$i]}-csr.json | cfssljson -bare ${WORKERS[$i]}
done

需要将上述的节点名称和IP改为自己本机的,实际执行命令:

# 设置你的worker节点列表
$ WORKERS=(homaybd04 homaybd05)
$ WORKER_IPS=(192.168.1.124 192.168.1.125)

$ for ((i=0;i<${#WORKERS[@]};i++)); do
cat > ${WORKERS[$i]}-csr.json <<EOF
{
  "CN": "system:node:${WORKERS[$i]}",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "Beijing",
      "O": "system:nodes",
      "OU": "seven",
      "ST": "Beijing"
    }
  ]
}
EOF
cfssl gencert \
  -ca=ca.pem \
  -ca-key=ca-key.pem \
  -config=ca-config.json \
  -hostname=${WORKERS[$i]},${WORKER_IPS[$i]} \
  -profile=kubernetes \
  ${WORKERS[$i]}-csr.json | cfssljson -bare ${WORKERS[$i]}
done

查看:

[root@hombd03 pki]# ls -l
total 68
-rw-r--r--. 1 root root 1009 Jun  4 00:36 admin.csr
-rw-r--r--. 1 root root  213 Jun  4 00:35 admin-csr.json
-rw-------. 1 root root 1679 Jun  4 00:36 admin-key.pem
-rw-r--r--. 1 root root 1407 Jun  4 00:36 admin.pem
-rw-r--r--. 1 root root  236 Jun  4 00:31 ca-config.json
-rw-r--r--. 1 root root 1005 Jun  4 00:33 ca.csr
-rw-r--r--. 1 root root  211 Jun  4 00:31 ca-csr.json
-rw-------. 1 root root 1679 Jun  4 00:33 ca-key.pem
-rw-r--r--. 1 root root 1367 Jun  4 00:33 ca.pem
-rw-r--r--. 1 root root 1025 Jun  4 00:43 homaybd04.csr
-rw-r--r--. 1 root root  227 Jun  4 00:43 homaybd04-csr.json
-rw-------. 1 root root 1679 Jun  4 00:43 homaybd04-key.pem
-rw-r--r--. 1 root root 1464 Jun  4 00:43 homaybd04.pem
-rw-r--r--. 1 root root 1025 Jun  4 00:43 homaybd05.csr
-rw-r--r--. 1 root root  227 Jun  4 00:43 homaybd05-csr.json
-rw-------. 1 root root 1679 Jun  4 00:43 homaybd05-key.pem
-rw-r--r--. 1 root root 1464 Jun  4 00:43 homaybd05.pem
[root@hombd03 pki]# 

4. kube-controller-manager客户端证书

kube-controller-manager客户端证书配置文件

继续在 node-1 节点执行:

$ cat > kube-controller-manager-csr.json <<EOF
{
    "CN": "system:kube-controller-manager",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
      {
        "C": "CN",
        "ST": "BeiJing",
        "L": "BeiJing",
        "O": "system:kube-controller-manager",
        "OU": "seven"
      }
    ]
}
EOF

生成kube-controller-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

5. kube-proxy客户端证书

kube-proxy客户端证书配置文件

$ cat > kube-proxy-csr.json <<EOF
{
  "CN": "system:kube-proxy",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "seven"
    }
  ]
}
EOF

生成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

6. kube-scheduler客户端证书

kube-scheduler客户端证书配置文件

$ cat > kube-scheduler-csr.json <<EOF
{
    "CN": "system:kube-scheduler",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
      {
        "C": "CN",
        "ST": "BeiJing",
        "L": "BeiJing",
        "O": "system:kube-scheduler",
        "OU": "seven"
      }
    ]
}
EOF

生成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

7. kube-apiserver服务端证书

kube-apiserver服务端证书配置文件

$ cat > kubernetes-csr.json <<EOF
{
  "CN": "kubernetes",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "seven"
    }
  ]
}
EOF

生成kube-apiserver服务端证书

服务端证书与客户端略有不同,客户端需要通过一个名字或者一个ip去访问服务端,所以证书必须要包含客户端所访问的名字或ip,用以客户端验证。

# apiserver的service ip地址(一般是svc网段的第一个ip),虚拟IP
# $ KUBERNETES_SVC_IP=10.233.0.1
$ KUBERNETES_SVC_IP=192.233.0.1  
# 所有的master内网ip,逗号分隔(云环境可以加上master公网ip以便支持公网ip访问),这里多写没关系,万一后边node-3会作为master节点
$ MASTER_IPS=192.168.1.123,192.168.1.124,192.168.1.125
# 生成证书
$ cfssl gencert \
  -ca=ca.pem \
  -ca-key=ca-key.pem \
  -config=ca-config.json \
  -hostname=${KUBERNETES_SVC_IP},${MASTER_IPS},127.0.0.1,kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster,kubernetes.svc.cluster.local \
  -profile=kubernetes \
  kubernetes-csr.json | cfssljson -bare kubernetes

8. Service Account证书

配置文件

$ cat > service-account-csr.json <<EOF
{
  "CN": "service-accounts",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "seven"
    }
  ]
}
EOF

生成证书

$ cfssl gencert \
  -ca=ca.pem \
  -ca-key=ca-key.pem \
  -config=ca-config.json \
  -profile=kubernetes \
  service-account-csr.json | cfssljson -bare service-account

9. proxy-client 证书

配置文件

$ cat > proxy-client-csr.json <<EOF
{
  "CN": "aggregator",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "seven"
    }
  ]
}
EOF

生成证书

$ cfssl gencert \
  -ca=ca.pem \
  -ca-key=ca-key.pem \
  -config=ca-config.json \
  -profile=kubernetes \
  proxy-client-csr.json | cfssljson -bare proxy-client

10. 分发客户端、服务端证书

分发worker节点需要的证书和私钥

for instance in ${WORKERS[@]}; do
  scp ca.pem ${instance}-key.pem ${instance}.pem root@${instance}:~/
done

分发master节点需要的证书和私钥

注意:由于下面分发的证书即包含了etcd的证书也包含了k8s主节点的证书。
所以 MASTER_IPS 中必须包含所有 master 节点以及 etcd 节点。如果没有包含所有etcd节点的证书,需要重新定义,逗号分隔

OIFS=$IFS
IFS=','
for instance in ${MASTER_IPS}; do
  scp ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \
    service-account-key.pem service-account.pem proxy-client.pem proxy-client-key.pem root@${instance}:~/
done
IFS=$OIFS

为者常成,行者常至