Share via


使用 StatefulSets 在 Kubernetes 上部署 SQL Server Linux 容器

適用於:SQL Server - Linux

本文包含使用 StatefulSets 在 Kubernetes 上執行 SQL Server 容器的最佳做法和指導。 建議在 Kubernetes 中為每個 Pod 部署一個 SQL Server 容器 (執行個體)。 因此,您在 Kubernetes 叢集中的每個 Pod 會部署一個 SQL Server 執行個體。

同樣地,部署指令碼建議是將 replicas 值設定為 1,以部署一個 SQL Server 執行個體。 如果您輸入的數字大於 replicas 作為 1 值,您會收到許多具有共同相關名稱的 SQL Server 執行個體。 例如,在以下指令碼中,如果您將數字 2 指派為 replicas 的值,則會分別部署兩個 SQL Server Pod,並別使用名稱 mssql-0mssql-1

我們建議每個部署指令碼一個 SQL Server 的另一個原因是,要允許對部署的每個 SQL Server 執行個體個別進行組態值、版本、追蹤旗標和其他組態的變更。

在下列範例中,StatefulSet 工作負載名稱應該符合 .spec.template.metadata.labels 值,在此案例中為 mssql。 如需詳細資訊,請參閱 StatefulSets

重要

SA_PASSWORD 環境變數已被取代。 請改用 MSSQL_SA_PASSWORD

apiVersion: apps/v1
kind: StatefulSet
metadata:
 name: mssql # name of the StatefulSet workload, the SQL Server instance name is derived from this. We suggest to keep this name same as the .spec.template.metadata.labels, .spec.selector.matchLabels and .spec.serviceName to avoid confusion.
spec:
 serviceName: "mssql" # serviceName is the name of the service that governs this StatefulSet. This service must exist before the StatefulSet, and is responsible for the network identity of the set.
 replicas: 1 # only one pod, with one SQL Server instance deployed.
 selector:
  matchLabels:
   app: mssql  # this has to be the same as .spec.template.metadata.labels
 template:
  metadata:
   labels:
    app: mssql # this has to be the same as .spec.selector.matchLabels, as documented [here](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/):
  spec:
   securityContext:
     fsGroup: 10001
   containers:
   - name: mssql # container name within the pod.
     image: mcr.microsoft.com/mssql/server:2019-latest
     ports:
     - containerPort: 1433
       name: tcpsql
     env:
     - name: ACCEPT_EULA
       value: "Y"
     - name: MSSQL_ENABLE_HADR
       value: "1"
     - name: MSSQL_AGENT_ENABLED
       value: "1"
     - name: MSSQL_SA_PASSWORD
       valueFrom:
         secretKeyRef:
          name: mssql
          key: MSSQL_SA_PASSWORD
     volumeMounts:
     - name: mssql
       mountPath: "/var/opt/mssql"
 volumeClaimTemplates:
   - metadata:
      name: mssql
     spec:
      accessModes:
      - ReadWriteOnce
      resources:
       requests:
        storage: 8Gi

如果您仍然選擇使用相同部署來部署 SQL Server 執行個體的多個複本,下一節將說明該案例。 不過,這些是個別的獨立 SQL Server 執行個體,而不是複本 (與 SQL Server 中的可用性群組複本不同)。

選擇工作負載類型

選擇適當的工作負載部署類型不會影響效能,但 StatefulSet 確實提供身分識別黏性需求。

StatefulSet 工作負載

SQL Server 是資料庫應用程式,因此大部分應該部署為 StatefulSet 工作負載類型。 將工作負載部署為 StatefulSet 有助於提供唯一網路識別、持續性且穩定的儲存體等功能。 如需此類型工作負載的詳細資訊,請參閱 Kubernetes 文件

使用與 StatefulSet 工作負載相同的部署 YAML 指令碼部署 SQL Server 容器的多個複本時,要考量的一個重要參數是 Pod 管理原則,也就是 .spec.podManagementPolicy

此設定有兩個可能的值:

  • OrderedReady:這是預設值,且其行為如部署和調整保證中所述。

  • 平行:這是將平行建立和啟動 Pod (此案例中為 SQL Server Pod) 而不需等候其他 Pod 建立的替代原則。同樣地,所有 Pod 會在終止期間平行刪除。 當您部署彼此獨立的 SQL Server 執行個體時,以及當您不打算依照順序啟動或刪除 SQL Server 執行個體時,可以使用此選項。

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: mssql
    spec:
      serviceName: "mssql"
      replicas: 2 # two independent SQL Server instances to be deployed
      podManagementPolicy: Parallel
      selector:
        matchLabels:
          app: mssql
      template:
        metadata:
          labels:
            app: mssql
        spec:
          securityContext:
            fsGroup: 10001
          containers:
            - name: mssql
              image: mcr.microsoft.com/mssql/server:2019-latest
              ports:
                - containerPort: 1433
                  name: tcpsql
              env:
                - name: ACCEPT_EULA
                  value: "Y"
                - name: MSSQL_ENABLE_HADR
                  value: "1"
                - name: MSSQL_AGENT_ENABLED
                  value: "1"
                - name: MSSQL_SA_PASSWORD
                  valueFrom:
                    secretKeyRef:
                      name: mssql
                      key: MSSQL_SA_PASSWORD
              volumeMounts:
                - name: mssql
                  mountPath: "/var/opt/mssql"
      volumeClaimTemplates:
        - metadata:
            name: mssql
          spec:
            accessModes:
              - ReadWriteOnce
            resources:
              requests:
                storage: 8Gi
    

因為部署在 Kubernetes 上的 SQL Server Pod 彼此獨立,Parallel 通常為用於 podManagementPolicy 的值。

下列範例是 kubectl get all 的範例輸出,就在使用平行原則建立 Pod 之後:

NAME          READY   STATUS              RESTARTS   AGE
pod/mssql-0   0/1     ContainerCreating   0          4s
pod/mssql-1   0/1     ContainerCreating   0          4s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   201.0.0.1    <none>        443/TCP   61d

NAME                     READY   AGE
statefulset.apps/mssql   1/1     4s

部署工作負載

在要將 SQL Server 容器部署為無狀態資料庫應用程式的案例中 (例如當資料持續性不重要時),您可以對 SQL Server 使用部署類型。 部分這類範例為測試/QA 或 CI/CD 用途。

透過命名空間隔離

命名空間提供在單一 Kubernetes 叢集內隔離資源群組的機制。 如需命名空間及其使用時機的詳細資訊,請參閱命名空間

從 SQL Server 的觀點來看,如果您計劃在同時裝載其他資源的 Kubernetes 叢集上執行 SQL Server Pod,應該在其自己的命名空間中執行 SQL Server Pod,以方便管理和管理。 例如,假設您有多個部門共用相同的 Kubernetes 叢集,而您想要為銷售小組部署一個 SQL Server 執行個體,且另一個用於行銷小組。 您將建立名為 salesmarketing 的兩個命名空間,如下列範例所示:

kubectl create namespace sales
kubectl create namespace marketing

若要檢查是否已建立命名空間,請執行 kubectl get namespaces,您會看到類似下列輸出的清單。

NAME              STATUS   AGE
default           Active   39d
kube-node-lease   Active   39d
kube-public       Active   39d
kube-system       Active   39d
marketing         Active   7s
sales             Active   26m

現在,您可以使用下列範例所示的 YAML,在每個命名空間中部署 SQL Server 容器。 請注意,namespace 中繼資料已新增至部署 YAML,因此此部署的所有容器和服務都會部署在 sales 命名空間中。

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: azure-disk
provisioner: kubernetes.io/azure-disk
parameters:
  storageAccountType: Standard_LRS
  kind: Managed
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mssql-sales
  namespace: sales
  labels:
    app: mssql-sales
spec:
  serviceName: "mssql-sales"
  replicas: 1
  selector:
    matchLabels:
      app: mssql-sales
  template:
    metadata:
      labels:
        app: mssql-sales
    spec:
      securityContext:
        fsGroup: 10001
      containers:
        - name: mssql-sales
          image: mcr.microsoft.com/mssql/server:2019-latest
          ports:
            - containerPort: 1433
              name: tcpsql
          env:
            - name: ACCEPT_EULA
              value: "Y"
            - name: MSSQL_ENABLE_HADR
              value: "1"
            - name: MSSQL_AGENT_ENABLED
              value: "1"
            - name: MSSQL_SA_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mssql
                  key: MSSQL_SA_PASSWORD
          volumeMounts:
            - name: mssql
              mountPath: "/var/opt/mssql"
  volumeClaimTemplates:
    - metadata:
        name: mssql
      spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 8Gi
---
apiVersion: v1
kind: Service
metadata:
  name: mssql-sales-0
  namespace: sales
spec:
  type: LoadBalancer
  selector:
    statefulset.kubernetes.io/pod-name: mssql-sales-0
  ports:
    - protocol: TCP
      port: 1433
      targetPort: 1433
      name: tcpsql

若要查看資源,您可以使用指定的命名空間來執行 kubectl get all 命令,以查看這些資源:

kubectl get all -n sales
NAME                READY   STATUS    RESTARTS   AGE
pod/mssql-sales-0   1/1     Running   0          17m

NAME                    TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
service/mssql-sales-0   LoadBalancer   10.0.251.120   20.23.79.52   1433:32052/TCP   17m

NAME                           READY   AGE
statefulset.apps/mssql-sales   1/1     17m

命名空間也可以用來限制在命名空間內建立的資源和 Pod,使用限制範圍和/或資源配額原則來管理在命名空間內的整體資源建立。

設定 Pod 服務品質

在單一 Kubernetes 叢集上部署多個 Pod 時,您必須適當地共用資源,以確保有效率地執行 Kubernetes 叢集。 您可以設定 Pod,使其獲指派特定服務品質 (QoS)。

Kubernetes 使用 QoS 類別來決定排程和收回 Pod。 如需不同 QoS 類別的詳細資訊,請參閱設定 Pod 服務品質

從 SQL Server 的觀點來看,建議您部署 SQL Server Pod,針對生產工作負載使用 QoS 作為 Guaranteed。 假設 SQL Server Pod 僅執行一個 SQL Server 容器執行個體,為達到該 Pod 的保證 QoS,您將必須為容器指定 CPU 和記憶體要求,其應該等於記憶體和 CPU 限制。 這可確保節點會在部署期間提供並認可所需的資源,並具有 SQL Server Pod 的可預測效能。

以下是範例部署 YAML,可在預設命名空間中部署一個 SQL Server 容器,因為未指定資源要求,但限制已根據保證服務品質範例中的指導方針指定,我們會看到以下範例中建立的 Pod 已將 QoS 設定為 Guaranteed。 未指定資源要求時,Kubernetes 會將資源限制視為等於資源要求

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
     name: azure-disk
provisioner: kubernetes.io/azure-disk
parameters:
  storageaccounttype: Standard_LRS
  kind: Managed
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
 name: mssql
 labels:
  app: mssql
spec:
 serviceName: "mssql"
 replicas: 1
 selector:
  matchLabels:
   app: mssql
 template:
  metadata:
   labels:
    app: mssql
  spec:
   securityContext:
     fsGroup: 10001
   containers:
   - name: mssql
     command:
       - /bin/bash
       - -c
       - cp /var/opt/config/mssql.conf /var/opt/mssql/mssql.conf && /opt/mssql/bin/sqlservr
     image: mcr.microsoft.com/mssql/server:2019-latest
     resources:
      limits:
       memory: 2Gi
       cpu: '2'
     ports:
     - containerPort: 1433
     env:
     - name: ACCEPT_EULA
       value: "Y"
     - name: MSSQL_ENABLE_HADR
       value: "1"
     - name: MSSQL_SA_PASSWORD
       valueFrom:
         secretKeyRef:
          name: mssql
          key: MSSQL_SA_PASSWORD
     volumeMounts:
     - name: mssql
       mountPath: "/var/opt/mssql"
     - name: userdata
       mountPath: "/var/opt/mssql/userdata"
     - name: userlog
       mountPath: "/var/opt/mssql/userlog"
     - name: tempdb
       mountPath: "/var/opt/mssql/tempdb"
     - name: mssql-config-volume
       mountPath: "/var/opt/config"
   volumes:
     - name: mssql-config-volume
       configMap:
        name: mssql
 volumeClaimTemplates:
   - metadata:
      name: mssql
     spec:
      accessModes:
      - ReadWriteOnce
      resources:
       requests:
        storage: 8Gi
   - metadata:
      name: userdata
     spec:
      accessModes:
      - ReadWriteOnce
      resources:
       requests:
        storage: 8Gi
   - metadata:
      name: userlog
     spec:
      accessModes:
      - ReadWriteOnce
      resources:
       requests:
        storage: 8Gi
   - metadata:
      name: tempdb
     spec:
      accessModes:
      - ReadWriteOnce
      resources:
       requests:
        storage: 8Gi

