← 返回上一頁
Kubernetes

在 Kubernetes 上部署 SQL Server Always On 可用性群組:高可用與讀取擴展實戰

本頁目錄

前言

在 Kubernetes 上運行有狀態的資料庫工作負載一直是具有挑戰性的議題。這篇文章記錄如何在 Kubernetes 叢集上部署 SQL Server Always On Availability Group(AG),實現資料庫層級的高可用性和讀取擴展(Read Scale-Out)。

整體架構是部署 3 個 SQL Server 實例:1 個 Primary(讀寫)和 2 個 Secondary(唯讀副本),其中一個副本採用同步提交模式,另一個採用非同步提交模式。

Always On Availability Group 簡介

SQL Server Always On AG 提供了資料庫層級的高可用性和容錯能力。在 SQL Server 2017 之後,引入了 Read Scale Availability Group,可以不依賴叢集管理器(如 WSFC 或 Pacemaker)獨立部署。

同步模式

模式 行為 適用場景
同步提交(Synchronous) Primary 的交易會等待 Secondary 確認 log 已寫入後才完成提交 需要零資料遺失的場景
非同步提交(Asynchronous) Primary 提交後不等待 Secondary 確認 跨地域部署、可接受少量資料遺失的場景

持久化儲存配置

在 Kubernetes 上部署有狀態工作負載,首先需要配置儲存。需要建立以下資源:

StorageClass

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: sqlserver-sc-csi
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: YOUR_CSI_PROVISIONER
parameters:
  datastoreurl: "YOUR_DATASTORE_URL"

PersistentVolumeClaim(為每個實例各建立一個)

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: mssql-primary
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 8Gi
  storageClassName: sqlserver-sc-csi

分別建立 mssql-primarymssql-secondary1mssql-secondary2 三個 PVC。

Secret

kubectl create secret generic mssql-secret \
  --from-literal=SA_PASSWORD="********"

部署 SQL Server 實例

Primary SQL Server

以 Kubernetes Deployment 部署,關鍵配置要點:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mssqlag-primary-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mssql-primary
  strategy:
    type: Recreate    # SQL Server 需要獨佔檔案鎖,必須先停舊再建新
  template:
    spec:
      terminationGracePeriodSeconds: 10
      securityContext:
        fsGroup: 10001
      hostname: mssql-primary    # 設定固定主機名
      containers:
      - name: mssql-primary
        image: mcr.microsoft.com/mssql/server:2019-CU15-ubuntu-20.04
        env:
        - name: ACCEPT_EULA
          value: "Y"
        - name: MSSQL_ENABLE_HADR
          value: "1"
        - name: MSSQL_AGENT_ENABLED
          value: "true"
        - name: MSSQL_SA_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mssql-secret
              key: SA_PASSWORD
        volumeMounts:
        - name: mssqldb
          mountPath: /var/opt/mssql
      volumes:
      - name: mssqldb
        persistentVolumeClaim:
          claimName: mssql-primary

幾個重要的設計決策:

  • strategy.type: Recreate:SQL Server 對資料檔案持有排他鎖,滾動更新會導致新 Pod 啟動失敗
  • securityContext.fsGroup:設定檔案系統的群組 ID
  • hostname:確保 SQL Server 實例有固定的伺服器名稱

同樣為兩個 Secondary 副本建立類似的 Deployment,並各自建立 LoadBalancer 類型的 Service 暴露 1433(SQL)和 5022(AG Endpoint)端口。

配置 Availability Group

Primary 端配置

在 Primary SQL Server 上依序執行以下操作:

  1. 建立測試資料庫並設定為 Full Recovery 模式
  2. 執行完整備份
  3. 建立 AG 登入帳戶
  4. 建立 Master Key 和憑證
  5. 建立 AG Endpoint(端口 5022,使用憑證驗證)
  6. 建立 Availability Group,指定 Primary 和 Secondary 副本
  7. 將資料庫加入 AG

複製憑證到 Secondary

透過 kubectl cp 將 Primary 產生的憑證和金鑰複製到 Secondary 實例:

# 取得 Pod 名稱
podagp=$(kubectl get pods -l app=mssql-primary -o json | jq -r '.items[0].metadata.name')
podags1=$(kubectl get pods -l app=mssql-secondary1 -o json | jq -r '.items[0].metadata.name')

# 從 Primary 複製到本地,再複製到 Secondary
kubectl cp $podagp:var/opt/mssql/ag_certificate.cert ag_certificate.cert
kubectl cp $podagp:var/opt/mssql/ag_certificate.key ag_certificate.key
kubectl cp ag_certificate.cert $podags1:var/opt/mssql
kubectl cp ag_certificate.key $podags1:var/opt/mssql

Secondary 端配置

在每個 Secondary 副本上:

  1. 建立 AG 登入帳戶(密碼須與 Primary 一致)
  2. 使用從 Primary 複製的憑證建立本地憑證
  3. 建立 AG Endpoint
  4. 加入 Availability Group

部署要點與注意事項

  • Strategy 必須設為 Recreate:SQL Server 的資料檔案有排他鎖,RollingUpdate 會導致新舊 Pod 衝突
  • hostname 必須固定:AG 配置中使用主機名稱來識別副本,如果不設定 hostname,Pod 重啟後名稱會變化
  • 憑證管理:AG 端點間的通訊使用憑證驗證,需確保所有副本使用相同的憑證
  • 密碼安全:所有敏感資訊都應該透過 Kubernetes Secret 管理,不要直接寫在 YAML 中
  • 儲存效能:SQL Server 對 I/O 效能敏感,建議使用 SSD 等級的儲存

個人觀點

在 Kubernetes 上運行 SQL Server AG 確實可行,但相較於雲端託管的資料庫服務(如 Azure SQL、AWS RDS),維運複雜度會高很多。我建議在以下場景考慮這種部署方式:

  • 需要完全控制資料庫環境的企業
  • 混合雲架構中需要統一管理的場景
  • 開發/測試環境中模擬生產環境的 HA 配置

對於大多數生產場景,如果雲端廠商有提供對應的託管服務,通常是更省心的選擇。

參考資料

分享這篇
X LinkedIn Facebook Hacker News Reddit

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料