
前面已經介紹了 Google 代管的 GTS 證書管理工具,而今天要介紹的 Cert-Manager 是一款強大的 Kubernetes 工具,能自動執行憑證的取得、更新和部署。無論您是否使用 GCP 雲端平台,Cert-Manager 都可以不依賴雲平台,簡化憑證管理流程,讓您可以專注於應用程式開發。在文章中,我們將深入探討 Cert-Manager 的功能、優勢,並提供如何整合 GCP Cloud DNS 的逐步指南。
Cert-Manager 是一款 Kubernetes 證書管理工具,能夠自動化獲取、更新和部署 TLS/SSL 證書。它支持 Let's Encrypt、Hashicorp Vault 等多種證書頒發機構 (CA),並可與 Ingress 資源無縫集成,自動為你的網站和應用程序提供 HTTPS 保護。
Cert-Manager 簡化了證書管理流程,無需手動操作,即可確保網站安全可靠,並獲得 HTTPS 帶來的 SEO 優勢和用戶信任。
$ helm repo add jetstack https://charts.jetstack.io && helm repo update
$ helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--version v1.15.3 \
--set installCRDs=true \
--set serviceAccount.create=true
使用 Day6 Workload Identity 教學,綁定 GKE 內的 cert-manager 服務帳戶使其擁有 Cloud DNS 的權限
    cert-manager = {
      gcp_service_account           = "cert-manager"
      k8s_service_account           = "cert-manager"
      k8s_service_account_namespace = "cert-manager"
      use_existing_gcp_sa           = false
      use_existing_k8s_sa           = true
      roles = [
        "roles/dns.admin"
      ],
      # 填入管理Cloud DNS所在的專案
      additional_projects = {
        "ithome-202409-demo" = [
          "roles/dns.admin"
        ]
      }
    },
建立 ClusterIssuer
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-demo # 替換自己的email
spec:
  acme:
    email: demo@demoit.shop
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-demo
    solvers:
      - dns01:
          cloudDNS:
            # The ID of the GCP project
            project: ithome-202409-demo
參數說明:
https://acme-staging-v02.api.letsencrypt.org/directory ,限制上會較為寬鬆創建 Ingress 來進行證書生成掛載示範
增加 Annotations 的參數 cert-manager.io/cluster-issuer: letsencrypt-demo
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: httpd-external-dns-test-ingress
  namespace: httpd
  annotations:
  # 指定用於自動化 TLS 證書管理的 ClusterIssuer 名稱為 "letsencrypt-demo"
    cert-manager.io/cluster-issuer: letsencrypt-demo
spec:
  ingressClassName: external-nginx
  tls:
    - hosts:
        - httpd-external-dns-test.demoit.shop # 指定要啟用 TLS 加密的域名
      secretName: httpd-external-dns-test-tls # 指定存放 TLS 證書和私鑰的 Secret 名稱
  rules:
    - host: httpd-external-dns-test.demoit.shop
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: httpd-service
                port:
                  number: 80
會發現 Cert-manager 會在CloudDNS 寫入一筆 TXT 紀錄來確定申請者的網域的擁有權

查看 Secret 物件,會發現 Cert-manager 創建了對應網址的 Cert 和 Key

訪問 https://httpd-external-dns-test.demoit.shop 檢查證書,可以看到是 Let’s Encrypt 簽發下來的

什麼時候會使用自簽署憑證?
這裡以 gRPC 端到端直連 mTLS 配置圖來解釋

首先為客戶端與服務端準備必要的證書。證書鏈如下

首先,你需要創建一個自簽發的根證書頒發機構 SelfSigned CA。這可以使用 Issuer 資源來完成
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: demo-ca-issuer
  namespace: httpd
spec:
  ca:
    secretName: demo-ca-secret
接下來,你需要創建一個證書請求,以從你的自簽發 CA 獲取證書。證書請求應該包含你的服務的域名
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: server-grpc-mtls
  namespace: httpd
  labels:
    component: certificate
spec:
  privateKey:
    algorithm: ECDSA
    size: 256
  duration: 9120h0m0s
  renewBefore: 720h0m0s
  dnsNames:
  - "server.demo.shop"
  commonName: "server.demo.shop"
  subject:
    organizations:
      - demo.shop
    organizationalUnits:
      - demoit
    countries:
      - US
    localities:
      - Iowa
  secretName: grpc-tls
  issuerRef:
    name: demo-ca-issuer
    kind: Issuer
    group: cert-manager.io
這樣 Server Side的證書就簽發出來了,重複此步驟,將 dnsNames 換成 Client 的網域即可
$ kubectl describe secrets grpc-tls -n httpd       
Name:         grpc-tls
Namespace:    httpd
Labels:       controller.cert-manager.io/fao=true
Annotations:  cert-manager.io/alt-names: *.demo.shop
              cert-manager.io/certificate-name: grpc-tls
              cert-manager.io/common-name: *.demo.shop
              cert-manager.io/ip-sans: 
              cert-manager.io/issuer-group: cert-manager.io
              cert-manager.io/issuer-kind: Issuer
              cert-manager.io/issuer-name: demo-ca-issuer
              cert-manager.io/subject-countries: US
              cert-manager.io/subject-localities: Iowa
              cert-manager.io/subject-organizationalunits: demoit
              cert-manager.io/subject-organizations: demo.shop
              cert-manager.io/uri-sans: 
Type:  kubernetes.io/tls
Data
====
ca.crt:   652 bytes
tls.crt:  721 bytes
tls.key:  227 bytes
在 Kubernetes 環境中部署和管理 SSL/TLS 證書是確保應用程式安全和可靠性的關鍵步驟。Cert-manager 提供了一個自動化的解決方案,簡化了證書生命週期管理。透過整合 Let's Encrypt 等憑證頒發機構,您可以輕鬆取得和更新免費的 SSL/TLS 證書,確保您的 GKE 應用程式具備 HTTPS 安全性。
由於 Day6 介紹的 Google 簽發的 GTS 證書申請時間較長,而且 GTS 無法在 K8s 內部使用自簽證書做 為服務 mTLS 彼此的溝通,如果需要快速產生的證書比較推薦使用 Cert-manager。