Implantar contêineres do SQL Server Linux no Kubernetes com StatefulSets
Aplica-se a:SQL Server - Linux
Este artigo contém práticas recomendadas e orientações para executar contêineres do SQL Server no Kubernetes com StatefulSets. Recomendamos implantar um contêiner do SQL Server (instância) por pod no Kubernetes. Assim, você tem uma instância do SQL Server implantada por pod no cluster do Kubernetes.
Da mesma forma, a recomendação do script de implantação é implantar uma instância do SQL Server definindo o valor replicas
como 1
. Se você inserir um número maior que 1
como o valor replicas
, obterá muitas instâncias do SQL Server com nomes correlacionados. Por exemplo, no script abaixo, se você atribuiu o número 2
como o valor para replicas
, implantaria dois pods do SQL Server, com os nomes mssql-0
e mssql-1
respectivamente.
Outro motivo pelo qual recomendamos um SQL Server por script de implantação é permitir que alterações em valores de configuração, edição, sinalizadores de rastreamento e outras configurações sejam feitas independentemente para cada instância do SQL Server implantada.
No exemplo a seguir, o nome da carga de trabalho StatefulSet deve corresponder ao valor .spec.template.metadata.labels
, que neste caso é mssql
. Para obter mais informações, consulte StatefulSets.
Importante
A variável de ambiente SA_PASSWORD
foi preterida. Use MSSQL_SA_PASSWORD
em vez disso.
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
Se você ainda optar por implantar mais de uma réplica da instância do SQL Server usando a mesma implantação, esse cenário será abordado na próxima seção. No entanto, essas são instâncias independentes separadas do SQL Server e não réplicas (ao contrário das réplicas de grupo de disponibilidade no SQL Server).
Escolha o tipo de carga de trabalho
Escolher o tipo de implementação de carga de trabalho correta para não afeta o desempenho, mas o StatefulSet fornece requisitos de persistência de identidade.
Cargas de trabalho StatefulSet
O SQL Server é um aplicativo de banco de dados e, portanto, principalmente deve ser implantado como um StatefulSet tipo de carga de trabalho. A implantação de cargas de trabalho como StatefulSet ajuda a fornecer recursos como identificações de rede exclusivas, armazenamento persistente e estável e muito mais. Para obter mais informações sobre esse tipo de carga de trabalho, consulte a documentação do Kubernetes.
Ao implantar mais de uma réplica de contêineres do SQL Server usando o mesmo script YAML de implantação como uma carga de trabalho StatefulSet, um parâmetro importante a ser considerado é políticas de gerenciamento de Pod, ou seja, .spec.podManagementPolicy
.
Há dois valores possíveis para essa configuração:
OrderedReady: Este é o valor padrão e o comportamento é o descrito nas garantias de implantação e dimensionamento .
Parallel: Esta é a política alternativa que cria e inicia os pods (neste caso, os pods do SQL Server) em paralelo, sem esperar que outros pods sejam criados Da mesma forma, todos os pods são excluídos em paralelo durante o encerramento. Você pode usar essa opção quando estiver implantando instâncias do SQL Server independentes umas das outras e quando não pretender seguir uma ordem para iniciar ou excluir as instâncias do 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
Como os pods do SQL Server implantados no Kubernetes são independentes uns dos outros, Parallel
é o valor normalmente usado para podManagementPolicy
.
O exemplo a seguir é a saída de exemplo para kubectl get all
, logo após a criação dos pods usando uma política paralela:
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
Cargas de trabalho de implantação
Pode usar o tipo de implantação para o SQL Server em cenários onde pretenda implementar contêineres do SQL Server como aplicações de base de dados sem estado, por exemplo, quando a persistência de dados não é crítica. Alguns desses exemplos são para fins de teste/QA ou CI/CD.
Isolamento através de namespaces
Os namespaces fornecem um mecanismo para isolar grupos de recursos em um único cluster do Kubernetes. Para obter mais informações sobre namespaces e quando usá-los, consulte Namespaces.
Do ponto de vista do SQL Server, se você planeja executar pods do SQL Server em um cluster do Kubernetes que também esteja hospedando outros recursos, deverá executar os pods do SQL Server em seu próprio namespace, para facilitar o gerenciamento e a administração. Por exemplo, considere que você tem vários departamentos compartilhando o mesmo cluster do Kubernetes e deseja implantar uma instância do SQL Server para a equipe de vendas e outra para a equipe de marketing. Você criará dois namespaces chamados sales
e marketing
, conforme mostrado no exemplo a seguir:
kubectl create namespace sales
kubectl create namespace marketing
Para verificar se os namespaces foram criados, execute kubectl get namespaces
e você verá uma lista semelhante à saída a seguir.
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
Agora você pode implantar contêineres do SQL Server em cada um desses namespaces usando o exemplo YAML de exemplo mostrado no exemplo a seguir. Observe os metadados namespace
adicionados ao YAML de implantação, para que todos os contêineres e serviços dessa implantação sejam implantados no namespace 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
Para ver os recursos, você pode executar o comando kubectl get all
com o namespace especificado para ver estes recursos:
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
Os namespaces também podem ser usados para limitar os recursos e pods criados dentro de um namespace, usando o intervalo de limite de e/ou políticas de de cota de recursos, para gerenciar a criação geral de recursos em um namespace.
Configurar a Qualidade de Serviço do pod
Ao implantar vários pods em um único cluster Kubernetes, você deve compartilhar recursos adequadamente, para garantir a execução eficiente do cluster Kubernetes. Você pode configurar pods para que lhes seja atribuída uma Qualidade de Serviço (QoS) específica.
O Kubernetes usa classes de QoS, como e, para tomar decisões sobre o agendamento e a expulsão de pods. Para obter mais informações sobre as diferentes classes de QoS, consulte Configurar a Qualidade de Serviço para Pods.
Do ponto de vista do SQL Server, recomendamos que você implante pods do SQL Server usando a QoS como Guaranteed
para cargas de trabalho baseadas em produção. Considerando que um pod do SQL Server tem apenas uma instância de contêiner do SQL Server em execução para obter QoS garantida para esse pod, você precisa especificar a CPU e as solicitações de de memória para o contêiner que devem ser iguais aos limites de memória e da CPU. Isso garante que os nós forneçam e alocem os recursos especificados como necessários durante a implantação, e tenham um desempenho consistente para os pods do SQL Server.
Aqui está um exemplo de implantação YAML que implanta um contêiner do SQL Server no namespace padrão e, como as solicitações de recursos não foram especificadas, mas os limites foram especificados de acordo com as diretrizes no exemplo Qualidade de Serviço Garantida exemplo, vemos que o pod criado no exemplo a seguir tem a QoS definida como Guaranteed
. Quando você não especifica as solicitações de recursos, o Kubernetes considera que os limites de de recursos iguais às solicitações de de recursos.
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
Você pode executar o comando kubectl describe pod mssql-0
para exibir a QoS como Guaranteed
, com saída semelhante ao trecho a seguir.
...
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
...
Para cargas de trabalho que não são de produção, onde o desempenho e a disponibilidade não são uma alta prioridade, você pode considerar definir a QoS como Burstable
ou BestEffort
.
Amostra de Burstable QoS
Para definir um exemplo YAML Burstable
, especifique os pedidos de recursos , e não os limites de de recursos; ou especifique os limites , que são superiores aos pedidos . O código a seguir exibe apenas a diferença do exemplo anterior, para definir uma carga de trabalho burstable .
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'
Você pode executar o comando kubectl describe pod mssql-0
para exibir a QoS como Burstable
, com saída semelhante ao trecho a seguir.
...
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
...
Amostra de QoS com melhor esforço
Para definir um exemplo de YAML Guaranteed
, a fim de definir uma carga de trabalho de melhor esforço . Essas são as opções menos recomendadas para pods do SQL Server, pois provavelmente seriam as primeiras a serem encerradas no caso de contenção de recursos. Mesmo para cenários de teste e controle de qualidade, recomendamos o uso da opção Burstable para 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
Você pode executar o comando kubectl describe pod mssql-0
para exibir a QoS como BestEffort
, com saída semelhante ao trecho a seguir.
...
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
...