Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Se aplica a:SQL Server en Linux
Este artículo contiene procedimientos recomendados e instrucciones para ejecutar contenedores de SQL Server en Kubernetes con StatefulSets. Se recomienda implementar un contenedor de SQL Server (instancia) por pod en Kubernetes. Por lo tanto, tiene una instancia de SQL Server implementada por pod en el clúster de Kubernetes.
De forma similar, la recomendación del script de implementación es implementar una instancia de SQL Server estableciendo el valor replicas en 1. Si escribe un número mayor que 1 como valor de replicas, obtendrá muchas instancias de SQL Server con nombres correlacionados. Por ejemplo, en el siguiente script, si asignó el número 2 como valor para replicas, implementaría dos pods de SQL Server, con los nombres mssql-0 y mssql-1, respectivamente.
Otra razón por la que se recomienda una instancia de SQL Server por script de implementación es permitir que los cambios en los valores de configuración, la edición, las marcas de seguimiento y otras opciones se realicen de forma independiente para cada instancia de SQL Server implementada.
En el ejemplo siguiente, el nombre de la carga de trabajo StatefulSet debe coincidir con el valor .spec.template.metadata.labels, que en este caso es mssql. Para obtener más información, consulte StatefulSets.
Importante
La variable de entorno SA_PASSWORD está en desuso. En su lugar, use 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
Si todavía decide implementar más de una réplica de la instancia de SQL Server mediante la misma implementación, ese escenario se trata en la sección siguiente. Sin embargo, se trata de instancias de SQL Server independientes diferentes y no réplicas (a diferencia de las réplicas del grupo de disponibilidad en SQL Server).
Elección del tipo de carga de trabajo
Elegir el tipo de implementación de carga de trabajo adecuado no afecta al rendimiento, pero StatefulSet proporciona requisitos de permanencia de identidad.
Cargas de trabajo StatefulSet
SQL Server es una aplicación de base de datos y, por tanto, principalmente debe implementarse como un tipo de carga de trabajo de StatefulSet. La implementación de cargas de trabajo como StatefulSet ayuda a proporcionar características como identificaciones de red única, almacenamiento persistente y estable, etc. Para más información sobre este tipo de carga de trabajo, consulte la documentación de Kubernetes.
Al implementar más de una réplica de contenedores de SQL Server con el mismo script de YAML de implementación que una carga de trabajo de StatefulSet, un parámetro importante que se debe tener en cuenta son las directivas de administración de pods, es decir, .spec.podManagementPolicy.
Hay dos valores posibles para esta configuración:
OrderedReady: este es el valor predeterminado y el comportamiento es como se describe en las garantías de implementación y escalado.
Paralelo: esta es la directiva alternativa que crea e inicia los pods (en este caso, pods de SQL Server) en paralelo, sin esperar a que se creen otros pods. De forma similar, todos los pods se eliminan en paralelo durante la finalización. Puede usar esta opción al implementar instancias de SQL Server independientes entre sí y cuando no tenga previsto seguir un orden para iniciar o eliminar las instancias de 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
Dado que los pods de SQL Server implementados en Kubernetes son independientes entre sí, Parallel es el valor que se usa normalmente para podManagementPolicy.
La muestra siguiente es la salida de ejemplo para kubectl get all, justo después de crear los pods mediante una directiva 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 trabajo de implementación
Puede usar el tipo deployment para SQL Server, en escenarios en los que desea implementar contenedores SQL Server como aplicaciones de base de datos sin estado, por ejemplo, cuando la persistencia de datos no es crítica. Algunos de estos ejemplos son para fines de prueba, control de calidad o CI/CD.
Aislamiento a través de espacios de nombres
Los espacios de nombres proporcionan un mecanismo para aislar grupos de recursos dentro de un único clúster de Kubernetes. Para obtener más información sobre los espacios de nombres y cuándo usarlos, consulte Espacios de nombres.
Desde la perspectiva de SQL Server, si pretende ejecutar pods de SQL Server en un clúster de Kubernetes que también hospeda otros recursos, debe ejecutar dichos pods en su propio espacio de nombres, para facilitar la gestión y la administración. Por ejemplo, suponga que tiene varios departamentos que comparten el mismo clúster de Kubernetes y quiere implementar una instancia de SQL Server para el equipo de ventas y otra para el equipo de marketing. Creará dos espacios de nombres denominados sales y marketing, como se muestra en el ejemplo siguiente:
kubectl create namespace sales
kubectl create namespace marketing
Para comprobar que se crean los espacios de nombres, ejecute kubectl get namespaces y verá una lista similar a la del siguiente resultado.
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
Ahora puede implementar contenedores de SQL Server en cada uno de estos espacios de nombres mediante el ejemplo de YAML que se muestra en el ejemplo siguiente. Observe los metadatos de namespace agregados al YAML de implementación, por lo que todos los contenedores y servicios de esta implementación se implementan en el espacio de nombres 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 los recursos, puede ejecutar el comando kubectl get all con el espacio de nombres especificado para ver estos 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
Los espacios de nombres también se pueden utilizar para limitar los recursos y pods creados dentro de un espacio de nombres mediante las políticas de rango de límites y/o cuota de recursos, con el fin de gestionar la creación total de recursos dentro de un espacio de nombres.
Configurar la calidad de servicio del pod
Al implementar varios pods en un único clúster de Kubernetes, debe compartir los recursos correctamente para garantizar la ejecución eficiente del clúster de Kubernetes. Puede configurar pods para que se les asigne una Calidad de servicio (QoS) determinada.
Kubernetes usa clases de QoS para tomar decisiones sobre la programación y el desalojo de pods. Para obtener más información sobre las distintas clases de QoS, consulte Configuración de la calidad de servicio para pods.
Desde la perspectiva de SQL Server, se recomienda implementar pods de SQL Server mediante QoS como Guaranteed para cargas de trabajo basadas en producción. Teniendo en cuenta que un pod de SQL Server solo tiene una instancia de contenedor de SQL Server que se ejecuta para lograr Calidad de servicio garantizada para ese pod, tiene que especificar las solicitudes de CPU y memoria para el contenedor que deben ser iguales a los límites de memoria y CPU. Esto asegura que los nodos proporcionen y confirmen los recursos necesarios especificados durante la implementación, y ofrezcan un rendimiento predecible para los pods de SQL Server.
Esta es una muestra de YAML de implementación que despliega un contenedor de SQL Server en el espacio de nombres predeterminado y, como las solicitudes de recursos no se especificaron pero sí los límites según las directrices del ejemplo Calidad de Servicio Garantizada, vemos que el pod que se crea en el siguiente ejemplo tiene la QoS asignada como Guaranteed. Cuando no se especifican las solicitudes de recursos, Kubernetes considera los límites de recursos iguales a las solicitudes 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
Puede ejecutar el comando kubectl describe pod mssql-0 para ver QoS como Guaranteed, con una salida similar al siguiente fragmento de código.
...
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
...
En el caso de las cargas de trabajo que no son de producción, donde el rendimiento y la disponibilidad no son una prioridad alta, puede considerar la posibilidad de establecer QoS en Burstable o BestEffort.
Ejemplo de QoS ampliable
Para definir un ejemplo de YAML Burstable, especifique las solicitudes de recursos, no los límites de recursos; o bien, especifique los límites, que es mayor que las solicitudes. El código siguiente muestra solo la diferencia con respecto al ejemplo anterior, con el fin de definir una carga de trabajo ampliable.
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'
Puede ejecutar el comando kubectl describe pod mssql-0 para ver QoS como Burstable, con una salida similar al siguiente fragmento de código.
...
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
...
Ejemplo de QoS de mejor esfuerzo
Para definir un ejemplo de YAML BestEffort, quite las solicitudes de recursos y los límites de recursos. Terminará con el QoS de mejor esfuerzo, tal como se define en Crear un Pod al que se le asigna una clase QoS de BestEffort. Como antes, el código siguiente muestra solo la diferencia con respecto al ejemplo Guaranteed, con el fin de definir una carga de trabajo de mejor esfuerzo. Estas son las opciones menos recomendadas para los pods de SQL Server, ya que podrían ser las primeras en finalizarse en caso de contención de recursos. Incluso para escenarios de prueba y control de calidad, se recomienda usar la opción de ráfaga 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
Puede ejecutar el comando kubectl describe pod mssql-0 para ver QoS como BestEffort, con una salida similar al siguiente fragmento de código.
...
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
...
Compatibilidad con el grupo de control (cgroup) v2
SQL Server detecta y respeta las restricciones del grupo de control (cgroup) v2, empezando por SQL Server 2025 (17.x) y SQL Server 2022 (16.x) Actualización acumulativa (CU) 20. Estas restricciones proporcionan un control específico en el kernel de Linux sobre los recursos de CPU y memoria, y mejoran el aislamiento de recursos en entornos de Docker, Kubernetes y OpenShift.
En versiones anteriores, las implementaciones en contenedores en clústeres de Kubernetes (por ejemplo, Azure Kubernetes Service v1.25 o posteriores) podían experimentar errores de memoria insuficiente (OOM) porque SQL Server no aplicaba límites de memoria definidos en las especificaciones del contenedor. La compatibilidad con cgroup v2 soluciona este problema.
Comprobación de la versión de cgroup
stat -fc %T /sys/fs/cgroup
Los resultados son los siguientes:
| Resultado | Description |
|---|---|
cgroup2fs |
Usted utiliza cgroup v2. |
cgroup |
Tú usas cgroup v1. |
Cambiar a la versión 2 de cgroup
La ruta de acceso más sencilla es elegir una distribución que admita cgroup v2 de fábrica.
Si necesita cambiar manualmente, agregue el siguiente parámetro a la configuración de GRUB:
systemd.unified_cgroup_hierarchy=1
A continuación, actualice GRUB. Por ejemplo, en Ubuntu, ejecute:
sudo update-grub
En Red Hat Enterprise Linux (RHEL), ejecute:
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
Informes de límite de CPU con cgroup v2
Al configurar límites de CPU mediante cgroup v2, SQL Server no muestra el recuento de núcleos de CPU configurados en el registro de errores. En su lugar, continúa informando del número total de CPU de host.
Para alinear el programador y los planes de consulta de SQL Server (por ejemplo, las decisiones de paralelismo) con el recuento de CPU previsto definido en el grupo de control v2, aplique la siguiente configuración.
Configuración de la afinidad de procesador
Establezca explícitamente la afinidad del procesador de SQL Server para que se alinee con la cuota de ejecución del cgroup. En el ejemplo siguiente, la cuota de cgroup es de cuatro CPU en un host de ocho núcleos:
ALTER SERVER CONFIGURATION
SET PROCESS AFFINITY CPU = 0 TO 3;
Esta configuración garantiza que SQL Server crea planificadores solo para el número deseado de CPUs. Para obtener más información, vea ALTER SERVER CONFIGURATION y Usar AFINIDAD DE PROCESOS para Nodo y/o CPUs.
Habilitación de la marca de seguimiento 8002 (recomendado)
Active el indicador de seguimiento 8002 para usar la afinidad flexible en la capa de SQLPAL.
sudo /opt/mssql/bin/mssql-conf traceflag 8002 on
De forma predeterminada, los programadores están asignados a CPU específicas definidas en la máscara de afinidad. La marca de seguimiento 8002 permite que los planificadores se muevan entre CPUs, lo que generalmente mejora el rendimiento, a la vez que respeta las afinidades y las restricciones de cgroup. Para obtener más información, vea DBCC TRACEON: marcas de seguimiento.
Reinicie SQL Server después de habilitar la marca de seguimiento.
Comportamiento esperado
Después del reinicio:
SQL Server crea solo el número de programadores definidos por la configuración de afinidad (por ejemplo, cuatro programadores).
El kernel de Linux sigue aplicando la cuota de ejecución de CPU de cgroup v2.
Las decisiones de optimización y paralelismo de consultas se basan en el recuento de CPU previsto, en lugar de en el total de CPU del host.
Nota:
El SQL Server registro de errores puede seguir mostrando el número total de CPU del host. Este comportamiento de registro y visualización no afecta al uso real de la CPU, la creación del programador ni la aplicación de CPU por cgroup v2 o afinidad de procesador.
Para obtener más información, consulte los siguientes recursos:
- Inicio rápido: Implementación de un contenedor de SQL Server en Linux en Azure Kubernetes Service (AKS) mediante gráficos de Helm
- Grupo de control v2 (documentación del kernel de Linux)
Contenido relacionado
- Inicio rápido: Implementación de un clúster de contenedores de SQL Server en Azure o Red Hat OpenShift
- Inicio rápido: Implementación de un contenedor de SQL Server en Linux en Azure Kubernetes Service (AKS) mediante gráficos de Helm
- Implementación de grupos de disponibilidad con DH2i DxEnterprise en Kubernetes