K8S 使用 cert-manager 签发泛域名免费证书

2025-09-12 37 0

cert-manager 是 Kubernetes 上的证书管理工具,支持基于 ACME 协议与 Let's Encrypt 签发免费证书并为证书自动续期。

安装 cert-manager

cert-manager 将证书和证书颁发者作为资源类型添加到 Kubernetes 集群中,并简化了获取、更新和使用这些证书的过程。

它可以从各种受支持的来源颁发证书,包括 Let’s Encrypt、HashiCorp Vault 和 Venafi 以及私有 PKI。

它将确保证书有效且是最新的,并在到期前的配置时间尝试更新证书。

image.png
上图显示,cert-manager 拥有 Issuer 和 Certificate 等自定义资源,我们稍后会创建这些资源。

添加 cert-manager 仓库

helm repo add jetstack https://charts.jetstack.io
helm repo update

生成 values.yaml

helm show values jetstack/cert-manager > values.yaml

修改 values.yaml

installCRDs: true

prometheus:
  enabled: false

webhook:
  timeoutSeconds: 10

如果想查看生成的清单,可以使用

helm template cert-manager jetstack/cert-manager -n cert-manager -f values.yaml > cert-manager.yaml

安装 cert-manager

helm install cert-manager jetstack/cert-manager -n cert-manager --create-namespace -f values.yaml

等待

kubectl wait --for=condition=Ready pods --all -n cert-manager

# pod/cert-manager-74cb9c54dd-rs446 condition met
# pod/cert-manager-cainjector-5b99cf9569-c6bpt condition met
# pod/cert-manager-webhook-b9999597-xtfl6 condition met

创建 Issuer

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

DNS-01 校验支持泛域名, 但是是不同 DNS 提供商的配置方式不同,DNS 提供商过多而 cert-manager 的 Issuer 不能全部支持。部分可以通过部署实现 cert-manager 的 Webhook 服务来扩展 Issuer 进行支持。例如阿里 DNS 就是通过 Webhook 的方式进行支持。

添加 DNS 记录
whoami.sundayhk.com 下面测试使用
image.png

前往个人资料 -> API 令牌, 使用编辑区域 DNS 模版, 创建一个 token。

image.png

测试令牌是否能正常工作:

curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
     -H "Authorization: Bearer <yout api token>" \
     -H "Content-Type:application/json"

敏感文件不提交git仓库,这里将 token信息保存到 .env 文件,并将 .env 添加到 .gitignore。

# .env
# api-token=<token>
api-token=Anbv2XXQ4pOqKYHGLtx5uSnnAqzTkvCPzxogjLKP

这里使用 Kustomize 来读取.env文件的token

可以直接使用kubectl kustomize命令

编写 kustomization.yaml

# kustomization.yaml
resources:
  - letsencrypt-issuer.yaml
namespace: cert-manager
secretGenerator:
  - name: cloudflare-api-token-secret
    envs:
      - .env # token本地文件
generatorOptions:
  disableNameSuffixHash: true

编写 letsencrypt-issuer.yaml

# letsencrypt-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-dns01
spec:
  acme:
    privateKeySecretRef:
      name: letsencrypt-dns01
    server: https://acme-v02.api.letsencrypt.org/directory
    solvers:
      - dns01:
          cloudflare:
            email: xxx@gmail.com # 替换成你的 cloudflare 邮箱账号
            apiTokenSecretRef:
              key: api-token
              name: cloudflare-api-token-secret # 引用上面cloudflare Secret

所生成的 Secret 可以使用下面的命令来检查

kubectl kustomize ./

如无问题,运行如下命令,创建 issuer

kubectl apply -k ./

查看 Let't Encrypt 注册状态

kubectl describe clusterissuer letsencrypt-dns01

如下表示注册成功

root@kr-master:~# kubectl describe clusterissuer letsencrypt-dns01
...
Status:
  Acme:
    Last Private Key Hash:  MjEcqc52vL8XCp+yKXJeqKnO6yVtJVx/S4zeU4CzYFd=
    Uri:                    https://acme-v02.api.letsencrypt.org/acme/acct/2653488531
  Conditions:
    Last Transition Time:  2025-09-11T05:32:16Z
    Message:               The ACME account was registered with the ACME server
    Observed Generation:   1
    Reason:                ACMEAccountRegistered
    Status:                True
    Type:                  Ready
Events:                    <none>

创建 Certificate

编写 certificate.yaml

# certificate.yaml 
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: wildcard-sundayhk-com
  namespace: default
spec:
  dnsNames:
    - "*.sundayhk.com" # 替换成自己要签发证书的域名
  issuerRef:
    kind: ClusterIssuer
    name: letsencrypt-dns01 # 引用 ClusterIssuer,名字和 letsencrypt-issuer.yaml 中保持一致
  secretName: wildcard-sundayhk-com-tls # 最终签发出来的证书会保存在这个 Secret 里面
kubectl apply -f certificate.yaml

查看证书是否签发成功

root@kr-master:~/ks# kubectl get certificate -w
NAME                    READY   SECRET                     AGE
wildcard-sundayhk-com   False   wildcard-letsencrypt-tls   13s
wildcard-sundayhk-com   False   wildcard-letsencrypt-tls   26s
wildcard-sundayhk-com   True    wildcard-letsencrypt-tls   26s
wildcard-sundayhk-com   True    wildcard-letsencrypt-tls   26s

注意:Let's Encrypt 一个星期内只为同一个域名颁发 5 次证书,sundayhk.com 和 whoami.sundayhk.com 被视为不同的域名。

测试

编写 whoami.yaml

# 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: containous/whoami
          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:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - "whoami.sundayhk.com"
      secretName: wildcard-sundayhk-com-tls
  rules:
    - host: whoami.sundayhk.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: whoami
                port:
                  number: 80
kubectl apply -f whoami.yaml

image.png

https://cert-manager.io/docs/installation/helm/
https://cert-manager.io/docs/configuration/acme/dns01/cloudflare/
https://www.tencentcloud.com/zh/document/product/457/38713

相关文章

kubespray 镜像加速配置
kubespray 离线安装自建配置
kubespray 安装kubernetes集群
kubernetes 部署argocd 自动同步项目代码
KubeSphere DevOps 流水线JAVA项目配置
虚拟机热添加内存 Kubernetes未生效

发布评论