跳到内容
观澜涉川 · 札记EN

在私有 AKS 配置 Cert Manager 管理TLS证书

· 约 2 分钟阅读

Cert Manager 是 Kubernetes 生态中用于自动化管理和签发 TLS 证书的工具,支持多种证书颁发机构。其提供的主要挑战方法包括 HTTP-01(通过 HTTP 验证域名控制权)和 DNS-01(通过 DNS 记录记录验证)等。本文介绍在私有 AKS 里使用 Cert Manager 的方法。

关键要点

  1. 私有 AKS 没有暴露给互联网。因此无法使用 HTTP-01 挑战;而应该使用 DNS-01 挑战;
  2. 私有 AKS 的虚拟网络可能关联了私有DNS区域,因此 Cert Manager在验证 DNS TXT 的时候,无法访问公共 DNS 区域。

安装和配置 Cert Manager

创建 UAI 并授予权限

确保 UAI 能够读写公共 DNS 区域的域名的 TXT 记录。如果能够接受不那么严格的最小权限原则,那么可以给它授予 DNS Zone Contributor 角色。

确保 Cert Manager 可创建 cert-manager.io:ClusterIssuer

Cert Manager 会创建集群级别的资源 cert-manager.io:ClusterIssuer,应该确保它有权限创建。

创建 Helm chart

Cert Manager 提供了使用 Helm 部署的详细文档 文档。可创建一个新的 Helm Chart,然后 cert-manager 作为依赖项。比如:

apiVersion: v2
name: cert-manager
description: Cert Manager
type: application
version: 1.0.0
appVersion: v1.18.2
dependencies:
- name: cert-manager
version: v1.18.2
repository: https://charts.jetstack.io
alias: cert-manager
condition: cert-manager.enabled

其默认的 values 文件为:

global:
leaderElection:
namespace: cert-manager
cert-manager:
enabled: true
namespace: cert-manager
crds:
enabled: true
podLabels:
azure.workload.identity/use: "true"
prometheus:
enabled: false
serviceAccount:
labels:
azure.workload.identity/use: "true"
dns01RecursiveNameserversOnly: true
dns01RecursiveNameservers: 8.8.8.8:53,1.1.1.1:53

注意:这里实质上给 cert-manager-controller 设置了 --dns01-recursive-nameservers-only=true --dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53 选项。这是因为如果 Cert Manager 所在的节点如果启用了私有DNS区域,那么无法访问公共 DNS 上的 TXT 记录来验证域名;启用这两个选项后,那么 Cert Manage 机会使用这两个公共的递归 DNS 服务器进行 TXT 记录查询。

除此之外,还需要创建一个模板,用于创建 ClusterIssuer。比如:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-dns-01
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: {{ .Values.clusterIssuer.email }}
privateKeySecretRef:
name: letsencrypt-dns-01
solvers:
- dns01:
azureDNS:
subscriptionID: {{ .Values.clusterIssuer.subscriptionID }}
resourceGroupName: {{ .Values.clusterIssuer.resourceGroupName }}
hostedZoneName: {{ .Values.clusterIssuer.hostedZoneName }}
environment: AzurePublicCloud
managedIdentity:
resourceID: {{ .Values.clusterIssuer.managedIdentityResourceID }}

这样 Helm Chart 就创建好了。

Values 文件

Helm Chart 里的 values 文件已经包含了大部分配置。在需要部署时,还需要执行 workload identity id 等。为此,创建部署时需要的额外的 values 文件,内部大致如下:

cert-manager:
serviceAccount:
annotations:
azure.workload.identity/client-id: {uai_client_id}
clusterIssuer:
email: ''
resourceGroupName: {resource_group_name}
hostedZoneName: {zone_name}
subscriptionID: {subscription_id}
managedIdentityResourceID: /subscriptions/{subscription_id}/resourceGroups/{resource_group_name}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{uai_name}

使用证书

在 Ingress 中使用证书

在 Ingress 中使用证书是一个常见的场景,见文档《Annotated Ingress resource》,使用 cert-manager.io/cluster-issuer 注解即可。

创建 Certificate

可创建如下的模板,用于创建证书:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: {{ .Value.certificate.name }}
namespace: {{ .Release.Namespace }}
spec:
secretName: {{ .Values.certificate.secretName }}
issuerRef:
name: {{ .Values.certificate.issuerName }}
kind: ClusterIssuer
commonName: {{ .Values.certificate.domain }}
dnsNames:
- {{ .Values.certificate.domain }}

在应用中,使用 Certificate 创建的 Secret,即可加载证书。但是需要注意的是创建顺序,因为这个 Secret 的创建会有延迟:创建了 Certificate 创建之后的,需要等一段时间才会成功签发证书,此后才会创建 Secret。