Partager via


Guide pratique pour utiliser des transactions distribuées avec des conteneurs SQL Server Linux

S’applique à : SQL Server - Linux

Cet article explique comment configurer des conteneurs SQL Server Linux pour les transactions distribuées, exigences et scénarios spéciaux inclus.

Les images de conteneur SQL Server prennent en charge Microsoft Distributed Transaction Coordinator (MSDTC), qui est nécessaire pour les transactions distribuées. Pour comprendre les exigences de communication pour MSDTC, consultez Comment configurer Microsoft Distributed Transaction Coordinator (MSDTC) sur Linux.

Notes

Les conteneurs SQL Server 2017 (14.x) s’exécutent dans des conteneurs racines par défaut, tandis que les conteneurs SQL Server 2019 (15.x) s’exécutent en tant qu’utilisateur non racine.

Configuration

Pour activer la transaction MSDTC dans des conteneurs SQL Serveur, vous devez définir deux nouvelles variables d’environnement :

  • MSSQL_RPC_PORT : le port TCP auquel le service mappeur de point de terminaison RPC est lié et sur lequel il écoute.
  • MSSQL_DTC_TCP_PORT : le port sur lequel le service MSDTC est configuré pour l’écoute.

Extraire et exécuter

L’exemple suivant montre comment utiliser ces variables d’environnement pour tirer (pull) et exécuter un seul conteneur SQL Server 2017 configuré pour MSDTC. Cela lui permet de communiquer avec n’importe quelle application sur tous les ordinateurs hôtes.

Important

La variable d’environnement SA_PASSWORD est dépréciée. Utilisez MSSQL_SA_PASSWORD à la place.

docker run \
   -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=<YourStrong!Passw0rd>' \
   -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=<YourStrong!Passw0rd>" `
   -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

L’exemple suivant montre comment utiliser ces variables d’environnement pour tirer (pull) et exécuter un seul conteneur SQL Server 2019 (15.x) configuré pour MSDTC. Cela lui permet de communiquer avec n’importe quelle application sur tous les ordinateurs hôtes.

Important

La variable d’environnement SA_PASSWORD est dépréciée. Utilisez MSSQL_SA_PASSWORD à la place.

docker run \
   -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=<YourStrong!Passw0rd>' \
   -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=<YourStrong!Passw0rd>" `
   -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

Dans cette commande, le service Mappeur de point de terminaison RPC est lié au port 135, et le service MSDTC au port 51000 au sein du réseau virtuel du conteneur. La communication TDS de SQL Server se produit sur le port 1433, également au sein du réseau virtuel du conteneur. Ces ports sont exposés en externe auprès de l’hôte sous la forme du port TDS 51433, du port 135 du mappeur de point de terminaison RPC et du port MSDTC 51000.

Il n’est pas nécessaire que le Mappeur de point de terminaison RPC et le port MSDTC soient identiques sur l’hôte et le conteneur. Ainsi, alors que le port du mappeur de point de terminaison RPC a été configuré pour être 135 sur le conteneur, il peut potentiellement être mappé au port 13501 ou à tout autre port disponible sur le serveur hôte.

Configurer le pare-feu

Pour pouvoir communiquer avec et via l’hôte, vous devez également configurer le pare-feu sur le serveur hôte pour les conteneurs. Ouvrez le pare-feu pour tous les ports exposés par le conteneur SQL Server pour la communication externe. Dans l’exemple précédent, il s’agirait des ports 135, 51433 et 51000. Il s’agit des ports sur l’hôte lui-même, et non des ports auxquels ils sont mappés dans le conteneur. Ainsi, si le port de mappeur de point de terminaison RPC 51000 du conteneur a été mappé au port 51001 de l’hôte, le port 51001 (et non 51000) doit être ouvert dans le pare-feu pour permettre la communication avec l’ordinateur hôte.

L’exemple suivant montre comment créer ces règles sur 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

L’exemple suivant montre comment effectuer cette opération sur 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

Configurer le routage de ports sur l’hôte

Dans l’exemple précédent, étant donné qu’un conteneur SQL Server unique fait correspondre le port RPC 135 avec le port 135 de l’hôte, les transactions distribuées devraient maintenant fonctionner avec l’hôte sans configuration supplémentaire. Il est possible d’utiliser directement le port 135 dans les conteneurs s’exécutant en tant que root, car SQL Server s’exécute avec des privilèges élevés dans ces conteneurs. Pour SQL Server en dehors d’un conteneur ou pour des conteneurs non root, vous devez utiliser un autre port éphémère (par exemple 13500) dans le conteneur, puis acheminer le trafic destiné au port 135 vers ce port. Vous devez également configurer des règles de routage de port dans le conteneur à partir du port 135 du conteneur vers le port éphémère.

Par ailleurs, si vous décidez de mapper le port 135 du conteneur à un port différent sur l’hôte, par exemple 13500, vous devez configurer le routage de port sur l’hôte. Cela permet au conteneur SQL Server de participer à des transactions distribuées avec l’hôte et d’autres serveurs externes.

Pour plus d’informations, consultez Configurer le routage de ports.

Conteneurs SQL Server avec MSDTC sur Kubernetes

Si vous déployez des conteneurs SQL Server sur une plateforme Kubernetes, consultez l'exemple suivant de manifeste de déploiement YAML. Dans cet exemple, la plateforme Kubernetes est Azure Kubernetes Service (AKS).

Scénario 1 : Client MSDTC se connectant à SQL Server dans un conteneur Kubernetes

Le diagramme suivant illustre le processus de connexion d’un client MSDTC à MSDTC sur SQL Server s’exécutant dans un conteneur Linux sur Kubernetes.

Diagramme du processus de connexion d’un client MSDTC à MSDTC sur SQL Server s’exécutant dans un conteneur Linux.

  1. Le client MSDTC établit une connexion au port 135 sur l’hôte Kubernetes.
  2. La connexion est transférée vers le port 135 sur le conteneur.
  3. Le conteneur transfère la connexion au mappeur de point de terminaison RPC, qui se trouve sur le port 13500 dans cet exemple.
  4. Le mappeur de point de terminaison indique au client MSDTC quel port MSDTC s’exécute dans le conteneur (le port 51000 dans cet exemple).
  5. Le client MSDTC établit une connexion directe à MSDTC en se connectant à l’hôte sur le port 51000, qui est transféré vers SQL Server dans le conteneur.

Scénario 2 : SQL Server se connectant à SQL Server dans un conteneur Kubernetes

Le diagramme suivant illustre le processus de connexion d’un conteneur SQL Server Linux à MSDTC dans un deuxième conteneur SQL Server Linux, sur Kubernetes.

Diagramme du processus de connexion d’un conteneur SQL Server Linux à MSDTC dans un deuxième conteneur SQL Server Linux.

  1. La première instance de SQL Server établit une connexion au port 135 sur l’hôte Kubernetes de la deuxième instance de SQL Server.
  2. La connexion est transférée vers le port 135 sur le conteneur de la deuxième instance.
  3. Le conteneur transfère la connexion au mappeur de point de terminaison RPC, qui se trouve sur le port 13500 dans cet exemple.
  4. Le mappeur de point de terminaison indique à la première instance de SQL Server quel port MSDTC s’exécute dans le deuxième conteneur (le port 51000 dans cet exemple).
  5. La première instance de SQL Server établit une connexion directe à MSDTC sur la deuxième instance en se connectant au second hôte sur le port 51000, qui est transféré vers SQL Server dans le conteneur.

Déploiement de conteneurs SQL Server avec MSDTC configuré sur une plateforme Kubernetes

Avant d’exécuter l’exemple de script de déploiement YAML, créez le secret nécessaire pour stocker le mot de passe sa, à l'aide de la commande suivante :

kubectl create secret generic mssql --from-literal=MSSQL_SA_PASSWORD="MyC0m9l&xP@ssw0rd"

Vous remarquez les points suivants dans le fichier manifeste :

  1. Dans le cluster, nous créons les objets suivants : StorageClass, deux pods SQL Server déployés en tant que statefulset et deux services d’équilibrage de charge pour la connexion aux instances SQL Server correspondantes.

  2. Vous remarquerez également que les services d’équilibrage de charge sont déployés avec des adresses IP statiques, qui peuvent être configurées sur Azure Kubernetes Service. Cf. Utilisation d’une adresse IP publique statique et d’une étiquette DNS avec l’équilibreur de charge d’Azure Kubernetes Service (AKS). Lorsque les services d’équilibrage de charge sont créés avec des adresses IP statiques, l’adresse IP externe ne change pas lorsque le service d’équilibrage de charge est supprimé et recréé.

  3. Dans le script suivant, vous pouvez voir que le port 13500 est utilisé pour la variable d’environnement MSSQL_RPC_PORT, et le port 51000 pour la variable d’environnement MSSQL_DTC_TCP_PORT, les deux étant obligatoires pour MSDTC.

  4. Le routage des ports (c'est-à-dire le routage du port 135 vers 13500) est configuré dans le script de l'équilibreur de charge en configurant de manière appropriée les paramètres port et targetPort, comme le montre l'exemple suivant :

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: 40.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: 20.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

En supposant que vous avez créé la ressource dans l'espace de noms par défaut, lorsque vous exécutez la commande kubectl get all après le déploiement précédent pour voir toutes les ressources créées, vous devriez obtenir la sortie indiquée dans l'exemple suivant.

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   40.88.213.209   1433:31875/TCP,51000:31219/TCP,135:30044/TCP   2d6h
service/mssql-1      LoadBalancer   10.0.16.180   20.72.137.129   1433:30353/TCP,51000:32734/TCP,135:31239/TCP   2d6h

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

Vous pouvez utiliser des outils tels que SQL Server Management Studio (SSMS) pour vous connecter à l'une des deux instances précédentes du serveur SQL et exécuter un exemple de transaction DTC. Dans cet exemple, vous vous connectez à mssql-1 (20.72.137.129) et créez le serveur lié à mssql-0 (40.88.213.209) pour exécuter la transaction distribuée, comme le montre l'exemple suivant.

USE [master]
GO
EXEC master.dbo.sp_addlinkedserver @server = N'40.88.213.209', @srvproduct=N'SQL Server';
GO

EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname = N'40.88.213.209', @rmtuser = 'sa', @rmtpassword = 'xxxx', @useself = N'False';
GO

Vous pouvez maintenant lancer la transaction distribuée. Cet exemple de code permet d’afficher les sys.sysprocesses de l’instance mssql-0 :

SET XACT_ABORT ON;

BEGIN DISTRIBUTED TRANSACTION
SELECT * FROM [40.88.213.209].master.dbo.sysprocesses;
COMMIT
GO