Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Gilt für:SQL Server unter Linux
Dieser Artikel enthält bewährte Methoden und Leitfäden zum Ausführen von SQL Server-Containern in Kubernetes mit StatefulSets. Es wird empfohlen, pro Pod einen SQL Server-Container (Instanz) in Kubernetes bereitzustellen. So verfügen Sie über eine SQL Server-Instanz, die pro Pod im Kubernetes-Cluster bereitgestellt wird.
Entsprechend lautet die Empfehlung des Bereitstellungsskripts, eine SQL Server-Instanz bereitzustellen, indem Sie den Wert von replicas auf 1 festlegen. Wenn Sie eine Zahl eingeben, die größer als 1 als replicas Wert ist, erhalten Sie so viele SQL Server-Instanzen mit korrelierten Namen. Wenn Sie beispielsweise im folgenden Skript die Zahl 2 als Wert für replicas zugewiesen haben, stellen Sie zwei SQL Server-Pods mit den Namen mssql-0 bzw. mssql-1 bereit.
Ein weiterer Grund, warum eine SQL Server-Instanz pro Bereitstellungsskript empfohlen wird, besteht darin, dass es dadurch möglich ist, Änderungen an Konfigurationswerten, Editionen, Ablaufverfolgungsflags und anderen Einstellungen unabhängig für jede bereitgestellte SQL Server-Instanz vorzunehmen.
Im folgenden Beispiel sollte der Name der StatefulSet-Workload mit dem Wert von .spec.template.metadata.labels übereinstimmen, der in diesem Fall mssql lautet. Weitere Informationen finden Sie unter StatefulSets.
Wichtig
Die Umgebungsvariable SA_PASSWORD ist veraltet. Verwenden Sie stattdessen 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. See <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
Ein Szenario, in dem Sie mehrere Replikate der SQL Server-Instanz mithilfe derselben Bereitstellung bereitstellen, wird im nächsten Abschnitt behandelt. Dies sind jedoch separate unabhängige SQL Server-Instanzen und keine Replikate (im Gegensatz zu Verfügbarkeitsgruppenreplikaten in SQL Server).
Auswählen des Workloadtyps
Die Wahl des richtigen Workload-Bereitstellungstyps beeinträchtigt die Leistung nicht, aber das StatefulSet stellt Anforderungen an die Identitätsfestigkeit.
StatefulSet-Workloads
SQL Server ist eine Datenbankanwendung und sollte daher typischerweise als StatefulSet-Workloadtyp bereitgestellt werden. Durch die Bereitstellung von Workloads als StatefulSet können Sie Features wie eindeutige Netzwerkkennungen, persistenten und stabilen Speicher und vieles mehr bereitstellen. Weitere Informationen zu diesem Workloadtyp finden Sie in der Kubernetes-Dokumentation.
Bei der Bereitstellung von mehreren Replikaten von SQL Server-Containern mit demselben YAML-Bereitstellungsskript wie für eine StatefulSet-Workload müssen Podverwaltungsrichtlinien berücksichtigt werden, d. h. .spec.podManagementPolicy.
Für diese Einstellung sind zwei Werte möglich:
OrderedReady: Dies ist der Standardwert, und das Verhalten entspricht dem in den Bereitstellungs- und Skalierungsgarantien beschriebenen Verhalten.
Parallel: Dies ist eine alternative Richtlinie, mit der die Pods (in diesem Fall SQL Server-Pods) parallel erstellt und gestartet werden, ohne darauf zu warten, dass andere Pods erstellt werden. Auf dieselbe Weise werden die Pods beim Beenden auch entfernt. Sie können diese Option verwenden, wenn Sie unabhängige SQL Server-Instanzen bereitstellen und wenn Sie nicht beabsichtigen, eine bestimmte Reihenfolge zum Starten oder Löschen der SQL Server-Instanzen zu befolgen.
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
Da die in Kubernetes bereitgestellten SQL Server-Pods unabhängig voneinander sind, wird normalerweise der Wert Parallel für podManagementPolicy verwendet.
Das folgende Beispiel zeigt die Ausgabe für kubectl get all direkt nach der Erstellung der Pods mithilfe einer parallelen Richtlinie.
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
Bereitstellungs-Workloads
Sie können den Bereitstellungstyp für SQL Server in Szenarien verwenden, in denen Sie SQL Server-Container als zustandslose Datenbankanwendungen bereitstellen möchten, z. B. wenn die Datenpersistenz nicht wichtig ist. Einige Beispiele hierfür dienen zu Test-/QA- oder CI/CD-Zwecken.
Isolation über Namespaces
Namespaces bieten einen Mechanismus für das Isolieren von Ressourcengruppen in einem einzelnen Kubernetes-Cluster. Weitere Informationen zu Namespaces und deren Verwendung finden Sie unter Namespaces.
Wenn Sie planen, SQL Server-Pods in einem Kubernetes-Cluster auszuführen, der auch andere Ressourcen hostet, sollten Sie die SQL Server-Pods aus Sicht von SQL Server in einem eigenen Namespace ausführen, um die Verwaltung zu vereinfachen. Stellen Sie sich beispielsweise vor, dass mehrere Abteilungen denselben Kubernetes-Cluster nutzen und Sie eine SQL Server-Instanz für das Vertriebsteam und eine andere für das Marketingteam bereitstellen möchten. Sie erstellen in diesem Fall zwei Namespaces mit den Namen sales und marketing, wie im folgenden Beispiel gezeigt:
kubectl create namespace sales
kubectl create namespace marketing
Um zu überprüfen, ob die Namespaces erstellt wurden, führen Sie kubectl get namespaces aus. Damit zeigen Sie eine Liste ähnlich der folgenden Ausgabe an.
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
Nun können Sie SQL Server-Container in jedem dieser Namespaces mithilfe des YAML-Codes bereitstellen, der im folgenden Beispiel gezeigt wird. Beachten Sie die namespace-Metadaten, die der YAML-Bereitstellung hinzugefügt wurden und die bewirken, dass alle Container und Dienste dieser Bereitstellung im Namespace sales bereitgestellt werden.
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
Um die Ressourcen anzuzeigen, können Sie den Befehl kubectl get all unter Angabe des Namespace ausführen, um die folgenden Ressourcen anzuzeigen:
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
Namespaces können auch verwendet werden, um die Ressourcen und Pods einzugrenzen, die in einem Namespace erstellt werden. Dazu verwenden Sie den Grenzwertbereich und/oder Richtlinien für das Ressourcenkontingent, um die gesamte Ressourcenerstellung innerhalb eines Namespace zu verwalten.
Konfigurieren der Servicequalität für Pods
Wenn Sie mehrere Pods in einem einzelnen Kubernetes-Cluster bereitstellen, müssen Sie Ressourcen so freigeben, dass eine effiziente Ausführung des Kubernetes-Clusters sichergestellt ist. Sie können Pods so konfigurieren, dass ihnen eine bestimmte Servicequalität (Quality of Service, QoS) zugewiesen wird.
Kubernetes verwendet QoS-Klassen, um Entscheidungen zur Planung und Räumung von Pods zu treffen. Weitere Informationen zu den verschiedenen QoS-Klassen finden Sie unter Konfigurieren der Servicequalität für Pods.
Aus SQL Server-Perspektive wird empfohlen, SQL Server-Pods mit der Servicequalität Guaranteed für produktionsbasierte Workloads bereitzustellen. Da ein SQL Server-Pod nur über eine SQL Server-Containerinstanz verfügt, die ausgeführt wird, um eine garantierte Servicequalität für diesen Pod zu erreichen, müssen Sie die CPU- und Arbeitsspeicheranforderungen für den Container angeben. Diese sollten den Grenzwerten für Arbeitsspeicher und CPU entsprechen. Dadurch wird sichergestellt, dass die Knoten die während der Bereitstellung angegebenen erforderlichen Ressourcen bereitstellen und zusichern, sowie eine vorhersagbare Leistung für die SQL Server-Pods bieten.
Das folgende Beispiel für YAML-Bereitstellungscode stellt einen SQL Server-Container im Standardnamespace bereit. Da zwar keine Ressourcenanforderungen, aber Grenzwerte gemäß den Richtlinien im Beispiel für garantierte Dienstqualität angegeben wurden, können Sie sehen, dass für den Pod, der im folgenden Beispiel erstellt wurde, die Servicequalität auf Guaranteed festgelegt wurde. Wenn Sie die Ressourcenanforderungen nicht angeben, verwendet Kubernetes als Ressourcengrenzwerte die Ressourcenanforderungen.
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
Sie können den Befehl kubectl describe pod mssql-0 ausführen, um die Servicequalität Guaranteed anzuzeigen. Die Ausgabe ähnelt dem folgenden Codeschnipsel.
...
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
...
Für Nicht-Produktionsworkloads, bei denen Leistung und Verfügbarkeit keine hohe Priorität haben, können Sie erwägen, die Servicequalität auf Burstable oder BestEffort festzulegen.
Beispiel für burstfähiges Servicequalität
Um ein Burstable YAML-Beispiel zu definieren, geben Sie die Ressourcenanforderungen und nicht die Ressourcengrenzwerte an. Sie können auch Grenzwerte angeben, die höher als die Anforderungen sind. Im folgenden Code werden nur die Unterschiede zum vorherigen Beispiel angezeigt, um eine burstfähige Arbeitslast zu definieren.
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'
Sie können den Befehl kubectl describe pod mssql-0 ausführen, um die Servicequalität Burstable anzuzeigen. Die Ausgabe ähnelt dem folgenden Codeschnipsel.
...
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
...
Beispiel für „Best-Effort“ QoS
Um ein BestEffort-YAML-Beispiel zu definieren, entfernen Sie die Ressourcenanforderungen und Ressourcengrenzwerte. Sie erhalten letztendlich die QoS-Klasse „BestEffort“, wie in Create a Pod that gets assigned a QoS class of BestEffort (Erstellen eines Pods mit der QoS-Klasse „BestEffort“) definiert. Auch im hier folgenden Code werden nur die Unterschiede zum Guaranteed-Beispiel angezeigt, um eine Best-Effort-Workload zu definieren. Dies sind die am wenigsten empfohlenen Optionen für SQL Server Pods, da sie wahrscheinlich die ersten wären, die im Falle eines Ressourcenkonflikts beendet werden. Auch für Test- und Qualitätssicherungs-Szenarien empfehlen wir die Verwendung der Burst-Option für 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
Sie können den Befehl kubectl describe pod mssql-0 ausführen, um die Servicequalität BestEffort anzuzeigen. Die Ausgabe ähnelt dem folgenden Codeschnipsel.
...
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
...
Unterstützung von cgroup v2
SQL Server erkennt und berücksichtigt Kontrollgruppeneinschränkungen (cgroup) v2, beginnend mit SQL Server 2025 (17.x) und SQL Server 2022 (16.x) Kumulatives Update (CU) 20. Diese Einschränkungen bieten eine differenzierte Kontrolle im Linux-Kernel über CPU- und Speicherressourcen und verbessern die Ressourcenisolation in Docker-, Kubernetes- und OpenShift-Umgebungen.
In früheren Versionen können containerisierte Bereitstellungen auf Kubernetes-Clustern (z. B. Azure Kubernetes Service v1.25+) fehler im Arbeitsspeicher (OOM) auftreten, da SQL Server in Containerspezifikationen definierte Speichergrenzwerte nicht erzwungen haben. Die Unterstützung für cgroup v2 behebt dieses Problem.
Cgroup-Version überprüfen
stat -fc %T /sys/fs/cgroup
Die Ergebnisse sind wie folgt:
| Ergebnis | Description |
|---|---|
cgroup2fs |
Sie verwenden cgroup v2 |
cgroup |
Sie verwenden cgroup v1 |
Wechseln zu cgroup v2
Der einfachste Weg ist die Auswahl einer Distribution, die cgroup v2 von Haus aus unterstützt.
Wenn Sie manuell wechseln müssen, fügen Sie der GRUB-Konfiguration den folgenden Parameter hinzu:
systemd.unified_cgroup_hierarchy=1
Aktualisieren Sie dann GRUB. Führen Sie beispielsweise unter Ubuntu Folgendes aus:
sudo update-grub
Führen Sie auf Red Hat Enterprise Linux (RHEL) Folgendes aus:
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
CPU-Grenzwertberichterstattung mit cgroup v2
Wenn Sie CPU-Grenzwerte mit cgroup v2 konfigurieren, zeigt SQL Server nicht die konfigurierte CPU-Kernanzahl im Fehlerprotokoll an. Stattdessen wird weiterhin die Gesamtanzahl der Host-CPUs angezeigt.
Wenden Sie die folgende Konfiguration an, um SQL Server Zeitplan- und Abfragepläne (z. B. Parallelitätsentscheidungen) mit der beabsichtigten CPU-Anzahl auszurichten, die in cgroup v2 definiert ist.
Konfigurieren der Prozessoraffinität
Legen Sie explizit SQL Server Prozessoraffinität so fest, dass sie dem Cgroup-Ausführungskontingent entspricht. Im folgenden Beispiel ist das cgroup-Kontingent vier CPUs auf einem achtkernigen Host:
ALTER SERVER CONFIGURATION
SET PROCESS AFFINITY CPU = 0 TO 3;
Diese Konfiguration stellt sicher, dass SQL Server Scheduler nur für die beabsichtigte Anzahl von CPUs erstellt. Weitere Informationen finden Sie unter ALTER SERVER CONFIGURATION und Verwendung von PROCESS AFFINITY für Knoten und/oder CPUs.
Traceflag 8002 aktivieren (empfohlen)
Aktivieren Sie die Ablaufverfolgungskennzeichnung 8002, um weiche Affinität auf der SQLPAL-Ebene zu verwenden:
sudo /opt/mssql/bin/mssql-conf traceflag 8002 on
Standardmäßig sind Scheduler an bestimmte CPUs gebunden, die in der Affinitätsmaske definiert sind. Das Ablaufverfolgungsflag 8002 ermöglicht es Schedulern stattdessen, über CPUs zu wechseln, was die Leistung im Allgemeinen verbessert, während die Affinität und cgroup-Einschränkungen eingehalten werden. Weitere Informationen finden Sie unter DBCC TRACEON – Ablaufverfolgungsflags.
Starten Sie SQL Server neu, nachdem Sie das Ablaufverfolgungs-Flag aktiviert haben.
Erwartetes Verhalten
Nach dem Neustart:
SQL Server erstellt nur die Anzahl der Planer, die durch die Affinitätseinstellung definiert sind (z. B. vier Planer).
Der Linux-Kernel erzwingt weiterhin das Cgroup v2 CPU-Ausführungskontingent.
Abfrageoptimierungs- und Parallelitätsentscheidungen basieren auf der vorgesehenen CPU-Anzahl und nicht auf den Gesamthost-CPUs.
Hinweis
Das SQL Server Fehlerprotokoll zeigt möglicherweise weiterhin die Gesamtanzahl der Host-CPU an. Dieses Protokollierungs- und Anzeigeverhalten wirkt sich nicht auf die tatsächliche CPU-Auslastung, die Erstellung des Zeitplans oder die CPU-Erzwingung durch cgroup v2 oder Prozessoraffinität aus.
Weitere Informationen finden Sie in den folgenden Ressourcen:
- Schnellstart: Bereitstellen eines Linux-SQL-Server-Containers in Kubernetes mithilfe von Helm-Charts
- Control Group v2 (Linux Kernel-Dokumentation)