使用 ACME/Let's Encrypt 证书进行故障排除
了解如何诊断 cert-manager 无法续订 ACME/Let's Encrypt 证书的问题。
概述
在请求 ACME 证书时,cert-manager 会创建 Order
和 Challenges
来完成请求。因此,如果在过程中出现问题,需要调查和调试更多资源。您可以在 概念页面 中阅读更多关于这些资源的信息。
在开始之前,您可能需要查看我们的 常规故障排除指南
1. 故障排除(集群)颁发者
首先检查您正在使用的(集群)颁发者是否处于就绪状态
$ kubectl get issuer$ kubectl get clusterissuerNAME READY AGEletsencrypt True 38mletsencrypt-http False 32m
如果您看到 False
,请使用 kubectl describe
检查状态。例如
$ kubectl describe issuer letsencrypt-http$ kubectl describe clusterissuer letsencrypt-httpName: letsencryptAPI Version: cert-manager.io/v1Kind: IssuerSpec:Acme:Email: cert-manager@example.comPrivate Key Secret Ref:Name: letsencryptServer: https://acme-staging-v02.api.letsencrypt.org/directoryStatus:Acme:Conditions:Message: Failed to update ACME account:400 urn:ietf:params:acme:error:invalidEmail: Unable to update account :: invalid contact domain. Contact emails @example.com are forbiddenReason: ErrUpdateACMEAccountStatus: FalseType: ReadyEvents:Type Reason Age From Message---- ------ ---- ---- -------Warning ErrUpdateACMEAccount 101s (x3 over 106s) cert-manager Failed to update ACME account:400 urn:ietf:params:acme:error:invalidEmail: Unable to update account :: invalid contact domain. Contact emails @example.com are forbidden
常见错误
Failed to update ACME account:400 urn:ietf:params:acme:error:invalidEmail
:您在颁发者配置中指定的电子邮件无效。Error initializing issuer: Failed to register ACME account: secrets "acme-key" already exists
:可能存在先前颁发者遗留的帐户,该帐户不再有效,您应该删除该密钥以便重新创建。Error accepting challenge: 400 urn:ietf:params:acme:error:malformed: Unable to update challenge :: authorization must be pending
:这表明在 cert-manager 向 ACME 服务器发送请求以接受挑战时,授权不在“待处理”状态。这可能是因为域验证已经失败,并且授权已被标记为“无效”。检查Order
或Challenge
状态上的授权 URL 以查看授权的状态和任何其他信息。
2. 故障排除订单
当我们在 CertificateRequest
资源上运行描述时,我们会看到已创建的 Order
$ kubectl describe certificaterequest example-com-2745722290...Events:Type Reason Age From Message---- ------ ---- ---- -------Normal OrderCreated 5s cert-manager Created Order resource default/example-com-2745722290-439160286
订单是向 ACME 实例发出的请求,要求颁发证书。通过在特定订单上运行 kubectl describe order
,可以收集有关过程中故障的信息
$ kubectl describe order example-com-2745722290-439160286...Reason:State: pendingURL: https://acme-v02.api.letsencrypt.org/acme/order/41123272/265506123Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Created 1m cert-manager Created Challenge resource "example-com-2745722290-439160286-0" for domain "test1.example.com"Normal Created 1m cert-manager Created Challenge resource "example-com-2745722290-439160286-1" for domain "test2.example.com"
在这里,我们可以看到 cert-manager 已创建了两个 Challenge 资源来验证我们是否控制了特定域,这是获得签名证书的 ACME 订单的要求。
然后,您可以继续运行 kubectl describe challenge example-com-2745722290-439160286-0
来进一步调试订单的进度。
一旦订单成功,您应该会看到以下事件
$ kubectl describe order example-com-2745722290-439160286...Reason:State: validURL: https://acme-v02.api.letsencrypt.org/acme/order/41123272/265506123Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Created 72s cert-manager Created Challenge resource "example-com-2745722290-439160286-0" for domain "test1.example.com"Normal Created 72s cert-manager Created Challenge resource "example-com-2745722290-439160286-1" for domain "test2.example.com"Normal OrderValid 4s cert-manager Order completed successfully
您可以查看有关需要验证为该订单一部分的 ACME 授权 状态的一些其他信息,方法是使用 Order
状态的授权 URL
$ kubectl get order <order-name> -ojsonpath='{.status.authorizations[x].url}'
如果订单未成功完成,您可以通过在 Challenge
资源上运行 kubectl describe
来调试订单的挑战,这将在以下步骤中介绍。
3. 故障排除挑战
为了确定为什么 ACME 订单没有完成,我们可以使用 cert-manager 创建的 Challenge
资源进行调试。
为了确定哪个 Challenge
失败,您可以运行 kubectl get challenges
$ kubectl get challenges...NAME STATE DOMAIN REASON AGEexample-com-2745722290-4391602865-0 pending example.com Waiting for dns-01 challenge propagation 22s
这表明挑战已使用 DNS01 解析器成功呈现,现在 cert-manager 正在等待“自我检查”通过。
您可以使用 kubectl describe
获取有关挑战及其生命周期的更多信息
$ kubectl describe challenge example-com-2745722290-4391602865-0...Status:Presented: trueProcessing: trueReason: Waiting for dns-01 challenge propagationState: pendingEvents:Type Reason Age From Message---- ------ ---- ---- -------Normal Started 19s cert-manager Challenge scheduled for processingNormal Presented 16s cert-manager Presented challenge using dns-01 challenge mechanism
有关每个挑战状态的进度将作为事件记录,或者记录在 Challenge 的 status
块中(如上所示)。
对于 DNS01,您将在这里找到来自 DNS 提供商的任何错误。
HTTP01 和 DNS01 都在 cert-manager 向 ACME 提供商呈现挑战之前先进行“自我检查”。这样做是为了避免由于 DNS 或负载均衡器传播导致的失败挑战过多而给 ACME 提供商带来过载。此状态可以在描述的 Status 块中找到
$ kubectl describe challenge[...]Status:Presented: trueProcessing: trueReason: Waiting for http-01 challenge propagation: failed to perform self check GET request 'http://example.com/.well-known/acme-challenge/_fgdLz0i3TFiZW4LBjuhjgd5nTOkaMBhxYmTY': Get "http://example.com/.well-known/acme-challenge/_fgdLz0i3TFiZW4LBjuhjgd5nTOkaMBhxYmTY: remote error: tls: handshake failureState: pending[...]
在这个例子中,我们的 HTTP01 检查由于网络问题而失败。您还将在这里看到来自您的 DNS 提供商的任何错误。
您还可以查看有关挑战应验证的 ACME 授权 状态的一些其他信息,方法是使用 Challenge
状态上的授权 URL
$ kubectl get challenge <challenge-name> -ojsonpath='{.spec.authorizationURL}'
HTTP01 故障排除
首先检查您是否可以从公共互联网看到挑战 URL,如果无法正常工作,请检查您的 Ingress 和防火墙配置以及 cert-manager 创建的用于解决 ACME 挑战的服务和 pod。如果此操作有效,请检查您的集群是否也可以看到它。重要的是从 Pod 内部测试这一点。如果您收到连接错误,建议检查集群的网络配置。如果您收到 tls: handshake failure
,请尝试在 Ingress 或 Certificate 资源上设置注释 cert-manager.io/issue-temporary-certificate: "true"
。这将为 Ingress 控制器颁发一个临时自签名证书,以在颁发实际证书之前使用。如果您仍然遇到问题,则您的 Ingress 控制器可能存在为同一个主机名处理多个资源的问题,在这种情况下,可能需要注释 acme.cert-manager.io/http01-edit-in-place: "true"
。
例如,在使用 GKE 和 Google Cloud Loadbalancer 时,建议设置
cert-manager.io/issue-temporary-certificate: "true"acme.cert-manager.io/http01-edit-in-place: "true"
这将允许 Google Cloud Loadbalancer 使用临时证书正确传播 HTTPS 端点,http01-edit-in-place
部分将阻止 GKE 为挑战端点分配第二个 IP 地址。
收到 404 状态代码
如果您的挑战自我检查失败并显示 404 未找到错误。请确保检查以下内容
- 您可以从公共互联网访问 URL
- ACME 解析器 pod 正在运行
- 使用
kubectl describe ingress
检查 HTTP01 解析器 Ingress 的状态。(除非您使用acme.cert-manager.io/http01-edit-in-place
,否则检查与您的域相同的 Ingress)
DNS01 故障排除
如果您没有看到有关您的 DNS 提供商的错误事件,您可以检查以下内容:检查您是否可以从公共互联网或在您的 DNS 提供商的界面中看到 _acme_challenge.domain
TXT DNS 记录。cert-manager 会通过查询集群的 DNS 解析器来检查 DNS 记录是否已传播。如果您能够从公共互联网看到它,但不能从集群内部看到它,您可能需要更改 用于自我检查的 DNS 服务器,因为某些云提供商会在内部覆盖 DNS。
cert-manager 识别了您域名错误的区域
cert-manager 默认使用 SOA(授权开始)记录来确定在您的 DNS 提供商处使用哪个区域名称。某些 DNS 解析器会过滤此信息,如果发生这种情况,cert-manager 无法确定区域,建议您更改 DNS01 自检的 DNS 服务器.
如果您使用dnsmasq
作为您的 DNS 服务器,如果您使用--filterwin2k
标志,则可能会发生这种情况。在OpenWRT 中有一个filterwin2k
配置选项。在LuCI 中有一个“过滤无用”选项。通过启用此标志,dnsmasq
会丢弃所有SOA
记录。
2020 年 3 月 Let's Encrypt CAA 重新检查错误
继3 月 4 日的公告之后,Let's Encrypt 将撤销一些证书,因为它们在验证 CAA 记录的方式上存在 bug,我们创建了一个工具来分析您现有的 cert-manager 管理的证书,并将它们的序列号与公布的已撤销证书列表进行比较。建议所有 Let's Encrypt 和 cert-manager 用户使用此工具进行检查,以确保他们在集群中不会遇到任何无效证书错误。您可以在此处找到检查工具的副本:https://github.com/jetstack/letsencrypt-caa-bug-checker.