Bereitstellen von SQL Server-Linux-Containern in Kubernetes mit StatefulSets
Gilt für: SQL Server – 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 größere Zahl als 1
als Wert von replicas
eingeben, erhalten Sie entsprechend viele SQL Server-Instanzen mit ähnlichen 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, 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
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 Auswahl des richtigen Workloadbereitstellungstyps wirkt sich nicht auf die Leistung aus, aber das StatefulSet stellt Anforderungen an die Identitätsbindung.
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: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
Da die in Kubernetes bereitgestellten SQL Server-Pods unabhängig voneinander sind, wird normalerweise der Wert Parallel
für podManagementPolicy
verwendet.
Das folgende Beispiel ist die Beispielausgabe für kubectl get all
direkt nach dem Erstellen 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
Bereitstellungsworkloads
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: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
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 Entfernung 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 erforderlichen Ressourcen bereitstellen und committen, die während der Bereitstellung angegeben werden, und eine vorhersagbare Leistung für die SQL Server-Pods aufweisen.
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: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
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, die erforderlich sind, um eine burstfähige Workload 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:2019-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 Servicequalität „BestEffort“
Um ein BestEffort
-YAML-Beispiel zu definieren, entfernen Sie die Ressourcenanforderungen und Ressourcengrenzwerte. Damit erhalten Sie eine Servicequalität der BestEffort-Klasse wie unter 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, die erforderlich sind, um eine BestEffort-Workload zu definieren. Diese Optionen werden für SQL Server-Pods nur eingeschränkt empfohlen, da sie wahrscheinlich die ersten wären, die im Fall eines Ressourcenkonflikts beendet werden. Auch für Test- und QA-Szenarien wird die Verwendung der burstfähigen Option für SQL Server empfohlen.
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
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
...