適用於: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 用戶端會連線至 Kubernetes 主機上的埠 135。
- 連線會轉送到容器上的埠 135。
- 容器會將連線轉送至 RPC 端點對應程式,在此範例中,位於埠 13500 上。
- 端點對應程式會告知 MSDTC 用戶端,MSDTC 在容器內運行的埠號是哪一個(此例中為埠 51000)。
- MSDTC 用戶端會直接通過連接至埠 51000 上的主機來連線到 MSDTC,而該連線會被轉送至容器內的 SQL Server。
案例 2:SQL Server 連線到 Kubernetes 容器中的 SQL Server
下圖顯示在 Kubernetes 上的一個 SQL Server Linux 容器如何連接到第二個 SQL Server Linux 容器中的 MSDTC 的過程。
- 第一個 SQL Server 執行個體會連線到第二個 SQL Server 執行個體的 Kubernetes 主機上的 135 埠。
- 連線會轉送到第二個執行個體容器上的埠 135。
- 容器會將連線轉送至 RPC 端點對應程式,在此範例中,位於埠 13500 上。
- 端點對應程式會告知第一個 SQL Server 執行個體,MSDTC 在第二個容器內執行哪個埠, (埠 51000)。
- 第一個 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 個字元。 盡可能使用長且複雜的密碼。
您會注意到資訊清單檔案中的以下幾個要點:
在叢集中,我們會建立下列物件:
StorageClass、部署為statefulset部署的兩個 SQL Server Pod,以及兩個負載平衡器服務以連線到個別的 SQL Server 執行個體。您也會注意到負載平衡器服務是使用靜態 IP 位址部署,可在 Azure Kubernetes Service 上設定。 請參閱在 Azure Kubernetes Service (AKS) 負載平衡器中使用靜態公用 IP 位址和 DNS 標籤。 使用靜態 IP 位址建立負載平衡器服務,可確保如果刪除並重新建立負載平衡器服務,外部 IP 位址不會變更。
在下列指令碼中,您可以看到埠 13500 用於
MSSQL_RPC_PORT環境變數,以及MSSQL_DTC_TCP_PORT環境變數的埠 51000,這兩者都是 MSDTC 的必要端口。埠路由 (也就是路由埠 135 到 13500) 在負載平衡器指令碼中適當設定
port和targetPort,如下範例中所示:
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