可用性グループを構築する場合、複数のサーバーを用意していましたが、クラスターレス可用性グループであれば、Docker のコンテナーを二つ用意すれば構成をとれるのではないだろうかと思って試してみました。
とりあえず、組めるかどうかを試したので、手動での対応の連続です…。
最初に次のコマンドで SQL Server のコンテナーを 2 個起動します。
docker run --name SoL1 -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=P@ssw0rd' -e 'MSSQL_LCID=1041' -e 'TZ=Asia/Tokyo' -p 11433:1433 -p 15022:5022 -d microsoft/mssql-server-linux docker run --name SoL2 -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=P@ssw0rd' -e 'MSSQL_LCID=1041' -e 'TZ=Asia/Tokyo' -p 21433:1433 -p 25022:5022 -d microsoft/mssql-server-linux
各コンテナーでは、SQL Server に起動するためのポートと、ミラーリングエンドポイントのポートにアクセス可能な状態としています。
- SoL1
- 11433 → 1433
- 15022 → 5022
- SoL2
- 21433 → 1433
- 25022 → 5022
次に各コンテナーに対話シェルでアクセスし HA の機能の有効化を行います。
docker exec -it SoL1 bash /opt/mssql/bin/mssql-conf set hadr.hadrenabled 1 exit docker exec -it SoL2 bash /opt/mssql/bin/mssql-conf set hadr.hadrenabled 1 exit docker restart SoL1 docker restart SoL2
次に SQL Server 周りの設定を行います。
最初に 1 台目の SQL Server で次のクエリを実行します。
ALTER EVENT SESSION AlwaysOn_health ON SERVER WITH (STARTUP_STATE=ON); GO ALTER EVENT SESSION [AlwaysOn_health] ON SERVER STATE=START GO CREATE LOGIN dbm_login WITH PASSWORD = '**<1Sample_Strong_Password!@#>**'; CREATE USER dbm_user FOR LOGIN dbm_login; GO CREATE MASTER KEY ENCRYPTION BY PASSWORD = '**<master_Key_Password>**'; CREATE CERTIFICATE dbm_certificate WITH SUBJECT = 'dbm'; BACKUP CERTIFICATE dbm_certificate TO FILE = '/var/opt/mssql/data/dbm_certificate.cer' WITH PRIVATE KEY ( FILE = '/var/opt/mssql/data/dbm_certificate.pvk', ENCRYPTION BY PASSWORD = '**<private_Key_Password>**' ); CREATE ENDPOINT [Hadr_endpoint] AS TCP (LISTENER_IP = (0.0.0.0), LISTENER_PORT = 5022) FOR DATA_MIRRORING ( ROLE = ALL, AUTHENTICATION = CERTIFICATE dbm_certificate, ENCRYPTION = REQUIRED ALGORITHM AES ); ALTER ENDPOINT [Hadr_endpoint] STATE = STARTED; GRANT CONNECT ON ENDPOINT::[Hadr_endpoint] TO [dbm_login];
証明書をマッピングしたログインを作成し、証明書のバックアップをコンテナー内に取得しています。
作成した証明書のバックアップを 2 台目のコンテナーにコピーを行います。
docker cp SoL1:/var/opt/mssql/data/dbm_certificate.cer . docker cp SoL1:/var/opt/mssql/data/dbm_certificate.pvk . docker cp ./dbm_certificate.cer SoL2:/var/opt/mssql/data/dbm_certificate.cer docker cp ./dbm_certificate.pvk SoL2:/var/opt/mssql/data/dbm_certificate.pvk
次に、2 台目のコンテナーでコピーした証明書を使用してエンドポイントの設定を行います。
ALTER EVENT SESSION AlwaysOn_health ON SERVER WITH (STARTUP_STATE=ON); GO ALTER EVENT SESSION [AlwaysOn_health] ON SERVER STATE=START GO CREATE LOGIN dbm_login WITH PASSWORD = '**<1Sample_Strong_Password!@#>**'; CREATE USER dbm_user FOR LOGIN dbm_login; GO CREATE MASTER KEY ENCRYPTION BY PASSWORD = '**<master_Key_Password>**'; CREATE CERTIFICATE dbm_certificate AUTHORIZATION dbm_user FROM FILE = '/var/opt/mssql/data/dbm_certificate.cer' WITH PRIVATE KEY ( FILE = '/var/opt/mssql/data/dbm_certificate.pvk', DECRYPTION BY PASSWORD = '**<private_Key_Password>**' ); CREATE ENDPOINT [Hadr_endpoint] AS TCP (LISTENER_IP = (0.0.0.0), LISTENER_PORT = 5022) FOR DATA_MIRRORING ( ROLE = ALL, AUTHENTICATION = CERTIFICATE dbm_certificate, ENCRYPTION = REQUIRED ALGORITHM AES ); ALTER ENDPOINT [Hadr_endpoint] STATE = STARTED; GRANT CONNECT ON ENDPOINT::[Hadr_endpoint] TO [dbm_login];
最後に可用性グループの設定を行うため、1 台目のコンテナーに SSMS で接続して、次のようなクエリを実行します。
エンドポイントの設定については、ホストからマッピングしている ポート番号を指定しています。
CREATE AVAILABILITY GROUP [ag1] WITH (DB_FAILOVER = ON, CLUSTER_TYPE = NONE) FOR REPLICA ON N'SoL1' WITH ( ENDPOINT_URL = N'tcp://10.200.0.3:15022', AVAILABILITY_MODE = SYNCHRONOUS_COMMIT, FAILOVER_MODE = MANUAL, SEEDING_MODE = AUTOMATIC, SECONDARY_ROLE (ALLOW_CONNECTIONS = ALL) ), N'SoL2' WITH ( ENDPOINT_URL = N'tcp://10.200.0.3:25022', AVAILABILITY_MODE = SYNCHRONOUS_COMMIT, FAILOVER_MODE = MANUAL, SEEDING_MODE = AUTOMATIC, SECONDARY_ROLE (ALLOW_CONNECTIONS = ALL) ) ALTER AVAILABILITY GROUP [ag1] GRANT CREATE ANY DATABASE CREATE DATABASE [db1] ALTER DATABASE [db1] SET RECOVERY FULL BACKUP DATABASE [db1] TO DISK = N'NUL' ALTER AVAILABILITY GROUP [ag1] ADD DATABASE [db1] ALTER AVAILABILITY GROUP [ag1] SET (REQUIRED_SYNCHRONIZED_SECONDARIES_TO_COMMIT = 0)
以前の Docker では、–hostname の設定内容が、SQL Server のサーバー名と連携していなかったようなのですが、RC1 では連携しているようですね。
@@servername does not reflect –hostname used when creating container
最後に 2 台目のコンテナーで、可用性グループに参加します。
ALTER AVAILABILITY GROUP [ag1] JOIN WITH (CLUSTER_TYPE = NONE) ALTER AVAILABILITY GROUP [ag1] GRANT CREATE ANY DATABASE
これで Docker コンテナー間でクラスターレス可用性グループが構築できるかと。
コンテナーだと再作成が簡単にできるので、軽く検証をしたい場合などは結構便利かなと。