在编写一个准入 Webhook 服务时,需要配置相关证书,k8s 提供了 api 用于对用户自主创建的证书进行认证签发。以下部分演示为 Webhook 服务创建 TLS 证书。
创建 TLS 证书
创建你的证书
通过运行以下命令生成私钥:
1 | cat <<EOF | cfssl genkey - | cfssljson -bare server |
此命令生成两个文件;它生成包含 PEM 编码 PKCS#10 证书请求的 server.csr, 以及 PEM 编码密钥的 server-key.pem,用于待生成的证书。
创建证书签名请求(CSR)
1 | cat <<EOF | kubectl apply -f - |
你能看到的输出类似于:
1 | certificatesigningrequest.certificates.k8s.io/example created |
Warning: certificates.k8s.io/v1beta1 CertificateSigningRequest is deprecated in v1.19+, unavailable in v1.22+; use certificates.k8s.io/v1 CertificateSigningRequest
CSR 处于 Pending 状态。执行下面的命令你将可以看到:
1 | kubectl get csr |
1 | NAME AGE SIGNERNAME REQUESTOR CONDITION |
批准证书签名请求(CSR)
1 | kubectl certificate approve example |
1 | certificatesigningrequest.certificates.k8s.io/example approved |
你现在应该能看到如下输出:
1 | kubectl get csr |
1 | NAME AGE SIGNERNAME REQUESTOR CONDITION |
下载证书并使用它
1 | kubectl get csr example -o jsonpath='{.status.certificate}' | base64 --decode > server.crt |
现在你可以将 server.crt 和 server-key.pem 作为你的服务的 https 认证了。
例如 kubebuilder 中使用 TLS 证书,将 server.crt 和 server-key.pem 放在 cert 目录中并修改名称为 tls.crt 和 tls.key,然后指定证书目录:
1 | mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ |
从 v1beta1 迁移到 v1
上述例子使用 certificates.k8s.io/v1beta1 API 版本的 CertificateSigningRequest 不在 v1.22 版本中继续提供。官方迁移指南点这里。 我们可以使用 certificates.k8s.io/v1 API 版本,此 API 从 v1.19 版本开始可用。
•certificates.k8s.io/v1 中需要额外注意的变更:
•对于请求证书的 API 客户端而言:
•spec.signerName 现在变成必需字段(参阅 已知的 Kubernetes 签署者), 并且通过 certificates.k8s.io/v1 API 不可以创建签署者为 kubernetes.io/legacy-unknown 的请求
•spec.usages 现在变成必需字段,其中不可以包含重复的字符串值, 并且只能包含已知的用法字符串
创建你的证书
通过运行以下命令生成私钥:
1 | cat <<EOF | cfssl genkey - | cfssljson -bare server |
创建证书签名请求(CSR)
这里 csr signerName 不能是 kubernetes.io/legacy-unknown,演示我们随便指定一个为 example.com/serving,v1beta1 版本默认是 kubernetes.io/legacy-unknown。
1 | cat <<EOF | kubectl apply -f - |
批准证书签名请求(CSR)
1 | kubectl certificate approve example |
1 | certificatesigningrequest.certificates.k8s.io/example approved |
你现在应该能看到如下输出:
1 | kubectl get csr |
1 | NAME AGE SIGNERNAME REQUESTOR CONDITION |
这里可以看到证书请求已被批准,但是没有自动签名,正在等待请求的签名者对其签名。
签名证书签名请求(CSR)
我们扮演证书签署者的角色,颁发证书并将其上传到 API 服务器。
创建证书颁发机构
通过运行以下命令创建签名证书:
1 | cat <<EOF | cfssl gencert -initca - | cfssljson -bare ca |
这会产生一个证书颁发机构密钥文件(ca-key.pem)和证书(ca.pem)。
颁发证书
创建文件 server-signing-config.json 内容如下:
1 | { |
使用 server-signing-config.json 签名配置、证书颁发机构密钥文件和证书来签署证书请求:
1 | kubectl get csr example -o jsonpath='{.spec.request}' | \ |
这会生成一个签名的服务证书文件,ca-signed-server.pem。
上传签名证书
1 | kubectl get csr example -o json | \ |
批准 CSR 并上传签名证书后,你现在应该能看到如下输出:
1 | kubectl get csr |
1 | NAME AGE SIGNERNAME REQUESTOR CONDITION |
这是你可以正常下载证书并使用它了。
参考文档
•https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/certificate-signing-requests/
•https://kubernetes.io/zh-cn/docs/tasks/tls/managing-tls-in-a-cluster/#configuring-your-cluster-to-provide-signing
•https://kubernetes.io/zh-cn/docs/reference/using-api/deprecation-guide/