×

了解服务提供证书

服务提供证书旨在支持需要加密的复杂中间件应用程序。这些证书作为 TLS Web 服务器证书颁发。

service-ca 控制器使用 x509.SHA256WithRSA 签名算法生成服务证书。

生成的证书和密钥采用 PEM 格式,分别存储在创建的密钥中的 tls.crttls.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

添加服务证书

要保护与服务的通信安全,请将已签名的服务证书和密钥对生成到与服务位于同一命名空间的密钥中。

生成的证书仅对内部服务 DNS 名称 <service.name>.<service.namespace>.svc 有效,并且仅对内部通信有效。如果您的服务是无头服务(未设置 clusterIP 值),则生成的证书还包含格式为 *.<service.name>.<service.namespace>.svc 的通配符主题。

由于生成的证书包含无头服务的通配符主题,因此如果您的客户端必须区分各个 Pod,则不得使用服务 CA。在这种情况下

  • 使用不同的 CA 生成单独的 TLS 证书。

  • 不要接受服务 CA 作为指向各个 Pod 并不得由其他 Pod 模拟的连接的受信任 CA。这些连接必须配置为信任用于生成单个 TLS 证书的 CA。

先决条件
  • 您必须定义一个服务。

步骤
  1. 使用 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)
    1 <service_name> 替换为要保护的服务的名称。
    2 <secret_name> 将是包含证书和密钥对的生成密钥的名称。为方便起见,建议将其与 <service_name> 相同。

    例如,使用以下命令注释服务 test1

    $ oc annotate service test1 service.beta.openshift.io/serving-cert-secret-name=test1
  2. 检查服务以确认注释是否存在

    $ 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
    ...
  3. 集群为您的服务生成密钥后,您的 Pod规范可以安装它,并且 Pod 在可用后将运行。

其他资源

将服务 CA 捆绑包添加到 ConfigMap

Pod 可以通过安装使用 service.beta.openshift.io/inject-cabundle=true 注释的 ConfigMap 对象来访问服务 CA 证书。注释后,集群会自动将服务 CA 证书注入到 ConfigMap 上的 service-ca.crt 密钥中。访问此 CA 证书允许 TLS 客户端验证与使用服务提供证书的服务的连接。

将此注释添加到 ConfigMap 后,其中的所有现有数据都会被删除。建议使用单独的 ConfigMap 来包含 service-ca.crt,而不是使用存储 Pod 配置的同一 ConfigMap。

步骤
  1. 使用 service.beta.openshift.io/inject-cabundle=true 注释 ConfigMap

    $ oc annotate configmap <config_map_name> \(1)
         service.beta.openshift.io/inject-cabundle=true
    1 <config_map_name> 替换为要注释的 ConfigMap 的名称。

    在卷装载中明确引用 service-ca.crt 密钥将阻止 Pod 启动,直到 ConfigMap 已注入 CA 捆绑包。可以通过为卷的服务证书配置将 optional 字段设置为 true 来覆盖此行为。

    例如,使用以下命令注释 ConfigMap test1

    $ oc annotate configmap test1 service.beta.openshift.io/inject-cabundle=true
  2. 查看配置映射以确保已注入服务 CA 证书。

    $ oc get configmap <config_map_name> -o yaml

    CA 证书显示为 YAML 输出中service-ca.crt 密钥的值。

    apiVersion: v1
    data:
      service-ca.crt: |
        -----BEGIN CERTIFICATE-----
    ...

将服务 CA 证书添加到 API 服务

您可以使用service.beta.openshift.io/inject-cabundle=true 注解APIService 对象,使其spec.caBundle 字段填充服务 CA 证书。这允许 Kubernetes API 服务器验证用于保护目标端点的服务 CA 证书。

步骤
  1. 使用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
  2. 查看 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>
    ...

将服务 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 证书才有用。

步骤
  1. 使用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
  2. 查看 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>
    ...

将服务 CA 证书添加到变异 webhook 配置

您可以使用service.beta.openshift.io/inject-cabundle=true 注解MutatingWebhookConfiguration 对象,使每个 webhook 的clientConfig.caBundle 字段填充服务 CA 证书。这允许 Kubernetes API 服务器验证用于保护目标端点的服务 CA 证书。

不要为需要为不同的 webhook 指定不同 CA 证书的准入 webhook 配置设置此注解。如果设置,则所有 webhook 都将注入服务 CA 证书。

步骤
  1. 使用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
  2. 查看变异 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>
    ...

将服务 CA 证书添加到验证 webhook 配置

您可以使用service.beta.openshift.io/inject-cabundle=true 注解ValidatingWebhookConfiguration 对象,使每个 webhook 的clientConfig.caBundle 字段填充服务 CA 证书。这允许 Kubernetes API 服务器验证用于保护目标端点的服务 CA 证书。

不要为需要为不同的 webhook 指定不同 CA 证书的准入 webhook 配置设置此注解。如果设置,则所有 webhook 都将注入服务 CA 证书。

步骤
  1. 使用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
  2. 查看验证 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>
    ...

手动轮换生成的服务器证书

您可以通过删除关联的密钥来轮换服务证书。删除密钥会导致自动创建新的密钥,从而生成新的证书。

先决条件
  • 必须为服务生成包含证书和密钥对的密钥。

步骤
  1. 检查服务以确定包含证书的密钥。这在serving-cert-secret-name 注解中找到,如下所示。

    $ oc describe service <service_name>
    示例输出
    ...
    service.beta.openshift.io/serving-cert-secret-name: <secret>
    ...
  2. 删除为服务生成的密钥。此过程将自动重新创建密钥。

    $ oc delete secret <secret> (1)
    1 <secret> 替换为上一步中密钥的名称。
  3. 通过获取新的密钥并检查AGE 来确认证书已重新创建。

    $ oc get secret <service_name>
    示例输出
    NAME              TYPE                DATA   AGE
    <service.name>    kubernetes.io/tls   2      1s

手动轮换服务 CA 证书

服务 CA 有效期为 26 个月,并在剩余有效期少于 13 个月时自动刷新。

如有必要,您可以使用以下步骤手动刷新服务 CA。

手动轮换的服务 CA 不会与之前的服务 CA 保持信任关系。在集群中的 Pod 重新启动之前,您可能会遇到短暂的服务中断,这确保了 Pod 使用由新的服务 CA 发出的服务服务器证书。

先决条件
  • 您必须以集群管理员身份登录。

步骤
  1. 使用以下命令查看当前服务 CA 证书的过期日期。

    $ oc get secrets/signing-key -n openshift-service-ca \
         -o template='{{index .data "tls.crt"}}' \
         | base64 --decode \
         | openssl x509 -noout -enddate
  2. 手动轮换服务 CA。此过程会生成一个新的服务 CA,该 CA 将用于签署新的服务证书。

    $ oc delete secret/signing-key -n openshift-service-ca
  3. 要将新证书应用于所有服务,请重新启动集群中的所有 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 在被删除后会自动重新启动。