官方文档中, 对 k8s 的证书制作提供了三种方式, 主流使用有两种
- openssl
- cfssl
具体证书制作步骤在此就不详细说明, 重点注意参考官方文档, 使用 openssl 方式制作证书时需要注意的事项
官方文档中, 使用 OpenSSL 制作证书, 在 KeyUsage 的设置上, 指定了如下功能:
1 | keyUsage=keyEncipherment,dataEncipherment |
在制作完 crt 证书后, 使用 openssl x509 -in /path/to/xxx.crt -text -noout
命令查看证书信息:
1 | X509v3 Key Usage: |
没毛病, 就是之前指定的两个功能, 一个不多一个不少, 但问题也出现在这里.
在实际使用中, 使用仅带有keyUsage=keyEncipherment,dataEncipherment
这两个功能的证书引导集群, 并没有出现什么问题, 但是在使用 Java 客户端访问 apiserver 时, 却报以下错误:
1 | io.kubernetes.client.ApiException: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: KeyUsage does not allow digital signatures |
报错信息很明确, 证书没有提供digital signatures
的功能. 查询另一篇证书说明文档(https://kubernetes.io/docs/setup/certificates/) 里面说的很清楚
1 | kind Key usage |
不管是服务端证书还是客户端证书, 都至少需要提供digital signature, key encipherment
这两个功能, 但是制作证书的官方文档中, openssl 方式创建的证书, 却没有显式指定 digital signatures
功能. 在后期的制作中, openssl 也没有默认给我们加入此功能, 结果导致 java 客户端无法完成 ssl 认证.
但是官方文档中, 使用 cfssl 工具也没有显示指定加入 digital signatures
功能, 但是制作证书时, 默认为我们加入了该功能. 就冲这点, 也强烈建议使用 cfssl 工具制作证书😆
解决方法:
- 使用 openssl 签发证书的话, 将
keyUsage=keyEncipherment,dataEncipherment
修改为–>keyUsage=digitalSignature,keyEncipherment,dataEncipherment
即可 - 使用 cfssl 签发证书, 默认就会加入
digitalSignature
功能
解决方案:
方案一: 重新制作所有证书, 加入digital signatures
功能, 并为集群更换证书
方案二: 重新制作 apiserver 服务端证书和 java 客户端使用的客户端证书, 加入digital signatures
功能, 替换所有 apiserver 和 java 使用的证书, 即可完成最小代价的替换
附录:
1 | KeyUsage ::= BIT STRING { |
参考文档:
k8s证书制作文档
- 中文文档: https://k8smeetup.github.io/docs/concepts/cluster-administration/certificates/#openssl
- 英文文档: https://kubernetes.io/docs/concepts/cluster-administration/certificates/
k8s证书使用说明文档
KeyUsage 文档: