059.Kubernetes cert-manager ACME HTTP01实战
·
项目设计
项目规划
当前结合ACME实现证书自动化管理,使用 HTTP01 验证方案,总体规划如下:
| 证书类型 | 业务域名 | 命名空间 | Issuer类型 | 申请邮箱 | secret名称 | 有效期 | 前置续期 |
|---|---|---|---|---|---|---|---|
| Let’s Encrypt免费证书 | spring.linuxsb.com | test | ClusterIssuer | x120952576@126.com | spring-linuxsb-com-tls | 90天 | 10天 |
项目实施
前置准备
正式项目实施前,建议检查相关环境情况。
- cert-manager 安装情况
[root@master01 ~]# kubectl -n cert-manager get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
cert-manager-746886b79c-l2ldj 1/1 Running 3 (2d14h ago) 6d8h 10.10.5.19 worker01 <none> <none>
cert-manager-cainjector-5664b56fc6-7w59h 1/1 Running 3 (2d14h ago) 6d8h 10.10.30.123 worker02 <none> <none>
cert-manager-webhook-7f644f6b8f-w9bnt 1/1 Running 3 (2d14h ago) 6d8h 10.10.30.91 worker02 <none> <none>
[root@master01 ~]# kubectl get crd | grep cert-manager.io
certificaterequests.cert-manager.io 2026-03-05T07:28:38Z
certificates.cert-manager.io 2026-03-05T07:28:38Z
challenges.acme.cert-manager.io 2026-03-05T07:28:38Z
clusterissuers.cert-manager.io 2026-03-05T07:28:38Z
issuers.cert-manager.io 2026-03-05T07:28:38Z
orders.acme.cert-manager.io 2026-03-05T07:28:38Z
- Nginx ingress 安装情况
[root@master01 ~]# kubectl -n ingress-nginx get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ingress-nginx-controller-cqktt 1/1 Running 9 (2d14h ago) 84d 10.10.241.112 master01 <none> <none>
ingress-nginx-controller-s92m7 1/1 Running 9 (2d14h ago) 84d 10.10.235.50 master03 <none> <none>
ingress-nginx-controller-wxqcs 1/1 Running 9 (2d14h ago) 84d 10.10.59.227 master02 <none> <none>
[root@master01 ~]# kubectl -n ingress-nginx get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
ingress-nginx-controller NodePort 10.20.60.120 <none> 80:80/TCP,443:443/TCP 89d app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
ingress-nginx-controller-admission ClusterIP 10.20.191.221 <none> 443/TCP 89d app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
[root@master01 ~]# kubectl get ingressclass
NAME CONTROLLER PARAMETERS AGE
nginx k8s.io/ingress-nginx <none> 89d
- 域名解析
HTTP01 验证需要能保证后续集群创建的临时验证Pod,能正常解析申请证书的域名,如 spring.linuxsb.com 。
本实验基于共有云场景,已将域名解析至集群入口。
[root@master01 ~]# dig +short spring.linuxsb.com
106.75.222.82
[root@master01 ~]# curl -I http://spring.linuxsb.com # 证明链路没问题
HTTP/1.1 404 Not Found
Date: Thu, 12 Mar 2026 10:28:20 GMT
Content-Type: text/html
Content-Length: 146
Connection: keep-alive
正式申请
创建命名空间
[root@master01 ~]# mkdir test
[root@master01 ~]# cd test/
[root@master01 test]# kubectl create namespace test
创建ClusterIssuer
- 创建请求
[root@master01 test]# vim clusterissuer-letsencrypt-prod.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-issuer-prod
spec:
acme:
email: x120952576@126.com
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-accountkey-prod
solvers:
- http01:
ingress:
ingressClassName: nginx
[root@master01 test]# kubectl apply -f clusterissuer-letsencrypt-prod.yaml
- 确认验证
[root@master01 test]# kubectl get clusterissuer
NAME READY AGE
letsencrypt-issuer-prod True 4s
[root@master01 test]# kubectl describe clusterissuers.cert-manager.io letsencrypt-issuer-prod
证书使用
方式一:证书注解申请
配置 ingress调用从 ingress-shim 自动创建的 Certificate ,采用注解的方式,直接一步到位,省去了些证书申请的过程。
- 配置ingress
主要配置ingress部分。
[root@master01 test]# vim test-spring-demo.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-spring-dp
namespace: test
spec:
selector:
matchLabels:
name: hello-spring
template:
metadata:
name: hello-spring
labels:
name: hello-spring
spec:
containers:
- name: hello-spring
image: registry.cn-hangzhou.aliyuncs.com/xhyimages/hello-spring:v1.0.0
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: hello-spring-svc
namespace: test
spec:
selector:
name: hello-spring
ports:
- port: 80
targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-spring-ingress
namespace: test
annotations:
cert-manager.io/cluster-issuer: letsencrypt-issuer-prod # 新增调用issuer的注解
cert-manager.io/duration: 2160h
cert-manager.io/renew-before: 240h
cert-manager.io/private-key-algorithm: RSA
cert-manager.io/private-key-size: "2048"
cert-manager.io/private-key-rotation-policy: Always
spec:
ingressClassName: nginx
tls: # 配置 TLS
- hosts:
- spring.linuxsb.com # 指定域名
secretName: spring-linuxsb-com-tls # 配置secret名称
rules:
- host: spring.linuxsb.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hello-spring-svc
port:
number: 80
释义:
如上注解主要是实现:
- cert-manager 注解:告诉 ingress-shim 用哪个 ClusterIssuer
- tls 配置:告诉它证书域名和 Secret 名称
- 正式创建
正式创建测试环境。
[root@master01 test]# kubectl apply -f test-spring-demo.yaml
[root@master01 test]# kubectl -n test get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hello-spring-dp-856699b7ff-fl4qw 1/1 Running 0 4m3s 10.10.19.81 worker03 <none> <none>
[root@master01 test]# kubectl -n test get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
hello-spring-svc ClusterIP 10.20.155.226 <none> 80/TCP 4m6s name=hello-spring
[root@master01 test]# kubectl -n test get ingress -o wide
NAME CLASS HOSTS ADDRESS PORTS AGE
hello-spring-ingress nginx spring.linuxsb.com 10.20.127.248 80, 443 4m9s
方式二:证书手动申请
如果ingress已存在,或者不方便修改ingress注解,可独立创建证书申请,然后ingress中引用即可。
- 创建证书申请
[root@master01 test]# vim certificate-spring-linuxsb-com.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: hello-spring-certificate
namespace: test
spec:
secretName: spring-linuxsb-com-tls
issuerRef:
name: letsencrypt-issuer-prod
kind: ClusterIssuer
group: cert-manager.io
dnsNames:
- spring.linuxsb.com
duration: 2160h # 90天
renewBefore: 240h # 提前10天续期
privateKey:
algorithm: RSA
size: 2048
rotationPolicy: Always
usages:
- digital signature
- key encipherment
- server auth
[root@master01 test]# kubectl apply -f certificate-spring-linuxsb-com.yaml
- 创建测试业务
不需要任何注解,只需要引用证书申请后创建的tls secret。
[root@master01 test]# vim test-spring-demo.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-spring-dp
namespace: test
spec:
selector:
matchLabels:
name: hello-spring
template:
metadata:
name: hello-spring
labels:
name: hello-spring
spec:
containers:
- name: hello-spring
image: registry.cn-hangzhou.aliyuncs.com/xhyimages/hello-spring:v1.0.0
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: hello-spring-svc
namespace: test
spec:
selector:
name: hello-spring
ports:
- port: 80
targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-spring-ingress
namespace: test
spec:
ingressClassName: nginx
tls:
- hosts:
- spring.linuxsb.com
secretName: spring-linuxsb-com-tls
rules:
- host: spring.linuxsb.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hello-spring-svc
port:
number: 80
[root@master01 test]# kubectl apply -f test-spring-demo.yaml
- 两种区别
| 对比项 | Ingress 注解方式 | 显式 Certificate 方式 |
|---|---|---|
| 证书触发入口 | Ingress | Certificate |
| 是否需要手工写 Certificate | 否 | 是 |
| Ingress 是否承担证书元数据 | 是 | 否 |
| 配置清晰度 | 中 | 高 |
| 自动化便捷性 | 高 | 中 |
| GitOps 可控性 | 中 | 高 |
| 排障可读性 | 中 | 高 |
| 适合场景 | 简单网站、快速接入 | 生产标准化、平台化 |
确认验证
确认证书申请和ingress业务。
[root@master01 test]# kubectl -n test get secrets -o wide
NAME TYPE DATA AGE
spring-linuxsb-com-tls kubernetes.io/tls 2 5m22s
[root@master01 test]# kubectl -n test get certificate
NAME READY SECRET AGE
spring-linuxsb-com-tls True spring-linuxsb-com-tls 45s
[root@master01 test]# kubectl -n test describe certificate spring-linuxsb-com-tls
#……
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Issuing 58s cert-manager-certificates-trigger Issuing certificate as Secret does not exist
Normal Generated 57s cert-manager-certificates-key-manager Stored new private key in temporary Secret resource "spring-linuxsb-com-tls-qgqqj"
Normal Requested 57s cert-manager-certificates-request-manager Created new CertificateRequest resource "spring-linuxsb-com-tls-1"
Normal Issuing 22s cert-manager-certificates-issuing The certificate has been successfully issued
[root@master01 test]# kubectl -n test describe ingress hello-spring-ingress
Name: hello-spring-ingress
Labels: <none>
Namespace: test
Address: 10.20.127.248
Ingress Class: nginx
Default backend: <default>
TLS:
spring-linuxsb-com-tls terminates spring.linuxsb.com
Rules:
Host Path Backends
---- ---- --------
spring.linuxsb.com
/ hello-spring-svc:80 (10.10.19.81:8080)
Annotations: cert-manager.io/cluster-issuer: letsencrypt-issuer-prod
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal CreateCertificate 100s cert-manager-ingress-shim Successfully created Certificate "spring-linuxsb-com-tls"
Normal Sync 65s (x2 over 100s) nginx-ingress-controller Scheduled for sync
还可以通过如下查看申请过程:
[root@master01 test]# kubectl -n test get certificaterequests.cert-manager.io spring-linuxsb-com-tls-1
NAME APPROVED DENIED READY ISSUER REQUESTER AGE
spring-linuxsb-com-tls-1 True True letsencrypt-issuer-prod system:serviceaccount:cert-manager:cert-manager 2m42s
[root@master01 test]# kubectl -n test describe certificaterequests.cert-manager.io spring-linuxsb-com-tls-1
浏览器访问 https://spring.linuxsb.com 。

更多推荐

所有评论(0)