共用方式為


如何在 Linux 容器上搭配 SQL Server 使用分散式交易

適用於:Linux 上的 SQL Server

本文說明如何為分散式交易設定 SQL Server Linux 容器,包括特殊需求和案例。

SQL Server 容器映像可以使用 Microsoft 分散式交易協調器 (MSDTC),這是分散式交易處理所需的功能。 若要了解 MSDTC 的通訊需求,請參閱如何在 Linux 上設定 Microsoft 分散式交易協調器 (MSDTC)

注意

根據預設,SQL Server 2017 (14.x) 會在根容器中執行,而 SQL Server 2019 (15.x) 和更新的容器則是以非根使用者的身分執行。

設定

若要在 SQL Server 容器中啟用 MSDTC 交易,您必須設定兩個新的環境變數:

  • MSSQL_RPC_PORT:RPC 端點對應程式服務繫結並接聽的 TCP 連接埠。
  • MSSQL_DTC_TCP_PORT:MSDTC 服務設定接聽的連接埠。

拉取並執行

下列範例示範如何使用這些環境變數來提取並執行針對 MSDTC 所設定的單一 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 所設定的單一 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 為底數的數字以及符號。 密碼長度最多可達 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,則應在防火牆中開啟連接埠 51001 (而不是 51000),以便與主機通訊。

下列範例顯示如何在 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

設定主機上的連接埠路由

在上述範例中,因為單一 SQL Server 容器會將 RPC 連接埠 135 對應至主機上的連接埠 135,所以搭配主機的分散式交易現在應該可以使用,不需要進一步設定。 您可以直接在以 root 身分執行的容器中使用連接埠 135,因為 SQL Server 會在這些容器中以較高的權限執行。 如果是容器外的 SQL Server 或非根容器,您需要使用不同的臨時埠(例如 13500),然後將用於埠 135 的流量路由至該埠。 您也必須在容器內將連接埠路由規則從容器連接埠 135 設定為臨時連接埠。

此外,如果您決定將容器的連接埠 135 對應至主機上不同連接埠 (例如 13500),則您必須在主機上設定連接埠路由。 這可讓 SQL Server 容器與主機和其他外部伺服器參與分散式交易。

如需連接埠路由的詳細資訊,請參閱設定連接埠路由

具有 MSDTC 的 SQL Server 容器在 Kubernetes 上

如果您要在 Kubernetes 平台上部署 SQL Server 容器,請參閱下面的範例 YAML 部署資訊清單。 在此範例中,所使用的 Kubernetes 平台是 Azure Kubernetes Service (AKS)。

案例 1:MSDTC 用戶端連線到 Kubernetes 容器中的 SQL Server

下圖顯示當 MSDTC 用戶端連接至在 Kubernetes 上的 Linux 容器內運行的 SQL Server 上的 MSDTC 的過程。

此圖顯示 MSDTC 用戶端在 Linux 容器內執行的 SQL Server 連線到 MSDTC 時的程式。

  1. MSDTC 用戶端會連線至 Kubernetes 主機上的埠 135。
  2. 連線會轉送到容器上的埠 135。
  3. 容器會將連線轉送至 RPC 端點對應程式,在此範例中,位於埠 13500 上。
  4. 端點對應程式會告知 MSDTC 用戶端,MSDTC 在容器內運行的埠號是哪一個(此例中為埠 51000)。
  5. MSDTC 用戶端會直接通過連接至埠 51000 上的主機來連線到 MSDTC,而該連線會被轉送至容器內的 SQL Server。

案例 2:SQL Server 連線到 Kubernetes 容器中的 SQL Server

下圖顯示在 Kubernetes 上的一個 SQL Server Linux 容器如何連接到第二個 SQL Server Linux 容器中的 MSDTC 的過程。

此圖顯示一個 SQL Server Linux 容器在第二個 SQL Server Linux 容器上連線到 MSDTC 的程式。

  1. 第一個 SQL Server 執行個體會連線到第二個 SQL Server 執行個體的 Kubernetes 主機上的 135 埠。
  2. 連線會轉送到第二個執行個體容器上的埠 135。
  3. 容器會將連線轉送至 RPC 端點對應程式,在此範例中,位於埠 13500 上。
  4. 端點對應程式會告知第一個 SQL Server 執行個體,MSDTC 在第二個容器內執行哪個埠, (埠 51000)。
  5. 第一個 SQL Server 執行個體會透過連接到埠 51000 上的第二部主機,直接與第二個執行個體上的 MSDTC 建立連接,而此連接埠會轉送至容器內的 SQL Server。

在 Kubernetes 平台上設定 MSDTC 部署 SQL Server 容器

在執行範例部署 YAML 指令碼之前,請先使用下列範例命令來建立必要的祕密來儲存 sa 密碼:

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

警告

您的密碼應遵循 SQL Server 預設 密碼原則。 依預設,密碼長度必須至少有 8 個字元,並包含下列四種字元組合中其中三種組合的字元:大寫字母、小寫字母、以 10 為底數的數字以及符號。 密碼長度最多可達 128 個字元。 盡可能使用長且複雜的密碼。

您會注意到資訊清單檔案中的以下幾個要點:

  1. 在叢集中,我們會建立下列物件:StorageClass、部署為 statefulset 部署的兩個 SQL Server Pod,以及兩個負載平衡器服務以連線到個別的 SQL Server 執行個體。

  2. 您也會注意到負載平衡器服務是使用靜態 IP 位址部署,可在 Azure Kubernetes Service 上設定。 請參閱在 Azure Kubernetes Service (AKS) 負載平衡器中使用靜態公用 IP 位址和 DNS 標籤。 使用靜態 IP 位址建立負載平衡器服務,可確保如果刪除並重新建立負載平衡器服務,外部 IP 位址不會變更。

  3. 在下列指令碼中,您可以看到埠 13500 用於 MSSQL_RPC_PORT 環境變數,以及 MSSQL_DTC_TCP_PORT 環境變數的埠 51000,這兩者都是 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) 之類的工具來連線到前述兩個 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 為底數的數字以及符號。 密碼長度最多可達 128 個字元。 盡可能使用長且複雜的密碼。

現在您可以啟動分散式交易,而此程式碼範例會顯示 sys.sysprocesses 執行個體中的 mssql-0

SET XACT_ABORT ON;

BEGIN DISTRIBUTED TRANSACTION;

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

COMMIT TRANSACTION;
GO