作者:来自 Elastic Anand Vyas

无需手动续订证书,通过 Vault 使用在 Kubernetes 外部密封的 CA 密钥 进行签名,并由 cert-manager 为每个 Elasticsearch Pod 交付新的证书,从而将 ECK 的自签名证书替换为你的企业 PKI。
亲手体验 Elasticsearch:深入了解我们在 Elasticsearch Labs 仓库 中的示例笔记本,开始 免费云试用,或者立即在你的 本地机器上尝试 Elastic。
你可以在自己的企业公钥基础设施(public key infrastructure - PKI)上运行 Elastic Cloud on Kubernetes(ECK),而无需让你的证书颁发机构(CA)的私钥进入 Kubernetes 集群。默认情况下,ECK 会为 Elasticsearch 和 Kibana 生成自签名证书。本文将 Elasticsearch 的 ECK 证书管理交给 HashiCorp Vault,由它保存中间 CA 并为每个证书签名,同时交给 cert-manager,由它请求和续订证书。在示例中,HTTP 证书有效期为七天,并在过期前一小时进行续订。传输证书来自 cert-manager 容器存储接口(CSI) 驱动程序 ,该驱动程序会在 Elasticsearch Pod 启动时直接为每个 Pod 签发一个证书,因此新节点会自动获得证书,并且它们的私钥永远不会存储为 Kubernetes Secrets。
ECK 的默认设置通过传输层安全协议(TLS)保护每个集群,并自动轮换自己的证书,这在安全策略要求所有证书必须来自你的企业 PKI 之前都运行良好。在这种情况下,你需要对证书签发和信任进行集中控制,同时仍然不希望手动续订证书。Vault 和 cert-manager 可以同时满足这两个需求。
ECK 默认生成的自签名证书
ECK Operator 会为 Elastic Stack 的各种组件生成自签名证书。下面是 ECK 为 Elasticsearch 和 Kibana 生成的不同类型自签名证书的高级概览:
markdown
`
1. ECK Certificate Management
2. ├── Elasticsearch
3. │ ├── HTTP
4. │ │ ├── HTTP CA
5. │ │ └── HTTP Server Certificate
6. │ │
7. │ └── Transport
8. │ ├── Transport CA
9. │ └── Node Transport Certificates
10. │
11. └── Kibana
12. └── HTTP
13. ├── HTTP CA
14. └── HTTP Server Certificate
`AI写代码
你的 CA 私钥应该存放在哪里?
使用 ECK 自定义证书会在暴露 CA 私钥的风险和自动化证书生命周期管理之间产生权衡。
将你自己的 CA 和私钥交给 ECK
当通过 Kubernetes Secret 提供 CA 证书和私钥时,ECK Operator 会自动化证书签发和续订。随后,ECK 会管理整个 Elastic Stack 中的证书生命周期,包括 Elasticsearch 的 HTTP 证书和传输证书。然而,将 CA 私钥存储在 Kubernetes 集群中被认为存在安全风险,可能不符合企业安全和 PKI 策略。
在 ECK 中使用手动签发的证书
ECK 可以使用通过 Kubernetes Secrets 提供的外部签发证书,同时让 CA 私钥保留在 Kubernetes 集群之外。但是,证书签发和续订必须单独管理,证书轮换也需要单独处理。这会造成运维瓶颈,尤其是对于传输证书,因为 Elasticsearch Pod 扩展或缩减时需要动态配置这些证书。
使用 Vault PKI 和 cert-manager
云原生工具消除了自带 CA 和密钥以及使用手动签发证书之间的权衡。HashiCorp Vault 和 cert-manager 将 Kubernetes 上的证书生命周期管理从 ECK Operator 中移出,同时保证企业 CA 私钥的安全。
-
HashiCorp Vault 是外部 PKI 系统,安全地管理 CA 私钥,并签发由企业 CA 签名的证书。证书签名操作保持安全,不会将 CA 私钥暴露为 Kubernetes Secret。
-
cert-manager 可以在 Kubernetes 中自动化证书生命周期。它可以从 Vault 请求证书,并监控证书有效性。它还可以在证书过期前自动续订证书。签发完成后,cert-manager 可以创建和更新相应的 Kubernetes Secrets,而这些 Secrets 会被 Elastic 组件使用。
使用 Vault PKI 和 cert-manager 可以让每个组件承担单一职责:Vault 管理信任和签名权限,cert-manager 管理证书生命周期。ECK 组件使用最终生成的证书。
Vault 和 cert-manager 让组织能够保留现有企业 PKI 控制能力,同时降低证书签发、续订和轮换相关的运维开销。
下面的表格比较了三种方案:
| 方案 | CA 密钥存放位置 | 证书生命周期 | Pod 扩展时的传输证书 | 与 PKI 策略的匹配度 |
|---|---|---|---|---|
| 自带 CA 和密钥 | Kubernetes Secret | 由 ECK 自动管理 | 自动 | 取决于策略是否允许 CA 密钥存在于集群中 |
| 手动签发证书 | 集群外部 | 手动 | 手动 | 保持 CA 密钥在集群外部 |
| Vault PKI 和 cert-manager | Vault | 由 cert-manager 自动管理 | 通过 cert-manager CSI 驱动程序自动完成 | 保持 CA 密钥在集群外部 |
ECK 证书管理架构
下图展示了该解决方案建议的架构:

