项目设计

项目规划

当前结合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

001

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