您可以執行命令 kubectl describe pod mssql-0,以將 QoS 視為 Guaranteed,其輸出類似下列程式碼片段。

...
QoS Class:                 Guaranteed
Node-Selectors:            <none>
Tolerations:               node.kubernetes.io/memory-pressure:NoSchedule op=Exists
                           node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                           node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
...

對於非生產工作負載,其中的效能和可用性不是高優先順序,則可以考量將 QoS 設定為 BurstableBestEffort

可高載 QoS 範例

若要定義 Burstable YAML 範例,您可以指定資源要求,而非是資源限制;或者可以指定高於要求限制。 下列程式碼只會顯示與上一個範例的差異,以定義可高載的工作負載。

apiVersion: apps/v1
kind: StatefulSet
metadata:
 name: mssql
 labels:
  app: mssql
spec:
 serviceName: "mssql"
 replicas: 1
 selector:
  matchLabels:
   app: mssql
 template:
  metadata:
   labels:
    app: mssql
  spec:
   securityContext:
     fsGroup: 10001
   containers:
   - name: mssql
     command:
       - /bin/bash
       - -c
       - cp /var/opt/config/mssql.conf /var/opt/mssql/mssql.conf && /opt/mssql/bin/sqlservr
     image: mcr.microsoft.com/mssql/server:2019-latest
     resources:
      requests:
       memory: 2Gi
       cpu: '2'

您可以執行命令 kubectl describe pod mssql-0,以將 QoS 視為 Burstable,其輸出類似下列程式碼片段。

...
QoS Class:                 Burstable
Node-Selectors:            <none>
Tolerations:               node.kubernetes.io/memory-pressure:NoSchedule op=Exists
                           node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                           node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
...

最佳 QoS 範例

若要定義 BestEffort YAML 範例,請移除資源要求和資源限制。 您最後會有最佳 QoS,如建立獲指派最佳 QoS 類別的 Pod 中所定義。 如前所述,下列程式碼只會顯示與 Guaranteed 範例的差異,以定義最佳工作負載。 這些是 SQL Server Pod 的最低建議選項,因為它們可能是發生資源爭用時會終止的優先選項。 即使針對測試和 QA 案例,我們也建議針對 SQL Server 使用高載選項。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mssql
  labels:
    app: mssql
spec:
  serviceName: "mssql"
  replicas: 1
  selector:
    matchLabels:
      app: mssql
  template:
    metadata:
      labels:
        app: mssql
    spec:
      securityContext:
        fsGroup: 10001
      containers:
        - name: mssql
          command:
            - /bin/bash
            - -c
            - cp /var/opt/config/mssql.conf /var/opt/mssql/mssql.conf && /opt/mssql/bin/sqlservr
          image: mcr.microsoft.com/mssql/server:2019-latest
          ports:
            - containerPort: 1433

您可以執行命令 kubectl describe pod mssql-0,以將 QoS 視為 BestEffort,其輸出類似下列程式碼片段。

...
QoS Class:                 BestEffort
Node-Selectors:            <none>
Tolerations:               node.kubernetes.io/memory-pressure:NoSchedule op=Exists
                           node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                           node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
...