次の方法で共有


SQL Server Linux コンテナーで分散トランザクションを使用する方法

適用対象:SQL Server - Linux

この記事では、分散トランザクションのために SQL Server Linux コンテナーをセットアップする方法について、特別な要件とシナリオを含めて説明します。

SQL Server のコンテナー イメージでは、分散トランザクションに必要な Microsoft 分散トランザクション コーディネーター (MSDTC) を使用できます。 MSDTC での通信要件を理解するために、「Linux 上の Microsoft 分散トランザクション コーディネーター (MSDTC) を構成する方法」を参照してください。

注意

SQL Server 2017 (14.x) は既定でルート コンテナーで実行されるのに対し、SQL Server 2019 (15.x) 以降のコンテナーは非ルート ユーザーとして実行されます。

構成

SQL Server コンテナーで MSDTC トランザクションを有効にするには、次の 2 つの新しい環境変数を設定する必要があります。

  • MSSQL_RPC_PORT: RPC エンドポイント マッパー サービスがバインドされてリッスンする TCP ポート。
  • MSSQL_DTC_TCP_PORT: MSDTC サービスがリッスンするように構成されているポート。

プルおよび実行

次の例では、これらの環境変数を使用して、MSDTC 用に構成された 1 つの SQL Server 2017 コンテナーをプルして実行する方法を示しています。 これにより、任意のホスト上の任意のアプリケーションと通信できるようになります。

重要

SA_PASSWORD 環境変数は非推奨です。 代わりに 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

次の例では、これらの環境変数を使用して、MSDTC 用に構成された 1 つの SQL Server 2019 (15.x) コンテナーをプルして実行する方法を示しています。 これにより、任意のホスト上の任意のアプリケーションと通信できるようになります。

重要

SA_PASSWORD 環境変数は非推奨です。 代わりに 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

注意事項

パスワードは SQL Server の既定のパスワード ポリシーに従う必要があります。 既定では、パスワードの長さは少なくとも 8 文字で、大文字、小文字、10 進数の数字、記号の 4 種類のうち 3 種類を含んでいる必要があります。 パスワードには最大 128 文字まで使用できます。 パスワードはできるだけ長く、複雑にします。

このコマンドでは、RPC エンドポイント マッパー サービスがポート 135 にバインドされ、MSDTC サービスがコンテナーの仮想ネットワーク内のポート 51000 にバインドされています。 SQL Server の TDS 通信は、コンテナーの仮想ネットワーク内のポート 1433 上でも行われます。 これらのポートは、TDS ポート 51433、RPC エンドポイント マッパーポート 135、および MSDTC ポート 51000 としてホストするために、外部に公開されています。

RPC エンドポイント マッパーと MSDTC ポートは、ホストとコンテナー上で同一になっている必要はありません。 そのため、RPC エンドポイント マッパーのポートはコンテナー上で 135 になるように構成されると共に、潜在的にはポート 13501 またはホスト サーバー上で利用できるその他の任意のポートにマップされる可能性があります。

ファイアウォールを構成する

ホストと通信するためには、コンテナー用のホスト サーバー上にファイアウォールを構成する必要もあります。 SQL Server コンテナーが外部通信用に公開しているすべてのポートに対して、ファイアウォールを開きます。 前の例では、これはポート 135、51433、および 51000 になります。 これらは、ホスト自体にあるポートであり、コンテナー内でマップされているポートではありません。 そのため、コンテナーの RPC エンドポイント マッパーのポート 51000 がホストのポート 51001 にマップされた場合は、ホストとの通信のためにファイアウォールに (51000 ではなく) ポート 51001 を開く必要があります。

次の例は、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

次の例は、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

ホスト上にポートのルーティングを構成する

前の例では、1 つの SQL Server コンテナーが RPC ポート 135 をホスト上のポート 135 にマップするため、それ以上構成しなくても、ホストによる分散トランザクションが機能するようになっています。 それらのコンテナーでは昇格された特権によって SQL Server が実行されるため、ルートとして実行されているコンテナー内でポート 135 を直接使用することができます。 コンテナー外にある SQL Server の場合、または非ルート コンテナーの場合、コンテナーで別の一時的なポート (13500 など) を使用する必要があり、ポート 135 に想定されるトラフィックはそのポートにルーティングされる必要があります。 コンテナー内のポート ルーティング規則を、コンテナー ポート 135 から一時的なポートに構成する必要もあります。

また、コンテナーのポート 135 をホスト上の別のポート (13500 など) にマップすることに決めた場合は、ホスト上にポートのルーティングを構成する必要があります。 これにより、ホストやその他の外部サーバーでの分散トランザクションに、SQL Server コンテナーが参加できるようになります。

ポートのルーティングの詳細については、「ポートのルーティングを構成する」を参照してください。

Kubernetes 上の MSDTC を含む SQL Server コンテナー

Kubernetes プラットフォームに SQL Server コンテナーを配置している場合は、以下の YAML 配置マニフェストの例を参照してください。 この例では、Kubernetes プラットフォームは Azure Kubernetes Service (AKS) です。

シナリオ 1: Kubernetes コンテナー内の SQL Server に接続する MSDTC クライアント

次の図は、MSDTC クライアントが、Kubernetes 上の Linux コンテナー内で実行されている SQL Server 上の MSDTC に接続するときのプロセスを示しています。

MSDTC クライアントが Linux コンテナー内で実行されている SQL Server 上の MSDTC に接続するときのプロセスを示す図。

  1. MSDTC クライアントが Kubernetes ホスト上のポート 135 に接続します。
  2. この接続はコンテナーのポート 135 に転送されます。
  3. コンテナーによって RPC エンドポイント マッパー (この例ではポート 13500) に接続が転送されます。
  4. エンドポイント マッパーによって、MSDTC がコンテナー内で実行されているポート (この例ではポート 51000) が MSDTC クライアントに通知されます。
  5. MSDTC クライアントは、コンテナー内の SQL Server に転送されるポート 51000 でホストに接続して、MSDTC に直接接続します。

シナリオ 2: Kubernetes コンテナー内の SQL Server に接続する MSDTC クライアント

次の図は、1 つの SQL Server Linux コンテナーが、Kubernetes 上の 2 番目の SQL Server Linux コンテナー上の MSDTC に接続するときのプロセスを示しています。

1 つの SQL Server Linux コンテナーが 2 番目の SQL Server Linux コンテナーの MSDTC に接続するプロセスを示す図。

  1. 最初の SQL Server インスタンスは、2 番目の SQL Server インスタンスの Kubernetes ホスト上のポート 135 に接続します。
  2. 接続は、2 番目のインスタンスのコンテナーのポート 135 に転送されます。
  3. コンテナーによって RPC エンドポイント マッパー (この例ではポート 13500) に接続が転送されます。
  4. エンドポイント マッパーによって、2 番目のコンテナー内で実行されているポート MSDTC (この例ではポート 51000) が最初の SQL Server インスタンスに通知されます。
  5. 最初の SQL Server インスタンスは、コンテナー内の SQL Server に転送されるポート 51000 で 2 番目のホストに接続して、2 番目のインスタンスの MSDTC に直接接続します。

Kubernetes プラットフォームで構成された MSDTC を使用して SQL Server コンテナーを配置する

サンプルの YAML 配置スクリプトを実行する前に、次のコマンド例を使用して、sa パスワードを格納するために必要なシークレットを作成します。

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

注意事項

パスワードは SQL Server の既定のパスワード ポリシーに従う必要があります。 既定では、パスワードの長さは少なくとも 8 文字で、大文字、小文字、10 進数の数字、記号の 4 種類のうち 3 種類を含んでいる必要があります。 パスワードには最大 128 文字まで使用できます。 パスワードはできるだけ長く、複雑にします。

マニフェスト ファイルでは次の点に気づくはずです。

  1. クラスターでは、StorageClassstatefulset の配置として配置された 2 つの SQL Server ポッド、それぞれの SQL Server インスタンスに接続する 2 つのロード バランサー サービスのオブジェクトを作成します。

  2. また、Azure Kubernetes Service で構成できる静的 IP アドレスを使用してロード バランサー サービスが配置されていることにも気づくはずです。 「Azure Kubernetes Service (AKS) ロード バランサーで静的パブリック IP アドレスと DNS ラベルを使用する」を参照してください。 静的 IP アドレスを使用してロード バランサー サービスを作成すると、ロード バランサー サービスが削除および再作成された場合、外部 IP アドレスは変更されません。

  3. 次のスクリプトでは、ポート 13500 が MSSQL_RPC_PORT 環境変数に、ポート 51000 が MSSQL_DTC_TCP_PORT 環境変数に使用されているのを確認できます。このどちらも MSDTC に必要です。

  4. ポート ルーティング (つまり、ルーティング ポート 135 から 13500) は、次の例に示すようにporttargetPort を適切に構成することで、ロード バランサー スクリプトで構成されます。

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

既定の名前空間でリソースを作成した場合、以前の配置の後に kubectl get all コマンドを実行して作成されたすべてのリソースを表示すると、次の例に示す出力が表示されます。

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

SQL Server Management Studio (SSMS) のようなツールを使用して、先ほどの 2 つの SQL Server インスタンスのどちらかに接続し、サンプルの DTC トランザクションを実行できます。 この例では、次の例に示すように、mssql-1 (10.72.137.129) に接続し、mssql-0 (10.88.213.209) へのリンク サーバーを作成して分散トランザクションを実行します。

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

注意事項

パスワードは SQL Server の既定のパスワード ポリシーに従う必要があります。 既定では、パスワードの長さは少なくとも 8 文字で、大文字、小文字、10 進数の数字、記号の 4 種類のうち 3 種類を含んでいる必要があります。 パスワードには最大 128 文字まで使用できます。 パスワードはできるだけ長く、複雑にします。

これで分散トランザクションを開始できます。このコード サンプルでは、sys.sysprocesses インスタンスから mssql-0 が表示されます。

SET XACT_ABORT ON;

BEGIN DISTRIBUTED TRANSACTION;

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

COMMIT TRANSACTION;
GO