K8s 中使用 cert-manager 申请免费 Https 证书
K8s 中使用 cert-manager 申請免費 Https 證書
Intro
最近在嘗試將自己的應用從自己用 kind 部署的一個 k8s 集群遷移到 Azure 的 AKS 上,其中一個問題就是 https 證書,原來的 k8s 集群是放在 nginx 后端的并沒有直接管理 https 證書,https 證書是放在 nginx 層面的,完全運行在 AKS 上的 k8s 集群中就要解決 https 證書的問題,我們可以使用 cert-manager 來申請由 Let's encrypt 提供的免費 https 證書,因為我的域名是在阿里云上的,并不在官方的 DNS 服務商支持范圍內,所以需要使用第三方的實現(xiàn)的 webhook 支持,而網上的一些第三方的很多 API version 都不對了,而且使用起來感覺也不太方便,所以自己基于別人的魔改了一版,完善了 helm 的支持,基本可以一個命令創(chuàng)建所有需要的資源
Cert-manager
隨著 HTTPS 不斷普及,越來越多的網站都在從 HTTP 升級到 HTTPS,現(xiàn)在如果不使用 https Chrome 瀏覽器都會提示不安全,而且有些服務可能會要求必須是 https 才可以,而 Let's encrypt 為大家提供了免費的 https 證書,免費證書的時間是三個月,我們可以在過期之前重新申請,對于個人來說是個不錯的選擇。
cert-manager 是 Kubernetes 上的全能證書管理工具,如果對安全級別和證書功能要求不高,可以利用 cert-manager 基于 ACME 協(xié)議與 Let's Encrypt 來簽發(fā)免費證書并自動續(xù)期,實現(xiàn)永久免費使用證書。
下面這張圖是一個 cert-manager 的總體架構圖
High level overview diagram explaining cert-manager architectureIssuer 是指證書的來源,它可以從各種受支持的來源頒發(fā)證書,包括 Let's Encrypt、HashiCorp Vault 和 Venafi 以及私有 PKI。
Certificates 就是指的證書,證書是由指定的 issuer 來簽發(fā)的
Kubernetes secrets 一般是指保存 https 證書的 secret,使用 https 的時候會用到這種 kubernetes.io/tls 類型的 secret
Issuer/ClusterIssuer: 用于指示 cert-manager 用什么方式簽發(fā)證書,本文主要講解簽發(fā)免費證書的 ACME 方式。ClusterIssuer 與 Issuer 的唯一區(qū)別就是 Issuer 只能用來簽發(fā)自己所在 namespace 下的證書,ClusterIssuer 可以簽發(fā)任意 namespace 下的證書。
Certificate: 用于告訴 cert-manager 我們想要什么域名的證書以及簽發(fā)證書所需要的一些配置,包括對 Issuer/ClusterIssuer 的引用
Let’s Encrypt 利用 ACME 協(xié)議來校驗域名是否真的屬于你,校驗成功后就可以自動頒發(fā)免費證書,證書有效期只有 90 天,在到期前需要再校驗一次來實現(xiàn)續(xù)期, cert-manager 可以自動續(xù)期,這樣就可以基本使用永久免費的證書了。如何校驗這個域名是否屬于你呢?主要有兩種校驗方式是 HTTP-01 和 DNS-01
HTTP-01 校驗原理
HTTP-01 的校驗原理是給你域名指向的 HTTP 服務增加一個臨時 location ,Let’s Encrypt 會發(fā)送 http 請求到 http:///.well-known/acme-challenge/,YOUR_DOMAIN 就是被校驗的域名,TOKEN 是 ACME 協(xié)議的客戶端負責放置的文件,在這里 ACME 客戶端就是 cert-manager,它通過修改或創(chuàng)建 Ingress 規(guī)則來增加這個臨時校驗路徑并指向提供 TOKEN 的服務。Let’s Encrypt 會對比 TOKEN 是否符合預期,校驗成功后就會頒發(fā)證書。此方法僅適用于給使用 Ingress 暴露流量的服務頒發(fā)證書,并且不支持泛域名證書。
DNS-01 校驗原理
DNS-01 的校驗原理是利用 DNS 提供商的 API Key 拿到你的 DNS 控制權限, 在 Let’s Encrypt 為 ACME 客戶端提供令牌后,ACME 客戶端 (cert-manager) 將創(chuàng)建從該令牌和您的帳戶密鑰派生的 TXT 記錄,并將該記錄放在 _acme-challenge.。然后 Let’s Encrypt 將向 DNS 系統(tǒng)查詢該記錄,如果找到匹配項,就可以頒發(fā)證書。此方法不需要你的服務使用 Ingress,并且支持泛域名證書。
HTTP-01 的校驗方式配置簡單通用,不管使用哪個 DNS 提供商都可以使用相同的配置方法;缺點是:需要依賴 Ingress,如果你的服務不是用 Ingress 暴露流量的就不適用,而且不支持泛域名證書。
DNS-01 的校驗方式不依賴 Ingress,也支持泛域名;缺點就是不同 DNS 提供商的配置方式不一樣,而且 DNS 提供商有很多,cert-manager 的 Issuer 不可能每個都去支持,不過有一些可以通過部署實現(xiàn)了 cert-manager 的 Webhook 的服務來擴展 Issuer 進行支持,比如 DNSPod 和 阿里 DNS,詳細 Webhook 列表請參考: https://cert-manager.io/docs/configuration/acme/dns01/#webhook
Sample
這里假定以后安裝好了 helm3,如果沒有安裝可以參考:https://helm.sh/docs/intro/install/ 先安裝 helm
首先我們需要安裝 cert-manager,你可以執(zhí)行下面的命令來通過 helm 安裝 cert-manager
helm?repo?add?jetstack?https://charts.jetstack.iohelm?repo?updatehelm?install?cert-manager?jetstack/cert-manager?-n?cert-manager?--create-namespace?--set?installCRDs=true?--version?v1.6.1安裝完 cert-manager 之后,就可以配置 issuer 和 證書了
HTTP-01 比較簡單,基本按照文檔就可以走通了,這里不多介紹了 https://cert-manager.io/docs/tutorials/acme/http-validation/
如果你的 DNS 服務商官方就支持了也是跟著文檔配置就可以了 https://cert-manager.io/docs/tutorials/acme/dns-validation/
而阿里云目前并非官方支持的,你需要使用第三方的,覺得不好用的,可以像我一樣基于別人的配置改造一下,下面我們就以阿里云為例來介紹使用 cert-manager 來配置阿里云的 DNS,以我改造的 AliDNS webhook 為例
首先克隆項目 https://github.com/WeihanLi/certmanager-webhook-alidns 到本地,然后在項目根目錄下執(zhí)行下面的命令來配置證書
#?切換目錄到?helm?chart?包目錄 cd?deploy/certmanager-webhook-alidns#?render?template,只展示渲染后的?yaml?文件,不安裝 helm?template?certmanager-webhook-alidns?.?--set?issuer.create=true?--set?issuer.host=weihanli.top?--set?issuer.email=weihanli@outlook.com?--set?issuer.secret.accessKeyId=AliAccessKeyId?--set?issuer.secret.accessKeySecret=AliAccessKeySecret?-n?cert-manager#?install?without?creating?ClusterIssuer,安裝?webhook,但是不創(chuàng)建證書?issuer?和申請證書 helm?install?certmanager-webhook-alidns?.?-n?cert-manager#?install?with?creating?ClusterIssuer,安裝?webhook?并創(chuàng)建證書?issuer?和申請?https?證書 helm?install?certmanager-webhook-alidns?.?--set?issuer.create=true?--set?issuer.host=weihanli.top?--set?issuer.email=weihanli@outlook.com?--set?issuer.secret.accessKeyId=AliAccessKeyId?--set?issuer.secret.accessKeySecret=AliAccessKeySecret?-n?cert-manager可以使用 helm template 來測試自己要安裝的資源情況
默認只安裝 webhook 不會創(chuàng)建 ClusterIssuer 以及證書,如果要創(chuàng)建需要提供更多參數(shù),需要指定 issuer.create 為 true,然后通過 issuer.email 來指定申請證書的郵箱,并且需要提供阿里云的 accessKeyId 和 accessKeySecret 來修改 DNS 解析記錄以實現(xiàn)自動地 DNS 驗證進而自動簽發(fā)證書,默認地創(chuàng)建 ClusterIssuer 的時候也會創(chuàng)建一個證書,如果不需要創(chuàng)建證書則配置 issuer.createCert 為 false,如果要創(chuàng)建需要指定一個域名,比如 weihanli.top
上面最后一個命令會自動創(chuàng)建證書,安裝完成后,我們就可以去檢查我們的證書了,執(zhí)行kubectl get cert -n cert-manager 來查看 cert-manager 命名空間下的證書,上面命令創(chuàng)建的證書名稱是 weihanli-top-tls-cert,會是 host 名字把 . 替換成 - 然后加上 -tls-cert,證書簽發(fā)完成 kubectl get secret -n cert-manager 會看到和證書同名的一個 secret
類似下面這樣
| weihanli-top-tls-cert | kubernetes.io/tls | 2 | 4d |
上面的命令會創(chuàng)建一個 ClusterIssuer 和 Certificate,yaml 定義如下:
apiVersion:?cert-manager.io/v1 kind:?ClusterIssuer metadata:name:?letsencryptlabels:app:?webhook-alidnschart:?webhook-alidns-0.1.0release:?certmanager-webhook-alidnsheritage:?Helm spec:acme:server:?https://acme-v02.api.letsencrypt.org/directoryemail:?"weihanli@outlook.com"privateKeySecretRef:name:?letsencryptsolvers:-?dns01:webhook:config:accessKeyId:?AliAccessKeyIdaccessKeySecretRef:key:?accessKeySecretname:?ali-credentialregionId:?"cn-shanghai"ttl:?600groupName:?certmanager.webhook.alidnssolverName:?alidnsapiVersion:?cert-manager.io/v1 kind:?Certificate metadata:name:?weihanli-top-tls-certlabels:app:?webhook-alidnschart:?webhook-alidns-0.1.0release:?certmanager-webhook-alidnsheritage:?Helm spec:commonName:?"weihanli.top"dnsNames:-?"weihanli.top"-?'*.weihanli.top'issuerRef:kind:?ClusterIssuername:?letsencryptsecretName:?weihanli-top-tls-cert同時還會有一個保存阿里云 accessKeyId 和 accessKeySecret 的 secret 生成
apiVersion:?v1 kind:?Secret metadata:labels:app:?webhook-alidnschart:?webhook-alidns-0.1.0release:?certmanager-webhook-alidnsheritage:?Helmname:?ali-credential type:?Opaque data:accessKeyId:?"QWxpQWNjZXNzS2V5SWQ="accessKeySecret:?"QWxpQWNjZXNzS2V5U2VjcmV0"有了證書之后我們就可以配置成 Ingress 默認的 https 證書,這樣就不需要每個 ingress 都指定證書 secret 了,我們使用基于 nginx 的 ingress-nginx 來配置,通過 helm 來安裝配置 ingress-nginx
helm?repo?add?ingress-nginx?https://kubernetes.github.io/ingress-nginxhelm?repo?updatehelm?install?ingress-nginx?ingress-nginx/ingress-nginx?-n?ingress-nginx?--set?controller.extraArgs.default-ssl-certificate=cert-manager/weihanli-top-tls-cert?--create-namespacecontroller.extraArgs.default-ssl-certificate 配置為我們的證書對應的 secret,格式為:<namespace>/<secret-name>
然后我們就可以在 ingress 中配置 https 了,下面是一個配置示例:
apiVersion:?networking.k8s.io/v1 kind:?Ingress metadata:annotations:cert-manager.io/cluster-issuer:?letsencryptkubernetes.io/ingress.class:?nginxname:?homepagenamespace:?default spec:rules:-?host:?weihanli.tophttp:paths:-?backend:service:name:?homepageport:number:?80path:?/pathType:?Prefixtls:-?hosts:-?weihanli.top這里我們不需要指定證書的 secret,因為我們已經設置了默認的證書配置,再看一個示例:
apiVersion:?networking.k8s.io/v1 kind:?Ingress metadata:annotations:kubernetes.io/ingress.class:?nginxnginx.ingress.kubernetes.io/rewrite-target:?/$1name:?sparktodo-api-ingress spec:rules:-?host:?"sparktodo-api.weihanli.top"http:paths:-?pathType:?Prefixpath:?"/?(.*)"backend:service:name:?sparktodo-apiport:number:?80-?pathType:?Prefixpath:?"/monitor/?(.*)"backend:service:name:?sparktodo-apiport:number:?52323tls:-?hosts:-?sparktodo-api.weihanli.top這個示例稍微復雜一些,主要是 /monitor/ 開頭的請求轉給 52323 端口,其他的請求轉給 80 端口
More
按照上面的 helm chart 來配置自我感覺還是比較簡單的,更多配置選項可以參考 helm chart 包的定義
https://github.com/WeihanLi/certmanager-webhook-alidns,
如果想自己玩一下,可能會遇到一些問題,cert-manager 的文檔可能會幫到你 https://cert-manager.io/docs/faq/acme/,你也可以基于我魔改的再魔改一下哈
另外 cert-manager 文檔上有一張非常詳細的圖來介紹證書的申請、驗證、頒發(fā)整個過程,值得一看
Life of a CertificateReferences
https://www.cnblogs.com/tencent-cloud-native/p/13883790.html
https://github.com/WeihanLi/certmanager-webhook-alidns
https://cert-manager.io/docs/installation/helm/
https://cert-manager.io/docs/faq/acme/
https://helm.sh/docs/intro/install/
總結
以上是生活随笔為你收集整理的K8s 中使用 cert-manager 申请免费 Https 证书的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2021,我的输入输出
- 下一篇: HangFire循环作业中作业因执行时间