Friday Reading 2018-01-26

It’s moving weekend! Hopefully two hard days and then I’ll be all settled in my new place. Cannot wait.

Inbetween packing all my belongings into cardboard boxes, I’ve been reading…

Linux Containers on Windows (LCOW)
Stefan Scherer (b|t) shows us how to run Linux containers side-by-side with Windows containers. Sadly it doesn’t work for SQL containers yet, but still really cool.

Dealing with Disappointment and Learning from Failures
Catherine Wilhelmsen (t) takes us through the range of emotions she experienced after a disappointing SQL Saturday (this is a must read for any speaker)

The world of Automatic Tuning – SQL Server 2017
Arun Sirpal (t) details the new auto-tuning feature in SQL 2017 (very cool)

Introducing the new Dv3 and Ev3 VM sizes
Old post from the Azure blogs but crucial to know if you want to run Docker in Azure (self install)

Parallelism in Hekaton (In-Memory OLTP)
Niko Neugebauer (t) goes through something interesting quirks that he’s discovered in Hekaton

Have a good weekend!

Configuring Persistent Storage for SQL Server in Azure Kubernetes Services

I’ve been playing around with SQL Server running in Kubernetes in Azure Container Services (AKS) for a while now and I think that the technology is really cool.


EDIT – Azure Container Services (AKS) has been renamed to Azure Kubernetes Services. Blog title has been updated


You can get a highly available instance of SQL Server up and running with a few lines of code! Ok, there’s a bit of setup to do but once you get that out of the way, you’re good to go.

One thing that has been missing though, is persistent storage. Any changes made to the SQL instance would have been lost if the pod that it was running in failed and was brought back up.

Until now.

I’ve been looking at Kubernetes persistent volumes but was really scratching my head on trying to get it to work. Thankfully Microsoft has now published how to do this: – https://docs.microsoft.com/en-us/sql/linux/tutorial-sql-server-containers-kubernetes

Let’s have a look at how this works. You don’t need to have read any of my previous articles to follow the code here, all you need is an Azure account.

I’m going to run in Bash for Windows but you can install the Azure-Cli for the command line (all the commands are the same). The MSI is available here.

If you are running in Bash for Windows the first thing to do is install Azure-CLI: –

echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ wheezy main" | \
     sudo tee /etc/apt/sources.list.d/azure-cli.list
      
sudo apt-key adv --keyserver packages.microsoft.com --recv-keys 52E16F86FEE04B979B07E28DB02C46DF417A0893
sudo apt-get install apt-transport-https
sudo apt-get update && sudo apt-get install azure-cli

Then whether you’re running in Bash for Windows or the command line, after the install confirm that it has been successful by running:-

az --version

Now log into Azure: –

az login

This is an odd process but hey, it seems to work.

Once the login process is complete, the resource group to hold all the objects of the Kubernetes cluster can be created: –

az group create --name ApResourceGroup1 --location eastus


I created the resource group in eastus because as much as I tried, I kept getting errors when using other locations (e.g. – ukwest)

After the resource group is created, the cluster can be built: –

az aks create --resource-group ApResourceGroup1 --name mySQLK8sCluster --node-count 2 --generate-ssh-keys

I find it incredibly cool that this can be done with one line of code. Log into Azure and see the amount of resources this one line creates in the background.

Anyway, to manage the cluster, install kubectl: –

az aks install-cli

Grab credentials in order to connect and manage the cluster: –

az aks get-credentials --resource-group=ApResourceGroup1 --name=mySQLK8sCluster

Cool! The cluster is setup and we can connect. This can be tested by running: –

kubectl get nodes

There are the two nodes of the cluster and it is ready to host a sql instance in a pod.

The persistent volume and SQL instance are created by referencing .yml files on the Microsoft page but instead of having to copy/paste I’ve dropped the two files into a Github repo. The only change I’ve made is that the image that used is my custom linux image with the agent installed (as I like to have the agent available).

To clone the repo to your local machine: –

git clone  https://github.com/dbafromthecold/SqlAksPersistentVolumes.git

Navigate to the files. The first file we will use is the PersistentVolume.yml file.

kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
     name: azure-disk
