最新:获取项目更新信息TwitterMastodon

Route53

本指南解释如何设置 IssuerClusterIssuer 以使用 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 请求。

您有两个选择

  1. (最佳实践)使用 具有临时安全凭据的 IAM 角色
  2. 使用 具有长期访问密钥的 IAM 用户

使用具有临时安全凭据的 IAM 角色被认为是最佳实践,因为

  1. 您不必存储长期访问密钥(例如,在秘密中)。
  2. 您不必管理 访问密钥轮换

如果 cert-manager 部署在 AWS 之外,但 DNS 区域位于 Route53 上,则使用 具有长期访问密钥的 IAM 用户 是一个合理的选择。

cert-manager 支持多种获取访问密钥的方法,这些方法可以分为“环境”或“非环境”类别。

环境凭据

环境凭据是通过以下机制之一在 cert-manager 控制器 Pod 中提供的凭据

环境凭据的优点是它们更容易设置,并且由 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/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
...
solvers:
- dns01:
route53: {}

ℹ️ 无论您使用哪种环境机制,都将保留 route53 部分,因为 cert-manager 可以通过查找环境变量来找到凭据、角色和区域,这些环境变量将被添加到 cert-manager Pod 中。

EKS Pod 身份

如果您在 EKS 上部署 cert-manager,EKS Pod 身份 是使用环境凭据的最简单方法。这是一个四步过程

  1. 在您的集群中 设置 EKS Pod 身份代理

  2. 将 IAM 角色分配给 cert-manager Kubernetes 服务帐户。.

  3. 重新启动 cert-manager Deployment,以便 EKS Pod 身份代理可以将必要的环境变量注入到 Pod 中。

  4. 创建一个 ClusterIssuer 资源

    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
    name: letsencrypt-prod
    spec:
    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 中设置一个挂载的服务帐户卷。

  1. 为您的集群创建 IAM OIDC 提供程序

    要将 IRSA 与 cert-manager 一起使用,您必须首先为您的集群启用该功能。请遵循 官方文档

  2. 创建信任关系

    在此配置中,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。权限策略与上面相同。

  3. 对 cert-manager ServiceAccount 进行注释

    apiVersion: v1
    kind: ServiceAccount
    metadata:
    annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-manager

    cert-manager Helm 图表提供了一个变量,用于将注释注入 cert-manager 的 ServiceAccount,如下所示

    serviceAccount:
    annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-manager

    ℹ️ 如果您正在遵循跨账户示例,请使用账户 Y 中的角色修改 ClusterIssuer

  4. (可选) 更新文件系统权限

    📢 请帮助我们改进此文档

    此可选步骤的原因是在 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: 1001
    runAsUser: 1001

    cert-manager Helm 图表提供了一个变量,用于修改 cert-manager 的 Deployment,如下所示

    securityContext:
    fsGroup: 1001
    runAsUser: 1001
  5. 重新启动 cert-manager Deployment

    重新启动 cert-manager Deployment,以便 webhook 可以将必要的 volumevolumemount 和环境变量注入 Pod。

  6. 创建一个 ClusterIssuer 资源

    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
    name: letsencrypt-prod
    spec:
    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 并使用此身份验证机制。

在此配置中,您可以在 IssuerClusterIssuer 中引用您自己的 ServiceAccounts,并且 cert-manager 将从 Kubernetes API 获取 ServiceAccount 令牌,它将将其发送到 STS 以换取 AWS 临时凭据。

此机制的优势在于

  1. 每个 Issuer 都可以引用不同的 ServiceAccount,这意味着您可以锁定权限,这样每个 ServiceAccount 都会映射到一个 IAM 角色,该角色只具有更新其所需区域的权限(与 Pod Identity 或 IRSA 不同)。
  2. 即使 cert-manager 部署在 AWS 之外,此机制也能正常工作。

以下是如何设置它

  1. 创建 ServiceAccount

    为了引用 ServiceAccount,它必须首先存在。与普通的 IRSA 不同,eks.amazonaws.com/role-arn 注释不是必需的。

    apiVersion: v1
    kind: ServiceAccount
    metadata:
    name: <service-account-name>
  2. 创建 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 对象的名称。
  3. 创建 RBAC 角色和 RoleBinding

    为了允许 cert-manager 使用您的 ServiceAccount 发行令牌,您必须将一些 RBAC 部署到集群中

    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
    name: <service-account-name>-tokenrequest
    namespace: <service-account-namespace>
    rules:
    - apiGroups: ['']
    resources: ['serviceaccounts/token']
    resourceNames: ['<service-account-name>']
    verbs: ['create']
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
    name: cert-manager-<service-account-name>-tokenrequest
    namespace: <service-account-namespace>
    subjects:
    - kind: ServiceAccount
    name: <cert-manager-service-account-name>
    namespace: <cert-manager-namespace>
    roleRef:
    apiGroup: rbac.authorization.k8s.io
    kind: Role
    name: <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 部署到的命名空间。
  4. 创建 Issuer 或 ClusterIssuer

    此时您应该已准备好配置 Issuer 以使用新的 ServiceAccount。您可以在下面看到此配置的示例

    apiVersion: cert-manager.io/v1
    kind: Issuer
    metadata:
    name: example
    spec:
    acme:
    ...
    solvers:
    - dns01:
    route53:
    region: us-east-1
    role: <iam-role-arn> # This must be set so cert-manager what role to attempt to authenticate with
    auth:
    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/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
...
solvers:
- dns01:
route53:
region: eu-central-1
accessKeyIDSecretRef:
name: prod-route53-credentials-secret
key: access-key-id
secretAccessKeySecretRef:
name: prod-route53-credentials-secret
key: secret-access-key
# (optional) you can also assume a role with these credentials
role: 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_REGIONAWS_DEFAULT_REGION 环境变量中获取区域(如果它们在 cert-manager 控制器 Pod 中设置)。

如果您使用 环境凭据,则 AWS_REGIONAWS_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 端点的使用。