New to KubeDB? Please start here.
Initialize Microsoft SQL Server using Script
This tutorial will show you how to use KubeDB to initialize a MSSQLServer database with *.sql
, *.sh
or *.sql.gz
script.
In this tutorial, we will use .sql script stored in GitHub repository kubedb/mssqlserver-init-scripts.
Note: The yaml files used in this tutorial are stored in docs/examples/mssqlserver folder in GitHub repository kubedb/docs.
Before You Begin
You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using kind.
Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps here. Make sure install with helm command including
--set global.featureGates.MSSQLServer=true
to ensure MSSQLServer CRD installation.To configure TLS/SSL in
MSSQLServer
,KubeDB
usescert-manager
to issue certificates. So first you have to make sure that the cluster hascert-manager
installed. To installcert-manager
in your cluster following steps here.To keep things isolated, this tutorial uses a separate namespace called
demo
throughout this tutorial.$ kubectl create ns demo namespace/demo created
Prepare Initialization Scripts
MSSQLServer supports initialization with .sh
, .sql
and .sql.gz
files. In this tutorial, we will use init.sql
script from mssqlserver-init-scripts git repository to create a database named mssql
and a table named kubedb_init
in that database.
We will use a ConfigMap as a script source. You can use any Kubernetes supported volumes as a script source.
At first, we will create a ConfigMap with init.sql
file. Then, we will provide this ConfigMap as script source in init.script
of the MSSQLServer CR spec.
Let’s create a ConfigMap with the init.sql
initialization script,
$ kubectl create configmap -n demo mssql-init-scripts \
--from-literal=init.sql="$(curl -fsSL https://github.com/kubedb/mssqlserver-init-scripts/raw/master/init.sql)"
configmap/mssql-init-scripts created
Deploy the Microsoft SQL Server database
At first, we need to create an Issuer/ClusterIssuer which will be used to generate the certificate used for TLS configurations.
Create Issuer/ClusterIssuer
Now, we are going to create an example Issuer
that will be used throughout the duration of this tutorial. Alternatively, you can follow this cert-manager tutorial to create your own Issuer
. By following the below steps, we are going to create our desired issuer,
- Start off by generating our ca-certificates using openssl,
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=MSSQLServer/O=kubedb"
- Create a secret using the certificate files we have just generated,
$ kubectl create secret tls mssqlserver-ca --cert=ca.crt --key=ca.key --namespace=demo
secret/mssqlserver-ca created
Now, we are going to create an Issuer
using the mssqlserver-ca
secret that contains the ca-certificate we have just created. Below is the YAML of the Issuer
CR that we are going to create,
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: mssqlserver-ca-issuer
namespace: demo
spec:
ca:
secretName: mssqlserver-ca
Let’s create the Issuer
CR we have shown above,
$ kubectl create -f https://github.com/kubedb/docs/raw/v2025.7.31/docs/examples/mssqlserver/standalone/mssqlserver-ca-issuer.yaml
issuer.cert-manager.io/mssqlserver-ca-issuer created
Deploy a Microsoft SQL Server database with Init-Script
KubeDB implements a MSSQLServer
CRD to define the specification of a Microsoft SQL Server database. Below is the MSSQLServer
object created in this tutorial.
Here, our issuer mssqlserver-ca-issuer
is ready to deploy a MSSQLServer
. Below is the YAML of SQL Server that we are going to create
apiVersion: kubedb.com/v1alpha2
kind: MSSQLServer
metadata:
name: ms-init
namespace: demo
spec:
version: "2022-cu19"
storageType: Durable
tls:
issuerRef:
name: mssqlserver-ca-issuer
kind: Issuer
apiGroup: "cert-manager.io"
clientTLS: false
podTemplate:
spec:
containers:
- name: mssql
env:
- name: ACCEPT_EULA
value: "Y"
- name: MSSQL_PID
value: Evaluation
init:
script:
configMap:
name: mssql-init-scripts
storage:
storageClassName: "standard"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
deletionPolicy: WipeOut
$ kubectl create -f https://github.com/kubedb/docs/raw/v2025.7.31/docs/examples/mssqlserver/initialization/yamls/initializ-standalone.yaml
mssqlserver.kubedb.com/ms-init created
apiVersion: kubedb.com/v1alpha2
kind: MSSQLServer
metadata:
name: ms-ag-init
namespace: demo
spec:
version: "2022-cu19"
replicas: 3
topology:
mode: AvailabilityGroup
availabilityGroup:
databases:
- agdb
- mssql
secondaryAccessMode: "All"
tls:
issuerRef:
name: mssqlserver-ca-issuer
kind: Issuer
apiGroup: "cert-manager.io"
clientTLS: false
podTemplate:
spec:
containers:
- name: mssql
env:
- name: ACCEPT_EULA
value: "Y"
- name: MSSQL_PID
value: Evaluation
init:
script:
configMap:
name: mssql-init-scripts
storageType: Durable
storage:
storageClassName: "standard"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
deletionPolicy: WipeOut
$ kubectl create -f https://github.com/kubedb/docs/raw/v2025.7.31/docs/examples/mssqlserver/initialization/yamls/initialize-ag-cluster.yaml
mssqlsever.kubedb.com/ms-ag-init created
Here,
spec.init.script
specifies a script source used to initialize the database. The scripts will be executed alphabetically. In this tutorial, a sample .sql script from the git repositoryhttps://github.com/kubedb/mssqlserver-init-scripts.git
is used to create a test database namedmssql
. You can use other volume sources instead ofConfigMap
. The *.sql, *sql.gz and/or *.sh scripts that are stored inside the folder will be executed alphabetically. The scripts inside child folders will be skipped.
KubeDB operator watches for MSSQLServer
objects using Kubernetes API. When a MSSQLServer
object is created, KubeDB operator will create a PetSet and Services, Secrets, and other necessary resouces for this MSSQLServer
Database.
$ kubectl dba describe ms -n demo ms-init
Name: ms-init
Namespace: demo
Labels: <none>
Annotations: <none>
API Version: kubedb.com/v1alpha2
Kind: MSSQLServer
Metadata:
Creation Timestamp: 2025-08-06T10:35:28Z
Finalizers:
kubedb.com
Generation: 3
Resource Version: 224203
UID: 0c2a7678-8086-4fc0-9d73-a232abf47135
Spec:
Auth Secret:
Active From: 2025-08-06T10:35:29Z
Name: ms-init-auth
Auto Ops:
Deletion Policy: WipeOut
Health Checker:
Failure Threshold: 1
Period Seconds: 10
Timeout Seconds: 10
Init:
Script:
Config Map:
Name: mssql-init-scripts
Pod Template:
Controller:
Metadata:
Spec:
Containers:
Env:
Name: ACCEPT_EULA
Value: Y
Name: MSSQL_PID
Value: Evaluation
Name: mssql
Resources:
Limits:
Memory: 2Gi
Requests:
Cpu: 1
Memory: 1536Mi
Security Context:
Allow Privilege Escalation: false
Capabilities:
Add:
NET_BIND_SERVICE
Drop:
ALL
Run As Group: 10001
Run As Non Root: true
Run As User: 10001
Seccomp Profile:
Type: RuntimeDefault
Init Containers:
Name: mssql-init
Resources:
Limits:
Memory: 512Mi
Requests:
Cpu: 200m
Memory: 256Mi
Security Context:
Allow Privilege Escalation: false
Capabilities:
Drop:
ALL
Run As Group: 10001
Run As Non Root: true
Run As User: 10001
Seccomp Profile:
Type: RuntimeDefault
Pod Placement Policy:
Name: default
Security Context:
Fs Group: 10001
Service Account Name: ms-init
Replicas: 1
Storage:
Access Modes:
ReadWriteOnce
Resources:
Requests:
Storage: 1Gi
Storage Type: Durable
Tls:
Certificates:
Alias: server
Secret Name: ms-init-server-cert
Subject:
Organizational Units:
server
Organizations:
kubedb
Alias: client
Secret Name: ms-init-client-cert
Subject:
Organizational Units:
client
Organizations:
kubedb
Client TLS: false
Issuer Ref:
API Group: cert-manager.io
Kind: Issuer
Name: mssqlserver-ca-issuer
Version: 2022-cu19
Status:
Conditions:
Last Transition Time: 2025-08-06T10:35:28Z
Message: The KubeDB operator has started the provisioning of MSSQLServer: demo/ms-init
Observed Generation: 1
Reason: DatabaseProvisioningStartedSuccessfully
Status: True
Type: ProvisioningStarted
Last Transition Time: 2025-08-06T10:37:34Z
Message: All replicas are ready for MSSQLServer demo/ms-init
Observed Generation: 3
Reason: AllReplicasReady
Status: True
Type: ReplicaReady
Last Transition Time: 2025-08-06T10:37:45Z
Message: database demo/ms-init is accepting connection
Observed Generation: 3
Reason: AcceptingConnection
Status: True
Type: AcceptingConnection
Last Transition Time: 2025-08-06T10:37:45Z
Message: database demo/ms-init is ready
Observed Generation: 3
Reason: AllReplicasReady
Status: True
Type: Ready
Last Transition Time: 2025-08-06T10:38:37Z
Message: The MSSQLServer: demo/ms-init is successfully provisioned.
Observed Generation: 3
Reason: DatabaseSuccessfullyProvisioned
Status: True
Type: Provisioned
Phase: Ready
KubeDB operator sets the status.phase
to Ready
once the database is successfully created.
KubeDB operator has created a new Secret called ms-init-auth
for storing the password for MSSQLServer SA user.
$ kubectl view-secret -n demo ms-init-auth -a
password='9jtGBoona46wUYmL'
username='sa'
Let’s connect ot the database pod and verify the init.sql
script is executed successfully or not.
$ kubectl exec -it -n demo ms-init-0 -- bash
Defaulted container "mssql" out of: mssql, mssql-init (init)
mssql@ms-init-0:/$ cd init-database/
mssql@ms-init-0:/init-database$ ls
init.sql
mssql@ms-init-0:/init-database$ cat init.sql
-- 1) Create a database if it doesn't already exist
IF DB_ID(N'mssql') IS NULL
BEGIN
PRINT N'Creating database [mssql]...';
CREATE DATABASE [mssql];
END
GO
-- 2) Switch context
USE [mssql];
GO
-- 3) Drop the table if it already exists
IF OBJECT_ID(N'dbo.kubedb_init', N'U') IS NOT NULL
BEGIN
PRINT N'Dropping existing table [dbo.kubedb_init]...';
DROP TABLE dbo.kubedb_init;
END
GO
-- 4) Create the table with an IDENTITY primary key
PRINT N'Creating table [dbo.kubedb_init]...';
CREATE TABLE dbo.kubedb_init (
id BIGINT IDENTITY(1,1) NOT NULL CONSTRAINT PK_kubedb_init PRIMARY KEY,
name NVARCHAR(255) NULL,
created_at DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME()
);
GO
-- 5) Seed it with some test data
PRINT N'Inserting sample rows...';
INSERT INTO dbo.kubedb_init (name) VALUES
(N'name1'),
(N'name2'),
(N'name3'),
(N'name4'),
(N'name5'),
(N'name6'),
(N'name7'),
(N'name8');
GO
-- 6) Confirmation
DECLARE @cnt INT = (SELECT COUNT(*) FROM dbo.kubedb_init);
PRINT N'Inserted ' + CAST(@cnt AS NVARCHAR(10)) + N' rows into dbo.kubedb_init.';
mssql@ms-init-0:/init-database$ /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P $MSSQL_SA_PASSWORD -No
1> select name from sys.databases;
2> go
name
--------------------------------------------------------------------------------------------------------------------------------
master
tempdb
model
msdb
mssql
kubedb_system
(6 rows affected)
1> use mssql;
2> go
Changed database context to 'mssql'.
1> select * from kubedb_init;
2> go
id name created_at
-------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------
1 name1 2025-08-06 10:36:49.5645412
2 name2 2025-08-06 10:36:49.5645412
3 name3 2025-08-06 10:36:49.5645412
4 name4 2025-08-06 10:36:49.5645412
5 name5 2025-08-06 10:36:49.5645412
6 name6 2025-08-06 10:36:49.5645412
7 name7 2025-08-06 10:36:49.5645412
8 name8 2025-08-06 10:36:49.5645412
(8 rows affected)
As you can see here, the initial script has successfully created a mssql
database and a table named kubedb_init
in mssql
database and inserted 8 rows of data into that table successfully.
Cleaning up
To clean up the kubernetes resources created by this tutorial, run:
kubectl patch -n demo mssqlserver/ms-init -p '{"spec":{"deletionPolicy":"WipeOut"}}' --type="merge"
kubectl delete -n demo mssqlserver/ms-init
kubectl delete ns demo
Next Steps
- Initialize MSSQLServer with Script.
- Monitor your MSSQLServer database with KubeDB using out-of-the-box Prometheus operator.
- Detail concepts of MSSQLServer object.
- Want to hack on KubeDB? Check our contribution guidelines.