Wednesday, August 26, 2020

Kubernetes Deployment with Azure DevOps

I still recall encountering containers and orchestrators for the first time - it sounded cool but I couldn't intuitively relate to the problems they solve. This lasted only until I tried integrating containerized builds into a CI/CD pipeline when I saw the beauty of it all. I aim to show the complete setup, from the ground up to a containerized app with automated build and release - all in a simple 1.5 hour webinar.

Here is the link: https://youtu.be/tRDM7ycWS-Q 

This blog post is the companion resource to the webinar, giving you quick access to the relevant scripts and code snippets. The whole setup is also accessible on a public Azure DevOps project: https://dev.azure.com/FirebrandSprint/KubernetesDevOps

While the code and the pipelines in the above project will remain available indefinitely, the Azure resources that the app relies on will be deleted a few days after the webinar takes place so the app itself and the pipelines will not actually work.

The scenario we'll go through goes like this, from a bird's eye view:

  • Provision resources (container registry, Kubernetes cluster)
  • Create the application
  • Build pipeline (CI)
  • Release pipeline (CD)

Below are all the relevant code snippets for each of these tasks:

Provision Resources

We need to have an Azure subscription to try this out but luckily we can get our hands on one for free, with enough allowance to try it out independently.

For this exercise we'll need only two Azure resources: Container Registry (ACR) and Azure Kubernetes Service (AKS). These can be trivially created through the portal but we can also script them - here are the snippets for AKS:

Create AKS cluster with AZ CLI

 az aks create
  --resource-group fbsprintAksDevops
  --name fbsprintAksDevopsCluster
  --node-count 2

Create AKS with PowerShell

New-AzAks
 -ResourceGroupName fbsprintAksDevops
 -Name fbsprintAksDevopsCluster
 -NodeCount 2

No matter which one you try it should be done within 15 minutes.

Create the Application

This can be done with any technology - that's the beauty of containers, you just pick the right base image and you can run anything. In the webinar I show a plain vanilla ASP.NET Core app, straight out of the Visual Studio template but anything else would do.

The application will also need to be furnished with a multi-stage dockerfile for building and distributing it. Whatever you use to create your app - it might support that (Visual Studio does), otherwise you'll need to create your own or fish one out from the internet.

Here is an example of a usable dockerized build for a web app using npm to resolve its dependencies:

FROM node as build
WORKDIR /app
COPY package*.json /app/
RUN npm install
COPY . /app
ARG configuration=production
RUN npm run build -- --outputPath=./dist/out --configuration $configuration

FROM nginx
COPY --from=build /app/dist/out/ /usr/share/nginx/html
COPY /nginx-custom.conf /etc/nginx/conf.d/default.conf

Build Pipeline (CI)

These days mostly everything is "as code" so that it can be stored in source control, merged, compared - you name it. The build pipeline definition is no exception - the default pipeline type is now YAML-based and here is the one we used:

trigger:
- master

resources:
- repo: self

variables:
#  tag: '$(Build.BuildId)'
  tag: '1'
  imageName: 'fbsprintregistry.azurecr.io/fbsprint-live'
  dockerRegistryServiceConnection: 'fbsprintRegistry'
stages:
- stage: Build
  displayName: Build image
  jobs: 
  - job: Build
    displayName: Build
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - task: Docker@2   
      displayName: Build and push an image to container registry
      inputs:
        command: buildAndPush
        repository: $(imageName)
        dockerfile: '$(Build.SourcesDirectory)/Dockerfile'
        containerRegistry: $(dockerRegistryServiceConnection)
        tags: |
          $(tag)

 

https://dev.azure.com/FirebrandSprint/_git/KubernetesDevOps?path=%2Fci.yml

Release Pipeline (CD)

The CD pipeline itself is not scriptable at the time of writing though I believe it's a matter of time before this also gets converted to YAML. We do have one important script to add here though and this is your YAML file - the file that encodes how you deploy your app to Kubernetes:

apiVersion: v1
kind: Service
metadata:
  name: fbsprint-live
  labels:
    app: fbsprint-live
spec:
  selector:
    app: fbsprint-live
  ports:
    - protocol: TCP
      port: 80
  type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: fbsprint-live
spec:
  selector:
    matchLabels:
      app: fbsprint-live
  replicas: 1
  template:
    metadata:
      labels:
        app: fbsprint-live
    spec:
      containers:
      - name: fbsprint-live
        image: fbsprintregistry.azurecr.io/fbsprintregistry.azurecr.io/fbsprint-live:1
        ports:
        - containerPort: 80
      imagePullSecrets:
      - name: secret

https://dev.azure.com/FirebrandSprint/_git/KubernetesDevOps?path=%2Fk8s-deployment.yaml

See if it works

For serious work you should have kubectl installed and configured locally but you can try it out in the cloud shell too - you need access to a storage account to run it. You get the local kubernetes config set up automatically with:

az aks get-credentials -g fbsprintAksDevops -n fbsprintAksDevopsClusterDemo

The you just do kubectl get services and you have your external IP. You can also take a look at the status of the pods and check logs with the following:

kubectl get pods
kubectl logs <pod_name>

What next?

There you have it, a completely automated CI/CD for a containerized application in 1.5 hours, give or take. What next then? In the webinar I point out directions in which you can take this setup to make it fully enterprise-grade: versioning, multiple environments, deployment approvals and release gates. 

If this has piqued your interest feel free to dive deeper into DevOps - I've accumulated a bunch of free resources which are now falling out of date but I plan to refresh this collection some time soon - feel free to poke me if you're interested in this!

Enjoy your DevOps journey and don't hesitate to let me know what you think down in the comments.

No comments: