Service Serving Certificate
Overview
Service 服务端证书为容器云平台中的 Service 提供自动化的 TLS 证书生成和管理功能。该能力实现了内部组件之间的安全 HTTPS 通信和流量加密,保障数据隐私和系统安全。
Features
该自动化证书配置机制具备以下关键特性:
- 零接触配置:开发者无需手动生成证书签名请求(CSR)或与证书颁发机构交互。证书颁发通过标准 Kubernetes 注解实现全自动化。
- 跨命名空间 CA 同步:免去手动将平台根 CA 复制到每个业务命名空间的繁琐操作。根 CA 证书自动同步,使服务间轻松验证身份。
- 自动生命周期管理:借助
cert-manager,证书不仅自动颁发,还能在到期前无缝续期,降低运维负担,避免因证书过期导致的服务中断。
- 安全标准统一:确保 TLS 证书由统一的、集中管理的
ClusterIssuer 生成,维护平台上所有应用的一致安全标准。
Configuration and Deployment (For Administrators)
为实现上述功能,平台系统管理员需提前配置 Kyverno 相关的准入策略(ClusterPolicy)及必要的 RBAC 权限。
Prerequisites
操作前请确保集群已安装并启用 Alauda Container Platform Compliance with Kyverno 插件。安装详情请参见 Install Compliance Plugin。
为赋予 Kyverno 创建相关资源及调用接口的权限,将以下权限聚合至平台后台控制器:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
rbac.kyverno.io/aggregate-to-background-controller: "true"
rbac.kyverno.io/aggregate-to-admission-controller: "true"
rbac.kyverno.io/aggregate-to-reports-controller: "true"
name: kyverno:serving-certs
rules:
- apiGroups:
- cert-manager.io
resources:
- certificates
verbs:
- create
- update
- delete
- get
- list
- watch
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
- update
- delete
- get
- list
- watch
2. Create Certificate
创建以下 Certificate 资源,作为服务根 CA:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: service-root-ca
namespace: cert-manager
spec:
commonName: ServiceRootCA
isCA: true
issuerRef:
kind: ClusterIssuer
name: cpaas-ca
secretName: service-root-ca
创建并应用以下三个核心 ClusterPolicy 资源:
- clone-ca-secret:监听 Namespace 创建事件,为新命名空间生成
service-root-ca Secret 资源。
- sync-ca-rotation:监听
service-root-ca 变更,通过 API 获取真实 CA 证书内容,并同步 ca.crt 到目标命名空间的 Secret。
- generate-service-cert:监听带有
service.alauda.io/serving-cert-secret-name 注解的 Service 资源,基于其名称和命名空间生成支持泛域名的 Certificate 颁发请求。
将以下 YAML 内容保存为文件并执行应用(kubectl apply -f):
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: clone-ca-secret
spec:
background: true
rules:
- name: generate-ca-secret-shell
match:
any:
- resources:
kinds:
- Namespace
exclude:
any:
- resources:
namespaces:
- kube-system
- cpaas-system
- cert-manager
generate:
apiVersion: v1
kind: Secret
name: service-root-ca
namespace: "{{request.object.metadata.name}}"
synchronize: true
generateExisting: true
data:
kind: Secret
type: Opaque
metadata:
labels:
app.kubernetes.io/managed-by: kyverno
generate.kyverno.io/policy-name: clone-ca-secret
- name: initial-sync-on-creation
match:
any:
- resources:
kinds:
- Secret
names:
- service-root-ca
exclude:
any:
- resources:
namespaces:
- cert-manager
- kube-system
- cpaas-system
context:
- name: cacrt
apiCall:
method: GET
urlPath: "/api/v1/namespaces/cert-manager/secrets/service-root-ca"
jmesPath: 'data."ca.crt"'
mutate:
patchStrategicMerge:
data:
ca.crt: "{{ cacrt }}"
---
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: sync-ca-rotation
spec:
mutateExistingOnPolicyUpdate: true
background: true
rules:
- name: rotation-sync
match:
any:
- resources:
kinds:
- Secret
namespaces:
- cert-manager
names:
- service-root-ca
mutate:
targets:
- apiVersion: v1
kind: Secret
name: service-root-ca
selector:
matchLabels:
app.kubernetes.io/managed-by: kyverno
generate.kyverno.io/policy-name: clone-ca-secret
patchStrategicMerge:
data:
ca.crt: '{{ request.object.data."ca.crt" }}'
---
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: generate-service-cert
spec:
background: true
rules:
- name: generate-cert
match:
any:
- resources:
kinds:
- Service
annotations:
service.alauda.io/serving-cert-secret-name: "?*"
generate:
apiVersion: cert-manager.io/v1
kind: Certificate
name: "{{request.object.metadata.name}}-cert"
namespace: "{{request.object.metadata.namespace}}"
synchronize: true
data:
spec:
secretName: '{{request.object.metadata.annotations."service.alauda.io/serving-cert-secret-name"}}'
issuerRef:
name: cpaas-ca
kind: ClusterIssuer
dnsNames:
- "{{request.object.metadata.name}}"
- "{{request.object.metadata.name}}.{{request.object.metadata.namespace}}"
- "{{request.object.metadata.name}}.{{request.object.metadata.namespace}}.svc"
- "{{request.object.metadata.name}}.{{request.object.metadata.namespace}}.svc.cluster.local"
User Guide (For Developers)
对于应用开发者,底层集群策略配置完成后,无需关心底层证书颁发逻辑。只需在定义业务 Service 资源时添加专属注解,即可实现自动证书配置:
- 为 Service 添加注解
在业务命名空间(如 my-namespace)下创建或更新 Service,添加 service.alauda.io/serving-cert-secret-name 注解,指定生成的证书 Secret 名称。例如:
apiVersion: v1
kind: Service
metadata:
name: my-secure-service
namespace: my-namespace
annotations:
service.alauda.io/serving-cert-secret-name: "my-secure-service-tls" # 将为您生成名为 my-secure-service-tls 的证书 Secret
spec:
ports:
- port: 443
targetPort: 8443
selector:
app: my-app
- 验证生成的证书 Secret
应用上述 Service 后:
- 检查自动生成的 TLS 证书 Secret 是否存在于命名空间:
kubectl get secret my-secure-service-tls -n my-namespace
- 检查用于验证的根 CA 证书是否也已自动复制到当前命名空间:
kubectl get secret service-root-ca -n my-namespace
- 在 Pod 中挂载并使用证书
由于 CA 证书 Secret(service-root-ca)和当前应用的 TLS 服务端证书 Secret(my-secure-service-tls)均已就绪,您可以在目标应用的 Deployment 或 StatefulSet 等工作负载中,将它们作为数据卷挂载。
以下是一个具体的 Deployment YAML 示例,演示如何挂载这些证书:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: my-namespace
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-container
image: my-app-image:latest
volumeMounts:
# 挂载服务端证书
- name: tls-cert
mountPath: "/etc/tls/certs"
readOnly: true
# 挂载根 CA 证书
- name: root-ca
mountPath: "/etc/tls/ca"
readOnly: true
volumes:
# 引用自动生成的 Service 证书 Secret
- name: tls-cert
secret:
secretName: my-secure-service-tls
# 引用自动同步的 CA 证书 Secret
- name: root-ca
secret:
secretName: service-root-ca
更多关于通过 Web 控制台配置工作负载的详情,请参见 Configure Containers 部分。