在创建pod时,经常会出现如下问题:
E0522 15:22:33.202410 7 authentication.go:64] Unable to authenticate the request due to an error: [invalid bearer token, [invalid bearer token, crypto/rsa: verification error]]
这个问题是在三个master节点生成了不同的 server.key 引起,由于 server.key 需要在 apiserver 启动时指定,在生成 service account 时会采用公钥认证。
在pod创建后,默认会在目录/var/run/secrets/kubernetes.io/serviceaccount/
生成token及 ca.crt 等。
如下所示:
[appuser@k8s-master-1 ~]$ kubectl -n helloworld exec -it nginx-hello-deployment-6d645cbbcb-kc52t sh
sh-4.1# cd /var/run/secrets/kubernetes.io/serviceaccount/
sh-4.1# ls
ca.crt namespace token
解决方法:在三个master节点统一的server.key即可。
为了解决多集群部署问题,统一使用提前生成好的ca.crt/ca.key作为root证书,由于这个证书是提前生成好的,在部署的时候所有集群就不需要重新生成不同的证书,直接使用该证书即可。
k8s 需要生成统一的 server.key 来做为私钥,一般的做法是在三台中的某台主机上生成 server.key (openssl genrsa -out server.key 2048
),
然后将生成的server.key scp
到其他两台master节点,但这样在部署的时候并不方便,特别是需要跳板机的用户环境,为了解决这个问题,直接将 ca.key 做为 server.key
即可。
在生成证书时,使用每个主机的 hostname 做为 subj
字段,这样就会生成不一样的 server.csr,然后结合 ca.crt/ca.key 就可以生成不同的 server.crt,这样每个集群的证书也就不一样了,防止了安全问题发生。
diff --git a/roles/k8smaster/files/create-master-crt.sh b/roles/k8smaster/files/create-master-crt.sh
index 948104b..d25e8ad 100644
--- a/roles/k8smaster/files/create-master-crt.sh
+++ b/roles/k8smaster/files/create-master-crt.sh
@@ -4,7 +4,7 @@ cd `dirname $0`
HN=`hostname`
echo "generate apiserver key & cert"
-openssl genrsa -out server.key 2048
+cp ca.key server.key
openssl req -new -key server.key -subj "/CN=$HN" -config master_ssl.cnf -out server.csr
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 5000 -extensions v3_req -extfile master_ssl.cnf -out server.crt
大概使用openssl来生成apiserver的证书如下:
使用 openssl 能够手动地为集群生成证书。
1、生成密钥位数为 2048 的 ca.key:
openssl genrsa -out ca.key 2048
2、依据 ca.key 生成 ca.crt (使用 -days 参数来设置证书有效时间):
openssl req -x509 -new -nodes -key ca.key -subj "/CN=${MASTER_IP}" -days 10000 -out ca.crt
3、生成密钥位数为 2048 的 server.key:
openssl genrsa -out server.key 2048
4、创建用于生成证书签名请求(CSR)的配置文件。 确保在将其保存至文件(如csr.conf)之前将尖括号标记的值(如<MASTER_IP>
) 替换为你想使用的真实值。 注意:MASTER_CLUSTER_IP
是前面小节中描述的 API 服务器的服务集群 IP (service cluster IP)。 下面的示例也假设用户使用 cluster.local 作为默认的 DNS 域名。
[ 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 = <MASTER_IP>
[ 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 = <MASTER_IP>
IP.2 = <MASTER_CLUSTER_IP>
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth,clientAuth
subjectAltName=@alt_names
5、基于配置文件生成证书签名请求:
openssl req -new -key server.key -out server.csr -config csr.conf
6、使用 ca.key、ca.crt 和 server.csr 生成服务器证书:
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out server.crt -days 10000 \
-extensions v3_ext -extfile csr.conf
7、查看证书:
openssl x509 -noout -text -in ./server.crt
最后,添加同样的参数到 API 服务器的启动参数中。