这个场景非常的有意思:
公司内部有若干个kubernetes集群,属于测试环境,研发搭建了一套SAAS的环境,这个环境需要xxx.abc.com的域名来访问,域名解析记录全都是192.168.0.x,供内部访问,域名会动态生成,需要证书也随之生成,且dns域名托管在cloudflare上。
基本环境如上,麻烦的是 cert-manager 不可能签发私网的证书,只能曲线救国,用dns验证的方式来签发证书了,如果配上 external-dns,那dns解析也不用做了;只要发布一个ingress,就直接生成dns解析记录和对应的https证书。
具体做法如下:
一、配置 cloudflare API token
登录cloudflare,去生成API Token,路径是:User Profile > API Tokens > API Tokens.
Permissions:
Zone - DNS - Edit
Zone Resources:
Include - All Zones
cert-manager的官方文档居然是错的,https://cert-manager.io/docs/configuration/acme/dns01/cloudflare/
推荐的 Zone - Zone - Read 是加不上的,有Edit就足够了

然后获得Token的字符串xxxxxx
二、安装cert-manager
这个简单,直接用helm安装
现在这个时间节点,2025.07.09,cert-manager 是 v1.18.2,所以用新命令执行安装
helm repo add jetstack https://charts.jetstack.io
helm repo update
#老版本比如1.0
helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set installCRDs=true
#新版本v1.18.2
helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set crds.enabled=true
三、准备签发机构Issuer
下面要特别注意,secret必须在namespace:cert-manager中,因为上一步我们创建了ns cert-manager,pod也在这个ns中,签发的过程中是由cert-manager中的pod发起请求的
# secret
---
apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-token-secret
namespace: cert-manager
type: Opaque
stringData:
api-token: xxxxxxxx
# Issuer
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: zhangranrui@gmail.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- dns01:
cloudflare:
email: zhangranrui@gmail.com
apiTokenSecretRef:
name: cloudflare-api-token-secret
key: api-token
四、准备pod和ingress
# nginx deployment
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
# nginx Service
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
然后我们直接发布一个ingress,就会自动签发证书了
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- test.abc.com
secretName: test-tls
rules:
- host: test.abc.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80
四、一些调试命令:
$ kubectl get issuer
$ kubectl get clusterissuer
$ kubectl get challenges
$ kubectl describe challenge
$ kubectl describe certificaterequest
$ kubectl describe order
五、直接申请证书
上面讲了通过ingress来自动申请证书,那我们如果不通过ingress,直接申请该怎么做呢?
也很简单,直接来个申请即可
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: tls-normal
namespace: default
spec:
secretName: tls-normal
commonName: abc.cde.com
dnsNames:
- abc.cde.com
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer