簡體   English   中英

可以從 cert-manager/letsencrypt 獲取 TLS 證書,用於 kube.netes 中的測試或生產環境,但不能同時獲取兩者

[英]Can get TLS certificates from cert-manager/letsencrypt for either testing or production enviroments in kubernetes, but not both

我編寫了一個 bash 腳本來使用 helm 和 kubectl 在 kube.netes 集群中自動部署應用程序。 我使用cert-manager來自動頒發和更新應用程序本身所需的letsencrypt獲得的 TLS 證書。

該腳本可以根據需要使用不同的設置和清單將應用程序部署在許多環境之一中,例如測試 (test) 和生產 (prod)。 對於每個環境,我創建一個單獨的名稱空間並在其中部署所需的資源。 在生產中,我使用letsencrypt生產服務器 (spec.acme.server: https://acme-v02.api.letsencrypt.org/directory ) 而在任何其他環境中,例如測試,我使用臨時服務器 (spec.acme .server: https://acme-staging-v02.api.letsencrypt.org/directory )。 我請求證書的主機名根據環境而有所不同:測試中的 xyz.test.mysite.tld 與生產中的 xyz.mysite.tld 我為所有環境提供相同的聯系電子郵件地址。

這里是用於測試的 letsencrypt 發行者的完整清單:

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    email: operations@mysite.tld
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-staging-issuer-private-key
    solvers:
    - http01:
        ingress:
          class: public-test-it-it

這里是用於生產的 letsencrypt 發行者的完整清單:

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-production
spec:
  acme:
    email: operations@mysite.tld
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-production-issuer-private-key
    solvers:
    - http01:
        ingress:
          class: public-prod-it-it

當我第一次部署應用程序時,無論是在測試環境還是生產環境中,一切都按預期工作,並且 cert-manager 獲得由 letsencrypt(分別是暫存服務器或生產服務器)簽名的 TLS 證書並存儲在秘密中。 但是當我在另一個環境中部署應用程序時(這樣我就可以同時運行測試和生產),cert-manager 無法再對證書進行簽名,並且鏈 certificaterequest->order->challenge 在挑戰步驟停止使用以下 output:

kubectl describe challenge xyz-tls-certificate
...
Status:
  Presented:   true
  Processing:  true
  Reason:      Waiting for HTTP-01 challenge propagation: wrong status code '404', expected '200'
  State:       pending
Events:        <none>

我可以驗證在嘗試 curl 任何挑戰的 URL 時我確實得到了 404:

curl -v http://xyz.test.mysite.tld/.well-known/acme-challenge/IECcFDmQF_fzGKcA9hJvFGEWRjDCAE_fs8dnBXlr_wY
*   Trying vvv.xxx.yyy.zzz:80...
* Connected to xyz.test.mysite.tld (vvv.xxx.yyy.zzz) port 80 (#0)
> GET /.well-known/acme-challenge/IECcFDmQF_fzGKcA9hJvFGEWRjDCAE_fs8dnBXlr_wY HTTP/1.1
> Host: xyz.test.mysite.tld
> User-Agent: curl/7.74.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< date: Thu, 21 Jul 2022 09:48:08 GMT
< content-length: 21
< content-type: text/plain; charset=utf-8
< 
* Connection #0 to host xyz.test.mysite.tld left intact
default backend - 404

所以 letsencrypt 無法訪問挑戰的 URL,也不會簽署 TLS 證書。

我嘗試調試 404 錯誤,發現我可以成功 curl 支持來自在集群/命名空間中運行的另一個 pod 的挑戰的 pod 和服務,但我從外部世界收到 404s。 這似乎是入口 controller 的問題(在我的例子中是 HAProxytech/kube.netes-ingress),但我無法解釋為什么該機制在第一次部署時起作用,然后就不再起作用了。

我檢查了證書管理器日志並發現了以下行:

kubectl logs -n cert-manager cert-manager-...
I0721 13:27:45.517637       1 ingress.go:99] cert-manager/challenges/http01/selfCheck/http01/ensureIngress "msg"="found one existing HTTP01 solver ingress" "dnsName"="xyz.test.mysite.tld" "related_resource_kind"="Ingress" "related_resource_name"="cm-acme-http-solver-8668s" "related_resource_namespace"="app-test-it-it" "related_resource_version"="v1" "resource_kind"="Challenge" "resource_name"="xyz-tls-certificate-hwvjf-2516368856-1193545890" "resource_namespace"="app-test-it-it" "resource_version"="v1" "type"="HTTP-01" 
E0721 13:27:45.527238       1 sync.go:186] cert-manager/challenges "msg"="propagation check failed" "error"="wrong status code '404', expected '200'" "dnsName"="xyz.test.mysite.tld" "resource_kind"="Challenge" "resource_name"="xyz-tls-certificate-hwvjf-2516368856-1193545890" "resource_namespace"="app-test-it-it" "resource_version"="v1" "type"="HTTP-01" 

這似乎證實了 cert-manager 可以從集群內部自我檢查挑戰的 URL 是否存在,但外部世界無法訪問這些 URL(傳播檢查失敗)。 看起來 cert-manager 設置挑戰的 pod/服務/入口沒問題,但是發送到挑戰的 URL 的請求不會路由到支持的 pod/服務。 這只是我第二次嘗試部署應用程序..

我還驗證了,在第一次部署時頒發證書后,cert-manager(正確地)從相關命名空間中刪除了所有相關的 pod/服務/入口,因此重復挑戰的資源不應該有任何沖突。

我在這里重申,證書是在我第一次部署應用程序時完美頒發的,無論是在測試環境還是生產環境中,但如果我在不同的環境中再次部署應用程序,它們將不再頒發。

知道為什么會這樣嗎?

終於知道是什么問題了。。

基本上,我為每個環境(測試/產品)安裝了一個單獨的 HAProxy ingress controller (haproxytech/kube.netes-ingress),因此每個命名空間都有自己的 ingress controller,我在我的清單中引用了它。 這在原則上應該可行,但事實證明,證書管理器在設置 letsencrypt 挑戰時無法引用正確的入口控制器。

該解決方案包括創建一個單一的 HAproxy 入口 controller(在它自己單獨的命名空間中)來服務整個集群並被所有其他環境/命名空間引用。 通過這種方式,測試和生產環境的挑戰由證書管理器正確設置並由 letsencrypt 驗證,后者簽署了所需的證書。

最后,我強烈建議每個集群使用一個 HAproxy ingress controller,安裝在它自己的命名空間中。 此配置冗余度較低,並消除了潛在問題,例如我遇到的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM