使用Cert-Manager为DNSPod的域名签发免费证书

概述

随着 HTTPS 不断普及,大多数网站开始由 HTTP 升级到 HTTPS。使用 HTTPS 需要向权威机构申请证书,并且需要付出一定的成本,如果需求数量多,则开支也相对增加。cert-manager 是 Kubernetes 上的全能证书管理工具,支持利用 cert-manager 基于 ACME 协议与 Let’s Encrypt 签发免费证书并为证书自动续期,实现永久免费使用证书。

域名使用腾讯云 DNSPod 管理,并期望在 Kubernetes 上为域名自动签发免费证书,可以使用 cert-manager 来实现。

cert-manager 支持许多 DNS provider,但不支持国内的 DNSPod,不过 cert-manager 提供了 Webhook 机制来扩展 provider,社区也有 DNSPod 的 provider 实现。本文将介绍如何结合 cert-manager 与 cert-manager-webhook-dnspod 来实现为 DNSPod 上的域名自动签发免费证书。

操作原理

cert-manager 工作原理

cert-manager 部署到 Kubernetes 集群后会查阅其所支持的自定义资源 CRD,可通过创建CRD 资源来指示 cert-manager 签发证书并为证书自动续期。如下图所示:

  • Issuers/ClusterIssuer: 用于指示 cert-manager 签发证书的方式,本文主要讲解签发免费证书的 ACME 方式。

    说明: Issuer 和 ClusterIssuer 之间的区别是 Issuer 只能用来签发自身所在 namespace 下的证书,ClusterIssuer 可以签发任意 namespace 下的证书。

  • Certificate: 用于向 cert-manager 传递域名证书信息、签发证书所需要的配置,以及对 Issuer/ClusterIssuer 的引用。

免费签发证书原理

Let’s Encrypt 利用 ACME 协议校验域名的归属,校验成功后可以自动颁发免费证书。免费证书有效期只有90天,需在到期前再校验一次实现续期。使用 cert-manager 可以自动续期,即实现永久使用免费证书。校验域名归属的两种方式分别是 HTTP-01DNS-01,校验原理详情可参见 Let’s Encrypt 的运作方式

HTTP-01 校验原理

HTTP-01 的校验原理是给域名指向的 HTTP 服务增加一个临时 location。此方法仅适用于给使用 Ingress 暴露流量的服务颁发证书,并且不支持泛域名证书。例如,Let’s Encrypt 会发送 HTTP 请求到 http:///.well-known/acme-challenge/YOUR_DOMAIN 是被校验的域名。TOKEN 是 ACME 协议客户端负责放置的文件,在此处 ACME 客户端即 cert-manager,通过修改或创建 Ingress 规则来增加临时校验路径并指向提供 TOKEN 的服务。Let’s Encrypt 会对比 TOKEN 是否符合预期,校验成功后就会颁发证书。

DNS-01 校验原理

DNS-01 的校验原理是利用 DNS 提供商的 API Key 拿到用户 DNS 控制权限。此方法不需要使用 Ingress,并且支持泛域名证书。在 Let’s Encrypt 为 ACME 客户端提供令牌后,ACME 客户端 \(cert-manager\) 将创建从该令牌和账户密钥派生的 TXT 记录,并将该记录放在 _acme-challenge.。Let’s Encrypt 将向 DNS 系统查询该记录,找到匹配项即可颁发证书。

校验方式对比

  • HTTP-01 校验方式的优点是配置简单通用,不同 DNS 提供商均可使用相同的配置方法。缺点是需要依赖 Ingress,若仅适用于服务支持 Ingress 暴露流量,不支持泛域名证书。

  • DNS-01 校验方式的优点是不依赖 Ingress,并支持泛域名。缺点是不同 DNS 提供商的配置方式不同,DNS 提供商过多而 cert-manager 的 Issuer 不能全部支持。部分可以通过部署实现 cert-manager 的 Webhook 服务来扩展 Issuer 进行支持。例如 DNSPod 和 阿里 DNS,详情请参见 Webhook 列表

操作步骤

安装 cert-manager

$ helm repo add jetstack https://charts.jetstack.io
"jetstack" has been added to your repositories

$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "jetstack" chart repository
...Successfully got an update from the "ingress-nginx" chart repository
Update Complete. ⎈Happy Helming!⎈

$ helm  search repo jetstack/cert-manager
NAME                                    CHART VERSION   APP VERSION     DESCRIPTION
jetstack/cert-manager                   v1.14.3         v1.14.3         A Helm chart for cert-manager
jetstack/cert-manager-approver-policy   v0.13.0         v0.13.0         approver-policy is a CertificateRequest approve...
jetstack/cert-manager-csi-driver        v0.7.1          v0.7.1          cert-manager csi-driver enables issuing secretl...
jetstack/cert-manager-csi-driver-spiffe v0.5.0          v0.5.0          csi-driver-spiffe is a Kubernetes CSI plugin wh...
jetstack/cert-manager-google-cas-issuer v0.8.0          v0.8.0          A Helm chart for jetstack/google-cas-issuer
jetstack/cert-manager-istio-csr         v0.8.1          v0.8.1          istio-csr enables the use of cert-manager for i...
jetstack/cert-manager-trust             v0.2.1          v0.2.0          DEPRECATED: The old name for trust-manager. Use...

$ helm pull jetstack/cert-manager
$ tar -xf cert-manager-v1.14.3.tgz
$ tree -L 1 cert-manager/
cert-manager/
├── Chart.yaml
├── README.md
├── templates
└── values.yaml

1 directory, 3 files

修改 values.yaml

installCRDs: true

prometheus:
  enabled: false

webhook:
  timeoutSeconds: 10

部署安装 cert-manager

$ helm install cert-manager -n cert-manager --create-namespace .
NAME: cert-manager
LAST DEPLOYED: Fri Mar  8 15:13:52 2024
NAMESPACE: cert-manager
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
cert-manager v1.14.3 has been deployed successfully!

In order to begin issuing certificates, you will need to set up a ClusterIssuer
or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer).

More information on the different types of issuers and how to configure them
can be found in our documentation:

https://cert-manager.io/docs/configuration/

For information on how to configure cert-manager to automatically provision
Certificates for Ingress resources, take a look at the `ingress-shim`
documentation:

https://cert-manager.io/docs/usage/ingress/

# 查看资源
kubectl get all -n cert-manager
NAME                                           READY   STATUS    RESTARTS   AGE
pod/cert-manager-6854c975d5-fcdmq              1/1     Running   0          2m22s
pod/cert-manager-cainjector-6976895488-tz4sh   1/1     Running   0          2m22s
pod/cert-manager-webhook-fcf48cc54-dvx9b       1/1     Running   0          2m22s

NAME                           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/cert-manager-webhook   ClusterIP   10.68.232.167   <none>        443/TCP   2m23s

NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/cert-manager              1/1     1            1           2m23s
deployment.apps/cert-manager-cainjector   1/1     1            1           2m23s
deployment.apps/cert-manager-webhook      1/1     1            1           2m23s

NAME                                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/cert-manager-6854c975d5              1         1         1       2m22s
replicaset.apps/cert-manager-cainjector-6976895488   1         1         1       2m22s
replicaset.apps/cert-manager-webhook-fcf48cc54       1         1         1       2m22s

创建DNSPod 密钥

登录 DNSPod 控制台,在 密钥管理 中创建密钥,复制自动生成的 IDToken 并保存

安装 cert-manager-webhook-dnspod

$ git clone --depth 1 https://github.com/qqshfox/cert-manager-webhook-dnspod.git
$ vim /apps/helm_chart/cert-manager-webhook-dnspod/dnspod-webhook-values.yaml
groupName: example.your.domain # 写一个标识 group 的名称,可以任意写

secrets: # 将前面生成的 id 和 token 粘贴到下面
  apiID: "<ID>"
  apiToken: "<Token>"

clusterIssuer:
  enabled: true # 自动创建出一个 ClusterIssuer
  email: your@email.com # 填写您的邮箱地址

$ helm upgrade --install -n cert-manager -f dnspod-webhook-values.yaml cert-manager-webhook-dnspod ./deploy/cert-manager-webhook-dnspod
NAME: cert-manager-webhook-dnspod
LAST DEPLOYED: Fri Mar  8 15:32:40 2024
NAMESPACE: cert-manager
STATUS: deployed
REVISION: 1
TEST SUITE: None
$ helm list -n cert-manager
NAME                            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                                 APP VERSION
cert-manager                    cert-manager    1               2024-03-08 15:13:52.057149727 +0800 CST deployed        cert-manager-v1.14.3                  v1.14.3
cert-manager-webhook-dnspod     cert-manager    1               2024-03-08 15:32:40.471751184 +0800 CST deployed        cert-manager-webhook-dnspod-0.3.3     0.2.0

# 查看资源
$ kubectl get pod -n cert-manager
NAME                                           READY   STATUS    RESTARTS   AGE
cert-manager-6854c975d5-fcdmq                  1/1     Running   0          19m
cert-manager-cainjector-6976895488-tz4sh       1/1     Running   0          19m
cert-manager-webhook-dnspod-65f9b65f6b-89dwl   1/1     Running   0          17s
cert-manager-webhook-fcf48cc54-dvx9b           1/1     Running   0          19m

创建证书

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: qiqios-com-crt
  namespace: default
spec:
  secretName: qiqios-com-crt-secret # 证书保存在这个 secret 中
  issuerRef:
    name: cert-manager-webhook-dnspod-cluster-issuer # 这里使用自动生成出来的 ClusterIssuer
    kind: ClusterIssuer
    group: cert-manager.io
  dnsNames: # 填入需要签发证书的域名列表,确保域名是使用 dnspod 管理的
  - test.qiqios.com

等待状态变成 Ready 表示签发成功:

$ kubectl get certificate
NAME             READY   SECRET                  AGE
qiqios-com-crt   True    qiqios-com-crt-secret   89s

#若签发失败可通过 describe 查看原因
$ kubectl describe certificate qiqios-com-crt

使用证书

cat test-ingress-nginx.yaml

# cert/whoami.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami
  labels:
    app: containous
    name: whoami
spec:
  replicas: 2
  selector:
    matchLabels:
      app: containous
      task: whoami
  template:
    metadata:
      labels:
        app: containous
        task: whoami
    spec:
      containers:
        - name: containouswhoami
          image: registry.cn-hangzhou.aliyuncs.com/qiqios/whoami_test:v1.5.0
          resources:
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: whoami
spec:
  ports:
    - name: http
      port: 80
  selector:
    app: containous
    task: whoami
  type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: whoami-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  tls:
    - hosts:
        - "test.qiqios.com"
      secretName: qiqios-com-crt-secret  # 引用证书 secret
  rules:
    - host: "test.qiqios.com"
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: whoami
                port:
                  number: 80

访问测试

$ curl  https://test.qiqios.com
Hostname: whoami-7cff74cc99-nkfbm
IP: 127.0.0.1
IP: ::1
IP: 172.20.248.142
IP: fe80::f0aa:6cff:fe0c:f085
RemoteAddr: 172.20.234.192:62165
GET / HTTP/1.1
Host: test.qiqios.com
User-Agent: curl/7.68.0
Accept: */*
X-Forwarded-For: 192.168.1.63
X-Forwarded-Host: test.qiqios.com
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Scheme: https
X-Real-Ip: 192.168.1.63
X-Request-Id: 54534722a887189e1fe9ff4a8f428cab
X-Scheme: https

使用Cert-Manager为DNSPod的域名签发免费证书
http://www.qiqios.cn/2024/03/08/2024-3-8-使用Cert-Manager为DNSPod的域名签发免费证书/
作者
一亩三分地
发布于
2024年3月8日
许可协议