使用 cert-manager 签发免费证书
概述
隨著 HTTPS 不斷普及,越來越多的網(wǎng)站都在從 HTTP 升級(jí)到 HTTPS,使用 HTTPS 就需要向權(quán)威機(jī)構(gòu)申請(qǐng)證書,需要付出一定的成本,如果需求數(shù)量多,也是一筆不小的開支。cert-manager 是 Kubernetes 上的全能證書管理工具,如果對(duì)安全級(jí)別和證書功能要求不高,可以利用 cert-manager 基于 ACME 協(xié)議與 Let's Encrypt 來簽發(fā)免費(fèi)證書并自動(dòng)續(xù)期,實(shí)現(xiàn)永久免費(fèi)使用證書。
cert-manager 工作原理
cert-manager 部署到 Kubernetes 集群后,它會(huì) watch 它所支持的 CRD 資源,我們通過創(chuàng)建 CRD 資源來指示 cert-manager 為我們簽發(fā)證書并自動(dòng)續(xù)期:
?
解釋下幾個(gè)關(guān)鍵的資源:
- Issuer/ClusterIssuer: 用于指示 cert-manager 用什么方式簽發(fā)證書,本文主要講解簽發(fā)免費(fèi)證書的 ACME 方式。ClusterIssuer 與 Issuer 的唯一區(qū)別就是 Issuer 只能用來簽發(fā)自己所在 namespace 下的證書,ClusterIssuer 可以簽發(fā)任意 namespace 下的證書。
- Certificate: 用于告訴 cert-manager 我們想要什么域名的證書以及簽發(fā)證書所需要的一些配置,包括對(duì) Issuer/ClusterIssuer 的引用。
免費(fèi)證書簽發(fā)原理
Let’s Encrypt 利用 ACME 協(xié)議來校驗(yàn)域名是否真的屬于你,校驗(yàn)成功后就可以自動(dòng)頒發(fā)免費(fèi)證書,證書有效期只有 90 天,在到期前需要再校驗(yàn)一次來實(shí)現(xiàn)續(xù)期,幸運(yùn)的是 cert-manager 可以自動(dòng)續(xù)期,這樣就可以使用永久免費(fèi)的證書了。如何校驗(yàn)這個(gè)域名是否屬于你呢?主流的兩種校驗(yàn)方式是 HTTP-01 和 DNS-01,詳細(xì)校驗(yàn)原理可參考 Let's Encrypt 的運(yùn)作方式,下面將簡(jiǎn)單描述下。
HTTP-01 校驗(yàn)原理
HTTP-01 的校驗(yàn)原理是給你域名指向的 HTTP 服務(wù)增加一個(gè)臨時(shí) location ,Let’s Encrypt 會(huì)發(fā)送 http 請(qǐng)求到 http:///.well-known/acme-challenge/,YOUR_DOMAIN 就是被校驗(yàn)的域名,TOKEN 是 ACME 協(xié)議的客戶端負(fù)責(zé)放置的文件,在這里 ACME 客戶端就是 cert-manager,它通過修改或創(chuàng)建 Ingress 規(guī)則來增加這個(gè)臨時(shí)校驗(yàn)路徑并指向提供 TOKEN 的服務(wù)。Let’s Encrypt 會(huì)對(duì)比 TOKEN 是否符合預(yù)期,校驗(yàn)成功后就會(huì)頒發(fā)證書。此方法僅適用于給使用 Ingress 暴露流量的服務(wù)頒發(fā)證書,并且不支持泛域名證書。
DNS-01 校驗(yàn)原理
DNS-01 的校驗(yàn)原理是利用 DNS 提供商的 API Key 拿到你的 DNS 控制權(quán)限, 在 Let’s Encrypt 為 ACME 客戶端提供令牌后,ACME 客戶端 (cert-manager) 將創(chuàng)建從該令牌和您的帳戶密鑰派生的 TXT 記錄,并將該記錄放在 _acme-challenge.。 然后 Let’s Encrypt 將向 DNS 系統(tǒng)查詢?cè)撚涗?#xff0c;如果找到匹配項(xiàng),就可以頒發(fā)證書。此方法不需要你的服務(wù)使用 Ingress,并且支持泛域名證書。
校驗(yàn)方式對(duì)比
HTTP-01 的校驗(yàn)方式的優(yōu)點(diǎn)是: 配置簡(jiǎn)單通用,不管使用哪個(gè) DNS 提供商都可以使用相同的配置方法;缺點(diǎn)是:需要依賴 Ingress,如果你的服務(wù)不是用 Ingress 暴露流量的就不適用,而且不支持泛域名證書。
DNS-01 的校驗(yàn)方式的優(yōu)點(diǎn)是沒有 HTTP-01 校驗(yàn)方式缺點(diǎn),不依賴 Ingress,也支持泛域名;缺點(diǎn)就是不同 DNS 提供商的配置方式不一樣,而且 DNS 提供商有很多,cert-manager 的 Issuer 不可能每個(gè)都去支持,不過有一些可以通過部署實(shí)現(xiàn)了 cert-manager 的 Webhook 的服務(wù)來擴(kuò)展 Issuer 進(jìn)行支持,比如 DNSPod 和 阿里 DNS,詳細(xì) Webhook 列表請(qǐng)參考: https://cert-manager.io/docs/configuration/acme/dns01/#webhook
選擇哪種方式呢?條件允許的話,建議是盡量用 DNS-01 的方式,限制更少,功能更全。
操作步驟
安裝 cert-manager
通常直接使用 yaml 方式一鍵安裝 cert-manager 到集群,參考官網(wǎng)文檔 Installing with regular manifests。
cert-manager 官方使用的鏡像在 quay.io,國(guó)內(nèi)拉取可能比較慢,也可以使用下面命令一鍵安裝(使用同步到國(guó)內(nèi) CCR 的鏡像):
?
kubectl apply --validate=false -f https://raw.githubusercontent.com/TencentCloudContainerTeam/manifest/master/cert-manager/cert-manager.yaml! 以上命令安裝方式要求集群版本不低于 1.16。
配置 DNS
登錄你的 DNS 提供商后臺(tái),配置域名的 DNS A 記錄,指向你需要證書的后端服務(wù)對(duì)外暴露的 IP 地址,以 cloudflare 為例:
?
HTTP-01 校驗(yàn)方式簽發(fā)證書
如果使用 HTTP-01 的校驗(yàn)方式,需要用到 Ingress 來配合校驗(yàn)。cert-manager 會(huì)通過自動(dòng)修改 Ingress 規(guī)則或自動(dòng)新增 Ingress 來實(shí)現(xiàn)對(duì)外暴露校驗(yàn)所需的臨時(shí) HTTP 路徑,這個(gè)就是在給 Issuer 配置 http01 校驗(yàn),指定 Ingress 的 name 或 class 的區(qū)別 (見下面的示例)。
TKE 自帶的 Ingress 是每個(gè) Ingress 資源都會(huì)對(duì)應(yīng)一個(gè) CLB,如果你使用 TKE 自帶的 Ingress 暴露服務(wù),并且使用 HTTP-01 方式校驗(yàn),那么只能使用自動(dòng)修改 Ingress 的方式,不能自動(dòng)新增 Ingress,因?yàn)樽詣?dòng)新增出來的 Ingress 會(huì)自動(dòng)創(chuàng)建其它 CLB,對(duì)外的 IP 地址就與我們后端服務(wù)的 Ingress 不一致,Let's Encrypt 校驗(yàn)時(shí)就無法從我們服務(wù)的 Ingress 找到校驗(yàn)所需的臨時(shí)路徑,從而導(dǎo)致校驗(yàn)失敗,無法簽發(fā)證書。如果使用自建 Ingress,比如 在 TKE 上部署 Nginx Ingress,同一個(gè) Ingress class 的 Ingress 共享同一個(gè) CLB,這樣就可以使用自動(dòng)新增 Ingress 的方式。
下面給出一些示例。
如果你的服務(wù)使用 TKE 自帶的 Ingress 暴露服務(wù),不太適合用 cert-manager 簽發(fā)管理免費(fèi)證書,因?yàn)樽C書是要上傳到 證書管理 來引用的,不在 K8S 中管理。
假設(shè)是 在 TKE 上部署 Nginx Ingress,且后端服務(wù)的 Ingress 是 prod/web,創(chuàng)建 Issuer 示例:
?
apiVersion: cert-manager.io/v1 kind: Issuer metadata:name: letsencrypt-http01namespace: prod spec:acme:server: https://acme-v02.api.letsencrypt.org/directoryprivateKeySecretRef:name: letsencrypt-http01-account-keysolvers:- http01:ingress:name: web # 指定被自動(dòng)修改的 Ingress 名稱使用上面的 Issuer 簽發(fā)證書,cert-manager 會(huì)自動(dòng)修改 prod/web 這個(gè) Ingress 資源,以暴露校驗(yàn)所需的臨時(shí)路徑,這是自動(dòng)修改 Ingress 的方式,你可以使用自動(dòng)新增 Ingress 的 方式,示例:
?
apiVersion: cert-manager.io/v1 kind: Issuer metadata:name: letsencrypt-http01namespace: prod spec:acme:server: https://acme-v02.api.letsencrypt.org/directoryprivateKeySecretRef:name: letsencrypt-http01-account-keysolvers:- http01:ingress:class: nginx # 指定自動(dòng)創(chuàng)建的 Ingress 的 ingress class使用上面的 Issuer 簽發(fā)證書,cert-manager 會(huì)自動(dòng)創(chuàng)建 Ingress 資源,以暴露校驗(yàn)所需的臨時(shí)路徑。
有了 Issuer,接下來就可以創(chuàng)建 Certificate 并引用 Issuer 進(jìn)行簽發(fā)了,示例:
?
apiVersion: cert-manager.io/v1 kind: Certificate metadata:name: test-mydomain-comnamespace: prod spec:dnsNames:- test.mydomain.com # 要簽發(fā)證書的域名issuerRef:kind: Issuername: letsencrypt-http01 # 引用 Issuer,指示采用 http01 方式進(jìn)行校驗(yàn)secretName: test-mydomain-com-tls # 最終簽發(fā)出來的證書會(huì)保存在這個(gè) Secret 里面DNS-01 校驗(yàn)方式簽發(fā)證書
如果使用 DNS-01 的校驗(yàn)方式,就需要看你使用的哪個(gè) DNS 提供商了,cert-manager 內(nèi)置了一些 DNS 提供商的支持,詳細(xì)列表和用法請(qǐng)參考 Supported DNS01 providers,不過 cert-manager 不可能去支持所有的 DNS 提供商,如果沒有你所使用的 DNS 提供商怎么辦呢?有兩種方案:
-
方案一:設(shè)置 Custom Nameserver。在你的 DNS 提供商后臺(tái)設(shè)置 custom nameserver,指向像 cloudflare 這種可以管理其它 DNS 提供商域名的 nameserver 地址,具體地址可登錄 cloudflare 后臺(tái)查看:
?
下面是 namecheap 設(shè)置 custom nameserver 的示例:
?
最后配置 Issuer 指定 DNS-01 驗(yàn)證時(shí),加上 cloudflare 的一些信息即可(見下文示例)。
-
方案二:使用 Webhook。使用 cert-manager 的 Webhook 來擴(kuò)展 cert-manager 的 DNS-01 驗(yàn)證所支持的 DNS 提供商,已經(jīng)有許多第三方實(shí)現(xiàn),包括國(guó)內(nèi)常用的 DNSPod 與阿里 DNS,詳細(xì)列表參考: Webhook。
下面以 cloudflare 為例來簽發(fā)證書:
登錄 cloudflare,點(diǎn)到 My Profile > API Tokens > Create Token 來創(chuàng)建 Token:
?
復(fù)制 Token 并妥善保管:
?
將 Token 保存到 Secret 中:
apiVersion: v1 kind: Secret metadata:name: cloudflare-api-token-secretnamespace: cert-manager type: Opaque stringData:api-token: <API Token> # 粘貼 Token 到這里,不需要 base64 加密。! 如果是要?jiǎng)?chuàng)建 ClusterIssuer,Secret 需要?jiǎng)?chuàng)建在 cert-manager 所在命名空間中,如果是 Issuer,那就創(chuàng)建在 Issuer 所在命名空間中。
創(chuàng)建 ClusterIssuer:
apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata:name: letsencrypt-dns01 spec:acme:privateKeySecretRef:name: letsencrypt-dns01server: https://acme-v02.api.letsencrypt.org/directorysolvers:- dns01:cloudflare:email: my-cloudflare-acc@example.com # 替換成你的 cloudflare 郵箱賬號(hào),API Token 方式認(rèn)證非必需,API Keys 認(rèn)證是必需apiTokenSecretRef:key: api-tokenname: cloudflare-api-token-secret # 引用保存 cloudflare 認(rèn)證信息的 Secret創(chuàng)建 Certificate:
apiVersion: cert-manager.io/v1 kind: Certificate metadata:name: test-mydomain-comnamespace: default spec:dnsNames:- test.mydomain.com # 要簽發(fā)證書的域名issuerRef:kind: ClusterIssuername: letsencrypt-dns01 # 引用 ClusterIssuer,指示采用 dns01 方式進(jìn)行校驗(yàn)secretName: test-mydomain-com-tls # 最終簽發(fā)出來的證書會(huì)保存在這個(gè) Secret 里面獲取和使用證書
創(chuàng)建好 Certificate 后,等一小會(huì)兒,我們可以 kubectl 查看是否簽發(fā)成功:
?
$ kubectl get certificate -n prod NAME READY SECRET AGE test-mydomain-com True test-mydomain-com-tls 1m如果 READY 為 False 表示失敗,可以通過 describe 查看 event 來排查失敗原因:
?
$ kubectl describe certificate test-mydomain-com -n prod如果為 True 表示簽發(fā)成功,證書就保存在我們所指定的 Secret 中 (上面的例子是 default/test-mydomain-com-tls),可以通過 kubectl 查看:
?
$ kubectl get secret test-mydomain-com-tls -n default ... data:tls.crt: <cert>tls.key: <private key>其中 tls.crt 就是證書,tls.key 是密鑰。
你可以將它們掛載到你需要證書的應(yīng)用中,或者使用自建的 Ingress,可以直接在 Ingress 中引用 secret,示例:
?
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata:name: test-ingressannotations:kubernetes.io/Ingress.class: nginx spec:rules:- host: test.mydomain.comhttp:paths:- path: /webbackend:serviceName: webservicePort: 80tls:hosts:- test.mydomain.comsecretName: test-mydomain-com-tls小結(jié)
本文介紹了 cert-manager 的工作原理,安裝方法以及簽發(fā)免費(fèi)證書的兩種校驗(yàn)方式 (HTTP-01 與 DNS-01) 的原理、對(duì)比以及操作方法。
參考資料
- cert-manager 官網(wǎng): https://cert-manager.io/
- Let's Encrypt 的運(yùn)作方式: https://letsencrypt.org/zh-cn/how-it-works/
- Issuer API 文檔: https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.Issuer
- Certificate API 文檔: https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.Certificate
作者:騰訊云原生
鏈接:https://www.jianshu.com/p/873e89179841
來源:簡(jiǎn)書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
總結(jié)
以上是生活随笔為你收集整理的使用 cert-manager 签发免费证书的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Cert manager自动签发/更新证
- 下一篇: 建设研发运营一体化平台