生成证书的三种方式

根据官方文档,生成k8s秘钥证书及相关管理证书有三种方式,其本质都是通过openssl:

  • cfssl
  • easyrsa
  • openssl

官方文档:https://kubernetes.io/docs/concepts/cluster-administration/certificates/

cfssl方式

1.cfssl下载地址:
1
2
3
4
5
VERSION=R1.2
for i in {cfssl,cfssljson,cfssl-certinfo}
do
wget https://pkg.cfssl.org/${VERSION}/${i}_linux-amd64 -O /usr/local/bin/${i}
done

工具解释

  • sign 签发证书
  • bundle 创建包含客户端证书的证书包
  • genkey 生成私钥和证书请求
  • gencert 生成私钥和证书
  • serve 启动证书服务器
  • version 打印版本
  • selfsign 生成自签证书
  • print-defaults 列出默认命令
2.生成CA配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mkdir ssl && cd ssl
cfssl print-defaults config > config.json
cfssl print-defaults csr > csr.json
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
EOF

这个策略,有一个default默认的配置,和一个profiles,profiles可以设置多个profile,这里的profilekubernetes

  • default默认策略,指定了证书的默认有效期是一年(8760h)
  • kubernetes:表示该配置(profile)的用途是为kubernetes生成证书及相关的校验工作
    • signing:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE
    • server auth:表示可以该CA 对 server 提供的证书进行验证
    • client auth:表示可以用该 CA 对 client 提供的证书进行验证
  • expiry:也表示过期时间,如果不写以default中的为准
3.生成CA签名配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cat > ca-csr.json << EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names":[{
"C": "CN",
"ST": "Beijing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}]
}
EOF
4.生成私钥和证书
1
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
5.创建一个用于生成API Server的密钥和证书的JSON配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
cat > kubernetes-csr.json <<EOF
{
"CN": "kubernetes",
"hosts": [
"127.0.0.1",
"<MASTER_IP>",
"<MASTER_CLUSTER_IP>",
"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"
}]
}
EOF
#该文件需要包含所有使用该证书的ip和域名列表,包括etcd集群、kubernetes master集群、以及apiserver 集群内部cluster ip。

参数介绍:

  • CN: Common Name,浏览器使用该字段验证网站是否合法,一般写的是域名。非常重要。浏览器使用该字段验证网站是否合法
  • key:生成证书的算法
  • hosts:表示哪些主机名(域名)或者IP可以使用此csr申请的证书,为空或者""表示所有的都可以使用(本例中没有hosts字段)
  • names:一些其它的属性
    • C: Country, 国家
    • ST: State,州或者是省份
    • L: Locality Name,地区,城市
    • O: Organization Name,组织名称,公司名称(在k8s中常用于指定Group,进行RBAC绑定)
    • OU: Organization Unit Name,组织单位名称,公司部门
6.生成 kubernetes 证书和私钥
1
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes
7.创建admin证书
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
cat > admin-csr.json <<EOF
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "system:masters",
"OU": "System"
}
]
}
EOF

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin
# 证书O配置为system:masters 在集群内部cluster-admin的clusterrolebinding将system:masters组和cluster-admin clusterrole绑定在一起
8.创建kube-proxy证书
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cat > kube-proxy-csr.json << EOF
{
"CN": "system:kube-proxy",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
# 该证书用户名为system:kube-proxy,预定义的system:node-proxier clusterrolebindings将 system:kube-proxy用户和system:node-proxier角色绑定在一起
9.校验证书信息
1
2
cfssl-certinfo -cert kubernetes.pem
openssl x509 -noout -text -in kubernetes.pem
10.拷贝证书
1
mkdir -p /etc/kubernetes/ssl/ && cp *.pem /etc/kubernetes/ssl/

easyrsa方式

1.下载:
1
curl -L -O https://storage.googleapis.com/kubernetes-release/easy-rsa/easy-rsa.tar.gztar xzf easy-rsa.tar.gzcd easy-rsa-master/easyrsa3./easyrsa init-pki./easyrsa --batch "--req-cn=172.26.6.1@`date +%s`" build-ca nopass
2.生成 kubernetes 证书和私钥
1
./easyrsa --subject-alt-name="IP:172.26.6.1,IP:10.254.0.1,DNS:kubernetes.default" build-server-full kubernetes-master nopass
3.签发admin证书
1
./easyrsa --dn-mode=org --req-cn=admin --req-org=system:masters --req-c= --req-st= --req-city= --req-email= --req-ou= build-client-full admin nopass

openssl方式

1.生成ca
1
2
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -subj "/CN=172.26.6.1" -days 10000 -out ca.crt
2.kubernetes证书和私钥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
openssl genrsa -out server.key 2048
cat >csr.conf <<EOF
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[ dn ]
C = <country>
ST = <state>
L = <city>
O = <organization>
OU = <organization unit>
CN = 172.26.6.1

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.cluster
DNS.5 = kubernetes.default.svc.cluster.local
IP.1 = 172.26.6.1
IP.2 = 10.254.0.1

[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth,clientAuth
subjectAltName=@alt_names
EOF

openssl req -new -key server.key -out server.csr -config csr.conf
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 10000 -extensions v3_ext -extfile csr.conf
openssl x509 -noout -text -in ./server.crt
3.admin证书
1
2
3
openssl genrsa -out admin.key 2048
openssl req -new -key admin.key -out admin.csr -subj "/O=system:masters/CN=dmin"
openssl x509 -req -set_serial $(date +%s%N) -in admin.csr -CA ca.crt -CAkey ca.key -out admin.crt -days 365 -extensions v3_req -extfile req.conf