前置条件和已测试版本
本文假设用户已经基本了解 Vault 和 cert-manager 的配置。在本文中,我们只关注实现此配置所需的设置。
有关安装 Vault、cert-manager 和 csi-driver 的相关说明,请参考官方 Vault 和 cert-manager 文档。
测试版本
我们在本文演示中使用了以下软件版本。有关与其他版本的兼容性考虑或配置差异,请参考相应的官方文档。
-
Elastic Stack 9.5.3
-
cert-manager 1.21.2
-
HashiCorp Vault 2.0.3(社区版)
将 HashiCorp Vault 作为你的企业 PKI
在 Vault 服务器上,需要启用 PKI Secrets 引擎,以安全存储用于签发叶证书的 CA 证书及其私钥。
作为最佳实践,根 CA 私钥应保留在 Vault 外部。根 CA 用于签署中间 CA 证书签名请求(CSR),之后,中间 CA 证书和私钥会安全地存储在 Vault 中。随后,Vault 使用这个中间 CA 和密钥来签发并签署叶证书。
除了 PKI Secrets 引擎之外,还需要启用 Kubernetes 身份验证方法,以便 Vault 可以验证来自 Kubernetes 的请求。配置一个专用的 Vault 角色,并为其设置严格限制的权限,确保它只为来自指定 Kubernetes ServiceAccount 和命名空间的请求签发证书。
从高层次来看,下面的树形结构展示了此配置所需的 Vault 组件:
markdown
`
1. HashiCorp Vault
2. │
3. ├── PKI
4. │ └── PKI Engine
5. │ ├── CA / Intermediate CA / Intermediate Key
6. │ └── Sign Role
7. │ └── Certificate issuance policy
8. │
9. └── Authentication
10. └── Kubernetes Auth Method
11. ├── Kubernetes API Server
12. └── Kubernetes Auth Role
13. ├── Bound ServiceAccount
14. └── Bound Namespace
`AI写代码
配置 Vault PKI 和 Vault Kubernetes 身份验证
- 在可以访问 Vault 命令行界面(CLI)的 Linux 主机上,生成根 CA 证书和密钥:
csharp
`openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout eck-root-ca.key -out eck-root-ca.crt -subj "/C=SG/ST=SG/L=SG/O=Elastic Demo/OU=ECK/CN=ECK Root"`AI写代码
**注意:**这仅用于演示目的。在生产环境实现中,请跳过上述步骤,并改用你的组织现有的企业 CA 和密钥。
- 在
eck/esintca路径启用 PKI Secrets 引擎,并配置最大证书租约期限为一年。此 PKI 引擎用于存储中间 CA,并为 Elastic Stack 组件签发证书:
ini
`
1. vault secrets enable -path=eck/esintca pki && \
2. vault secrets tune -max-lease-ttl=8760h eck/esintca
`AI写代码
- 使用
eck/esintcaPKI 引擎生成内部中间 CA 密钥和 CSR。生成的响应包含 CSR,并存储在eck_esint.json中,以便后续签名步骤使用:
ini
`vault write -format=json eck/esintca/intermediate/generate/internal common_ key_bits=2048 > eck_esint.json`AI写代码
- 从 Vault 响应中提取中间 CA CSR,并保存为
eck_esint.csr。此 CSR 会提交给根 CA 进行签名。
markdown
`
1. jq -r
2. '.data.csr'
3. eck_esint.json > eck_esint.csr
`AI写代码
- 创建一个 OpenSSL 扩展配置文件,用于定义中间 CA 属性。该配置会将证书标记为 CA,并将证书路径长度限制为零。同时启用所需的密钥用途和证书标识扩展。此配置会在使用根 CA 签署中间 CA CSR 时使用。
ini
`
1. cat > eck-ext.cnf <<'EOF'
2. basicConstraints = critical, CA:true, pathlen:0
3. keyUsage = critical, keyCertSign, cRLSign
4. subjectKeyIdentifier = hash
5. authorityKeyIdentifier = keyid,issuer
6. EOF
`AI写代码
- 使用根 CA 证书和私钥签署中间 CA CSR,生成中间 CA 证书。该证书有效期为 365 天,使用 SHA-256,并应用
eck-ext.cnf中定义的 CA 扩展。生成的eck_esint.crt将被 Vault 用于签发和签署叶证书。
objectivec
`openssl x509 -req -in eck_esint.csr -CA eck-root-ca.crt -CAkey eck-root-ca.key -CAcreateserial -out eck_esint.crt -days 365 -sha256 -extfile eck-ext.cnf`AI写代码
- 将中间 CA 证书与根 CA 证书合并,创建完整的 CA 证书链。Vault 在签发证书时使用此证书链,使客户端能够信任回根 CA 的完整链路。
bash
`{ cat eck_esint.crt; printf '\n'; cat eck-root-ca.crt; } > eck_es_cachain.crt`AI写代码
- 将已签名的中间 CA 证书链上传到 Vault PKI 引擎。这会完成中间 CA 配置,并使 Vault 可以使用它来签发由 Elasticsearch 中间 CA 签名的证书。
arduino
`vault write eck/esintca/intermediate/set-signed certificate=@eck_es_cachain.crt`AI写代码
- 使用用于获取签发 CA 证书和证书吊销列表(CRL)的 URL 配置 Vault PKI 引擎。将
<replace-with-vault-server-endpoint>替换为你的环境中特定的 Vault 服务器端点。客户端使用这些 URL 获取 CA 证书,并在需要时检查证书吊销状态。
arduino
`
1. vault write eck/esintca/config/urls issuing_certificates="https://<replace-with-vault-server-endpoint>:8200/v1/eck/esintca/ca" && \
3. vault write eck/esintca/config/urls crl_distribution_points="https://<replace-with-vault-server-endpoint>:8200/v1/eck/esintca/crl"
`AI写代码
- 从可以访问 Kubernetes 集群的 Linux 主机上,获取当前
kubectl上下文中的 Kubernetes API 服务器端点。此端点用于配置 Vault 的 Kubernetes 身份验证,并允许 Vault 与 Kubernetes API 服务器通信,以验证 ServiceAccount 令牌。
ini
`
1. export KUBE_API_SERVER=$(kubectl config view --minify \
2. -o jsonpath='{.clusters[0].cluster.server}{"\n"}')
`AI写代码
- 从当前
kubectl上下文中提取 Kubernetes API 服务器的 CA 证书,并将其解码为kubeapi-ca.crt。Vault 使用此 CA 证书与 Kubernetes API 服务器建立受信任的 TLS 连接。
css
`
1. kubectl config view --raw --minify \
2. -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' \
3. | base64 -d > kubeapi-ca.crt
`AI写代码
**注意:**如果同一个 Linux 主机同时可以访问 Kubernetes 集群和 Vault 服务器,请从该主机运行以下命令。否则,将 Kubernetes API 服务器端点、受众 URL 和 CA 证书复制到可以访问 Vault 服务器的主机上,并在那里运行这些命令。
- 在
eck路径启用 Kubernetes 身份验证方法。之后,Vault 会使用 Kubernetes 工作负载的 ServiceAccount 令牌验证来自 Kubernetes 工作负载的请求。
ini
`vault auth enable -path=eck kubernetes`AI写代码
- 使用 Kubernetes API 服务器端点及其 CA 证书配置 Vault。Vault 使用该 CA 证书建立并验证与 Kubernetes API 服务器之间的受信任 TLS 连接。
arduino
`vault write auth/eck/config kubernetes_host="$KUBE_API_SERVER" kubernetes_ca_cert=@kubeapi-ca.crt`AI写代码
- 创建 Vault PKI 角色,用于定义 Elasticsearch 证书允许使用的域名和证书参数。该角色允许指定的 Kubernetes 服务域名和子域名,并接受 CSR 中的通用名称(CN)和主题备用名称(SAN)。同时限制签发证书的最大生存时间(TTL)为 168 小时(七天)。
ini
`vault write eck/esintca/roles/elasticsearch allowed_domains="elastic-cluster.svc,elastic-cluster.svc.cluster.local,elasticsearch-es-http" allow_subdomains=true allow_bare_domains=true use_csr_common_`AI写代码
**注意:**在此示例中,Elasticsearch 集群名称为
elasticsearch,部署在elastic-cluster命名空间中。因此,Elasticsearch HTTP 服务被引用为elasticsearch-es-http,域名为elastic-cluster.svc。请根据你的环境替换集群名称、命名空间以及对应的服务名称。
- 创建 Vault 策略,授予使用
elasticsearchPKI 签名角色的权限。该策略仅提供证书签名端点所需的update能力,遵循最小权限原则。
markdown
`
1. cat > eck-es-policy.hcl <<'EOF'
2. path "eck/esintca/sign/elasticsearch" {
3. capabilities = ["update"]
4. }
5. EOF
`AI写代码
- 使用之前定义的策略文件,在 Vault 中创建
eck-es-policy策略。此策略与 Kubernetes 身份验证角色关联,并授予请求 Elasticsearch 证书所需的权限。
arduino
`vault policy write eck-es-policy eck-es-policy.hcl`AI写代码
- 创建
eck-es-role角色,并将其绑定到elastic-cluster命名空间中的cert-manager-vault-accessServiceAccount。该角色使用指定的 Kubernetes 令牌受众,并附加eck-es-policy,使 ServiceAccount 可以向 Vault 进行身份验证并请求 Elasticsearch 证书。身份验证令牌配置为 10 分钟 TTL。
ini
`
1. vault write auth/eck/role/eck-es-role bound_service_account_names=cert-manager-vault-access bound_service_account_namespaces=elastic-cluster audience=
2. "vault://elastic-cluster/eck-es-issuer"
3. policies=eck-es-policy ttl=
4. 10m
`AI写代码
**注意:**在 Kubernetes 集群中,请确保 Vault 身份验证请求来自
elastic-cluster命名空间,并使用cert-manager-vault-accessServiceAccount 以及其关联令牌。
使用 cert-manager 自动化证书续订
cert-manager 用于管理 Elastic Stack 所需证书的生命周期。它监控 Kubernetes Certificate 资源,并从配置的 Issuer 请求证书,在此解决方案中,该 Issuer 由 Vault 提供支持。
cert-manager 使用专用 Kubernetes ServiceAccount 向 Vault 进行身份验证。随后,Vault 验证请求工作负载的身份,并根据配置的 Vault 角色和策略授权证书签发。
Vault 签发证书后,cert-manager 会创建并维护相应的 Kubernetes Secret,其中包含证书和私钥。cert-manager 还会监控证书有效期,并在证书过期之前自动管理续订和轮换。
使用 cert-manager CSI 驱动程序签发传输证书
对于 Elasticsearch 传输证书,cert-manager CSI 驱动程序会直接向 Elasticsearch Pod 提供证书。CSI 驱动程序请求证书,并通过 Kubernetes CSI 接口将其直接挂载到 Pod 中,因此证书和私钥无需持久化为 Kubernetes Secret。
使用 CSI 驱动程序时,cert-manager 仍然负责管理证书生命周期,并从由 Vault 支持的 Issuer 获取证书。CSI 驱动程序负责将这些证书交付给 Elasticsearch Pod,在那里它们可用于 Elasticsearch 节点之间的安全传输通信。
创建 Vault Issuer 和 HTTP 证书
- 在 Kubernetes 集群中,创建
elastic-cluster命名空间,并在其中创建专用的cert-manager-vault-accessServiceAccount。此 ServiceAccount 用于获取 cert-manager 向 Vault 进行身份验证时提供的 Kubernetes 令牌。
go
`kubectl create ns elastic-cluster`AI写代码
go
`kubectl create sa cert-manager-vault-access -n elastic-cluster`AI写代码
- 在
elastic-cluster命名空间中创建所需的基于角色的访问控制(RBAC)权限,以支持 Vault 身份验证。Role和RoleBinding允许 cert-manager ServiceAccount 为专用的cert-manager-vault-accessServiceAccount 请求令牌。ClusterRoleBinding允许 Vault 使用此 ServiceAccount 通过 Kubernetes API 验证 Kubernetes ServiceAccount 令牌,因此 Vault 可以验证请求工作负载的身份。
markdown
`
1. kubectl apply -f - <<'EOF'
2. apiVersion: rbac.authorization.k8s.io/v1
3. kind: Role
4. metadata:
5. name: cert-manager-vault-token-request
6. namespace: elastic-cluster
7. rules:
8. - apiGroups: [""]
9. resources:
10. - serviceaccounts/token
11. resourceNames:
12. - cert-manager-vault-access
13. verbs:
14. - create
15. ---
16. apiVersion: rbac.authorization.k8s.io/v1
17. kind: RoleBinding
18. metadata:
19. name: cert-manager-vault-token-request
20. namespace: elastic-cluster
21. subjects:
22. - kind: ServiceAccount
23. name: cert-manager
24. namespace: cert-manager
25. roleRef:
26. apiGroup: rbac.authorization.k8s.io
27. kind: Role
28. name: cert-manager-vault-token-request
29. ---
30. apiVersion: rbac.authorization.k8s.io/v1
31. kind: ClusterRoleBinding
32. metadata:
33. name: cert-manager-vault-access-token-review
34. roleRef:
35. apiGroup: rbac.authorization.k8s.io
36. kind: ClusterRole
37. name: system:auth-delegator
38. subjects:
39. - kind: ServiceAccount
40. name: cert-manager-vault-access
41. namespace: elastic-cluster
42. EOF
`AI写代码
- 为
defaultServiceAccount 生成令牌,并解码其 JSON Web Token(JWT)负载以检查令牌声明。此步骤用于确定配置 Vault Kubernetes 身份验证时使用的令牌受众(aud)。
markdown
`
1. export
2. aud=$(kubectl create token default | cut -d. -f2 | base64 -d
3. 2
4. >/dev/null | sed -n
5. 's/.*"aud":\["\([^"]*\)".*/\1/p'
6. )
`AI写代码
- 创建一个
Issuer对象,将 cert-manager 连接到 Vault PKI 签名端点。配置 Vault 服务器端点和 PKI 签名路径,同时提供 Vault 服务器 CA 证书,使 cert-manager 可以与 Vault 建立受信任连接。Kubernetes 身份验证配置指定eck-es-roleVault 角色和cert-manager-vault-accessServiceAccount。cert-manager 使用此身份和受众向 Vault 进行身份验证,并请求 Elasticsearch 证书。在下面的 YAML 中,替换 Vault 服务器端点、CA Bundle,以及上一步生成的受众,并将其保存到issuer.yaml文件中:
markdown
`
1. apiVersion: cert-manager.io/v1
2. kind: Issuer
3. metadata:
4. name: eck-es-issuer
5. namespace: elastic-cluster
6. spec:
7. vault:
8. server: https://<replace-with-vault-server-endpoint>:8200
9. path: eck/esintca/sign/elasticsearch
10. caBundle: <ca-cert-of-vault-endpoint-in-base64>
11. auth:
12. kubernetes:
13. role: eck-es-role
14. mountPath: /v1/auth/eck
15. serviceAccountRef:
16. name: cert-manager-vault-access
17. audiences:
18. - $aud
`AI写代码
应用清单文件以创建对象:
go
`kubectl create -f issuer.yaml`AI写代码
- 在
elastic-cluster命名空间中创建 cert-managerCertificate资源,以从eck-es-issuerIssuer 请求 Elasticsearch HTTP 证书。该证书配置了 Elasticsearch 服务访问所需的域名系统(DNS)名称,并设置七天有效期,同时在过期前 60 分钟进行续订。cert-manager 会将生成的证书和私钥存储在eck-es-httpKubernetes Secret 中,其中使用 RSA 2048 位私钥,并采用公钥密码标准 #1(PKCS#1)格式编码。
markdown
`
1. kubectl apply -f - <<'EOF'
2. apiVersion: cert-manager.io/v1
3. kind: Certificate
4. metadata:
5. name: eck-http-certificate
6. namespace: elastic-cluster
7. spec:
8. duration: '168h'
9. renewBefore: '60m'
10. isCA: false
11. secretName: eck-es-http
12. issuerRef:
13. name: eck-es-issuer
14. kind: Issuer
15. commonName: elasticsearch-es-http.elastic-cluster.svc
16. dnsNames:
17. - elasticsearch-es-http
18. - elasticsearch-es-http.elastic-cluster.svc
19. - elasticsearch-es-http.elastic-cluster.svc.cluster.local
20. privateKey:
21. algorithm: RSA
22. encoding: PKCS1
23. size: 2048
24. EOF
`AI写代码
- 验证 cert-manager 是否已成功处理
Certificate资源并创建对应的 Kubernetes Secret。该 Secret 应包含为 Elasticsearch HTTP 端点生成的证书和私钥。Certificate应显示READY状态为True,表示证书已成功签发并且 Secret 已创建。
arduino
`
1. kubectl get certificate eck-http-certificate -n elastic-cluster && \
2. kubectl get secret eck-es-http -n elastic-cluster
`AI写代码
让你的自定义 CA 对 ECK 可用
Vault 和 cert-manager 已经通过 CSI 驱动程序挂载,提供了 Elasticsearch 节点之间传输信任所需的 ca.crt 文件。但是,在 CA 经常变化,或者远程集群配置要求 CA 在多个集群之间被信任的场景中,还需要将自定义 CA 作为 elastic-cluster 命名空间中的 ConfigMap 提供,以便 ECK Operator 自身能够识别它。
提供此 ConfigMap 有两种方式。
使用 trust-manager 自动同步 CA
trust-manager 是一个 Kubernetes Operator,可以自动保持信任包的最新状态。它添加了一个 Bundle 自定义资源,该资源从源(例如 Kubernetes Secret)读取 CA,并将其发布到 ConfigMap 中,在源发生变化时保持同步。
安装 trust-manager 时,将其源 Secret 命名空间设置为 elastic-cluster,这样它就可以读取下面 Bundle 中使用的 eck-es-http Secret。有关更多信息,请参考其官方文档。
markdown
`
1. kubectl apply -f - <<'EOF'
2. apiVersion: elasticsearch.k8s.elastic.co/v1
3. kind: Elasticsearch
4. metadata:
5. name: elasticsearch
6. namespace: elastic-cluster
7. spec:
8. version: 9.5.3
9. nodeSets:
10. - name: default
11. count: 3
12. config:
13. xpack.security.transport.ssl.key: /usr/share/elasticsearch/config/cert-manager-certs/tls.key
14. xpack.security.transport.ssl.certificate: /usr/share/elasticsearch/config/cert-manager-certs/tls.crt
15. podTemplate:
16. spec:
17. containers:
18. - name: elasticsearch
19. volumeMounts:
20. - name: transport-certs
21. mountPath: /usr/share/elasticsearch/config/cert-manager-certs
22. volumes:
23. - name: transport-certs
24. csi:
25. driver: csi.cert-manager.io
26. readOnly: true
27. volumeAttributes:
28. csi.cert-manager.io/issuer-name: eck-es-issuer
29. csi.cert-manager.io/issuer-kind: Issuer
30. csi.cert-manager.io/common-name: "${POD_NAME}.${POD_NAMESPACE}.svc.cluster.local"
31. csi.cert-manager.io/dns-names: "${POD_NAME}.${POD_NAMESPACE}.svc.cluster.local"
32. transport:
33. tls:
34. certificateAuthorities:
35. configMapName: custom-ca-trust
36. selfSignedCertificates:
37. disabled: true
38. http:
39. tls:
40. certificate:
41. secretName: eck-es-http
42. EOF
`AI写代码
手动创建 CA ConfigMap
之前由 cert-manager 创建的 eck-es-http Secret 已经在其 ca.crt 密钥下包含 CA 证书。你可以直接提取它,并使用它创建 ConfigMap。
ini
`
1. kubectl get secret eck-es-http -n elastic-cluster -o jsonpath='{.data.ca\.crt}' | base64 -d > ca.crt && \
2. kubectl create configmap custom-ca-trust --from-file=ca.crt=ca.crt -n elastic-cluster
`AI写代码
kubectl create configmap custom-ca-trust --from-file=ca.crt=ca.crt -n elastic-cluster
使用企业 PKI 证书部署 Elasticsearch
使用以下 ECK 配置部署 Elasticsearch 集群。该集群配置为使用之前配置的 cert-manager 和 Vault 集成所提供的证书,而不是依赖 ECK 默认的自签名证书管理。HTTP 证书通过 cert-manager 创建的 Kubernetes Secret 提供,而 Elasticsearch 传输证书则通过 cert-manager CSI 驱动程序交付。
由于传输证书通过 CSI 驱动程序以挂载文件的形式提供,而不是作为 Kubernetes Secret 提供,因此下面的配置直接将 xpack.security.transport.ssl.key 和 xpack.security.transport.ssl.certificate 指向这些文件路径:
markdown
`
1. kubectl apply -f - <<'EOF'
2. apiVersion: elasticsearch.k8s.elastic.co/v1
3. kind: Elasticsearch
4. metadata:
5. name: elasticsearch
6. namespace: elastic-cluster
7. spec:
8. version: 9.5.3
9. nodeSets:
10. - name: default
11. count: 3
12. config:
13. xpack.security.transport.ssl.key: /usr/share/elasticsearch/config/cert-manager-certs/tls.key
14. xpack.security.transport.ssl.certificate: /usr/share/elasticsearch/config/cert-manager-certs/tls.crt
15. podTemplate:
16. spec:
17. containers:
18. - name: elasticsearch
19. volumeMounts:
20. - name: transport-certs
21. mountPath: /usr/share/elasticsearch/config/cert-manager-certs
22. volumes:
23. - name: transport-certs
24. csi:
25. driver: csi.cert-manager.io
26. readOnly: true
27. volumeAttributes:
28. csi.cert-manager.io/issuer-name: eck-es-issuer
29. csi.cert-manager.io/issuer-kind: Issuer
30. csi.cert-manager.io/common-name: "${POD_NAME}.${POD_NAMESPACE}.svc.cluster.local"
31. csi.cert-manager.io/dns-names: "${POD_NAME}.${POD_NAMESPACE}.svc.cluster.local"
32. transport:
33. tls:
34. certificateAuthorities:
35. configMapName: custom-ca-trust
36. selfSignedCertificates:
37. disabled: true
38. http:
39. tls:
40. certificate:
41. secretName: eck-es-http
42. EOF
`AI写代码
验证 Elasticsearch 是否正在使用你的企业 PKI 证书
验证 Elasticsearch 是否正在使用通过 Vault 支持的 cert-manager 配置签发的自定义证书。首先,从 cert-manager 创建的 Kubernetes Secret 中获取证书,然后检查其主题和签发者,以及有效期。
输出应显示证书 CN/SAN 中预期的 Elasticsearch 服务名称、由 Vault 管理的中间 CA 作为签发者,以及证书的 notBefore 和 notAfter 值。
ini
`kubectl get secret eck-es-http -n elastic-cluster -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -subject -issuer -dates -ext subjectAltName`AI写代码
验证 Elasticsearch 是否正在提供通过 Vault 支持的 cert-manager 配置签发的证书。输出应显示证书详细信息中的预期 Elasticsearch 服务名称,以及由 Vault 管理的中间 CA 作为签发者。同时也应显示证书有效期。
bash
`kubectl exec -n elastic-cluster elasticsearch-es-default-0 -- curl -v --cacert /usr/share/elasticsearch/config/http-certs/ca.crt https://elasticsearch-es-http.elastic-cluster.svc:9200 2>&1 | grep -E 'subject:|issuer:|start date:|expire date:|subjectAltName'`AI写代码
使用以下命令验证 Elasticsearch 集群的健康状态:
arduino
`kubectl -n elastic-cluster get elasticsearch`AI写代码
在 Elastic Stack 中扩展 ECK 证书管理
我们在本文中介绍的方法可以通过下面的图表进行总结:

我们在这里重点介绍了为 Elasticsearch 配置自定义证书。通过使用 HashiCorp Vault 和 cert-manager 管理证书生命周期,同样的方法也可以扩展到其他 Elastic Stack 组件,例如 Kibana。
使用 Vault 和 cert-manager 等云原生工具,可以将 ECK 默认的自签名证书替换为由企业 PKI 支持的证书。我们在这里演示的配置提供了一个实用的起点,可以根据不同的企业 PKI 环境和整个 ECK Stack 中的证书需求进行调整。
请在你自己的环境中尝试此方法,建议从非生产环境的 ECK 集群开始,并探索它如何融入你组织现有的证书管理和安全实践。
本文中描述的任何功能或特性的发布和时间安排均由 Elastic 自行决定。任何当前尚未提供的功能或特性可能不会按时交付,或者可能不会交付。
原文:ECK certificate management: Enterprise PKI for Elasticsearch | Elasticsearch Labs