APISIX Ingress 如何使用 Cert Manager 管理證書

API7_技術團隊發表於2023-02-07

Apache APISIX Ingress Controller 是一款以 Apache APISIX 作為資料面的 Kubernetes Ingress Controller 開源工具,目前已經更新到 v1.3 版本,實現瞭如證書管理、負載均衡、金絲雀釋出等功能。

長久以來,證書管理都不是一件簡單的事情,雖然 Apache APISIX Ingress Controller 支援從 Kubernetes Secrets 資源中提取證書和私鑰,並轉換為 Apache APISIX 可識別的 SSL 物件,但這只是整個證書管理鏈中的一部分,證書的頒發、輪轉、吊銷邏輯依然需要管理員執行,尤其當證書數量比較多時,工作量往往並不小,因而會佔用管理員不少的時間。

Cert Manager 是一款致力於在 Kubernetes 平臺上簡化證書管理的軟體,它支援對接許多不同的證書源,如 Let's EncryptHashiCorp Vault

如果你在使用 Apache APISIX Ingress Controller 時,遇到了證書管理的麻煩,那麼使用 Cert Manager 將會是一個不錯的選擇,本文將介紹如何透過 Cert Manager 來建立證書並對接到 Apache APISIX Ingress Controller。

步驟一:環境準備

如果你希望按照本文的指導進行實際的操作,請確保以下環境和工具已準備就緒:

  1. 準備一個可用的 Kubernetes 叢集,開發環境中,你可以使用 KindMinikube
  2. 安裝 kubectl
  3. 安裝 Helm v3
請注意,下文所有的操作都將在 ingress-apisix 名稱空間中執行,因此需要先建立該名稱空間:kubectl create namespace ingress-apisix

步驟二:安裝 Apache APISIX Ingress Controller

我們可以透過 Helm 來安裝 Apache APISIX Ingress Controller,包括資料面的 Apache APISIX 和 etcd 叢集。

helm repo add apisix https://charts.apiseven.com
helm repo update
helm install apisix apisix/apisix --set gateway.tls.enabled=true --set ingress-controller.enabled=true --namespace ingress-apisix

點選檢視詳細安裝介紹

步驟三:安裝 Cert Manager

透過 Helm 來安裝 Cert Manager,點選可檢視詳細安裝介紹

helm install cert-manager jetstack/cert-manager --namespace ingress-apisix  --set prometheus.enabled=false --set installCRDs=true

安裝完畢後請等待一會後檢視元件的執行狀態,確保所有元件都已正常執行,你可以透過如下命令進行檢視。

kubectl get all -n ingress-apisix

返回結果如下所示,表示所有元件都已正常執行。

NAME                                             READY   STATUS        RESTARTS   AGE
pod/apisix-5d99956d88-j68sj                      1/1     Running       0          63s
pod/apisix-69459554d4-btnwn                      0/1     Terminating   0          57m
pod/apisix-etcd-0                                1/1     Running       0          57m
pod/apisix-etcd-1                                1/1     Running       0          57m
pod/apisix-etcd-2                                0/1     Running       0          50s
pod/apisix-ingress-controller-7b5c767cc7-j62hb   1/1     Running       0          55m
pod/cert-manager-5ffd4f6c89-q9f7m                1/1     Running       0          45m
pod/cert-manager-cainjector-748dc889c5-nrvkh     1/1     Running       0          45m
pod/cert-manager-startupapicheck-kmgxf           0/1     Completed     0          45m
pod/cert-manager-webhook-bc964d98b-mkjj7         1/1     Running       0          45m

NAME                                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/apisix-admin                ClusterIP   10.96.16.25     <none>        9180/TCP                     57m
service/apisix-etcd                 ClusterIP   10.96.232.251   <none>        2379/TCP,2380/TCP            57m
service/apisix-etcd-headless        ClusterIP   None            <none>        2379/TCP,2380/TCP            57m
service/apisix-gateway              NodePort    10.96.118.75    <none>        80:32039/TCP,443:30107/TCP   57m
service/apisix-ingress-controller   ClusterIP   10.96.13.76     <none>        80/TCP                       57m
service/cert-manager-webhook        ClusterIP   10.96.182.188   <none>        443/TCP                      45m

NAME                                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/apisix                      1/1     1            1           57m
deployment.apps/apisix-ingress-controller   1/1     1            1           57m
deployment.apps/cert-manager                1/1     1            1           45m
deployment.apps/cert-manager-cainjector     1/1     1            1           45m
deployment.apps/cert-manager-webhook        1/1     1            1           45m

