MiniO KES(密钥加密服务)是 MinIO 开发的一项服务,旨在弥合在 Kubernetes 中运行的应用程序与集中式密钥管理服务 (KMS) 之间的差距。中央 KMS 服务器包含所有状态信息,而 KES 在需要执行与获取新密钥或更新现有密钥相关的任何操作时与 KMS 通信。一旦它获取了密钥,只要不需要更新或删除它,它就会缓存在 KES 中,因此后续调用会快得多。
那么,为什么要使用 KES 而不是直接使用 KMS?根据所使用的 KMS 及其需要处理的负载,有时 KMS 系统没有能力或支持来处理大型部署,在这些部署中,它必须来回管理数百甚至数千个密钥,而 Kubernetes 集群会给它们带来巨大的负载。在这些情况下,使用 KES 至关重要,因为它可以非常轻松地进行水平扩展,这与传统的 KMS 系统不同。
应用程序 <-> KES 之间以及 KES <-> KMS 之间的所有 KES 操作都使用 mTLS 身份验证进行身份验证和授权功能。这是使用一对公钥/私钥和 X.509 证书完成的。证书的问题是它们有一个非常普遍的问题,它们往往会过期,当它们过期时,周围的服务都会以几乎没有韵律或理由的方式失败。这是什么意思?
我们的意思是,一旦证书过期,您将开始在 KES 日志中看到此类错误
{"message":"2024/01/04 02:23:21 http: TLS handshake error from 10.244.2.9:32816: remote error: tls: bad certificate"}
{"message":"2024/01/04 02:23:28 http: TLS handshake error from 10.244.3.11:53456: remote error: tls: bad certificate"}
{"message":"2024/01/04 02:23:28 http: TLS handshake error from 10.244.1.9:56722: remote error: tls: bad certificate"}
{"message":"2024/01/04 02:23:28 http: TLS handshake error from 10.244.4.11:34152: remote error: tls: bad certificate"}
{"message":"2024/01/04 02:23:28 http: TLS handshake error from 10.244.2.9:55300: remote error: tls: bad certificate"}
{"message":"2024/01/04 02:23:28 http: TLS handshake error from 10.244.4.11:34160: remote error: tls: bad certificate"}
此外,当 MinIO 尝试执行定期 IAM 刷新时,这些刷新也会失败,并在 MinIO 日志中显示以下消息
Error: Failure in periodic refresh for IAM (took 0.03s): Post "https://kes-tenant-kes-hl-svc.default.svc.cluster.local:7373/v1/key/decrypt/my-minio-key": x509: certificate has expired or is not yet valid: current time 2024-01-04T02:27:31Z is after 2024-01-04T02:12:40Z (*errors.errorString)
如果幸运的话,您会看到一条明显的消息,例如 certificate has expired
.其他时候,它并不那么明显,在尝试创建或删除密钥时,您还可能会看到边缘情况问题以及许多其他问题。最快的解决方案是尽快使用新证书续订和更新 KES。在这篇文章中,我们将向您展示如何做到这一点。
如何续费
让我们首先创建一个新的私钥
openssl genrsa -out private.key 2048
创建一个名为 cert.cnf
的文件,该文件将用于 openssl
创建证书签名请求 (CSR)
[req]
distinguished_name = req_distinguished_name
req_extensions = req_ext
prompt = no
[req_distinguished_name]
O = "system:nodes"
C = US
CN = "system:node:*.kes-tenant-kes-hl-svc.default.svc.cluster.local"
[req_ext]
subjectAltName = @alt_names
[alt_names]
DNS.1 = kes-tenant-kes-0.kes-tenant-kes-hl-svc.default.svc.cluster.local
DNS.2 = kes-tenant-kes-hl-svc.default.svc.cluster.local
请务必修改 Common Name CN 和 Subject Alternative Names SAN (在 下 [alt_names] ),以匹配 KES 节点的 FQDN。请务必使用正确的 FQDN,而不是 IP 地址。
使用以下命令创建 CSR
openssl req -new -config cert.cnf -key private.key -out kes.csr
将 CSR 转换为编码字符串,以便将其作为 CertificateSigningRequest 资源添加到 Kubernetes。
cat kes.csr | base64 | tr -d "\n"
使用以下内容创建一个文件 kes-csr.yaml ,并将上述编码的 CSR 粘贴到 request 字段中。证书已被截断,因此您可以看到整个 yaml。
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: kes-csr
spec:
expirationSeconds: 604800
groups:
- system:serviceaccounts
- system:serviceaccounts:minio-operator
- system:authenticated
- system:nodes
request: LS0tLS1CRUdJTiBDRV…FUVVFU1QtLS0tLQo=
signerName: kubernetes.io/kubelet-serving
usages:
- digital signature
- key encipherment
- server auth
username: system:serviceaccount:minio-operator:minio-operator
添加编码的 CSR 并设置其他设置后,应用 yaml。
kubectl apply -f kes-csr.yaml
请务必批准上面创建的 kes-csr CSR
kubectl certificate approve kes-csr
从 csr
资源获取公共证书
kubectl get csr kes-csr -o jsonpath='{.status.certificate}'| base64 -d > public.crt
将(从过程开始)和 private.key public.crt (从上一步开始)转换为编码字符串。
cat private.key | base64 | tr -d "\n"
cat public.crt | base64 | tr -d "\n"
使用上面的编码字符串,我们将更新现有的 Secret
kes-tenant-kes-tls
,为此,请按照以下步骤操作。
复制现有过期证书所在的现有密钥。
kubectl get secret kes-tenant-kes-tls -o yaml > kes-tls-secret.yaml
备份现有密钥后,将其删除
kubectl delete secret kes-tenant-kes-tls
使用过期的证书打开 kes-tls-secret.yaml
,并将以下两个字段替换为其各自的 base64 编码字符串。
data:
private.key: >-
LS0tLS1CRUd…ZLS0tLS0
public.crt: >-
LS0tLS1CRUdJTi…tLS0K
添加新证书后,应用 , Secret
这将重新创建 kes-tenant-kes-tls
kubectl apply -f kes-tls-secret.yaml
添加有效证书后,请务必重启 KES 服务,应看到如下所示的输出:
'http://vault.default.svc.cluster.local:8200' ...
Endpoint: https://127.0.0.1:7373 https://10.244.4.16:7373
Admin: _ [ disabled ]
Auth: off [ any client can connect but policies still apply ]
Keys: Hashicorp Vault: http://vault.default.svc.cluster.local:8200
CLI: export KES_SERVER=https://127.0.0.1:7373
export KES_CLIENT_KEY= // e.g. $HOME/root.key
export KES_CLIENT_CERT= // e.g. $HOME/root.cert
kes --help
MinIO 日志也应该是干净的,不应再显示任何 TLS 错误。
Waiting for all MinIO sub-systems to be initialized.. lock acquired
Automatically configured API requests per node based on available memory on the system: 221
All MinIO sub-systems initialized successfully in 15.44125ms
MinIO Object Storage Server
Copyright: 2015-2024 MinIO, Inc.
License: GNU AGPLv3
Version: RELEASE.2024-01-04T09-40-09Z (go1.19.4 linux/arm64)
Status: 4 Online, 0 Offline.
API: https://minio.default.svc.cluster.local
Console: https://10.244.3.12:9443 https://127.0.0.1:9443
Documentation: https://min.io/docs/minio/linux/index.html
最后的思考
在管理用于加密对象的密钥时,KES 是一个不可或缺的部分。以最快的方式对对象进行加密和解密非常重要,因为执行这些操作所需的每纳秒,最终用户获取对象的速度就会慢得多。是的,最终,低效和缓慢的 KMS 系统会降低集群的整体性能。因此,确保执行这些操作的服务快速、精简、高性能和可扩展至关重要。MinIO 的 KES 使任何 KMS 都成为高性能和可扩展的服务,而无需对现有 KMS 进行任何修改。按照上述步骤操作,您可以立即让 KES 恢复到拥有有效的未过期证书!