使用 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-0
和 mssql-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:2022-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:2022-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 執行個體,且另一個用於行銷小組。 您將建立名為 sales
和 marketing
的兩個命名空間,如下列範例所示:
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:2022-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:2022-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 設定為 Burstable
或 BestEffort
。
可高載 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:2022-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:2022-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
...