Create a SQL Server Availability Group in Kubernetes
DxOperator is a software extension to Kubernetes that uses custom resource definitions to automate the deployment of DxEnterprise clusters. DxEnterprise then provides all of the instrumentation to create, configure, manage and provide automatic failover for Microsoft SQL Server availability group workloads in Kubernetes.
For a free developer license to test DxOperator - Request a free license.
Prerequisites
- A Kubernetes cluster installed with at least 8GB of RAM.
- A valid DxEnterprise license with availability group management features and tunnels enabled. A fully featured Developer Edition is available free for non-production use. To purchase DxEnterprise software for production workloads, please contact us.
Install DxOperator
-
Download the DxOperator YAML.
curl https://dxoperator.dh2i.com/dxsqlag/files/v2.yaml -o v2.yaml -
Apply the DxOperator YAML.
kubectl apply -f v2.yaml -
Wait for the DxOperator pod to become ready.
kubectl get pods -n dxoperator-v2-system -w
Create a SQL Server Availability Group
-
Create secrets for the DxEnterprise passkey and license key, and the SQL Server SA account.
kubectl create secret generic dxe --from-literal=DX_PASSKEY=<password> --from-literal=DX_LICENSE=<license_key>kubectl create secret generic mssql --from-literal=MSSQL_SA_PASSWORD=<password> -
(OPTIONAL) Apply a ConfigMap YAML for the
mssql.conffile.infoSee the Microsoft documentation for all supported variables for MSSQL.
configmap.yamlkind: ConfigMap
apiVersion: v1
metadata:
name: mssql-config
data:
mssql.conf: |
[sqlagent]
enabled = truekubectl apply -f configmap.yaml -
Copy the example
DxSqlAg.yamlfile below.infoThere are many configuration options for the DxSqlAg custom resource beyond those that are shown in this example. View the DxSqlAg API Reference for more information.
apiVersion: dh2i.com/v1
kind: DxSqlAg
metadata:
name: dxsqlag
spec:
sqlAgConfiguration:
synchronousReplicas: 3
asynchronousReplicas: 0
# ConfigurationOnlyReplicas are only allowed with availabilityGroupClusterType set to EXTERNAL
configurationOnlyReplicas: 0
availabilityGroupName: AG1
# Adds auto-generated load balancers to serviceTemplates for easy cluster access
# For more customization, use the serviceTemplates section below
#createLoadBalancers: true
# Listener port for the availability group (uncomment to apply)
#availabilityGroupListenerPort: 14033
# For a contained availability group, add the option CONTAINED
#availabilityGroupOptions: CONTAINED
# Disables automatic availability mode switching when scaling down
#disableModeSwitching: true
# Service templates are used to create a service for each pod in the cluster
serviceTemplates:
- name: custom-service
type: LoadBalancer
ports:
- name: dxe-admin
port: 7979
protocol: TCP
# Per-service customizations are used to specify values specific to a service
perServiceCustomizations:
- name: custom-service-dxsqlag-0
metadata:
annotations:
cloud-provider: "10.0.0.100"
- name: custom-service-dxsqlag-1
metadata:
annotations:
cloud-provider: "10.0.0.101"
statefulSetSpec:
podSpec:
dxEnterpriseContainer:
image: "docker.io/dh2i/dxe:latest"
imagePullPolicy: Always
acceptEula: true
clusterSecret: dxe
vhostName: VHOST1
# Configuration options for the required persistent volume claim for DxEnterprise
#volumeClaimConfiguration:
# Set custom storage class for DxE PVC
#storageClassName: example-class
mssqlServerContainer:
image: "mcr.microsoft.com/mssql/server:2025-latest"
imagePullPolicy: Always
mssqlSecret: mssql
acceptEula: true
mssqlPID: Developer
# Set a non-default SQL Server port. DxOperator will auto-detect
# the port from other sources too, such as mssqlConfigMap
#mssqlTcpPort: 51433
# The MSSQL configMap (mssql.conf file)
#mssqlConfigMap: mssql-config
# Configuration options for the required persistent volume claim for SQL Server
#volumeClaimConfiguration:
# resources:
# requests:
# storage: 2Gi
# Additional pod containers, such as mssql-tools
#containers:
#- name: mssql-tools
#image: "mcr.microsoft.com/mssql-tools"
#command: [ "/bin/sh" ]
#args: [ "-c", "tail -f /dev/null" ]SECURITY CAUTION: Avoid Default Listening Port for SQL ServerFor security best practices, do not use the default SQL Server port (1433) when configuring SQL Server instances in production environments. Using the default port can expose your instance to automated scanning and brute-force attacks. In production environments, it is strongly recommended to configure a non-standard port to reduce the attack surface and improve security posture. For more information on configuring SQL Server to use a non-default port, see: Configure SQL Server's Listening Port
Also note: If you applied a ConfigMap in the previous optional step, you must explicitly set
spec.mssqlServerContainer.mssqlConfigMapto ensure it is used:mssqlConfigMap: mssql-config -
Apply the DxSqlAg custom resource YAML.
kubectl apply -f DxSqlAg.yaml -
Verify the StatefulSet has been created.
kubectl get sts dxsqlag
That's it! DxOperator will begin spinning up a new SQL Server Availability Group in Kubernetes and should - depending on cluster resources - finish within a few minutes. You can check on the progress using kubectl exec -itc dxe dxsqlag-0 -- dxcli get-ags-detail <vhost_name> <ag_name>.
Creating an Availability Group Listener
-
Assign the
availabilityGroupListenerPort.Update the following value in the
DxSqlAg.yamlfile:DxSqlAg.yamlspec:
sqlAgConfiguration:
availabilityGroupListenerPort: 14033Apply the file:
kubectl apply -f DxSqlAg.yaml -
In the DxSqlAg
spec, uncomment the entry for the AG Listener. -
Apply the service YAML to add a load balancer for the listener.
infoMake sure to set the selector to
dh2i.com/entity-name: <DxSqlAg_name>, using the name that was applied in theDxSqlAg.yamlabove.Example Load Balancer ServiceapiVersion: v1
kind: Service
metadata:
name: dxsqlag-cluster-lb
spec:
type: LoadBalancer
selector:
dh2i.com/entity-name: dxsqlag
# This label points to whichever pod is the active Vhost member
dh2i.com/active-vhost-vhost1: "true"
ports:
- name: sql
protocol: TCP
port: 1433
targetPort: 1433
- name: listener
protocol: TCP
port: 14033
targetPort: 14033
- name: dxe
protocol: TCP
port: 7979
targetPort: 7979 -
Verify the load balancer assignments.
kubectl get services
What You Accomplished
Congratulations! You've successfully deployed a SQL Server Availability Group with automatic failover capabilities in Kubernetes using DxOperator. You now have:
- Enterprise-grade high availability for your SQL Server workloads running in containers
- Automatic failover that keeps your applications running even during node or instance failures
- A foundation for production-ready database deployments that scale with your organization
Ready to take the next step? Contact DH2i to learn how DxOperator can power your mission-critical SQL Server workloads in Kubernetes.
Removing Custom Resources and DxOperator
The below steps will allow you to delete the custom resources and PVCs to redeploy with the same operator (steps 1 & 2). Or you can optionally also delete DxOperator completely (step 3).
-
Delete the DxSqlAg custom resource YAML.
kubectl delete -f DxSqlAg.yaml -
Delete the persistent volume claims (PVC).
kubectl delete pvc --all -
Delete the DxOperator YAML.
dangerRunning this command will delete the DxEnterpriseSqlAg CRD. If any DxEnterpriseSqlAg custom resources remain in the Kubernetes cluster, Kubernetes will destroy them as part of the deletion process. Only run this command if you intend on removing every DxEnterpiseSqlAg too!
To list all DxSqlAgs, run 'kubectl get dxsqlag'.
kubectl delete -f v2.yaml