8.3. 使用服务提供的证书 secret 保护服务流量
8.3.1. 了解服务用证书
服务用证书旨在为需要加密的复杂中间件应用程序提供支持。这些证书是作为 TLS web 服务器证书发布的。
service-ca
控制器使用 x509.SHA256WithRSA
签名算法来生成服务证书。
生成的证书和密钥采用 PEM 格式,分别存储在所创建 secret 的 tls.crt
和 tls.key
中。证书和密钥在接近到期时自动替换。
用于发布服务证书的服务 CA 证书在 26 个月内有效,并在有效期少于 6 个月时进行自动轮转。轮转后,以前的服务 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
8.3.2. 添加服务证书
要保证与服务的通信的安全,请在与服务相同的命名空间中将签名的服务证书和密钥对生成 secret。
生成的证书仅对内部服务 DNS 名称 <service.name>.<service.namespace>.svc
有效,并且只适用于内部通信。
先决条件
- 必须定义了服务。
流程
使用
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
例如,使用以下命令来注解服务
foo
:$ oc annotate service foo service.beta.openshift.io/serving-cert-secret-name=foo
检查服务以确认是否存在注解。
$ 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 后,PodSpec 可以挂载它,Pod 也会在可用后运行。
8.3.3. 向 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。
流程
使用
service.beta.openshift.io/inject-cabundle=true
注解 ConfigMap。$ oc annotate configmap <configmap-name> \1 service.beta.openshift.io/inject-cabundle=true
- 1
- 将
<configmap-name>
替换为要注解的 ConfigMap 的名称。
注意在 volumeMount 中明确引用
service-ca.crt
键会使 Pod 无法启动,直到 ConfigMap 通过 CA 捆绑包注入后为止。例如,若要注解 ConfigMap
foo
,应使用以下命令:$ oc annotate configmap foo service.beta.openshift.io/inject-cabundle=true
查看 ConfigMap 以确保证书已经生成。这在 YAML 输出中显示为
service-ca.crt
。$ oc get configmap <configmap-name> -o yaml apiVersion: v1 data: service-ca.crt: | -----BEGIN CERTIFICATE----- ...
8.3.4. 手动轮转生成的服务证书
您可以通过删除关联的 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
8.3.5. 手动轮转服务 CA 证书
服务 CA 证书在 26 个月内有效,并在有效期少于 6 个月时进行刷新。
如果需要,您可以按照以下步骤手动刷新服务 CA。
手动轮换的服务 CA 不会保留对上一个服务 CA 的信任。在集群中的 Pod 重启完成前,您的服务可能会临时中断。Pod 重启可以确保 Pod 使用由新服务 CA 发布的证书服务。
先决条件
- 必须以集群管理员身份登录。
流程
使用以下命令,查看当前服务 CA 证书的到期日期。
$ oc get secrets/signing-key -n openshift-service-ca \ -o template='{{index .data "tls.crt"}}' \ | base64 -d \ | 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 会在删除后自动重启。