1. 环境准备
本文档基于以下环境:
- System:Windows;
- IDE:GoLand;
1.1 apiserver
1.1.1 etcd
-
下载 etcd:github.com/etcd-io/etc…
-
解压;
-
启动 etcd:.\etcd.exe
-
在启动参数中指定 etcd
--etcd-servers=127.0.0.1:2379
1.1.2 证书
需要的文件 ext.conf:
[ca]
basicConstraints=critical,CA:true
extendedKeyUsage=serverAuth,clientAuth
[apiserver]
subjectAltName=DNS:kubernetes,DNS:kubernetes.default,DNS:kubernetes.default.svc,DNS:kubernetes.default.svc.cluster,DNS:kubernetes.default.svc.cluster.local,IP:127.0.0.1,IP:10.96.0.1,IP:192.168.0.1
所有命令如下:
# ca
openssl genrsa -out ca.key 2048
openssl req -new -key ca.key -out ca.csr -subj "/CN=Kubernetes CA" -addext "basicConstraints=critical,CA:TRUE"
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt -days 365 -extfile ext.conf -extensions ca
# apiserver
openssl genrsa -out apiserver.key 2048
openssl req -new -key apiserver.key -out apiserver.csr -subj "/CN=kubernetes"
openssl x509 -req -in apiserver.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out apiserver.crt -days 365 -extfile ext.conf -extensions apiserver
# kubelet
openssl genrsa -out kubelet.key 2048
openssl req -new -key kubelet.key -out kubelet.csr -subj "/CN=node1" -addext "subjectAltName = IP:10.0.0.2,DNS:node1"
openssl x509 -req -in kubelet.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out kubelet.crt -days 365
# service-account
openssl genrsa -out service-account.key 2048
openssl rsa -in service-account.key -pubout -out service-account.pub
接下来进行说明。
-
安装 openssl
-
生成 CA 证书和私钥
-
生成 CA 私钥
openssl genrsa -out ca.key 2048这将生成一个 2048 位的 RSA 私钥,保存为
ca.key文件。 -
生成 CA 证书签名请求(CSR)
openssl req -new -key ca.key -out ca.csr -subj "/CN=Kubernetes CA"这里
-subj参数指定了证书的主题,CN是证书的通用名称,你可以根据需要修改。 -
自签名 CA 证书
创建 extension 文件,写入以下信息:
[ca] basicConstraints=critical,CA:true extendedKeyUsage=serverAuth,clientAuth [apiserver] subjectAltName=DNS:kubernetes,DNS:kubernetes.default,DNS:kubernetes.default.svc,DNS:kubernetes.default.svc.cluster,DNS:kubernetes.default.svc.cluster.local,IP:127.0.0.1,IP:10.96.0.1,IP:192.168.0.1其中 ca 项是 ca 证书会用到的,主要表明是一个 ca 证书,apiserver 项是后面 apiserver 会用到的,要注意的是 192.168.0.1 是apiserver的访问地址。
使用 CA 私钥对 CA 证书签名请求进行签名,生成一个有效期为 365 天的 CA 证书
ca.crt,并添加 ca extension:openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt -days 365 -extfile ext.conf -extensions ca
-
-
生成 apiserver 证书和私钥
-
生成 apiserver 私钥
openssl genrsa -out apiserver.key 2048 -
生成 apiserver 证书签名请求(CSR)
openssl req -new -key apiserver.key -out apiserver.csr -subj "/CN=kubernetes"这里
-subj参数指定了证书的主题,CN是证书的通用名称。-addext参数用于添加扩展名,指定 apiserver 的 DNS 名称和 IP 地址。你需要根据实际情况替换10.96.0.1为你的 apiserver 服务的 IP 地址。 -
使用 CA 证书签名 apiserver 证书
openssl x509 -req -in apiserver.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out apiserver.crt -days 365 -extfile ext.conf -extensions apiserver这将使用 CA 证书和私钥对 apiserver 的证书签名请求进行签名,生成一个有效期为 365 天的 apiserver 证书
apiserver.crt。
-
-
生成 service-account 验证文件
-
生成私钥文件
openssl genrsa -out service-account.key 2048 -
生成公钥文件
openssl rsa -in service-account.key -pubout -out service-account.pub
-
-
生成 kubectl 证书
为后续 curl 命令生成需要的证书,和 apiserver 几乎一致(不想创建的话,后面直接使用 apiserver 的证书):
openssl genrsa -out kubelet.key 2048 openssl req -new -key kubelet.key -out kubelet.csr -subj "/CN=node1" -addext "subjectAltName = IP:10.0.0.2,DNS:node1" openssl x509 -req -in kubelet.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out kubelet.crt -days 365 -
验证证书
你可以使用以下命令验证生成的证书:
openssl x509 -in apiserver.crt -text -noout这将显示 apiserver 证书的详细信息,包括主题、颁发者、有效期和扩展名等。
-
配置 kube-apiserver
在 apiserver 的启动参数中指定证书和私钥的路径,例如:
--tls-cert-file=${your_path}/apiserver.crt --tls-private-key-file=${your_path}/apiserver.key --client-ca-file=${your_path}/ca.crt --service-account-issuer=https://kubernetes.default.svc.cluster.local --api-audiences=https://kubernetes.default.svc.cluster.local --service-account-signing-key-file=${your_path}/service-account.key --service-account-key-file=${your_path}/service-account.pubGoLand 配置位置为:
1.1.3 验证
-
启动 etcd 后 再启动 apiserver;
-
调用接口:
curl --cacert ./ca.crt --cert ./kubelet.crt --key ./kubelet.key "https://192.168.0.1:6443/api/v1/pods"结果为:
1.1.4 问题记录
-
windows 的 curl 命令不是平常理解上的 curl 命令,是 Invoke-WebRequest 的别名。
取消别名,下载 curl 命令(推荐使用 scoop)。
-
curl: (58) schannel: Failed to import cert file .\kubelet.crt, last error is 0x80092002
curl 版本有问题(
curl 8.9.1 (Windows)),删除系统的curl(C:\Windows\System32),使用scoop重新安装(8.11.1 (x86_64-w64-mingw32))。 -
访问 apiserver 时返回码为401。
在生成 openssla csr 的时候使用 -addext 参数添加 extension,但实际生成的 ca 证书没有 basicConstraints=critical,CA:true 这一项,导致报错:invalid signature: parent certificate cannot sign this kind of certificate " while trying to verify candidate authority certificate "Kubernetes CA" ",最后通过在生成 crt 的时候使用 -extfile 添加extension。
该逻辑代码具体位置为:go1.23.0/src/crypto/x509/parser.go#processExtensions
func processExtensions(out *Certificate) error { var err error for _, e := range out.Extensions { unhandled := false if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 { switch e.Id[3] { ... case 19: out.IsCA, out.MaxPathLen, err = parseBasicConstraintsExtension(e.Value) if err != nil { return err } out.BasicConstraintsValid = true out.MaxPathLenZero = out.MaxPathLen == 0 ... } } ... } return nil }在添加了 basicConstraints=critical,CA:true 的 extension 之后会在证书的 IsCA 置为 true,后续验证客户端证书的签发信息的时候会用到,若 ca 证书的 IsCA 为 false 则会返回 401。