Kubernetes Operator 與 Custom Resources (CRD)

在 Kubernetes 中,我們熟悉了 Deployment, Service, ConfigMap 等內建資源。但如果這些內建資源無法滿足你的需求怎麼辦?例如,你想在 K8s 上管理一個 "MySQLCluster",並且希望它能自動處理備份、Failover 與復原。

這時候,你需要的是 Custom Resources (自定義資源)Operator Pattern

這也是 Kubernetes 之所以在雲原生時代如此強大的原因:它允許你無限擴充 K8s 的 API

什麼是 Custom Resource Definition (CRD)?

CRD 允許你定義「新的資源類型」。 一旦你建立了 CRD,Kubernetes API Server 就會多出一種新的 API。

舉個例子,假設我們定義了一個叫做 MySQL 的 CRD,你就可以用這樣的 YAML 來建立資料庫:

# 這完全是自定義的 API Group (公司網域通常作為 Group Name)
apiVersion: database.example.com/v1
# 這是我們自己定義的 Resource Kind
kind: MySQL
metadata:
  name: my-db
spec:
  # 下面的欄位都是我們自己在 CRD 裡面定義的 (Schema)
  version: '8.0'
  storage: 100Gi
  replicas: 3

有了 CRD,K8s 只知道「有這個資料結構」,但還不知道「該怎麼做」。 就像你在資料庫開了一張表,但沒有程式去讀寫它,它就只是一個靜態的資料而已。

這時候就需要 Operator 出場了。

什麼是 Operator?

Operator 是一個軟體 (通常也是跑在 K8s 裡的 Pod),它的工作是:

  1. 監聽 (Watch) 特定 CRD 的變動 (Create/Update/Delete)。
  2. 協調 (Reconcile): 比較「期望狀態 (Spec)」與「實際狀態 (Status)」。
  3. 執行動作: 呼叫 K8s API 或外部 API,讓實際狀態趨近於期望狀態。

公式:Operator = Controller + Custom Resource (CR) + Domain Knowledge (領域知識)

為什麼這很強大?

Operator 將「人類維運工程師的知識」寫成了程式碼。

  • 傳統方式: 資料庫壞了 -> Call 工程師 -> 工程師 SSH 進去修 -> 恢復。
  • Operator: 資料庫壞了 -> Operator 偵測到 -> Operator 自動重啟/切換 -> 恢復。

常見的 Operator 範例

Kubernetes 生態系中有數千個 Operator,最著名的包括:

  1. Prometheus Operator: 自動管理 Prometheus Server, AlertManager, 並且只要新增一個 ServiceMonitor CRD,Prometheus 就會自動去抓 metrics,完全不用手改設定檔。
  2. ECK (Elastic Cloud on Kubernetes): 自動部署與管理 Elasticsearch Cluster。
  3. Cert-Manager: 自動申請與續約 TLS 憑證 (支援 Let's Encrypt)。它定義了 CertificateIssuer 這些 CRD。

實戰:安裝並使用 Cert-Manager

我們以 Cert-Manager 為例,看看 Operator 是如何運作的。

1. 安裝 Operator (連同 CRD)

大部分 Operator 都可以用 Helm 安裝:

helm repo add jetstack https://charts.jetstack.io
helm repo update

# 安裝 cert-manager
# installCRDs=true 會自動幫你建立 Certificate, Issuer 等 CRD
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --set installCRDs=true

2. 檢查 CRD

安裝完後,你會發現叢集多了一些「看不懂」的資源類型:

kubectl get crd
# 輸出範例:
# certificates.cert-manager.io
# issuers.cert-manager.io
# ...

3. 使用自定義資源 (建立 Issuer)

有了 CRD,我們就能建立 ClusterIssuer 資源 (這不是 K8s 內建的,是 cert-manager 擴充的):

# issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    email: user@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            class: nginx
kubectl apply -f issuer.yaml

過程發生了什麼事?

  1. 你 Apply 了 YAML。
  2. API Server 存下了這個物件。
  3. Cert-Manager Controller (Operator) 監聽到有一個 ClusterIssuer 被建立了。
  4. 它開始驗證這個 Issuer 的設定是否正確,並準備好去跟 Let's Encrypt 溝通。

如何開發自己的 Operator?

雖然 Operator 很強大,但從零開始寫 Controller 非常困難 (要處理併發、Retry、Cache 等)。 通常我們會使用框架來開發:

  1. Kubebuilder: 官方 SIG 維護的 SDK (Go 語言)。最推薦,效能最好。
  2. Operator SDK: RedHat 推出的 SDK,支援 Go, Ansible, Helm。

開發流程通常是:

  1. 定義 API (struct fields)。
  2. 生成 CRD YAML。
  3. 撰寫 Reconcile Loop (核心邏輯)。

總結

  • CRD: 定義 API 介面 (資料結構)。
  • Operator: 實作 API 邏輯 (程式碼)。
  • 效益: 將複雜的「有狀態應用 (Stateful App)」或「維運流程」程式碼化,實現真正的自動化維運。

如果你只是想「使用」K8s,通常只需要會安裝現成的 Operator (如 Prometheus, ArgoCD)。但如果你想成為 K8s 專家或開發平台工具,理解並開發 Operator 是必經之路。