Deploy Azure Kubernetes Service using Terraform with Azure DevOps pipeline and deploying a sample application

In my previous blog post; you may have saw how you can deploy Azure Kubernetes Service (AKS) with Application Gateway Ingress using Terraform. In this blog post I am going to show how you can deploy the same Terraform code in Azure DevOps with an Azure DevOps pipeline and deploy sample application

I have modified the Terraform code into Terraform modules, a blog post I created a while back “Creating reusable Terraform with Terraform modules” details why you should create Terraform modules. Also with this; another I recommend you read, Creating templates in Azure DevOps Pipelines as the Azure DevOps Pipeline I use will be templated

Deploy using Azure DevOps

The Azure DevOps pipeline as mentioned above, will reference various templates. it is split into 5 stages with 3 potential actions

Actions

The actions are configured as to how you would deploy terraform with plan, apply & destroy

Stages

  • terraform validate:- confirms the terraform that will be plan/applied/destroyed is valid format
  • terraform plan:- Returns a plan of the terraform
  • terraform apply:- Applies the terraform configuration
  • bootstrap:- Once the AKS cluster is built, deploy sample application
  • terraform destroy:- Destroys terraform which has been referenced in the .tfstate stored in the Azure Storage Account

Azure DevOps Pipeline Breakdown

Currently no triggers are set or any stages to run during a PR

Parameters setup are the Terraform commands: Plan, Apply or Destroy which show as below within the Azure DevOps Pipeline UI

Highlighted is the variables that can be changed to match additional Terraform setups

name: $(BuildDefinitionName)_$(date:yyyyMMdd)$(rev:.r)

trigger: none

pr: none

parameters:

  - name: Action
    displayName: Action
    type: string
    default: 'Plan'
    values:
    - Plan
    - Apply
    - Destroy

variables:
  - name: backendServiceArm
    value: 'thomasthorntoncloud'
  - name: backendAzureRmResourceGroupName
    value: 'thomasthorntoncloud'
  - name: backendAzureRmStorageAccountName
    value: 'thomasthorntontfstate'
  - name: backendAzureRmContainerName
    value: 'aksdeployazuredevops'
  - name: backendAzureRmKey
    value: 'terraform.tfstate'
  - name: environment
    value: 'production'
  - name: terraform_version
    value: '0.13.4'
  - name: action
    value: ${{ parameters.Action }}

Next is the 5 stages mentioned above

stages :   
  - stage: terraform_validate
    condition: ne('${{ parameters.Action }}', 'Destroy')
    jobs:
      - template: templates/terraform-validate.yaml
        parameters:
          backendServiceArm: ${{ variables.backendServiceArm }}
          backendAzureRmResourceGroupName: ${{ variables.backendAzureRmResourceGroupName }}
          backendAzureRmStorageAccountName: ${{ variables.backendAzureRmStorageAccountName }}
          backendAzureRmContainerName: ${{ variables.backendAzureRmContainerName }}
          backendAzureRmKey: ${{ variables.backendAzureRmKey }}
          environment: ${{ variables.environment }}
          terraform_version: ${{ variables.terraform_version }}

  - stage: terraform_plan
    dependsOn: [terraform_validate]
    condition: ne('${{ parameters.Action }}', 'Destroy')
    jobs:
      - template: templates/terraform-plan.yaml
        parameters:
          backendServiceArm: ${{ variables.backendServiceArm }}
          backendAzureRmResourceGroupName: ${{ variables.backendAzureRmResourceGroupName }}
          backendAzureRmStorageAccountName: ${{ variables.backendAzureRmStorageAccountName }}
          backendAzureRmContainerName: ${{ variables.backendAzureRmContainerName }}
          backendAzureRmKey: ${{ variables.backendAzureRmKey }}
          environment: ${{ variables.environment }}
          terraform_version: ${{ variables.terraform_version }}

  - stage: terraform_apply
    dependsOn: [terraform_plan]
    condition: ne('${{ parameters.Action }}', 'Destroy')
    jobs:
      - template: templates/terraform-apply.yaml
        parameters:
          backendServiceArm: ${{ variables.backendServiceArm }}
          backendAzureRmResourceGroupName: ${{ variables.backendAzureRmResourceGroupName }}
          backendAzureRmStorageAccountName: ${{ variables.backendAzureRmStorageAccountName }}
          backendAzureRmContainerName: ${{ variables.backendAzureRmContainerName }}
          backendAzureRmKey: ${{ variables.backendAzureRmKey }}
          environment: ${{ variables.environment }}
          terraform_version: ${{ variables.terraform_version }}

  - stage: bootstrap
    dependsOn: [terraform_apply]
    condition: ne('${{ parameters.Action }}', 'Destroy')
    jobs:
      - template: templates/az-cli.yaml

  - stage: terraform_destroy
    condition: contains('${{ parameters.Action }}', 'Destroy')
    jobs:
      - template: templates/terraform-destroy.yaml
        parameters:
          backendServiceArm: ${{ variables.backendServiceArm }}
          backendAzureRmResourceGroupName: ${{ variables.backendAzureRmResourceGroupName }}
          backendAzureRmStorageAccountName: ${{ variables.backendAzureRmStorageAccountName }}
          backendAzureRmContainerName: ${{ variables.backendAzureRmContainerName }}
          backendAzureRmKey: ${{ variables.backendAzureRmKey }}
          environment: ${{ variables.environment }}
          terraform_version: ${{ variables.terraform_version }}

As mentioned, the pipeline references templates which are found in this location

The bootstrap stage deploys a test application into AKS with Application Gateway ingress; configured within a job/AzureCLI@2 task as below:

  jobs:
    - job: azcli_resourcegroup_create
      steps:
            - task: AzureCLI@2
              displayName: 'BootStrap AKS Cluster'
              inputs:
                azureSubscription: 'thomasthorntoncloud'
                scriptType: bash
                scriptLocation: inlineScript
                addSpnToEnvironment: true
                inlineScript: |
                  #!/usr/bin/env bash
                  set -x

                  AKS_RG="azuredevopsaksdeployaks-rg"
                  AKS_NAME="azuredevopsaksdeployaks"

                  # Get AKS Credentials
                  az aks get-credentials -g $AKS_RG -n $AKS_NAME --admin

                  # For AAD Pod Identity
                  kubectl create -f https://raw.githubusercontent.com/thomast1906/thomasthorntoncloud-examples/master/Azure-AKS-Deploy-Azure-DevOps/scripts/deployment.yaml

Once the bootstrap stage has been completed, the test application will be deployed. Viewing the services and ingresses in Azure, you will notice an ingress azure-vote-front with external IP

Accessing the External IP , will load the test voting application

Awesome! Successfully deployed Azure AKS using Azure DevOps and deploying sample application!

GitHub repository containing all the configuration – Check it out & thank you for viewing!

6 thoughts on “Deploy Azure Kubernetes Service using Terraform with Azure DevOps pipeline and deploying a sample application”

Leave a Reply

Discover more from Thomas Thornton Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading

Discover more from Thomas Thornton Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading