適用於:Linux 上的 SQL Server
本文說明如何為分散式交易設定 SQL Server Linux 容器,包括特殊需求和案例。
SQL Server 容器映像可以使用 Microsoft 分散式交易協調器 (MSDTC),這是分散式交易處理所需的功能。 若要了解 MSDTC 的通訊需求,請參閱如何在 Linux 上設定 Microsoft 分散式交易協調器 (MSDTC)。
Note
根據預設,SQL Server 2017 (14.x) 會在根容器中執行,而 SQL Server 2019 (15.x) 和更新的容器則是以非根使用者的身分執行。
Configuration
要在 SQL Server 容器中啟用 MSDTC 交易,您必須設定兩個環境變數:
-
MSSQL_RPC_PORT: 即 RPC 端點映射服務綁定並監聽的 TCP 埠。 -
MSSQL_DTC_TCP_PORT:MSDTC 服務設定為接聽的連接埠。
拉取並執行
下列範例示範如何使用這些環境變數來提取並執行針對 MSDTC 所設定的單一 SQL Server 2017 容器。 這讓它能與任何主機上的任何應用程式通訊。
Important
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) 容器。 這讓它能與任何主機上的任何應用程式通訊。
Important
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。 這些是主機本身的連接埠,而不是它們對應至容器中的連接埠。 因此,如果容器的 MSDTC 埠 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
下圖顯示一個 SQL Server Linux 容器連接到另一個 Kubernetes 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