Compartir por


Procedimiento para usar transacciones distribuidas con contenedores de SQL Server en Linux

Se aplica a:SQL Server en Linux

En este artículo, se explica cómo configurar contenedores de SQL Server en Linux para realizar transacciones distribuidas, incluidos requisitos y escenarios especiales.

Las imágenes de contenedor de SQL Server pueden usar Microsoft DTC (Coordinador de transacciones distribuidas), que es necesario para las transacciones distribuidas. Para comprender los requisitos de comunicaciones de MSDTC, vea Procedimiento para configurar Microsoft DTC (Coordinador de transacciones distribuidas) en Linux.

Nota

SQL Server 2017 (14.x) se ejecuta en contenedores raíz de forma predeterminada, mientras que los contenedores de SQL Server 2019 (15.x) y posteriores se ejecutan como un usuario no raíz.

Configuración

Para habilitar la transacción de Coordinador de transacciones distribuidas en contenedores de SQL Server, debe establecer dos nuevas variables de entorno:

  • MSSQL_RPC_PORT: el puerto TCP al que se enlaza el servicio del asignador de puntos de conexión de RPC y en el que escucha.
  • MSSQL_DTC_TCP_PORT: el puerto en el que se ha configurado el servicio MSDTC para escuchar.

Extraer y ejecutar

En el ejemplo siguiente, se muestra cómo usar estas variables de entorno para extraer y ejecutar un único contenedor de SQL Server 2017 configurado para MSDTC. Esto le permite comunicarse con cualquier aplicación en cualquier host.

Importante

La variable de entorno SA_PASSWORD está en desuso. En su lugar, use MSSQL_SA_PASSWORD.

docker run \
   -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=<password>' \
   -e 'MSSQL_RPC_PORT=135' -e 'MSSQL_DTC_TCP_PORT=51000' \
   -p 51433:1433 -p 135:135 -p 51000:51000  \
   -d mcr.microsoft.com/mssql/server:2017-latest
docker run `
   -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=<password>" `
   -e "MSSQL_RPC_PORT=135" -e "MSSQL_DTC_TCP_PORT=51000" `
   -p 51433:1433 -p 135:135 -p 51000:51000  `
   -d mcr.microsoft.com/mssql/server:2017-latest

En el ejemplo siguiente, se muestra cómo usar estas variables de entorno para extraer y ejecutar un único contenedor de SQL Server 2019 (15.x) configurado para MSDTC. Esto le permite comunicarse con cualquier aplicación en cualquier host.

Importante

La variable de entorno SA_PASSWORD está en desuso. En su lugar, use MSSQL_SA_PASSWORD.

docker run \
   -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=<password>' \
   -e 'MSSQL_RPC_PORT=135' -e 'MSSQL_DTC_TCP_PORT=51000' \
   -p 51433:1433 -p 135:135 -p 51000:51000  \
   -d mcr.microsoft.com/mssql/server:2019-GA-ubuntu-20.04
docker run `
   -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=<password>" `
   -e "MSSQL_RPC_PORT=135" -e "MSSQL_DTC_TCP_PORT=51000" `
   -p 51433:1433 -p 135:135 -p 51000:51000  `
   -d mcr.microsoft.com/mssql/server:2019-GA-ubuntu-20.04

Precaución

La contraseña debe seguir la directiva de contraseña predeterminada de SQL Server. De forma predeterminada, la contraseña debe tener al menos ocho caracteres y contener caracteres de tres de los siguientes cuatro conjuntos: mayúsculas, minúsculas, dígitos en base 10 y símbolos. Las contraseñas pueden tener hasta 128 caracteres. Use contraseñas lo más largas y complejas posible.

En este comando, el servicio Asignador de puntos de conexión de RPC está enlazado al puerto 135, y el servicio Coordinador de transacciones distribuidas está enlazado al puerto 51000 en la red virtual del contenedor. La comunicación de TDS de SQL Server se realiza en el puerto 1433, también en la red virtual del contenedor. Estos puertos están expuestos externamente al host, como el puerto TDS 51433, el puerto 135 del asignador de puntos de conexión de RPC y el puerto 51000 de MSDTC.

El asignador de puntos de conexión de RPC y el puerto de Coordinador de transacciones distribuidas no tienen que coincidir en el host y en el contenedor. Por lo tanto, si el puerto del asignador de puntos de conexión de RPC se ha configurado en el puerto 135 del contenedor, podría asignarse al puerto 13501 o a cualquier otro puerto disponible en el servidor host.

Configuración del firewall

Para comunicarse con el host y a través de este, también necesita configurar el firewall en el servidor host para los contenedores. En el firewall, abra todos los puertos donde el contenedor de SQL Server se exponga para las comunicaciones externas. En el ejemplo anterior, se usarían los puertos 135, 51433 y 51000. Estos son los puertos en el host en sí, y no los puertos a los que se asignan en el contenedor. Por lo tanto, si el puerto 51000 del asignador de puntos de conexión de RPC del contenedor se ha asignado al puerto 51001 del host, el puerto 51001 (y no el puerto 51000) tiene que abrirse en el firewall para permitir la comunicación con el host.

En el ejemplo siguiente, se muestra cómo crear estas reglas en Ubuntu.

sudo ufw allow from any to any port 51433 proto tcp
sudo ufw allow from any to any port 51000 proto tcp
sudo ufw allow from any to any port 135 proto tcp

En el ejemplo siguiente, se muestra cómo podría realizarse este procedimiento en Red Hat Enterprise Linux (RHEL):

sudo firewall-cmd --zone=public --add-port=51433/tcp --permanent
sudo firewall-cmd --zone=public --add-port=51000/tcp --permanent
sudo firewall-cmd --zone=public --add-port=135/tcp --permanent
sudo firewall-cmd --reload

Configurar el enrutamiento de puertos en el host

En el ejemplo anterior, como un único contenedor de SQL Server asigna el puerto 135 de RPC al puerto 135 en el host, las transacciones distribuidas con el host tendrían que funcionar sin una configuración adicional. Se puede usar directamente el puerto 135 en los contenedores que se ejecutan como raíz, ya que SQL Server se ejecuta con privilegios elevados en esos contenedores. Para SQL Server fuera de un contenedor o para contenedores que no son raíz, debe usar en el contenedor otro puerto efímero (por ejemplo, 13500). Además, el tráfico al puerto 135 tiene que enrutarse a ese puerto. También debe configurar las reglas de enrutamiento de puertos en el contenedor del puerto 135 del contenedor al puerto efímero.

Además, si decide asignar el puerto 135 del contenedor a otro puerto del host (por ejemplo, 13500), necesita configurar el enrutamiento del puerto en el host. Esto permite al contenedor de SQL Server participar en transacciones distribuidas con el host y con otros servidores externos.

Para obtener más información sobre el enrutamiento de puertos, vea Configuración del enrutamiento de puertos.

Contenedores de SQL Server con MSDTC en Kubernetes

Si va a implementar contenedores de SQL Server en una plataforma de Kubernetes, consulte el siguiente manifiesto de implementación de YAML de ejemplo. En este ejemplo, la plataforma de Kubernetes es Azure Kubernetes Service (AKS).

Escenario 1: Cliente MSDTC que se conecta a SQL Server en un contenedor de Kubernetes

En el diagrama siguiente se muestra el proceso cuando un cliente MSDTC se conecta a MSDTC en SQL Server que se ejecuta dentro de un contenedor de Linux en Kubernetes.

Diagrama que muestra el proceso cuando un cliente MSDTC se conecta a MSDTC en SQL Server que se ejecuta dentro de un contenedor de Linux.

  1. El cliente MSDTC realiza una conexión al puerto 135 en el host de Kubernetes.
  2. La conexión se reenvía al puerto 135 en el contenedor.
  3. El contenedor reenvía la conexión al asignador de puntos de conexión RPC, que se encuentra en el puerto 13500 en este ejemplo.
  4. El asignador de puntos de conexión indica al cliente MSDTC qué puerto MSDTC se ejecuta dentro del contenedor (puerto 51000 en este ejemplo).
  5. El cliente MSDTC realiza una conexión directamente con MSDTC mediante la conexión al host en el puerto 51000, que se reenvía a SQL Server dentro del contenedor.

Escenario 2: SQL Server que se conecta a SQL Server en un contenedor de Kubernetes

En el diagrama siguiente se muestra el proceso cuando un contenedor de SQL Server Linux se conecta a MSDTC en un segundo contenedor de Linux SQL Server, en Kubernetes.

Diagrama que muestra el proceso cuando un contenedor de SQL Server Linux se conecta a MSDTC en un segundo contenedor de Linux SQL Server.

  1. La primera instancia de SQL Server establece una conexión con el puerto 135 en el host de Kubernetes de la segunda instancia de SQL Server.
  2. La conexión se reenvía al puerto 135 en el contenedor de la segunda instancia.
  3. El contenedor reenvía la conexión al asignador de puntos de conexión RPC, que se encuentra en el puerto 13500 en este ejemplo.
  4. El asignador de puntos de conexión indica a la primera instancia de SQL Server qué puerto MSDTC se ejecuta dentro del segundo contenedor (puerto 51000 en este ejemplo).
  5. La primera instancia de SQL Server realiza una conexión directamente con MSDTC en la segunda instancia mediante la conexión al segundo host en el puerto 51000, que se reenvía a SQL Server dentro del contenedor.

Implementación de contenedores de SQL Server con Coordinador de transacciones distribuidas configurado en una plataforma de Kubernetes

Antes de ejecutar el script de YAML de implementación de ejemplo, cree el secreto necesario para almacenar la contraseña sa con el siguiente comando de ejemplo:

kubectl create secret generic mssql --from-literal=MSSQL_SA_PASSWORD="<password>"

Precaución

La contraseña debe seguir la directiva de contraseña predeterminada de SQL Server. De forma predeterminada, la contraseña debe tener al menos ocho caracteres y contener caracteres de tres de los siguientes cuatro conjuntos: mayúsculas, minúsculas, dígitos en base 10 y símbolos. Las contraseñas pueden tener hasta 128 caracteres. Use contraseñas lo más largas y complejas posible.

Observe los siguientes puntos en el archivo de manifiesto:

  1. En el clúster, creamos los siguientes objetos: StorageClass, dos pods SQL Server implementados como implementaciones statefulset y dos servicios del equilibrador de carga para conectarse a las instancias de SQL Server correspondientes.

  2. También observa que los servicios del equilibrador de carga se implementan con direcciones IP estáticas, que se pueden configurar en Azure Kubernetes Service. Consulte Uso de una dirección IP pública estática y una etiqueta DNS con el equilibrador de carga de Azure Kubernetes Service (AKS). La creación de los servicios del equilibrador de carga con direcciones IP estáticas garantiza que la dirección IP externa no cambie si el servicio del equilibrador de carga se elimina y se vuelve a crear.

  3. En el script siguiente, puede ver que se usa el puerto 13500 para la variable de entorno MSSQL_RPC_PORT y el puerto 51000 para la variable de entorno MSSQL_DTC_TCP_PORT, ambas necesarias para Coordinador de transacciones distribuidas.

  4. El enrutamiento de puertos (es decir, el enrutamiento del puerto 135 a 13500) se configura en el script del equilibrador de carga mediante la configuración adecuada de port y targetPort como se muestra en el siguiente ejemplo:

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: 2
 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
     - containerPort: 13500
       name: dtcport
     - containerPort: 51000
       name: dtctcpport
     env:
     - name: ACCEPT_EULA
       value: "Y"
     - name: MSSQL_ENABLE_HADR
       value: "1"
     - name: MSSQL_AGENT_ENABLED
       value: "1"
     - name: MSSQL_RPC_PORT
       value: "13500"
     - name: MSSQL_DTC_TCP_PORT
       value: "51000"
     - 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-0
spec:
  type: LoadBalancer
  loadBalancerIP: 10.88.213.209
  selector:
    statefulset.kubernetes.io/pod-name: mssql-0
  ports:
  - protocol: TCP
    port: 1433
    targetPort: 1433
    name: tcpsql
  - protocol: TCP
    port: 51000
    targetPort: 51000
    name: dtctcpport
  - protocol: TCP
    port: 135
    targetPort: 13500
    name: nonrootport
---
apiVersion: v1
kind: Service
metadata:
  name: mssql-1
spec:
  type: LoadBalancer
  loadBalancerIP: 10.72.137.129
  selector:
    statefulset.kubernetes.io/pod-name: mssql-1
  ports:
  - protocol: TCP
    port: 1433
    targetPort: 1433
    name: tcpsql
  - protocol: TCP
    port: 51000
    targetPort: 51000
    name: dtctcpport
  - protocol: TCP
    port: 135
    targetPort: 13500
    name: nonrootport

Suponiendo que ha creado el recurso en el espacio de nombres predeterminado, al ejecutar el comando kubectl get all después de la implementación anterior para ver todos los recursos creados, debería ver la salida que se muestra en el siguiente ejemplo.

NAME          READY   STATUS    RESTARTS   AGE
pod/mssql-0   1/1     Running   0          4d22h
pod/mssql-1   1/1     Running   0          4d22h

NAME                 TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)                                        AGE
service/kubernetes   ClusterIP      10.0.0.1      <none>          443/TCP                                        6d6h
service/mssql-0      LoadBalancer   10.0.18.186   10.88.213.209   1433:31875/TCP,51000:31219/TCP,135:30044/TCP   2d6h
service/mssql-1      LoadBalancer   10.0.16.180   10.72.137.129   1433:30353/TCP,51000:32734/TCP,135:31239/TCP   2d6h

NAME                     READY   AGE
statefulset.apps/mssql   2/2     5d1h

Puede usar herramientas como SQL Server Management Studio (SSMS) para conectarse a cualquiera de las dos instancias de SQL Server anteriores y ejecutar una transacción DTC de ejemplo. En este ejemplo, se conecta a mssql-1 (10.72.137.129) y crea el servidor vinculado en mssql-0 (10.88.213.209) para ejecutar la transacción distribuida, como se muestra en el ejemplo siguiente.

USE [master];
GO

EXECUTE master.dbo.sp_addlinkedserver
    @server = N'10.88.213.209',
    @srvproduct = N'SQL Server';
GO

EXECUTE master.dbo.sp_addlinkedsrvlogin
    @rmtsrvname = N'10.88.213.209',
    @rmtuser = 'sa',
    @rmtpassword = '<password>',
    @useself = N'False';
GO

Precaución

La contraseña debe seguir la directiva de contraseña predeterminada de SQL Server. De forma predeterminada, la contraseña debe tener al menos ocho caracteres y contener caracteres de tres de los siguientes cuatro conjuntos: mayúsculas, minúsculas, dígitos en base 10 y símbolos. Las contraseñas pueden tener hasta 128 caracteres. Use contraseñas lo más largas y complejas posible.

Ahora puede iniciar la transacción distribuida y este ejemplo de código le muestra sys.sysprocesses desde la instancia de mssql-0:

SET XACT_ABORT ON;

BEGIN DISTRIBUTED TRANSACTION;

SELECT *
FROM [10.88.213.209].master.dbo.sysprocesses;

COMMIT TRANSACTION;
GO