적용 대상:SQL Server on Linux
이 문서에서는 특별 요구 사항과 시나리오를 비롯하여 분산 트랜잭션에 대해 SQL Server Linux 컨테이너를 설정하는 방법을 설명합니다.
SQL Server 컨테이너 이미지는 분산 트랜잭션에 필요한 MSDTC(Microsoft Distributed Transaction Coordinator)를 사용할 수 있습니다. MSDTC에 대한 통신 요구 사항을 이해하려면 Linux에서 MSDTC(Microsoft Distributed Transaction Coordinator)를 구성하는 방법을 참조하세요.
참고
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자 이상이어야 하며 대문자, 소문자, 0~9까지의 숫자 및 기호 네 가지 집합 중 세 집합의 문자를 포함해야 합니다. 암호 길이는 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
다음 예제에서는 RHEL(Red Hat Enterprise Linux)에서 이 작업을 수행하는 방법을 보여 줍니다.
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에 매핑하기 때문에 이제 호스트를 통한 분산 트랜잭션은 추가 구성 없이도 작동합니다. SQL Server는 이러한 컨테이너에서 상승된 권한으로 실행되므로 루트로서 실행되는 컨테이너에서 포트 135를 직접 사용할 수 있습니다. 컨테이너 외부 또는 루트가 아닌 컨테이너의 SQL Server의 경우 컨테이너에 다른 임시 포트(예: 13500)를 사용해야 하며 포트 135에 대해 의도된 트래픽은 해당 포트로 라우팅되어야 합니다. 또한 컨테이너 포트 135에서 임시 포트까지 컨테이너 내에서 포트 라우팅 규칙도 구성해야 합니다.
또 컨테이너의 포트 135를 호스트의 다른 포트(예: 13500)에 매핑하려면 호스트에서 포트 라우팅을 구성해야 합니다. 이를 통해 SQL Server 컨테이너는 호스트 및 다른 외부 서버를 통해 분산 트랜잭션에 참여할 수 있습니다.
라우팅 포트에 대한 자세한 내용은 포트 라우팅 구성을 참조하세요.
SQL Server 컨테이너 - Kubernetes에서 MSDTC 사용
Kubernetes 플랫폼에서 SQL Server 컨테이너를 배포하는 경우 다음 YAML 배포 매니페스트 예제를 참조하세요. 이 예제에서 Kubernetes 플랫폼은 AKS(Azure Kubernetes Service)를 말합니다.
시나리오 1: Kubernetes 컨테이너의 SQL Server로 연결하는 MSDTC 클라이언트
다음 다이어그램은 MSDTC 클라이언트가 Kubernetes의 Linux 컨테이너 내에서 실행되는 SQL Server MSDTC에 연결하는 프로세스를 보여 줍니다.
- MSDTC 클라이언트는 Kubernetes 호스트의 포트 135에 연결합니다.
- 연결은 컨테이너의 포트 135로 전달됩니다.
- 컨테이너는 이 예제의 포트 13500에 있는 RPC 엔드포인트 매퍼에 연결을 전달합니다.
- 엔드포인트 매퍼는 MSDTC 클라이언트에 컨테이너 내에서 실행 중인 포트 MSDTC를 알려줍니다(이 예제에서는 포트 51000).
- MSDTC 클라이언트는 컨테이너 내부의 SQL Server 전달되는 포트 51000의 호스트에 연결하여 MSDTC에 직접 연결합니다.
SQL Server가 Kubernetes 컨테이너의 SQL Server에 연결하는 시나리오 2
다음 다이어그램은 한 SQL Server Linux 컨테이너가 Kubernetes의 두 번째 SQL Server Linux 컨테이너에서 MSDTC에 연결하는 프로세스를 보여 줍니다.
- 첫 번째 SQL Server 인스턴스는 두 번째 SQL Server 인스턴스의 Kubernetes 호스트에서 포트 135에 연결합니다.
- 연결은 두 번째 인스턴스의 컨테이너에서 포트 135로 전달됩니다.
- 컨테이너는 이 예제의 포트 13500에 있는 RPC 엔드포인트 매퍼에 연결을 전달합니다.
- 엔드포인트 매퍼는 첫 번째 SQL Server 인스턴스에 MSDTC가 두 번째 컨테이너 내에서 실행되고 있는 포트(이 예제에서는 포트 51000)를 알려줍니다.
- 첫 번째 SQL Server 인스턴스는 포트 51000을 통해 두 번째 호스트에 연결하고, 이 포트는 컨테이너 내부의 SQL Server로 포워딩되어 두 번째 인스턴스의 MSDTC와 직접 연결됩니다.
Kubernetes 플랫폼에 구성된 MSDTC를 사용하여 SQL Server 컨테이너 배포
샘플 배포 YAML 스크립트를 실행하기 전에 다음 예제 명령을 사용하여 sa 암호를 저장하는 데 필요한 보안 암호를 만듭니다.
kubectl create secret generic mssql --from-literal=MSSQL_SA_PASSWORD="<password>"
주의
암호는 SQL Server 기본 암호 정책을 따라야 합니다. 기본적으로 암호는 8자 이상이어야 하며 대문자, 소문자, 0~9까지의 숫자 및 기호 네 가지 집합 중 세 집합의 문자를 포함해야 합니다. 암호 길이는 128자까지 가능하며 되도록 길고 복잡한 암호를 사용합니다.
매니페스트 파일에서 다음 사항을 확인할 수 있습니다.
클러스터에서는
StorageClass,statefulset배포로서 배포된 두 개의 SQL Server Pod 및 각 SQL Server 인스턴스에 연결할 두 개의 부하 분산 장치 서비스 개체를 만듭니다.또한 부하 분산 장치 서비스는 Azure Kubernetes Service에서 구성할 수 있는 고정 IP 주소를 사용하여 배포됩니다. AKS(Azure Kubernetes Service) 부하 분산 장치와 함께 고정 공용 IP 주소 및 DNS 레이블 사용을 참조하세요. 고정 IP 주소를 사용하여 부하 분산 장치 서비스를 만들면 부하 분산 장치 서비스가 삭제되고 다시 생성될 경우 외부 IP 주소가 변경되지 않습니다.
다음 스크립트에서는
MSSQL_RPC_PORT환경 변수에 포트 13500이 사용되고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
SSMS(SQL Server Management Studio)와 같은 도구를 사용하여 이전 두 개의 SQL Server 인스턴스 중 하나에 연결하고 샘플 DTC 트랜잭션을 실행할 수 있습니다. 이 예제에서는 다음 예제와 같이 (10.72.137.129)에 연결 mssql-1 하고(10.88.213.209)에 연결된 서버를 mssql-0 만들어 분산 트랜잭션을 실행합니다.
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자 이상이어야 하며 대문자, 소문자, 0~9까지의 숫자 및 기호 네 가지 집합 중 세 집합의 문자를 포함해야 합니다. 암호 길이는 128자까지 가능하며 되도록 길고 복잡한 암호를 사용합니다.
이제 분산 트랜잭션을 시작할 수 있으며, 이 코드 샘플은 sys.sysprocesses 인스턴스에서 mssql-0를 표시합니다.
SET XACT_ABORT ON;
BEGIN DISTRIBUTED TRANSACTION;
SELECT *
FROM [10.88.213.209].master.dbo.sysprocesses;
COMMIT TRANSACTION;
GO