provisioner: kubernetes.io/azure-disk
parameters:
  storageaccounttype: Standard_LRS
  kind: Managed
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: mssql-data
  annotations:
    volume.beta.kubernetes.io/storage-class: azure-disk
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 8Gi

What this does is setup a storage class (as an Azure-Disk) and then specifies a persistent volume claim. It is the persistent volume claim that we will use to attach to the SQL Server instance within the pod.

To create the persistent volume & claim: –

kubectl apply -f PersistentVolume.yml

To confirm the volume and claim have been created: –

kubectl describe pvc mssql-data

kubectl describe pv

Now that the storage is provisioned, the SQL instance can be setup.

But before the SQL instance is created, there’s one more step that needs to be done. Previously when I’ve worked with SQL in AKS I’ve specified the SA password in the .yml file used to create the pod that contains the instance.

This isn’t secure so instead of doing that, let’s create a secret to hold the password: –

kubectl create secret generic mssql --from-literal=SA_PASSWORD="Testing1122"

Great! So here’s the .yml file that will create the instance of SQL: –

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: mssql-deployment
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: mssql
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: mssql
        image: microsoft/mssql-server-linux
        ports:
        - containerPort: 1433
        env:
        - name: ACCEPT_EULA
          value: "Y"
        - name: SA_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mssql
              key: SA_PASSWORD 
        volumeMounts:
        - name: mssqldb
          mountPath: /var/opt/mssql
      volumes:
      - name: mssqldb
        persistentVolumeClaim:
          claimName: mssql-data
---
apiVersion: v1
kind: Service
metadata:
  name: mssql-deployment
spec:
  selector:
    app: mssql
  ports:
    - protocol: TCP
      port: 1433
      targetPort: 1433
  type: LoadBalancer

What this does is spin up a pod with our SQL instance running from my custom image dbafromthecold/sqlserverlinuxagent:latest. It then maps the persistent volume claim to /var/opt/mssql to our pod (this is the important step). Finally, creates a service so that we can connect to the instance using the service’s external IP and the password specified in the secret.

To create the SQL pod and service: –

kubectl apply -f sqlserver.yml

Wait a few minutes for the pod to come online. Check this by running: –

kubectl get pods

Once the pod is up and running, check the service for the external IP: –

kubectl get service

The external IP is used to connect to SQL within the cluster: –

In previous posts I’ve written, HA is provided to the SQL instance by respawning the pod if the current one running fails. However, data within the instance is not persisted (aka any new databases/data will be lost when the pod is respawned).

But now that we have implemented a persistent volume, the SQL instance and its databases should be available in a new pod if there’s a failure.

Let’s test this by creating some databases: –

CREATE DATABASE [DatabaseA];
CREATE DATABASE [DatabaseB];
CREATE DATABASE [DatabaseC];
CREATE DATABASE [DatabaseD];
CREATE DATABASE [DatabaseE];

The trick here is that the databases were created using the default settings.

USE [DatabaseA];
GO

EXEC sp_helpfile;
GO

The database files were created in /var/opt/mssql/data which is on the volume that we mapped to the persistent volume claim. This means that if the existing pod fails, the database files will be retained and available in the new pod.

To simulate a failure, manually delete the pod: –

kubectl delete pods --all

The old pod will be terminated and a new one automatically created: –

kubectl get pods

Once that pod is up and running, reconnect to SQL (using the same external IP of the service).

And the databases are there! The original instance within the pod has been deleted but a new pod running SQL Server and the persistent volume was automatically created!

This means that we can deploy a SQL instance within AKS that can recover from a failure with no data loss. And that, to me, is awesome.

OK, it’s not perfect. It can error out when you’re setting up (ping me if you run into any problems), the new pod takes a little too long to come online, and there’s still no windows authentication but it’s looking pretty promising!

Last thing, to remove all the objects built in this demo you just need to run: –

az group delete --name ApResourceGroup1

Thanks for reading!

Perfecting my presentations

After a considerable amount of “umming and ahhing” last year I decided to start presenting full hour long sessions. Well, I decided to start submitting sessions to events and see what happened.

I’d presented a few lightening talks at SQL Saturdays and my local user group so I wanted to see if I could actually present a 60 minute long session to a group of my peers.

At first it really was just to see if I could do it. Public speaking terrifies me and I honestly thought I’d clam up and not be able to say a single word. But I started submitting…like crazy.

The first full session I did was at SQL Saturday Iceland and oh boy, was I nervous. I was on at 3pm and I think I spent most of that day wandering around the venue, trying not to freak out.

And then I was on. I was nervous but managed to get through it. All my demos worked, the attendees asked questions at the end (which to me means that I conveyed the topic clearly) and I finished on time, so goal achieved!

As the year went on, it became not just about being able to present my session but being able to present a high quality, thought provoking, well delivered session. I now knew that I could do it, it’s now about how well I can do it.

And that’s what I want to build on this year. I’ve got a couple of new sessions written and I’ll be presenting the first of them at SQL Bits in February.

I’m still working on the demos, I want them to be broken down into easy to understand parts so that each attendee will be able to download and run through with ease. That’s the key part for me.

As long as the demos work, the slides come second. I’m not great at designing slides so I keep them minimal, just with the points on that I’m trying to get across and I practice without looking at them (to avoid the dreaded “reading what’s on the slides” presentation).

So over the next year I’m hoping that I can build on the skills that I already have and be able to deliver the highest quality presentations that I can.

I’m really looking forward to the challenge.

Have a good week!

Friday Reading 2018-01-19

It’s been absolutely freezing here in Dublin this week. Been spending pretty much all time wrapped up indoors reading…

Discussing PASS Linux Content with OVA Winner Tracy Boggiano
Tracy Boggiano (b|t) talks to PASS about Linux content in the PASS Virtual Groups

Best newish SSMS feature
Jason Brimhall (t) shows us how to enable the scrollbar map in SSMS

When A Log Backup Does Not Truncate Your SQL Server Log Files In An Availability Group
Edwin Sarmiento (t) explains a situation where logs files won’t be truncated when a database is in an availability group and how you can monitor

Pester 4.2.0 has a Because…… because 🙂
Rob Sewell (t) details the Because parameter in the Pester pre-release version 4.2.0

How I designed my VMware vSAN based Home Lab
Klaus Aschenbrenner (t) goes into detail on the specs of his home lab (v. cool)

A Closer Look at OUTPUT
Mark Wilkinson (t) shows us some interesting ways to use the OUTPUT clause

Have a good weekend!

Using Windows stored credentials to connect to SQL in containers

I work with SQL Server in containers pretty much exclusively when testing code and one of my real bug bears is that SQL Server in containers does not support Windows authentication (unless you’re using Windocks).

So when I’m working I find it quite annoying to have to specify a SA username & password when I want to connect.

OK, I can use Get-Credential, assign to a variable, and then reference that in a connection string but I want something a bit more permanent especially as I always use the same password for all my containers (shoot me, it’s local dev 🙂 )

What I’ve setup on my laptop is a stored credential using the CredentialManager powershell module.

Here’s how it works, first I create the credential: –

Import-Module CredentialManager

New-StoredCredential -Target "SqlDocker" -UserName "sa" -Password "Testing1122" -Persist LocalMachine

The -Persist LocalMachine allows me to reference this credential in other sessions as the default scope is session only. I can check this in another session by running: –

Get-StoredCredential -Target "SqlDocker"

So now run a container (using the same credentials as stored above): –

docker run -d -p 15789:1433 `
    --env ACCEPT_EULA=Y `
        --env SA_PASSWORD=Testing1122 `
            --name testcontainer microsoft/mssql-server-linux:latest

And now use the credential to connect to the container. I’m going to drop it into the dbatools Connect-DbaInstance cmdlet to pull information back about the SQL instance within the container: –

# set credential to variable
$cred = Get-StoredCredential -Target "SqlDocker"

# connect to Sql using credential
$srv = Connect-DbaInstance 'localhost,15789' -Credential $cred
    $srv.Edition
    $srv.HostDistribution
    $srv.HostPlatform
    $srv.Version

Boom! Connected to the SQL instance within the container using the stored credential. No more fudging passwords when typing out commands 🙂

Thanks for reading!