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 伺服器發送請求以接受挑戰時,授權並未處於「pending」狀態。這可能是因為網域驗證已失敗,並且授權已被標記為「invalid」。請查看Order
或Challenge
的狀態上的授權 URL,以查看授權的狀態和任何其他資訊。
2. 疑難排解 Order
當我們在 CertificateRequest
資源上執行 describe 時,我們可以看到已建立 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
Order 是向 ACME 實例發出憑證的請求。藉由在特定 order 上執行 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 order 取得簽署憑證的要求。
然後,您可以繼續執行 kubectl describe challenge example-com-2745722290-439160286-0
,以進一步除錯 Order 的進度。
一旦 Order 成功,您應該會看到類似以下的事件
$ 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
您可以使用 Order
狀態中的授權 URL,查看更多關於需要驗證的ACME 授權狀態的額外資訊。
$ kubectl get order <order-name> -ojsonpath='{.status.authorizations[x].url}'
如果 Order 未成功完成,您可以執行 kubectl describe
來除錯 Order 的挑戰,這在以下步驟中說明。
3. 疑難排解 Challenges
為了判斷 ACME Order 未完成的原因,我們可以使用 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
每個挑戰的狀態進度將記錄為事件或挑戰的 status
區塊(如上所示)。
在 DNS01 的情況下,您會在此處找到來自 DNS 提供者的任何錯誤。
HTTP01 和 DNS01 都會先經過「自我檢查」,然後 cert-manager 才會向 ACME 提供者呈現挑戰。這樣做是為了避免因 DNS 或負載平衡器傳播而導致失敗的挑戰使 ACME 提供者超載。此狀態可以在 describe 的 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 提供者的任何錯誤。
您可以使用 Challenge
狀態中的授權 URL,查看更多關於挑戰應驗證的ACME 授權狀態的額外資訊。
$ kubectl get challenge <challenge-name> -ojsonpath='{.spec.authorizationURL}'
HTTP01 疑難排解
首先,檢查您是否可以從公共網際網路看到挑戰 URL,如果這不起作用,請檢查您的 Ingress 和防火牆設定,以及 cert-manager 建立來解決 ACME 挑戰的服務和 pod。如果這確實有效,請檢查您的叢集是否也能看到它。從 Pod 內部進行測試非常重要。如果您收到連線錯誤,建議檢查叢集的網路設定。如果您收到 tls: handshake failure
,請嘗試在 Ingress 或憑證資源上設定註釋 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 記錄的方式存在錯誤而撤銷許多憑證,我們建立了一個工具來分析您現有的 cert-manager 管理的憑證,並將其序號與已發布的撤銷憑證列表進行比較。建議 Let's Encrypt 和 cert-manager 的所有使用者都使用此工具執行檢查,以確保他們在叢集中不會遇到任何無效的憑證錯誤。您可以在這裡找到檢查工具的副本:https://github.com/jetstack/letsencrypt-caa-bug-checker。