NAME                                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/apisix-5d99956d88                      1         1         1       63s
replicaset.apps/apisix-69459554d4                      0         0         0       57m
replicaset.apps/apisix-ingress-controller-74c6b5fbdd   0         0         0       57m
replicaset.apps/apisix-ingress-controller-7b5c767cc7   1         1         1       55m
replicaset.apps/apisix-ingress-controller-7d58db957c   0         0         0       55m
replicaset.apps/cert-manager-5ffd4f6c89                1         1         1       45m
replicaset.apps/cert-manager-cainjector-748dc889c5     1         1         1       45m
replicaset.apps/cert-manager-webhook-bc964d98b         1         1         1       45m

NAME                           READY   AGE
statefulset.apps/apisix-etcd   2/3     57m

NAME                                     COMPLETIONS   DURATION   AGE
job.batch/cert-manager-startupapicheck   1/1           6m24s      45m
Kubernetes Controller Manager 的機制決定了 Pod 名稱會有所不同。

步驟四:申請證書並測試

首先我們需要配置證書頒發物件。

# issuer.yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: issuer
  namespace: ingress-apisix
spec:
  selfSigned: {}

並建立自簽名證書頒發者。

kubectl apply -f issuer.yaml
請注意,自簽名頒發物件不推薦使用在生產環境中!更多證書頒發物件的配置請參考這裡
然後為域名 httpbin.org 建立一張證書。
# httpbin-cert.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: httpbin
  namespace: ingress-apisix
spec:
  secretName: httpbin
  duration: 2160h # 90d
  renewBefore: 360h # 15d
  subject:
    organizations:
      - foo
  commonName: httpbin.org
  isCA: false
  privateKey:
    algorithm: RSA
    encoding: PKCS1
    size: 2048
  usages:
    - server auth
  dnsNames:
    - "httpbin.org"
    - "*.httpbin.org"
  issuerRef:
    name: issuer
    kind: Issuer
    group: cert-manager.io
kubectl apply -f httpbin-cert.yaml

此時需要檢視對應 Secrets 是否已經被建立。

kubectl get secrets -n ingress-apisix httpbin
NAME      TYPE                DATA   AGE
httpbin   kubernetes.io/tls   3      2m5s

透過上述驗證,該 Secrets 物件的建立事件已經被 Apache APISIX Ingress Controller 捕獲到,我們嘗試訪問 Apache APISIX Ingress Controller 來驗證證書是否生效,首先我們需要建立額外的路由物件。

# 建立後端
kubectl run httpbin --image kennethreitz/httpbin --namespace ingress-apisix
kubectl expose pod httpbin -n ingress-apisix --port 80
# 定義 ApisixTls 物件
apiVersion: apisix.apache.org/v1
kind: ApisixTls
metadata:
  name: httpbin
  namespace: ingress-apisix
spec:
  hosts:
  - httpbin.org
  secret:
    name: httpbin
    namespace: ingress-apisix
---
# 定義訪問後端的路由
apiVersion: apisix.apache.org/v2beta1
kind: ApisixRoute
metadata:
  name: httpbin
  namespace: ingress-apisix
spec:
  http:
  - name: httpbin
    match:
      paths:
      - /*
      hosts:
      - httpbin.org
    backends:
    - serviceName: httpbin
      servicePort: 80

接下來訪問服務 apisix-gateway。注意,預設情況下該服務的型別為 NodePort,你可以根據需要修改其型別,比如你的 Kubernetes 叢集是雲廠商託管的,則可以考慮將其修改為 LoadBalancer 型別,以獲取一個外部可達的 IP。

這裡我們透過埠轉發的方式將服務對映到本地。

kubectl port-forward -n ingress-apisix svc/apisix-gateway 8443:443

然後開始配置訪問。

curl https://httpbin.org:8443/json --resolve 'httpbin.org:8443:127.0.0.1' -sk
{
  "slideshow": {
    "author": "Yours Truly",
    "date": "date of publication",
    "slides": [
      {
        "title": "Wake up to WonderWidgets!",
        "type": "all"
      },
      {
        "items": [
          "Why <em>WonderWidgets</em> are great",
          "Who <em>buys</em> WonderWidgets"
        ],
        "title": "Overview",
        "type": "all"
      }
    ],
    "title": "Sample Slide Show"
  }
}

經過上述操作,可以看到訪問成功,說明證書已經生效。注意,由於證書是自簽名的,這裡需要加上 -k 選項來忽略證書的校驗。

此外,如果你想要輪轉證書,刪除 httpbin 這一 Secret 物件即可,Cert Manager 會立刻建立一個新的 httpbin Secret 物件,並且包含新的證書。

總結

本文主要講解了如何利用 Cert Manager 在 Apache APISIX Ingress Controller 中進行證書的建立和管理。想了解更多關於 Apache APISIX Ingress 的介紹與內容,可參考本篇文章 或者參與 Apache APISIX Ingress 專案每兩週舉行的線上討論,分享當下專案進度、最佳實踐及設計思路等多個話題,可檢視具體 issue 瞭解更多。

相關文章