Route53
本指南解释如何设置 Issuer
或 ClusterIssuer
以使用 Amazon Route53 来解决 DNS01 ACME 挑战。建议您先阅读 DNS01 挑战提供程序 页面,以更深入地了解 cert-manager 如何处理 DNS01 挑战。
ℹ️ 本指南假设您已在 Route53 中拥有托管区域。
📖 阅读 AWS + LoadBalancer + Let's Encrypt 教程,其中包含针对 cert-manager 和 AWS 新手的端到端说明。
设置 IAM 策略
cert-manager 需要能够向 Route53 添加记录才能解决 DNS01 挑战。为此,请创建具有以下权限的 IAM 策略
{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Action": "route53:GetChange","Resource": "arn:aws:route53:::change/*"},{"Effect": "Allow","Action": ["route53:ChangeResourceRecordSets","route53:ListResourceRecordSets"],"Resource": "arn:aws:route53:::hostedzone/*"},{"Effect": "Allow","Action": "route53:ListHostedZonesByName","Resource": "*"}]}
ℹ️ 如果您指定(可选)
hostedZoneID
,则可以删除route53:ListHostedZonesByName
语句。您可以通过限制 cert-manager 访问的托管区域来进一步收紧策略(例如arn:aws:route53:::hostedzone/DIKER8JEXAMPLE
)。📖 阅读 Amazon Route 53 支持的操作,了解 Amazon Route 53 API 参考。
📖 了解
eksctl
如何自动创建 cert-manager IAM 策略,如果您使用 EKS。
凭据
cert-manager 需要一个 AWS 访问密钥,以向 Route53 API 进行身份验证。AWS 将访问密钥定义如下
**访问密钥**:访问密钥 ID(例如,
AKIAIOSFODNN7EXAMPLE
)和秘密访问密钥(例如,wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
)的组合。您使用访问密钥来签署您对 AWS 发出的 API 请求。
您有两个选择
- (最佳实践)使用 具有临时安全凭据的 IAM 角色。
- 使用 具有长期访问密钥的 IAM 用户。
使用具有临时安全凭据的 IAM 角色被认为是最佳实践,因为
- 您不必存储长期访问密钥(例如,在秘密中)。
- 您不必管理 访问密钥轮换。
如果 cert-manager 部署在 AWS 之外,但 DNS 区域位于 Route53 上,则使用 具有长期访问密钥的 IAM 用户 是一个合理的选择。
cert-manager 支持多种获取访问密钥的方法,这些方法可以分为“环境”或“非环境”类别。
环境凭据
环境凭据是通过以下机制之一在 cert-manager 控制器 Pod 中提供的凭据
- EKS Pod 身份:
cert-manager 从 在每个 Kubernetes 节点上运行的 EKS Auth API 获取凭据。 - 用于服务帐户的 EKS IAM 角色 (IRSA):
cert-manager 使用 Kubernetes ServiceAccount 令牌,该令牌 被挂载到 cert-manager 控制器 Pod 中。 - EC2 实例元数据服务 (IMDS):
cert-manager 从 IMDS 的iam/security-credentials/<role-name>
端点获取凭据。 - 环境变量:
如果存在,cert-manager 会从 cert-manager 控制器 Pod 中的AWS_ACCESS_KEY_ID
和AWS_SECRET_ACCESS_KEY
环境变量加载凭据。 - 共享配置和凭据文件:
cert-manager 从挂载到 cert-manager 控制器 Pod 中的文件(~/.aws/config
和~/.aws/credentials
)加载凭据。
环境凭据的优点是它们更容易设置,并且由 Amazon AWS 进行了广泛的文档记录。环境凭据的缺点是它们对所有 ClusterIssuer 和所有 Issuer 资源都可用,这意味着在多租户环境中,任何有权创建 Issuer 或 ClusterIssuer 的租户都可以使用环境凭据并获得授予该帐户的权限。
📖 阅读 AWS SDK 和工具标准化凭据提供程序,了解 cert-manager 如何支持所有这些环境凭据来源。
⚠️ 默认情况下,cert-manager 只会对
ClusterIssuer
资源使用环境凭据,而不是Issuer
资源。这是为了防止特权用户(有权创建 Issuer 资源)使用 cert-manager 偶然访问的凭据来颁发证书。ClusterIssuer 资源是集群范围的(不是命名空间范围的),只有平台管理员应该被授予创建它们的权限。
⚠️ 可以在
Issuer
资源上启用环境身份验证机制(但不推荐),方法是在 cert-manager 控制器上设置--issuer-ambient-credentials
标志为 true。
以下是用 Route53 环境凭据的 ClusterIssuer
的示例
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-prodspec:acme:...solvers:- dns01:route53: {}
ℹ️ 无论您使用哪种环境机制,都将保留
route53
部分,因为 cert-manager 可以通过查找环境变量来找到凭据、角色和区域,这些环境变量将被添加到 cert-manager Pod 中。
EKS Pod 身份
如果您在 EKS 上部署 cert-manager,EKS Pod 身份 是使用环境凭据的最简单方法。这是一个四步过程
-
在您的集群中 设置 EKS Pod 身份代理。
-
重新启动 cert-manager Deployment,以便 EKS Pod 身份代理可以将必要的环境变量注入到 Pod 中。
-
创建一个
ClusterIssuer
资源apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-prodspec:acme:solvers:- dns01:route53: {}
用于服务帐户的 EKS IAM 角色 (IRSA)
如果您在 EKS 上部署 cert-manager,用于服务帐户的 IAM 角色 (IRSA) 是使用环境凭据的另一种方法。它比 Pod 身份更复杂,需要 Kubernetes 集群管理员和 AWS 帐户管理员之间的协调。它涉及在 Kubernetes 中对 cert-manager
ServiceAccount 进行注释,并在 AWS 中设置 IAM 角色、信任策略和信任关系。一个变异 Webhook 将自动在 cert-manager Pod 中设置一个挂载的服务帐户卷。
-
为您的集群创建 IAM OIDC 提供程序
要将 IRSA 与 cert-manager 一起使用,您必须首先为您的集群启用该功能。请遵循 官方文档。
-
创建信任关系
在此配置中,IAM 角色映射到 cert-manager
ServiceAccount
,允许它对 AWS 进行身份验证。您映射到ServiceAccount
的 IAM 角色需要对 cert-manager 将使用的任何和所有 Route53 区域具有权限。通过将以下信任策略添加到 IAM 角色来创建信任关系{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Action": "sts:AssumeRoleWithWebIdentity","Principal": {"Federated": "arn:aws:iam::<aws-account-id>:oidc-provider/oidc.eks.<aws-region>.amazonaws.com/id/<eks-hash>"},"Condition": {"StringEquals": {"oidc.eks.<aws-region>.amazonaws.com/id/<eks-hash>:sub": "system:serviceaccount:<namespace>:<service-account-name>"}}}]}替换以下内容
-
<aws-account-id>
为 EKS 集群的 AWS 帐户 ID。 -
<aws-region>
为 EKS 集群所在的区域。 -
<eks-hash>
为 EKS API URL 中的哈希;这将是一个随机的 32 个字符的十六进制字符串(例如:45DABD88EEE3A227AF0FA468BE4EF0B5
)。 -
<namespace>
为 cert-manager 运行的命名空间。 -
<service-account-name>
为 cert-manager 创建的ServiceAccount
对象的名称。
ℹ️ 如果您正在遵循跨帐户示例,则此信任策略附加到帐户 X 中的 cert-manager 角色,其 ARN 为
arn:aws:iam::XXXXXXXXXXX:role/cert-manager
。权限策略与上面相同。 -
-
对 cert-manager
ServiceAccount
进行注释apiVersion: v1kind: ServiceAccountmetadata:annotations:eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-managercert-manager Helm 图表提供了一个变量,用于将注释注入 cert-manager 的
ServiceAccount
,如下所示serviceAccount:annotations:eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-managerℹ️ 如果您正在遵循跨账户示例,请使用账户 Y 中的角色修改
ClusterIssuer
。 -
(可选) 更新文件系统权限
📢 请帮助我们改进此文档
此可选步骤的原因是在 EKS Fargate 和某些旧版本的 EKS 上,您可能会观察到以下错误
无法读取文件 /var/run/secrets/eks.amazonaws.com/serviceaccount/token
打开 /var/run/secrets/eks.amazonaws.com/serviceaccount/token:权限被拒绝
在这种情况下,您可以更改 cert-manager 进程的用户和组,以便它能够读取已挂载的 ServiceAccount 令牌。
阅读
cert-manager/website#697
: IRSA 需要runAsUser: 1001
并告诉我们此步骤是否仍然必要或已过时。您可能还需要使用不同的用户和组修改 cert-manager
Deployment
,以便可以读取ServiceAccount
令牌。spec:template:spec:securityContext:fsGroup: 1001runAsUser: 1001cert-manager Helm 图表提供了一个变量,用于修改 cert-manager 的
Deployment
,如下所示securityContext:fsGroup: 1001runAsUser: 1001 -
重新启动 cert-manager Deployment
重新启动 cert-manager Deployment,以便 webhook 可以将必要的
volume
、volumemount
和环境变量注入 Pod。 -
创建一个
ClusterIssuer
资源apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-prodspec:acme:solvers:- dns01:route53: {}
非环境凭据
非环境凭据是在 Issuer 或 ClusterIssuer 资源上显式配置的凭据。例如
- 访问密钥 Secret 引用:
其中 cert-manager 从 Kubernetes Secret 资源加载长期访问密钥。 - ServiceAccount 引用:
其中 cert-manager 从 Kubernetes API 服务器获取 ServiceAccount 令牌(已签署的 JWT),并使用 STS AssumeRoleWithWebIdentity 端点将其交换为临时的 AWS 凭据。
非环境凭据的优势在于 cert-manager 可以在多租户环境中执行 Route53 操作。每个租户可以被授予在其命名空间中创建和更新 Issuer 资源的权限,并且他们可以在其命名空间中提供自己的 AWS 凭据。
带有专用 Kubernetes ServiceAccount 的 IAM 角色
📖 阅读 AWS + LoadBalancer + Let's Encrypt 教程 了解如何在 EKS 上部署 cert-manager 并使用此身份验证机制。
在此配置中,您可以在 Issuer
或 ClusterIssuer
中引用您自己的 ServiceAccounts
,并且 cert-manager 将从 Kubernetes API 获取 ServiceAccount 令牌,它将将其发送到 STS 以换取 AWS 临时凭据。
此机制的优势在于
- 每个 Issuer 都可以引用不同的
ServiceAccount
,这意味着您可以锁定权限,这样每个ServiceAccount
都会映射到一个 IAM 角色,该角色只具有更新其所需区域的权限(与 Pod Identity 或 IRSA 不同)。 - 即使 cert-manager 部署在 AWS 之外,此机制也能正常工作。
以下是如何设置它
-
创建 ServiceAccount
为了引用
ServiceAccount
,它必须首先存在。与普通的 IRSA 不同,eks.amazonaws.com/role-arn
注释不是必需的。apiVersion: v1kind: ServiceAccountmetadata:name: <service-account-name> -
创建 IAM 角色信任策略
对于您想要用于 AWS 身份验证的每个
ServiceAccount
,您必须首先设置信任策略{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Action": "sts:AssumeRoleWithWebIdentity","Principal": {"Federated": "arn:aws:iam::<aws-account-id>:oidc-provider/oidc.eks.<aws-region>.amazonaws.com/id/<eks-hash>"},"Condition": {"StringEquals": {"oidc.eks.<aws-region>.amazonaws.com/id/<eks-hash>:sub": "system:serviceaccount:<namespace>:<service-account-name>"}}}]}替换以下内容
<aws-account-id>
为 EKS 集群的 AWS 帐户 ID。<aws-region>
为 EKS 集群所在的区域。<eks-hash>
为 EKS API URL 中的哈希;这将是一个随机的 32 个字符的十六进制字符串(例如:45DABD88EEE3A227AF0FA468BE4EF0B5
)。<namespace>
使用ServiceAccount
对象的命名空间。<service-account-name>
使用ServiceAccount
对象的名称。
-
创建 RBAC 角色和 RoleBinding
为了允许 cert-manager 使用您的
ServiceAccount
发行令牌,您必须将一些 RBAC 部署到集群中apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata:name: <service-account-name>-tokenrequestnamespace: <service-account-namespace>rules:- apiGroups: ['']resources: ['serviceaccounts/token']resourceNames: ['<service-account-name>']verbs: ['create']---apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata:name: cert-manager-<service-account-name>-tokenrequestnamespace: <service-account-namespace>subjects:- kind: ServiceAccountname: <cert-manager-service-account-name>namespace: <cert-manager-namespace>roleRef:apiGroup: rbac.authorization.k8s.iokind: Rolename: <service-account-name>-tokenrequest替换以下内容
<service-account-name>
ServiceAccount
对象的名称。<service-account-namespace>
ServiceAccount
对象的命名空间。<cert-manager-service-account-name>
cert-managers 的ServiceAccount
对象的名称,在 cert-manager 安装期间创建。<cert-manager-namespace>
cert-manager 部署到的命名空间。
-
创建 Issuer 或 ClusterIssuer
此时您应该已准备好配置 Issuer 以使用新的
ServiceAccount
。您可以在下面看到此配置的示例apiVersion: cert-manager.io/v1kind: Issuermetadata:name: examplespec:acme:...solvers:- dns01:route53:region: us-east-1role: <iam-role-arn> # This must be set so cert-manager what role to attempt to authenticate withauth:kubernetes:serviceAccountRef:name: <service-account-name> # The name of the service account created
带有长期访问密钥的 IAM 用户
在此机制中,cert-manager 将从 Secret 资源加载凭据。如果您使用 Issuer
资源,则 Secret 必须与 Issuer 位于同一个命名空间。如果您使用 ClusterIssuer
资源,则 Secret 必须位于 cert-manager
命名空间或 --cluster-resource-namespace
的任何值中 cert-manager 组件的选项。
此机制的优势在于它很简单,即使 cert-manager 部署在 AWS 之外也能正常工作。
以下是一个 ClusterIssuer
配置示例
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-prodspec:acme:...solvers:- dns01:route53:region: eu-central-1accessKeyIDSecretRef:name: prod-route53-credentials-secretkey: access-key-idsecretAccessKeySecretRef:name: prod-route53-credentials-secretkey: secret-access-key# (optional) you can also assume a role with these credentialsrole: arn:aws:iam::YYYYYYYYYYYY:role/dns-manager
跨账户访问
示例:账户 Y 管理 Route53 DNS 区域。现在您希望在账户 X(或许多其他账户)中运行的 cert-manager 能够管理在账户 Y 中托管的 Route53 区域中的记录。
首先,在账户 Y 中创建一个具有上述权限策略的角色(我们称该角色为 dns-manager
),并附加一个类似于下面的信任关系。
{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"AWS": "arn:aws:iam::XXXXXXXXXXX:role/cert-manager"},"Action": "sts:AssumeRole"}]}
请记住,在账户 Y 上创建 cert-manager
角色之前,您将无法定义此策略。如果您使用配置语言进行设置,您可能希望将主体定义为
"Principal": {"AWS": "XXXXXXXXXXX"}
并在以后的步骤中,在所有角色创建后对其进行限制。
这允许账户 X 中的 cert-manager
角色在账户 Y 中假定 dns-manager
角色以管理账户 Y 中的 Route53 DNS 区域。有关更多信息,请访问 官方文档。
其次,在账户 X 中创建 cert-manager 角色;这将用作在账户 X 中运行的 cert-manager Pod 的凭据来源。将以下**权限**策略附加到该角色
{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Resource": "arn:aws:iam::YYYYYYYYYYYY:role/dns-manager","Action": "sts:AssumeRole"}]}
以及以下信任关系(根据需要添加 AWS 服务
)
{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"Service": "ec2.amazonaws.com"},"Action": "sts:AssumeRole"}]}
区域
如果您省略 .spec.acme.solvers.dns01.route53.region
字段,cert-manager 将从 AWS_REGION
和 AWS_DEFAULT_REGION
环境变量中获取区域(如果它们在 cert-manager 控制器 Pod 中设置)。
如果您使用 环境凭据,则 AWS_REGION
和 AWS_DEFAULT_REGION
环境变量具有更高的优先级,并且只有在未设置环境变量时才会使用 .spec.acme.solvers.dns01.route53.region
字段。
如果您使用 EKS Pod Identities,则会忽略 .spec.acme.solvers.dns01.route53.region
字段,因为 Amazon EKS Pod Identity Agent 会将 AWS_REGION
环境变量添加到 cert-manager 控制器 Pod 中。
如果您使用 IAM Roles for Service Accounts (IRSA),则会忽略 .spec.acme.solvers.dns01.route53.region
字段,因为 Amazon EKS Pod Identity Webhook 会将 AWS_REGION
环境变量添加到 cert-manager 控制器 Pod 中。
ℹ️ Route53 是一种全球服务,没有区域端点,但区域用作提示,以帮助计算连接到 Route53 时正确的 AWS 凭据范围和分区。
📖 阅读 Amazon Route 53 端点和配额 和 全局服务,了解更多信息。
ℹ️ STS 是一种区域服务,cert-manager 将使用从
region
字段或环境变量计算的区域 STS 端点 URL。STS 用于 IRSA 凭据、专用 ServiceAccount 凭据 和 跨账户访问。📖 阅读 在 AWS 区域中管理 AWS STS,了解哪些区域支持 STS。
📖 阅读 AWS STS 区域端点,了解如何使用环境变量配置区域 STS 端点的使用。