签名、密封、交付:使用 Vault 和 cert-manager 进行 ECK 证书管理

作者:来自 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写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

你的 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写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

配置 Vault PKI 和 Vault Kubernetes 身份验证

  1. 在可以访问 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 和密钥。

  1. 在 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写代码
  1. 使用 eck/esintca PKI 引擎生成内部中间 CA 密钥和 CSR。生成的响应包含 CSR,并存储在 eck_esint.json 中,以便后续签名步骤使用:
ini 复制代码
`vault write -format=json eck/esintca/intermediate/generate/internal common_ key_bits=2048 > eck_esint.json`AI写代码
  1. 从 Vault 响应中提取中间 CA CSR,并保存为 eck_esint.csr。此 CSR 会提交给根 CA 进行签名。
markdown 复制代码
`

1.  jq -r 
2.  '.data.csr' 
3.  eck_esint.json > eck_esint.csr

`AI写代码
  1. 创建一个 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写代码
  1. 使用根 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写代码
  1. 将中间 CA 证书与根 CA 证书合并,创建完整的 CA 证书链。Vault 在签发证书时使用此证书链,使客户端能够信任回根 CA 的完整链路。
bash 复制代码
`{ cat eck_esint.crt; printf '\n'; cat eck-root-ca.crt; } > eck_es_cachain.crt`AI写代码
  1. 将已签名的中间 CA 证书链上传到 Vault PKI 引擎。这会完成中间 CA 配置,并使 Vault 可以使用它来签发由 Elasticsearch 中间 CA 签名的证书。
arduino 复制代码
`vault write eck/esintca/intermediate/set-signed certificate=@eck_es_cachain.crt`AI写代码
  1. 使用用于获取签发 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写代码
  1. 从可以访问 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写代码
  1. 从当前 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 服务器的主机上,并在那里运行这些命令。

  1. 在 eck 路径启用 Kubernetes 身份验证方法。之后,Vault 会使用 Kubernetes 工作负载的 ServiceAccount 令牌验证来自 Kubernetes 工作负载的请求。
ini 复制代码
`vault auth enable -path=eck kubernetes`AI写代码
  1. 使用 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写代码
  1. 创建 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。请根据你的环境替换集群名称、命名空间以及对应的服务名称。

  1. 创建 Vault 策略,授予使用 elasticsearch PKI 签名角色的权限。该策略仅提供证书签名端点所需的 update 能力,遵循最小权限原则。
markdown 复制代码
`

1.  cat > eck-es-policy.hcl <<'EOF'
2.  path "eck/esintca/sign/elasticsearch" {
3.    capabilities = ["update"]
4.  }
5.  EOF

`AI写代码
  1. 使用之前定义的策略文件,在 Vault 中创建 eck-es-policy 策略。此策略与 Kubernetes 身份验证角色关联,并授予请求 Elasticsearch 证书所需的权限。
arduino 复制代码
`vault policy write eck-es-policy eck-es-policy.hcl`AI写代码
  1. 创建 eck-es-role 角色,并将其绑定到 elastic-cluster 命名空间中的 cert-manager-vault-access ServiceAccount。该角色使用指定的 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-access ServiceAccount 以及其关联令牌。

使用 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 证书

  1. 在 Kubernetes 集群中,创建 elastic-cluster 命名空间,并在其中创建专用的 cert-manager-vault-access ServiceAccount。此 ServiceAccount 用于获取 cert-manager 向 Vault 进行身份验证时提供的 Kubernetes 令牌。
go 复制代码
`kubectl create ns elastic-cluster`AI写代码
go 复制代码
`kubectl create sa cert-manager-vault-access -n elastic-cluster`AI写代码
  1. 在 elastic-cluster 命名空间中创建所需的基于角色的访问控制(RBAC)权限,以支持 Vault 身份验证。Role 和 RoleBinding 允许 cert-manager ServiceAccount 为专用的 cert-manager-vault-access ServiceAccount 请求令牌。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写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)
  1. 为 default ServiceAccount 生成令牌,并解码其 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写代码
  1. 创建一个 Issuer 对象,将 cert-manager 连接到 Vault PKI 签名端点。配置 Vault 服务器端点和 PKI 签名路径,同时提供 Vault 服务器 CA 证书,使 cert-manager 可以与 Vault 建立受信任连接。Kubernetes 身份验证配置指定 eck-es-role Vault 角色和 cert-manager-vault-access ServiceAccount。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写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

应用清单文件以创建对象:

go 复制代码
`kubectl create -f issuer.yaml`AI写代码
  1. 在 elastic-cluster 命名空间中创建 cert-manager Certificate 资源,以从 eck-es-issuer Issuer 请求 Elasticsearch HTTP 证书。该证书配置了 Elasticsearch 服务访问所需的域名系统(DNS)名称,并设置七天有效期,同时在过期前 60 分钟进行续订。cert-manager 会将生成的证书和私钥存储在 eck-es-http Kubernetes 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写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)
  1. 验证 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写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

手动创建 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写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

验证 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

相关推荐
看浪的路人2 小时前
第5讲:Prompt 管理与版本追踪
大数据·数据库·elasticsearch
Elastic 中国社区官方博客16 小时前
Kubernetes attributes processor v1:它对 EDOT Collector 意味着什么
java·大数据·elasticsearch·搜索引擎·贪心算法·kubernetes·全文检索
Elastic 中国社区官方博客17 小时前
Elasticsearch Serverless 如何通过 hollow shards 将索引节点关闭次数降低 30%
大数据·数据库·elasticsearch·搜索引擎·serverless·全文检索
w***48821 天前
SpringBoot整合easy-es
spring boot·后端·elasticsearch
guo_wen_qiang1 天前
云服务器elasticsearch环境搭建-单台
运维·elasticsearch·容器
Elasticsearch1 天前
使用 Jev 作为 search reranker:基准测试与实现方法
elasticsearch
Elastic 中国社区官方博客1 天前
14 个 alerts,1 个 incident:使用 Elasticsearch 中的 ES|QL 衡量 alerting rule 噪声
大数据·运维·数据库·elasticsearch·搜索引擎·全文检索
SelectDB技术团队2 天前
一条日志两套引擎的账:把 Elasticsearch 检索与分析合并到同一份数据的落地写法
大数据·数据库·elasticsearch·搜索引擎·全文检索·日志·apache doris
Elastic 中国社区官方博客2 天前
使用 Lucene 搜索你的 Bean —— Elasticsearch
大数据·开发语言·人工智能·elasticsearch·搜索引擎·全文检索·lucene