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 uses cert-manager to issue certificates. So first you have to make sure that the cluster has cert-manager installed. To install cert-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 repository https://github.com/kubedb/mssqlserver-init-scripts.git is used to create a test database named mssql. You can use other volume sources instead of ConfigMap. 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