3.3. 使用服务提供的证书 secret 保护服务流量
3.3.1. 了解服务用证书
服务用证书旨在为需要加密的复杂中间件应用程序提供支持。这些证书是作为 TLS web 服务器证书发布的。
service-ca
控制器使用 x509.SHA256WithRSA
签名算法来生成服务证书。
生成的证书和密钥采用 PEM 格式,分别存储在所创建 secret 的 tls.crt
和 tls.key
中。证书和密钥在接近到期时自动替换。
用于发布服务证书的服务 CA 证书在 26 个月内有效,并在有效期少于 13 个月时进行自动轮转。轮转后,以前的服务 CA 配置仍会被信任直到其过期为止。这将为所有受影响的服务建立一个宽限期,以在过期前刷新其密钥内容。如果没有在这个宽限期内对集群进行升级(升级会重启服务并刷新其密钥),您可能需要手动重启服务以避免在上一个服务 CA 过期后出现故障。
您可以使用以下命令来手动重启集群中的所有 pod。此命令会导致服务中断,因为它将删除每个命名空间中运行的所有 pod。这些 Pod 会在删除后自动重启。
$ for I in $(oc get ns -o jsonpath='{range .items[*]} {.metadata.name}{"\n"} {end}'); \ do oc delete pods --all -n $I; \ sleep 1; \ done
3.3.2. 添加服务证书
要保证与服务的通信的安全,请在与服务相同的命名空间中将签名的服务证书和密钥对生成 secret。
生成的证书仅对内部服务 DNS 名称 <service.name>.<service.namespace>.svc
有效,并且只适用于内部通信。如果您的服务是一个无头服务(未设置 clusterIP
值),则生成的证书还包含通配符主题,格式为 *.<service.name>.<service.namespace>.svc
。
因为生成的证书包含无头服务的通配符主题,因此如果您的客户端必须区分不同的 pod,则不得使用服务 CA。在这种情况下:
- 使用其他 CA 生成各个 TLS 证书。
- 对于定向到单个 pod 且不得被其他 pod 模拟的连接,不接受服务 CA 作为可信 CA。这些连接必须配置为信任用于生成单个 TLS 证书的 CA。
先决条件:
- 必须定义了服务。
流程
使用
service.beta.openshift.io/serving-cert-secret-name
注解该服务:$ oc annotate service <service_name> \1 service.beta.openshift.io/serving-cert-secret-name=<secret_name> 2
例如,使用以下命令来注解服务
test1
:$ oc annotate service test1 service.beta.openshift.io/serving-cert-secret-name=test1
检查服务以确认是否存在注解:
$ oc describe service <service_name>
输出示例
... Annotations: service.beta.openshift.io/serving-cert-secret-name: <service_name> service.beta.openshift.io/serving-cert-signed-by: openshift-service-serving-signer@1556850837 ...
-
在集群为服务生成 secret 后,
Pod
spec 可以挂载它,pod 将在可用后运行。
其他资源
- 您可以使用服务证书来配置使用重新加密 TLS 终止的安全路由。如需更多信息,请参阅使用自定义证书创建重新加密路由。
3.3.3. 将服务 CA 捆绑包添加到配置映射中
Pod 可通过挂载使用 service.beta.openshift.io/inject-cabundle=true
注解的 ConfigMap
对象来访问服务 CA 证书。注解后,集群会自动将服务 CA 证书注入配置映射上的 service-ca.crt
键。访问此 CA 证书可允许 TLS 客户端使用服务用证书验证服务连接。
将这个注解添加到配置映射后,会删除其中的所有现有数据。建议您使用单独的配置映射来包含 service-ca.crt
,而不是使用存储您的 Pod 配置的同一配置映射。
流程
使用
service.beta.openshift.io/inject-cabundle=true
注解配置映射:$ oc annotate configmap <config_map_name> \1 service.beta.openshift.io/inject-cabundle=true
- 1
- 将
<config_map_name>
替换为配置映射的名称。
注意在卷挂载中明确引用
service-ca.crt
键可防止 pod 启动,直到配置映射使用 CA 捆绑包注入为止。可通过为卷的 serving 证书将optional
字段设置为true
来覆盖此行为。例如,使用以下命令来注解配置映射
test1
:$ oc annotate configmap test1 service.beta.openshift.io/inject-cabundle=true
查看配置映射,以确保注入了服务 CA 捆绑包:
$ oc get configmap <config_map_name> -o yaml
CA 捆绑包在 YAML 输出中作为
service-ca.crt
键的值显示:apiVersion: v1 data: service-ca.crt: | -----BEGIN CERTIFICATE----- ...
3.3.4. 将服务 CA 捆绑包添加到 API 服务
您可以使用 service.beta.openshift.io/inject-cabundle=true
注解 APIService
对象,使其 spec.caBundle
字段由服务 CA 捆绑包填充。这可让 Kubernetes API 服务器验证用于保护目标端点的安全的服务 CA 证书。
流程
使用
service.beta.openshift.io/inject-cabundle=true
注解 API 服务:$ oc annotate apiservice <api_service_name> \1 service.beta.openshift.io/inject-cabundle=true
- 1
- 将
<api_service_name>
替换为要注解的 API 服务的名称。
例如,使用以下命令来注解 API 服务
test1
:$ oc annotate apiservice test1 service.beta.openshift.io/inject-cabundle=true
查看 API 服务,以确保注入了服务 CA 捆绑包:
$ oc get apiservice <api_service_name> -o yaml
CA 捆绑包在 YAML 输出中的
spec.caBundle
字段中显示:apiVersion: apiregistration.k8s.io/v1 kind: APIService metadata: annotations: service.beta.openshift.io/inject-cabundle: "true" ... spec: caBundle: <CA_BUNDLE> ...
3.3.5. 将服务 CA 捆绑包添加到自定义资源定义中
您可以使用 service.beta.openshift.io/inject-cabundle=true
注解 CustomResourceDefinition
(CRD)对象,使其 spec.conversion.webhook.clientConfig.caBundle 字段
由服务 CA 捆绑包填充。这可让 Kubernetes API 服务器验证用于保护目标端点的安全的服务 CA 证书。
只有在 CRD 被配置为使用 webhook 进行转换,才会将服务 CA 捆绑包注入 CRD。只有在 CRD 的 webhook 需要使用服务 CA 证书时,注入服务 CA 捆绑包才有意义。
流程
使用
service.beta.openshift.io/inject-cabundle=true
注解 CRD:$ oc annotate crd <crd_name> \1 service.beta.openshift.io/inject-cabundle=true
- 1
- 将
<crd_name>
替换为要注解的 CRD 的名称。
例如,使用以下命令来注解 CRD
test1
:$ oc annotate crd test1 service.beta.openshift.io/inject-cabundle=true
查看 CRD,以确保注入了服务 CA 捆绑包:
$ oc get crd <crd_name> -o yaml
CA 捆绑包在 YAML 输出中的
spec.conversion.webhook.clientConfig.caBundle
字段中显示:apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: service.beta.openshift.io/inject-cabundle: "true" ... spec: conversion: strategy: Webhook webhook: clientConfig: caBundle: <CA_BUNDLE> ...
3.3.6. 将服务 CA 捆绑包添加到变异的 webhook 配置中
您可以使用 service.beta.openshift.io/inject-cabundle=true
注解 MutatingWebhookConfiguration
对象,使每个 webhook 的 clientConfig.caBundle
字段由服务 CA 捆绑包填充。这可让 Kubernetes API 服务器验证用于保护目标端点的安全的服务 CA 证书。
不要为 admission webhook 配置设置此注解,不同的 webhook 需要指定不同的 CA 捆绑包。如果您这样做了,则会为所有 webhook 注入这个服务 CA 捆绑包。
流程
使用
service.beta.openshift.io/inject-cabundle=true
注解变异 Webhook 配置:$ oc annotate mutatingwebhookconfigurations <mutating_webhook_name> \1 service.beta.openshift.io/inject-cabundle=true
- 1
- 将
<mutating_webhook_name>
替换为要注解的变异 Webhook 配置的名称。
例如,使用以下命令来注解变异 Webhook 配置
test1
:$ oc annotate mutatingwebhookconfigurations test1 service.beta.openshift.io/inject-cabundle=true
查看变异 Webhook 配置,以确保注入了服务 CA 捆绑包:
$ oc get mutatingwebhookconfigurations <mutating_webhook_name> -o yaml
CA 捆包在 YAML 输出中所有 webhook 的
clientConfig.caBundle
字段中显示:apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: annotations: service.beta.openshift.io/inject-cabundle: "true" ... webhooks: - myWebhook: - v1beta1 clientConfig: caBundle: <CA_BUNDLE> ...
3.3.7. 将服务 CA 捆绑包添加到验证 webhook 配置中
您可以使用 service.beta.openshift.io/inject-cabundle=true
注解 ValidatingWebhookConfiguration
对象,使每个 webhook 的 clientConfig.caBundle 字段
由服务 CA 捆绑包填充。这可让 Kubernetes API 服务器验证用于保护目标端点的安全的服务 CA 证书。
不要为 admission webhook 配置设置此注解,不同的 webhook 需要指定不同的 CA 捆绑包。如果您这样做了,则会为所有 webhook 注入这个服务 CA 捆绑包。
流程
使用
service.beta.openshift.io/inject-cabundle=true
注解验证 Webhook 配置:$ oc annotate validatingwebhookconfigurations <validating_webhook_name> \1 service.beta.openshift.io/inject-cabundle=true
- 1
- 将
<validating_webhook_name>
替换为要注解的验证 webhook 配置的名称。
例如,使用以下命令来注解验证 webhook 配置
test1
:$ oc annotate validatingwebhookconfigurations test1 service.beta.openshift.io/inject-cabundle=true
查看验证 Webhook 配置,以确保注入了服务 CA 捆绑包:
$ oc get validatingwebhookconfigurations <validating_webhook_name> -o yaml
CA 捆包在 YAML 输出中所有 webhook 的
clientConfig.caBundle
字段中显示:apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: annotations: service.beta.openshift.io/inject-cabundle: "true" ... webhooks: - myWebhook: - v1beta1 clientConfig: caBundle: <CA_BUNDLE> ...
3.3.8. 手动轮转生成的服务证书
您可以通过删除关联的 secret 来轮换服务证书。删除 secret 会导致自动创建新 secret,进而生成新的证书。
先决条件
- 必须为服务生成了包含证书和密钥对的 secret。
流程
检查该服务以确定包含证书的 secret。这可以在
service-cert-secret-name
注解中找到,如下所示。$ oc describe service <service_name>
输出示例
... service.beta.openshift.io/serving-cert-secret-name: <secret> ...
删除为服务生成的 secret。此过程将自动重新创建 secret。
$ oc delete secret <secret> 1
- 1
- 将
<secret>
替换为前一步中的 secret 名称。
通过获取新 secret 并检查
AGE
来确认已经重新创建了证书。$ oc get secret <service_name>
输出示例
NAME TYPE DATA AGE <service.name> kubernetes.io/tls 2 1s
3.3.9. 手动轮转服务 CA 证书
服务 CA 在 26 个月内有效,并在有效期少于 13 个月时进行刷新。
如果需要,您可以按照以下步骤手动刷新服务 CA。
手动轮换的服务 CA 不会保留对上一个服务 CA 的信任。在集群中的 pod 重启完成前,您的服务可能会临时中断。pod 重启可以确保 Pod 使用由新服务 CA 发布的证书服务。
先决条件
- 必须以集群管理员身份登录。
流程
使用以下命令,查看当前服务 CA 证书的到期日期。
$ oc get secrets/signing-key -n openshift-service-ca \ -o template='{{index .data "tls.crt"}}' \ | base64 --decode \ | openssl x509 -noout -enddate
手动轮转服务 CA。此过程会生成一个新的服务 CA,用来为新服务证书签名。
$ oc delete secret/signing-key -n openshift-service-ca
要将新证书应用到所有服务,请重启集群中的所有 pod。此命令确保所有服务都使用更新的证书。
$ for I in $(oc get ns -o jsonpath='{range .items[*]} {.metadata.name}{"\n"} {end}'); \ do oc delete pods --all -n $I; \ sleep 1; \ done
警告此命令会导致服务中断,因为它将遍历并删除每个命名空间中运行的 Pod。这些 Pod 会在删除后自动重启。