使用 cert-manager 签发免费证书
概述
随着 HTTPS 不断普及,越来越多的网站都在从 HTTP 升级到 HTTPS,使用 HTTPS 就需要向权威机构申请证书,需要付出一定的成本,如果需求数量多,也是一笔不小的开支。cert-manager 是 Kubernetes 上的全能证书管理工具,如果对安全级别和证书功能要求不高,可以利用 cert-manager 基于 ACME 协议与 Let’s Encrypt 来签发免费证书并自动续期,实现永久免费使用证书。
cert-manager 工作原理
cert-manager 部署到 Kubernetes 集群后,它会 watch 它所支持的 CRD 资源,我们通过创建 CRD 资源来指示 cert-manager 为我们签发证书并自动续期:
解释下几个关键的资源:
- Issuer/ClusterIssuer: 用于指示 cert-manager 用什么方式签发证书,本文主要讲解签发免费证书的 ACME 方式。ClusterIssuer 与 Issuer 的唯一区别就是 Issuer 只能用来签发自己所在 namespace 下的证书,ClusterIssuer 可以签发任意 namespace 下的证书。
- Certificate: 用于告诉 cert-manager 我们想要什么域名的证书以及签发证书所需要的一些配置,包括对 Issuer/ClusterIssuer 的引用。
免费证书签发原理
Let’s Encrypt 利用 ACME 协议来校验域名是否真的属于你,校验成功后就可以自动颁发免费证书,证书有效期只有 90 天,在到期前需要再校验一次来实现续期,幸运的是 cert-manager 可以自动续期,这样就可以使用永久免费的证书了。如何校验这个域名是否属于你呢?主流的两种校验方式是 HTTP-01 和 DNS-01,详细校验原理可参考 Let’s Encrypt 的运作方式,下面将简单描述下。
HTTP-01 校验原理
HTTP-01 的校验原理是给你域名指向的 HTTP 服务增加一个临时 location ,Let’s Encrypt 会发送 http 请求到 http://<YOUR_DOMAIN>/.well-known/acme-challenge/
DNS-01 校验原理
DNS-01 的校验原理是利用 DNS 提供商的 API Key 拿到你的 DNS 控制权限, 在 Let’s Encrypt 为 ACME 客户端提供令牌后,ACME 客户端 (cert-manager) 将创建从该令牌和您的帐户密钥派生的 TXT 记录,并将该记录放在 _acme-challenge.<YOUR_DOMAIN>。 然后 Let’s Encrypt 将向 DNS 系统查询该记录,如果找到匹配项,就可以颁发证书。此方法不需要你的服务使用 Ingress,并且支持泛域名证书。
校验方式对比
HTTP-01 的校验方式的优点是: 配置简单通用,不管使用哪个 DNS 提供商都可以使用相同的配置方法;缺点是:需要依赖 Ingress,如果你的服务不是用 Ingress 暴露流量的就不适用,而且不支持泛域名证书。
DNS-01 的校验方式的优点是没有 HTTP-01 校验方式缺点,不依赖 Ingress,也支持泛域名;缺点就是不同 DNS 提供商的配置方式不一样,而且 DNS 提供商有很多,cert-manager 的 Issuer 不可能每个都去支持,不过有一些可以通过部署实现了 cert-manager 的 Webhook 的服务来扩展 Issuer 进行支持,比如 DNSPod 和 阿里 DNS,详细 Webhook 列表请参考: https://cert-manager.io/docs/configuration/acme/dns01/#webhook
选择哪种方式呢?条件允许的话,建议是尽量用 DNS-01 的方式,限制更少,功能更全。
安装使用
K8S和cert-manager对应的版本
https://cert-manager.io/docs/installation/supported-releases/
使用manifest方式安装
https://cert-manager.io/docs/installation/kubectl/
1 | $ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.11.0/cert-manager.yaml |
默认是安装在
cert-manager
名称空间的, 如有需要可自行修改
HTTP0-1
https://cert-manager.io/docs/configuration/acme/http01/
如果使用 HTTP-01 的校验方式,需要用到 Ingress 来配合校验。cert-manager 会通过自动修改 Ingress 规则或自动新增 Ingress 两种方式之一来实现对外暴露校验所需的临时 HTTP 路径,这个就是在给 Issuer 配置 http01 校验,指定 Ingress 的 name 或 class 的区别 (见下面的示例)。
1 | apiVersion: cert-manager.io/v1 |
使用上面的 Issuer 签发证书,cert-manager 会自动修改 prod/web 这个 Ingress 资源,以暴露校验所需的临时路径,这是自动修改 Ingress 的方式,你也可以使用自动新增 Ingress 的 方式,示例:
1 | apiVersion: cert-manager.io/v1 |
使用上面的 Issuer 签发证书,cert-manager 会自动创建 Ingress 资源,以暴露校验所需的临时路径。
有了 Issuer,接下来就可以创建 Certificate 并引用 Issuer 进行签发了,示例:
1 | apiVersion: cert-manager.io/v1 |
DNS-01
https://cert-manager.io/docs/configuration/acme/dns01/
如果使用 DNS-01 的校验方式,就需要看你使用的哪个 DNS 提供商了,cert-manager 内置了一些 DNS 提供商的支持,详细列表和用法请参考 Supported DNS01 providers,不过 cert-manager 不可能去支持所有的 DNS 提供商,如果没有你所使用的 DNS 提供商怎么办呢?有两种方案:
方案一:设置 Custom Nameserver。在你的 DNS 提供商后台设置 custom nameserver,指向像 cloudflare 这种可以管理其它 DNS 提供商域名的 nameserver 地址,具体地址可登录 cloudflare 后台查看:
方案二:使用 Webhook。使用 cert-manager 的 Webhook 来扩展 cert-manager 的 DNS-01 验证所支持的 DNS 提供商,已经有许多第三方实现,包括国内常用的 DNSPod 与阿里 DNS,详细列表参考: Webhook。
如果使用 DNS-01 的校验方式,就需要看你使用的哪个 DNS 提供商了,cert-manager 内置了一些 DNS 提供商的支持,详细列表和用法请参考 https://cert-manager.io/docs/configuration/acme/dns01/#supported-dns01-providers
DNSPod的webhook 使用manifest方式安装
1 | $ kubectl apply -f https://raw.githubusercontent.com/imroc/cert-manager-webhook-dnspod/master/bundle.yaml |
默认是安装在
cert-manager
名称空间的, 如有需要可自行修改
转载自 https://imroc.cc/kubernetes/trick/certs/sign-free-certs-with-cert-manager.html