Aracılığıyla paylaş


StatefulSets ile Kubernetes'te SQL Server Linux kapsayıcıları dağıtma

Şunlar için geçerlidir:Linux üzerinde SQL Server

Bu makale, StatefulSets ile Kubernetes'te SQL Server kapsayıcılarını çalıştırmaya yönelik en iyi yöntemleri ve yönergeleri içerir. Kubernetes'te pod başına bir SQL Server kapsayıcısı (örnek) dağıtmanızı öneririz. Bu nedenle Kubernetes kümesinde pod başına dağıtılan bir SQL Server örneğiniz vardır.

Benzer şekilde, dağıtım betiği önerisi, replicas değerini 1olarak ayarlayarak bir SQL Server örneği dağıtmaktır. 1 değeri olarak replicas'den büyük bir sayı girerseniz, bağıntılı adlarla bu kadar çok SQL Server örneği alırsınız. Örneğin, aşağıdaki betikte, 2değeri olarak replicas sayısını atadıysanız, sırasıyla mssql-0 ve mssql-1 adlarıyla iki SQL Server podu dağıtırsınız.

Dağıtım betiği başına bir SQL Server kullanmanızın bir diğer nedeni de yapılandırma değerlerinde, sürümde, izleme bayraklarında ve diğer ayarlarda yapılan değişikliklerin dağıtılan her SQL Server örneği için bağımsız olarak yapılmasına izin vermektir.

Aşağıdaki örnekte StatefulSet iş yükü adı .spec.template.metadata.labels değeriyle eşleşmelidir ve bu örnekte mssql. Daha fazla bilgi için bkz. statefulSets.

Önemli

SA_PASSWORD ortam değişkeni kullanım dışıdır. Bunun yerine MSSQL_SA_PASSWORD kullanın.

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

Yine de aynı dağıtımı kullanarak SQL Server örneğinin birden fazla çoğaltmasını dağıtmayı seçerseniz, bu senaryo sonraki bölümde ele alınmıştır. Ancak bunlar ayrı bağımsız SQL Server örnekleridir ve çoğaltma değildir (SQL Server'daki kullanılabilirlik grubu çoğaltmalarından farklı olarak).

İş yükü türünü seçin

Doğru iş yükü dağıtım türü seçilmesi performansa etki etmez, ancak StatefulSet, kimlik yapışkanlığı gereksinimlerini karşılar.

StatefulSet iş yükleri

SQL Server bir veritabanı uygulamasıdır ve bu nedenle çoğunlukla StatefulSet iş yükü türü olarak dağıtılmalıdır. statefulSet olarak iş yüklerinin dağıtılması, benzersiz ağ tanımları, kalıcı ve kararlı depolama ve daha fazlası gibi özellikler sağlamaya yardımcı olur. Bu iş yükü türü hakkında daha fazla bilgi içinKubernetes belgelerine bakın.

StatefulSet iş yükü kullanılarak aynı dağıtım YAML betiğiyle birden fazla SQL Server kapsayıcı kopyası dağıtılırken dikkate alınması gereken önemli bir parametre, Pod yönetim politikalarıdır, yani .

Bu ayar için iki değer mümkündür:

  • OrderedReady: Bu varsayılan değerdir ve davranış, dağıtım ve ölçeklendirme garantilerinde açıklandığı gibi.

  • Paralel: Bu, diğer podların oluşturulmasını beklemeden podları (bu örnekte SQL Server podları) paralel olarak oluşturan ve başlatan alternatif ilkedir. Benzer şekilde, sonlandırma sırasında tüm podlar paralel olarak silinir. Birbirinden bağımsız SQL Server örneklerini dağıtırken ve SQL Server örneklerini başlatmak veya silmek için bir sırayı izlemeyi amaçlamadığınızda bu seçeneği kullanabilirsiniz.

    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'te dağıtılan SQL Server podları birbirinden bağımsız olduğundan, Parallel normalde podManagementPolicyiçin kullanılan değerdir.

Aşağıdaki örnek, paralel bir ilke kullanarak podları oluşturduktan hemen sonra kubectl get alliçin örnek çıktıdır:

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

Dağıtım iş yükleri

SQL Server kapsayıcılarını durum bilgisi olmayan veritabanı uygulamaları olarak dağıtmak istediğiniz senaryolarda (örneğin, veri kalıcılığı kritik olmadığında) SQL Server için dağıtım türünü kullanabilirsiniz. Bu tür örneklerin bazıları test/Soru-Cevap veya CI/CD amaçlarına yöneliktir.

Ad Alanları Kullanarak Yalıtım

Ad alanları, tek bir Kubernetes kümesindeki kaynak gruplarını yalıtmak için bir mekanizma sağlar. Ad alanları ve bunların ne zaman kullanılacağı hakkında daha fazla bilgi için bkz. ad alanları.

SQL Server açısından bakıldığında, SQL Server podlarını diğer kaynakları barındıran bir Kubernetes kümesinde çalıştırmayı planlıyorsanız, yönetim ve yönetim kolaylığı için SQL Server podlarını kendi ad alanında çalıştırmanız gerekir. Örneğin, aynı Kubernetes kümesini paylaşan birden çok departmanınız olduğunu ve Satış ekibi için bir SQL Server örneği ve Pazarlama ekibi için de başka bir SQL Server örneği dağıtmak istediğinizi düşünün. Aşağıdaki örnekte gösterildiği gibi sales ve marketingadlı iki ad alanı oluşturacaksınız:

kubectl create namespace sales
kubectl create namespace marketing

Ad alanlarının oluşturulup oluşturulmadığını denetlemek için kubectl get namespacesçalıştırın ve aşağıdaki çıkışa benzer bir liste görürsünüz.

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

Artık aşağıdaki örnekte gösterilen örnek YAML'yi kullanarak bu ad alanlarının her birine SQL Server kapsayıcıları dağıtabilirsiniz. Dağıtım YAML'sine eklenen namespace meta verilerine dikkat edin, bu nedenle bu dağıtımın tüm kapsayıcıları ve hizmetleri sales ad alanına dağıtılır.

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

Kaynakları görmek için kubectl get all komutunu belirtilen ad alanıyla çalıştırarak şu kaynakları görebilirsiniz:

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

Ad alanları, ad alanı içinde genel kaynak oluşturmayı yönetmek için sınır aralığı ve/veya kaynak kotası ilkeleri kullanılarak ad alanı içinde oluşturulan kaynakları ve podları sınırlamak için de kullanılabilir.

Pod Hizmet Kalitesini Ayarla

Tek bir Kubernetes kümesinde birden çok pod dağıtırken, Kubernetes kümesinin verimli bir şekilde çalıştığından emin olmak için kaynakları uygun şekilde paylaşmanız gerekir. Podları belirli bir Hizmet Kalitesine (QoS) atanması için yapılandırabilirsiniz.

Kubernetes, podları zamanlama ve çıkarma hakkında kararlar almak için QoS sınıflarını kullanır. Farklı QoS sınıfları hakkında daha fazla bilgi için bkz. Podlar için Hizmet Kalitesini Yapılandırma.

SQL Server açısından bakıldığında, üretim tabanlı iş yükleri için Guaranteed olarak QoS kullanarak SQL Server podlarını dağıtmanızı öneririz. Bir SQL Server podunun, bu pod için garantili QoS elde etmek için yalnızca bir SQL Server kapsayıcı örneği çalıştırdığını göz önünde bulundurarak,bellek ve CPU sınırlarına eşit olması gereken kapsayıcı için CPU ve bellek isteklerini belirtmeniz gerekir. Bu, düğümlerin dağıtım sırasında belirtilen gerekli kaynakları sağlamasını ve taahhüt etmesini ve SQL Server podları için öngörülebilir bir performans göstermesini sağlar.

Aşağıda, varsayılan ad alanında bir SQL Server kapsayıcısı dağıtan örnek bir dağıtım YAML verilmiştir ve kaynak istekleri belirtilmediğinden ancak sınırlar Garantili Hizmet Kalitesi örneğindeki yönergelere göre belirtildiğinden, aşağıdaki örnekte oluşturulan podun QoS'nin Guaranteedolarak ayarlandığını görüyoruz. Kaynak isteklerini belirtmediğinizde Kubernetes,kaynak isteklerine eşit kaynak sınırlarını dikkate alır.

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 komutunu, QoS'yi Guaranteedolarak görüntülemek için, aşağıdaki kod parçacığına benzer bir çıkış alacak şekilde çalıştırabilirsiniz.

...
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
...

Performans ve kullanılabilirlik yüksek öncelikli olmayan üretim dışı iş yükleri için QoS'yi Burstable veya BestEffortolarak ayarlayabilirsiniz.

Seri Hale Dönüştürülebilir QoS örneği

YAML örneği tanımlamak için, kaynak isteklerini, değil kaynak sınırlarınıbelirtirsiniz; veyaisteklerinden daha yüksek olansınırlarını belirtirsiniz. Aşağıdaki kod, patlayıcı bir iş yükünü tanımlamak için yalnızca önceki örnekten farklı olan kısımları gösterir.

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 komutunu, QoS'yi Burstableolarak görüntülemek için, aşağıdaki kod parçacığına benzer bir çıkış alacak şekilde çalıştırabilirsiniz.

...
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
...

En iyi çaba QoS örneği

YAML örneği tanımlamak için,kaynak isteklerini ve kaynak sınırlarını kaldırın. BestEffort QoS sınıfına atanan bir Pod oluşturma bölümünde açıklandığı gibi, sonuçta BestEffort QoS sınıfına sahip olacaksınız. Daha önce olduğu gibi, aşağıdaki kod yalnızca Guaranteed örneğinden farkı gösterir ve bu sayede seviyesinde bir iş yükü için en iyi çabayı tanımlar. Bunlar SQL Server podları için en az önerilen seçeneklerdir, kaynak çekişmesi durumunda sonlandırılacak ilk seçenekler olabilir. Test ve Kalite Güvence senaryoları için bile SQL Server için Burstable seçeneğini kullanmanızı öneririz.

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 komutunu, QoS'yi BestEffortolarak görüntülemek için, aşağıdaki kod parçacığına benzer bir çıkış alacak şekilde çalıştırabilirsiniz.

...
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
...

Denetim grubu (cgroup) v2 ile bellek sınırlarını yapılandırma

SQL Server 2025 (17.x) ve SQL Server 2022 (16.x) CU 20'den başlayarak, SQL Server denetim grubu (cgroup) v2 kısıtlamalarını algılar ve buna uyar ve Docker, Kubernetes ve OpenShift ortamlarında performans kararlılığını ve kaynak yalıtımını artırır. Denetim grupları Linux çekirdeğinde CPU ve bellek gibi sistem kaynakları üzerinde ayrıntılı denetim sağlar.

Cgroup v2 desteğiyle SQL Server, kapsayıcılı dağıtımlarda daha önce gözlemlenen bellek (OOM) hatalarını azaltır; özellikle kapsayıcı belirtimlerinde tanımlanan bellek sınırlarının zorlanmadığı Kubernetes kümelerinde (örneğin AKS v1.25+).

Cgroup sürümünü denetleme

stat -fc %T /sys/fs/cgroup

Sonuçlar aşağıdaki gibidir:

Result Description
cgroup2fs Cgroup v2 kullanıyorsunuz
cgroup cgroup v1 kullanıyorsunuz

cgroup v2'ye geçme

En kolay yol, kutudan çıkararak cgroup v2'yi destekleyen bir dağıtım seçmektir.

El ile geçiş yapmanız gerekiyorsa GRUB yapılandırmanıza aşağıdaki satırı ekleyin:

systemd.unified_cgroup_hierarchy=1

Ardından, GRUB'yi güncelleştirmek için aşağıdaki komutu çalıştırın:

sudo update-grub

Daha fazla bilgi için aşağıdaki kaynaklara bakın: