{"id":12173,"date":"2018-12-18T16:06:43","date_gmt":"2018-12-18T15:06:43","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/"},"modified":"2018-12-18T16:06:43","modified_gmt":"2018-12-18T15:06:43","slug":"deploying-sql-server-on-k8s-with-helm-charts","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/","title":{"rendered":"Deploying SQL Server on K8s with Helm charts"},"content":{"rendered":"<p>During the last <a href=\"https:\/\/europe-2018.dockercon.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">DockerCon EU<\/a> in Barcelona, I heard a lot about <a href=\"https:\/\/github.com\/helm\/charts\">Helm<\/a> with K8s architectures. It\u00a0was also\u00a0a good opportunity to write about it after attending to this conference.<\/p>\n<p><a href=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/blog-149-0-banner.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-30215\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/blog-149-0-banner.jpg\" alt=\"blog 149 - 0 - banner\" width=\"766\" height=\"236\" \/><\/a><\/p>\n<p>In a nutshell, Helm is a package manager for K8s and you may think of it like the other ones available on the Linux side with apt, yum or zypper to cite few of them. Helm charts are a key component of the Helm architecture and make deployments easy, standardized and reusable and this is definitely what I was looking for our current CI\/CD pipeline implementation for <a href=\"https:\/\/www.dbi-services.com\/offering\/products\/dmk-management-kit\/\" target=\"_blank\" rel=\"noopener noreferrer\">DMK maintenance<\/a> tool.<\/p>\n<p>Helm matters for enterprise-scale deployments by addressing common challenges with the following (non-exhaustive) list of capabilities<\/p>\n<ul>\n<li>Helm charts can be shared easily across the enterprise or with contributors over the world from <a href=\"https:\/\/github.com\/helm\/charts\/tree\/master\/stable\/mssql-linux\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub<\/a> repository.<\/li>\n<li>Using helm charts allow to get quickly a specific environment for testing<\/li>\n<li>Existing charts can be authored for specific deployments regarding the context<\/li>\n<li>The easy deployment and deletion of applications make the Helm adoption easier<\/li>\n<li>Production- ready packages are possible and eliminate deployment errors due to incorrect configuration files and reduce the complexity of maintaining application catalog<\/li>\n<\/ul>\n<p>In my case, it\u2019s been a while since I have in mind to simplify my first SQL Server container deployments on K8s with a complex YAML file including a lot of objects like services, pods, secrets and persistent volumes with Helm charts. One additional motivation was the capability to change in-flight some preconfigured settings in the deployment when I wanted to switch from my minikube environment to my AKS cluster on Azure.<\/p>\n<p>In this <a href=\"https:\/\/www.dbi-services.com\/blog\/introducing-sql-server-on-kubernetes\/\" target=\"_blank\" rel=\"noopener noreferrer\">first write-up<\/a> I used a custom dbi services image for SQL Server (a production-ready docker image) and I decided to use this image as based of my custom Helm chart. First of all, let\u2019s say I didn\u2019t start from scratch and I used the mssql-linux stable chart available of <a href=\"https:\/\/github.com\/helm\/charts\/tree\/master\/stable\/mssql-linux\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub<\/a> but obviously I customized it for my own requirements:<\/p>\n<ul>\n<li>The custom dbi services image for SQL Server includes the creation of the <a href=\"https:\/\/www.dbi-services.com\/blog\/sql-server-on-linux-and-experimental-flexible-architecture\/\" target=\"_blank\" rel=\"noopener noreferrer\">flexible architecture<\/a> and I had to update the persistence volume and claims configuration with this new storage map.<\/li>\n<li>The custom image leverages the deployment of our <a href=\"https:\/\/www.dbi-services.com\/offering\/products\/dmk-management-kit\/\" target=\"_blank\" rel=\"noopener noreferrer\">DMK maintenance tool<\/a> (optional) that includes different SQL objects to perform maintenance of customer databases (basically update stats, rebuild index and backup tasks). So, I needed to add a parameter to enable or not the deployment of this tool inside the pod.<\/li>\n<li>TSQL scripts are also executed during the container startup and they\u00a0apply different server level configuration, configure tempdb database files placement and add some trace flags to meet our best practices. But no real impact on the helm chart here.<\/li>\n<li>An \u201capplication\u201d user may be created (optional) and will be part of the db_creator server role according to the least privilege principle. In most cases we consider an application doesn\u2019t need sysadmin privileges even on a SQL Server pod and more generally speaking on microservice architectures. So as already done for the DMK parameter described previously, I had to add another one parameter for creating this user when the pod is spin up.<\/li>\n<\/ul>\n<p>Let\u2019s first begin with my helm chart hierarchy folder which includes important files including <em>Chart.yaml<\/em>, <em>values.yaml<\/em> and <em>deployment.yaml<\/em>.<\/p>\n<pre class=\"brush: shell; gutter: true; first-line: 1\">[dab@DBI-LT-DAB:#]&gt; tree \/f\n\u2026\nT:.\n\u2502   .helmignore\n\u2502   Chart.yaml\n\u2502   values.yaml\n\u2502\n\u251c\u2500\u2500\u2500charts\n\u2514\u2500\u2500\u2500templates\n        deployment.yaml\n        NOTES.txt\n        pvc-app.yaml\n        pvc-backup.yaml\n        pvc-data.yaml\n        pvc-tempdb.yaml\n        pvc-tranlog.yaml\n        secret.yaml\n        service.yaml\n        _helpers.tpl<\/pre>\n<p>&nbsp;<\/p>\n<p>Let\u2019s focus on the <em>deployment.yaml<\/em> file and\u00a0the customized part within the <em>spec.containers.env <\/em>section related to my docker image specifications:<\/p>\n<ul>\n<li><strong>MSSQL_USER<\/strong>, <strong>MSSQL_USER_PASSWORD<\/strong> are environment variables related to my \u201capplication\u201d user<\/li>\n<li><strong>DMK<\/strong> environment variable enables deployment of the DMK maintenance tool<\/li>\n<\/ul>\n<p>In addition, the <a href=\"https:\/\/docs.microsoft.com\/en-us\/sql\/linux\/sql-server-linux-configure-environment-variables?view=sql-server-2017\" target=\"_blank\" rel=\"noopener noreferrer\">environment variables<\/a> related to the database file placement have been customized for master, tempdb and user databases according to my flexible architecture specifications with:<\/p>\n<ul>\n<li><strong>\/u00<\/strong> (for application files)<\/li>\n<li><strong>\/u01<\/strong> (for user data and system database files)<\/li>\n<li>\/<strong>u02<\/strong> (for transaction log files)<\/li>\n<li><strong>\/u03<\/strong> (for tempdb database files)<\/li>\n<li><strong>\/u98<\/strong> (for backup files).<\/li>\n<\/ul>\n<p>MountPaths and persistent volume claims section have also been updated accordingly as shown below:<\/p>\n<pre class=\"brush: xml; gutter: true; first-line: 1\">apiVersion: apps\/v1beta2\nkind: Deployment\nmetadata:\n  name: {{ template \"mssql.fullname\" . }}\n  labels:\n    app: {{ template \"mssql.name\" . }}\n    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}\n    release: {{ .Release.Name }}\n    heritage: {{ .Release.Service }}\n{{- if .Values.deployment.annotations }}\n  annotations:\n{{ toYaml .Values.deployment.annotations | indent 4 }}\n{{- end }}\nspec:\n  replicas: {{ .Values.replicaCount }}\n  selector:\n    matchLabels:\n      app: {{ template \"mssql.name\" . }}\n      release: {{ .Release.Name }}\n  template:\n    metadata:\n      labels:\n        app: {{ template \"mssql.name\" . }}\n        release: {{ .Release.Name }}\n    spec:\n      containers:\n        - name: {{ .Chart.Name }}\n          image: \"{{ .Values.image.repository }}:{{ .Values.image.tag }}\"\n          imagePullPolicy: {{ .Values.image.pullPolicy }}\n          env:\n            - name: ACCEPT_EULA\n              value: \"{{ .Values.acceptEula.value | upper }}\"\n            - name: MSSQL_PID\n              value: \"{{ .Values.edition.value }}\"\n            - name: MSSQL_SA_PASSWORD\n              valueFrom:\n               secretKeyRef:\n                 name: {{ template \"mssql.fullname\" . }}-sa-secret\n                 key: sapassword\n            - name: MSSQL_USER\n              value: \"{{ .Values.usersql.value }}\"\n            - name: MSSQL_USER_PASSWORD\n              valueFrom:\n               secretKeyRef:\n                 name: {{ template \"mssql.fullname\" . }}-user-secret\n                 key: userpassword\n            - name: DMK\n              value: \"{{ .Values.DMK.value }}\"\n            - name: MSSQL_MASTER_DATA_FILE\n              value: \/u01\/sqlserverdata\/mssqlserver\/master.mdf\n            - name: MSSQL_MASTER_LOG_FILE\n              value: \/u01\/sqlserverdata\/mssqlserver\/mastlog.ldf\n            - name: MSSQL_DATA_DIR\n              value: \/u01\/sqlserverdata\/mssqlserver\n            - name: MSSQL_LOG_DIR\n              value: \/u02\/sqlserverlog\/mssqlserver\n            - name: MSSQL_TEMPDBDATA_DIR\n              value: \/u03\/sqlservertempdb\/mssqlserver\n            - name: MSSQL_TEMPDBLOG_DIR\n              value: \/u03\/sqlservertempdb\/mssqlserver\n            - name: MSSQL_BACKUP_DIR\n              value: \/u98\/sqlserver\/backup\/mssqlserver\n            - name: MSSQL_ERROR_LOG\n              value: \/u00\/app\/sqlserver\/admin\/mssqlserver\/log\n            - name: MSSQL_DUMP_DIR\n              value: \/u00\/app\/sqlserver\/admin\/mssqlserver\/dump\n            - name: MSSQL_TCP_PORT\n              value: \"{{ .Values.service.port.value }}\"\n            - name: MSSQL_LCID\n              value: \"{{ .Values.lcid.value }}\"\n            - name: MSSQL_COLLATION\n              value: \"{{ .Values.collation.value }}\"\n            - name: MSSQL_ENABLE_HADR\n              value: \"{{ .Values.hadr.value }}\"\n            {{ if .Values.resources.limits.memory }}\n            - name: MSSQL_MEMORY_LIMIT_MB\n              valueFrom:\n                resourceFieldRef:\n                  resource: limits.memory\n                  divisor: 1Mi\n            {{ end }}\n          ports:\n            - name: mssql\n              containerPort: {{ .Values.service.port.value }}\n          volumeMounts:\n            - name: data\n              mountPath: \/u01\n            - name: transactionlog\n              mountPath: \/u02\n            - name: tempdb\n              mountPath: \/u03\n            - name: backup\n              mountPath: \/u98 \n            - name: app\n              mountPath: \/u00\n          livenessProbe:\n            tcpSocket:\n               port: mssql\n            initialDelaySeconds: {{ .Values.livenessprobe.initialDelaySeconds }}\n            periodSeconds: {{ .Values.livenessprobe.periodSeconds }}\n          readinessProbe:\n            tcpSocket:\n               port: mssql\n            initialDelaySeconds: {{ .Values.readinessprobe.initialDelaySeconds }}\n            periodSeconds: {{ .Values.readinessprobe.periodSeconds }}\n          resources:\n{{ toYaml .Values.resources | indent 12 }}\n    {{- if .Values.nodeSelector }}\n      nodeSelector:\n{{ toYaml .Values.nodeSelector | indent 8 }}\n    {{- end }}\n      volumes:\n      - name: master\n      {{- if .Values.persistence.enabled }}\n        persistentVolumeClaim:\n          {{- if .Values.persistence.existingMasterClaim }}\n          claimName: {{ .Values.persistence.existingMasterClaim }}\n          {{- else }}\n          claimName: {{ template \"mssql.fullname\" . }}-master\n          {{- end }}\n      {{- else }}\n        emptyDir: {}\n      {{- end }}\n      - name: data\n      {{- if .Values.persistence.enabled }}\n        persistentVolumeClaim:\n          {{- if .Values.persistence.existingDataClaim }}\n          claimName: {{ .Values.persistence.existingDataClaim }}\n          {{- else }}\n          claimName: {{ template \"mssql.fullname\" . }}-data\n          {{- end -}}\n      {{- else }}\n        emptyDir: {}\n      {{- end }}\n      - name: transactionlog\n      {{- if .Values.persistence.enabled }}\n        persistentVolumeClaim:\n          {{- if .Values.persistence.existingTransactionLogClaim }}\n          claimName: {{ .Values.persistence.existingTransactionLogClaim }}\n          {{- else }}\n          claimName: {{ template \"mssql.fullname\" . }}-translog\n          {{- end }}\n      {{- else }}\n        emptyDir: {}\n      {{- end }}\n      - name: tempdb\n      {{- if .Values.persistence.enabled }}\n        persistentVolumeClaim:\n          {{- if .Values.persistence.existingTempdbClaim }}\n          claimName: {{ .Values.persistence.existingTempdbClaim }}\n          {{- else }}\n          claimName: {{ template \"mssql.fullname\" . }}-tempdb\n          {{- end }}\n      {{- else }}\n        emptyDir: {}\n      {{- end }}\n      - name: backup\n      {{- if .Values.persistence.enabled }}\n        persistentVolumeClaim:\n          {{- if .Values.persistence.existingBackupClaim }}\n          claimName: {{ .Values.persistence.existingBackupClaim }}\n          {{- else }}\n          claimName: {{ template \"mssql.fullname\" . }}-backup\n          {{- end }}\n      {{- else }}\n        emptyDir: {}\n      {{- end }}\n      - name: app\n      {{- if .Values.persistence.enabled }}\n        persistentVolumeClaim:\n          {{- if .Values.persistence.existingApppClaim }}\n          claimName: {{ .Values.persistence.existingAppClaim }}\n          {{- else }}\n          claimName: {{ template \"mssql.fullname\" . }}-app\n          {{- end }}\n      {{- else }}\n        emptyDir: {}\n      {{- end }}<\/pre>\n<p>&nbsp;<\/p>\n<p>Referring to my flexible architecture, I added 2 YAML files that contain the new persistent volumes definition for respectively <strong><em>pvc-app<\/em><\/strong> for <em>\/u00 (app)<\/em> and <strong><em>pvc-tempdb<\/em><\/strong> for <em>\/u03 (tempdb)<\/em>.<\/p>\n<p>Here\u00a0the content\u00a0of my persistent volume claim for tempdb for instance:<\/p>\n<pre class=\"brush: xml; gutter: true; first-line: 1\">{{- if and .Values.persistence.enabled (not .Values.persistence.existingTempdbClaim) }}\nkind: PersistentVolumeClaim\napiVersion: v1\nmetadata:\n  name: {{ template \"mssql.fullname\" . }}-tempdb\n  labels:\n    app: {{ template \"mssql.fullname\" . }}\n    chart: \"{{ .Chart.Name }}-{{ .Chart.Version }}\"\n    release: \"{{ .Release.Name }}\"\n    heritage: \"{{ .Release.Service }}\"\n{{- if .Values.persistence.annotations }}\n  annotations:\n{{ toYaml .Values.persistence.annotations | indent 4 }}\n{{- end }}\nspec:\n  accessModes:\n    - {{ .Values.persistence.tempdbAccessMode | quote }}\n  resources:\n    requests:\n      storage: {{ .Values.persistence.tempdbSize | quote }}\n{{- if .Values.persistence.storageClass }}\n{{- if (eq \"-\" .Values.persistence.storageClass) }}\n  storageClassName: \"\"\n{{- else }}\n  storageClassName: \"{{ .Values.persistence.storageClass }}\"\n{{- end }}\n{{- end }}\n{{- end -}}<\/pre>\n<p>&nbsp;<\/p>\n<p>I added\u00a0to\u00a0the <em>secret.yaml<\/em> to include a section dedicated\u00a0to my \u201capplication\u201d user password<\/p>\n<pre class=\"brush: xml; gutter: true; first-line: 1\">---\napiVersion: v1\nkind: Secret\nmetadata:\n  name: {{ template \"mssql.fullname\" . }}-user-secret\n  labels:\n    app: {{ template \"mssql.name\" . }}\n    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}\n    release: {{ .Release.Name }}\n    heritage: {{ .Release.Service }}\ntype: Opaque\ndata:\n  {{ if .Values.userpassword }}\n  userpassword:  {{ .Values.userpassword.value | b64enc | quote }}\n  {{ else }}\n  userpassword: {{ randAlphaNum 20 | b64enc | quote }}\n{{ end }}<\/pre>\n<p>&nbsp;<\/p>\n<p>Note the helm chart allows you to define your own password or if empty it will generate an random password instead.<\/p>\n<p>Finally, the <strong><em>values.yaml<\/em><\/strong> file contains predefined values for my release deployment<\/p>\n<pre class=\"brush: xml; gutter: true; first-line: 1\"># General parameters\nacceptEula: \n  value: \"Y\"\nedition: \n  value: \"Developer\"\nDMK: \n  value: \"N\"\ncollation: \n  value: SQL_Latin1_General_CP1_CI_AS\nlcid: \n  value: 1033\nhadr: \n    value: 0\n# User parameters\nsapassword: \n  value: Password1\nusersql: \n  value: dbi_user\nuserpassword: \n  value: Password2\n# Image parameters\nimage:\n  repository: dbi\/mssql-server-linux\n  tag: 2017-CU12\n  pullPolicy: IfNotPresent\n# Service parameters\nservice:\n  type: \n    value: LoadBalancer\n  port: \n    value: 1433\n  annotations: {}\ndeployment:\n  annotations: {}\n# Volumes &amp; persistence parameters\npersistence:\n  enabled: true\n  # existingDataClaim:\n  # existingTransactionLogClaim:\n  # existingBackupClaim:\n  # existingMasterClaim:\n  # existingAppClaim:\n  # existingTempdbClaim:\n  storageClass: \"\"\n  dataAccessMode: ReadWriteOnce\n  dataSize: 5Gi\n  transactionLogAccessMode: ReadWriteOnce\n  transactionLogSize: 5Gi\n  tempdbAccessMode: ReadWriteOnce\n  tempdbSize: 5Gi\n  backupAccessMode: ReadWriteOnce\n  backupSize: 5Gi\n  masterAccessMode: ReadWriteOnce\n  masterSize: 5Gi\n  appAccessMode: ReadWriteOnce\n  appSize: 5Gi\n# Probe parameters\nlivenessprobe:\n  initialDelaySeconds: 20\n  periodSeconds: 15\nreadinessprobe:\n  initialDelaySeconds: 20\n  periodSeconds: 15\n# Resourcep parameters\nresources:\n  limits:\n  #  cpu: 100m\n    memory: 5Gi\n  # requests:\n  #  cpu: 100m\n  #  memory: 2Gi\nnodeSelector: {}\n  # kubernetes.io\/hostname: minikube\n\n<\/pre>\n<p>Let\u2019s install my environment release from the helm command below:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">$ helm install --name sqlhelm . --set DMK.value=Y --set service.port.value=1451<\/pre>\n<p>&nbsp;<\/p>\n<p>Pretty simple right? Note also that I may change predefined parameter values according to my context very easily. For instance, the DMK maintenance tool is not installed by default when the container is spin up by default and I changed it by explicitly setup the <em>DMK.value<\/em> to <em>Y<\/em>. The same applies for the SQL Server port exposed through the service, by default 1433 changed to 1451 in my helm command.<\/p>\n<p>The result is as follows:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">LAST DEPLOYED: Mon Dec 17 23:23:26 2018\nNAMESPACE: default\nSTATUS: DEPLOYED\n\nRESOURCES:\n==&gt; v1\/PersistentVolumeClaim\nNAME                              STATUS  VOLUME                                    CAPACITY  ACCESS MODES  STORAGECLASS  AGE\nsqlhelm-dbi-mssql-linux-app       Bound   pvc-5faffb52-024a-11e9-bd56-00155d0013d3  5Gi       RWO           hostpath      8m57s\nsqlhelm-dbi-mssql-linux-backup    Bound   pvc-5fb0c43a-024a-11e9-bd56-00155d0013d3  5Gi       RWO           hostpath      8m57s\nsqlhelm-dbi-mssql-linux-data      Bound   pvc-5fb32657-024a-11e9-bd56-00155d0013d3  5Gi       RWO           hostpath      8m57s\nsqlhelm-dbi-mssql-linux-tempdb    Bound   pvc-5fb680fe-024a-11e9-bd56-00155d0013d3  5Gi       RWO           hostpath      8m57s\nsqlhelm-dbi-mssql-linux-translog  Bound   pvc-5fbb9350-024a-11e9-bd56-00155d0013d3  5Gi       RWO           hostpath      8m57s\n\n==&gt; v1\/Service\nNAME                     TYPE          CLUSTER-IP   EXTERNAL-IP  PORT(S)         AGE\nsqlhelm-dbi-mssql-linux  LoadBalancer  10.99.4.205  localhost    1451:32569\/TCP  8m57s\n\n==&gt; v1beta2\/Deployment\nNAME                     DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE\nsqlhelm-dbi-mssql-linux  1        1        1           1          8m57s\n\n==&gt; v1\/Pod(related)\nNAME                                      READY  STATUS   RESTARTS  AGE\nsqlhelm-dbi-mssql-linux-67c4898dfb-qlfgr  1\/1    Running  0         8m56s\n\n==&gt; v1\/Secret\nNAME                                 TYPE    DATA  AGE\nsqlhelm-dbi-mssql-linux-user-secret  Opaque  1     8m57s\nsqlhelm-dbi-mssql-linux-sa-secret    Opaque  1     8m57s<\/pre>\n<p>&nbsp;<\/p>\n<p>This command provides a picture of the deployed components and their different status including the persistent volume claims, my SQL Server pod, the service that exposes the SQL Server port and the K8s secrets for sa and my \u201capplication\u201d user passwords. This picture is available at any moment by executing the following command:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">$ helm status sqlhelm<\/pre>\n<p>&nbsp;<\/p>\n<p>We may also retrieve a list of existing releases from the following helm command:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">$ helm ls sqlhelm\nNAME    REVISION        UPDATED                         STATUS          CHART                   APP VERSION     NAMESPACE\nsqlhelm 1               Mon Dec 17 23:23:26 2018        DEPLOYED        dbi-mssql-linux-1.0.0   1.0             default<\/pre>\n<p>&nbsp;<\/p>\n<p>It\u2019s worth noting that each resource is identified by labels (a very powerful feature on K8s) and we may easily\u00a0get components installed and related to my release by filtering by the corresponding label (app or release) as follows:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">$ kubectl get all -l release=sqlhelm\nNAME                                           READY     STATUS    RESTARTS   AGE\npod\/sqlhelm-dbi-mssql-linux-67c4898dfb-qlfgr   1\/1       Running   1          16h\n\nNAME                              TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE\nservice\/sqlhelm-dbi-mssql-linux   LoadBalancer   10.99.4.205   localhost     1451:32569\/TCP   16h\n\nNAME                                      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE\ndeployment.apps\/sqlhelm-dbi-mssql-linux   1         1         1            1           16h\n\nNAME                                                 DESIRED   CURRENT   READY     AGE\nreplicaset.apps\/sqlhelm-dbi-mssql-linux-67c4898dfb   1         1         1         16h<\/pre>\n<p>&nbsp;<\/p>\n<p>Let\u2019s just take a look at my SQL Server pod log and let\u2019s focus on the different custom steps applied during the startup of the corresponding pod. All the custom steps are well executed with input values from\u00a0the <em>values.yaml<\/em> files.<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">kubectl logs sqlhelm-dbi-mssql-linux-67c4898dfb-qlfgr\n\n======= 2018-12-17 22:29:44 Configuring tempdb database files placement OK =======\n======= 2018-12-17 22:29:44 Configuring max server memory =======\n2018-12-17 22:29:45.01 spid51      Configuration option 'show advanced options' changed from 0 to 1. Run the RECONFIGURE statement to install.\n2018-12-17 22:29:45.03 spid51      Configuration option 'max server memory (MB)' changed from 2147483647 to 3840. Run the RECONFIGURE statement to install\n\u2026\n======= 2018-12-17 22:29:45 Configuring max server memory OK =======\n======= 2018-12-17 22:29:45 Creating login dbi_user =======\n======= 2018-12-17 22:29:45 Creating login dbi_user OK =======\n======= 2018-12-17 22:29:45 Installing DMK =======\nChanged database context to 'master'.\nCreating dbi_tools...\n======= 2018-12-17 22:30:08 Installing DMK OK =======\n======= MSSQL CONFIG COMPLETED =======<\/pre>\n<p>&nbsp;<\/p>\n<p>Finally let\u2019s connect from mssql-cli utility to my SQL Server pod and let\u2019s check if everything is ok from a configuration perspective:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">master&gt; select name as logical_name, physical_name\n....... from sys.master_files;\n+----------------+-------------------------------------------------+\n| logical_name   | physical_name                                   |\n|----------------+-------------------------------------------------|\n| master         | \/u01\/sqlserverdata\/mssqlserver\/master.mdf       |\n| mastlog        | \/u01\/sqlserverdata\/mssqlserver\/mastlog.ldf      |\n| tempdev        | \/u03\/sqlservertempdb\/mssqlserver\/tempdb.mdf     |\n| templog        | \/u03\/sqlservertempdb\/mssqlserver\/templog.ldf    |\n| tempdbdev_2    | \/u03\/sqlservertempdb\/mssqlserver\/tempdb2.ndf    |\n| tempdbdev_3    | \/u03\/sqlservertempdb\/mssqlserver\/tempdb3.ndf    |\n| tempdbdev_4    | \/u03\/sqlservertempdb\/mssqlserver\/tempdb4.ndf    |\n| modeldev       | \/u01\/sqlserverdata\/mssqlserver\/model.mdf        |\n| modellog       | \/u01\/sqlserverdata\/mssqlserver\/modellog.ldf     |\n| MSDBData       | \/u01\/sqlserverdata\/mssqlserver\/MSDBData.mdf     |\n| MSDBLog        | \/u01\/sqlserverdata\/mssqlserver\/MSDBLog.ldf      |\n| dbi_tools      | \/u01\/sqlserverdata\/mssqlserver\/dbi_tools.mdf    |\n| dbi_tools_log  | \/u02\/sqlserverlog\/mssqlserver\/dbi_tools_log.ldf |\n+----------------+-------------------------------------------------+<\/pre>\n<p>&nbsp;<\/p>\n<p>The database file placement meets my flexible architecture requirements. The DMK maintenance tool is also deployed correctly with the dbi_tools database as show below:<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">master&gt; use dbi_tools;\nCommands completed successfully.\nTime: 0.253s\ndbi_tools&gt; select name as table_name\n.......... from sys.tables;\n+-----------------------------------+\n| table_name                        |\n|-----------------------------------|\n| dbi_maintenance_task_logs         |\n| dbi_maintenance_task_details_logs |\n| dbi_maintenance_configuration     |\n| __RefactorLog                     |\n+-----------------------------------+<\/pre>\n<p>&nbsp;<\/p>\n<p><em>sa<\/em> and <em>dbi_user<\/em> (name by default in my template) logins are available for sysadmin and classical user connections.<\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">master&gt; select name AS login_name\n....... from sys.server_principals\n....... where type = 'S' and name not like '##%##';\n+--------------+\n| login_name   |\n|--------------|\n| sa           |\n| dbi_user     |\n+--------------+<\/pre>\n<p>&nbsp;<\/p>\n<p>Deployment is done successfully! It was a brief overview of Helm capabilities with SQL Server and other write-ups will come soon!<\/p>\n<p>Happy deployment!<\/p>\n<p><span style=\"float: none;background-color: #ffffff;color: #333333;cursor: text;font-family: Georgia,'Times New Roman','Bitstream Charter',Times,serif;font-size: 16px;font-style: normal;font-variant: normal;font-weight: 400;letter-spacing: normal;text-align: left;text-decoration: none;text-indent: 0px;text-transform: none\">By David Barbarin<\/span><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>During the last DockerCon EU in Barcelona, I heard a lot about Helm with K8s architectures. It\u00a0was also\u00a0a good opportunity to write about it after attending to this conference. In a nutshell, Helm is a package manager for K8s and you may think of it like the other ones available on the Linux side with [&hellip;]<\/p>\n","protected":false},"author":26,"featured_media":12174,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[229,1320,1504,1522],"tags":[769,1523,1524,1365,1525,1526,1346],"type_dbi":[],"class_list":["post-12173","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-database-administration-monitoring","category-devops","category-docker","category-kubernetes","tag-deployment","tag-helm","tag-helm-chart","tag-k8s","tag-mssql","tag-release","tag-sqlserver"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Deploying SQL Server on K8s with Helm charts<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Deploying SQL Server on K8s with Helm charts\" \/>\n<meta property=\"og:description\" content=\"During the last DockerCon EU in Barcelona, I heard a lot about Helm with K8s architectures. It\u00a0was also\u00a0a good opportunity to write about it after attending to this conference. In a nutshell, Helm is a package manager for K8s and you may think of it like the other ones available on the Linux side with [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2018-12-18T15:06:43+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/blog-149-0-banner.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"766\" \/>\n\t<meta property=\"og:image:height\" content=\"236\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Microsoft Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Microsoft Team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/\"},\"author\":{\"name\":\"Microsoft Team\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/bfab48333280d616e1170e7369df90a4\"},\"headline\":\"Deploying SQL Server on K8s with Helm charts\",\"datePublished\":\"2018-12-18T15:06:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/\"},\"wordCount\":1107,\"commentCount\":0,\"image\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/blog-149-0-banner.jpg\",\"keywords\":[\"Deployment\",\"helm\",\"helm chart\",\"k8s\",\"mssql\",\"release\",\"SQLServer\"],\"articleSection\":[\"Database Administration &amp; Monitoring\",\"DevOps\",\"Docker\",\"Kubernetes\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/\",\"name\":\"Deploying SQL Server on K8s with Helm charts\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/blog-149-0-banner.jpg\",\"datePublished\":\"2018-12-18T15:06:43+00:00\",\"author\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/bfab48333280d616e1170e7369df90a4\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/#primaryimage\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/blog-149-0-banner.jpg\",\"contentUrl\":\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/blog-149-0-banner.jpg\",\"width\":766,\"height\":236},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/www.dbi-services.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Deploying SQL Server on K8s with Helm charts\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/\",\"name\":\"dbi Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/bfab48333280d616e1170e7369df90a4\",\"name\":\"Microsoft Team\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/c44a1a792c059f24055763aa77d80a244467f6eef724a8bd13db8d4a350b7a4c?s=96&d=mm&r=g\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/c44a1a792c059f24055763aa77d80a244467f6eef724a8bd13db8d4a350b7a4c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/c44a1a792c059f24055763aa77d80a244467f6eef724a8bd13db8d4a350b7a4c?s=96&d=mm&r=g\",\"caption\":\"Microsoft Team\"},\"url\":\"https:\/\/www.dbi-services.com\/blog\/author\/microsoft-team\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Deploying SQL Server on K8s with Helm charts","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/","og_locale":"en_US","og_type":"article","og_title":"Deploying SQL Server on K8s with Helm charts","og_description":"During the last DockerCon EU in Barcelona, I heard a lot about Helm with K8s architectures. It\u00a0was also\u00a0a good opportunity to write about it after attending to this conference. In a nutshell, Helm is a package manager for K8s and you may think of it like the other ones available on the Linux side with [&hellip;]","og_url":"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/","og_site_name":"dbi Blog","article_published_time":"2018-12-18T15:06:43+00:00","og_image":[{"width":766,"height":236,"url":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/blog-149-0-banner.jpg","type":"image\/jpeg"}],"author":"Microsoft Team","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Microsoft Team","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/"},"author":{"name":"Microsoft Team","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/bfab48333280d616e1170e7369df90a4"},"headline":"Deploying SQL Server on K8s with Helm charts","datePublished":"2018-12-18T15:06:43+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/"},"wordCount":1107,"commentCount":0,"image":{"@id":"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/#primaryimage"},"thumbnailUrl":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/blog-149-0-banner.jpg","keywords":["Deployment","helm","helm chart","k8s","mssql","release","SQLServer"],"articleSection":["Database Administration &amp; Monitoring","DevOps","Docker","Kubernetes"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/","url":"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/","name":"Deploying SQL Server on K8s with Helm charts","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/#primaryimage"},"image":{"@id":"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/#primaryimage"},"thumbnailUrl":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/blog-149-0-banner.jpg","datePublished":"2018-12-18T15:06:43+00:00","author":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/bfab48333280d616e1170e7369df90a4"},"breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/#primaryimage","url":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/blog-149-0-banner.jpg","contentUrl":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/blog-149-0-banner.jpg","width":766,"height":236},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/deploying-sql-server-on-k8s-with-helm-charts\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Deploying SQL Server on K8s with Helm charts"}]},{"@type":"WebSite","@id":"https:\/\/www.dbi-services.com\/blog\/#website","url":"https:\/\/www.dbi-services.com\/blog\/","name":"dbi Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/bfab48333280d616e1170e7369df90a4","name":"Microsoft Team","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/c44a1a792c059f24055763aa77d80a244467f6eef724a8bd13db8d4a350b7a4c?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/c44a1a792c059f24055763aa77d80a244467f6eef724a8bd13db8d4a350b7a4c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c44a1a792c059f24055763aa77d80a244467f6eef724a8bd13db8d4a350b7a4c?s=96&d=mm&r=g","caption":"Microsoft Team"},"url":"https:\/\/www.dbi-services.com\/blog\/author\/microsoft-team\/"}]}},"_links":{"self":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/12173","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/users\/26"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/comments?post=12173"}],"version-history":[{"count":0,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/12173\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media\/12174"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=12173"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=12173"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=12173"},{"taxonomy":"type","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/type_dbi?post=12173"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}