# Installing Flux using Azure DevOps and Helm on AKS

[Flux](https://landscape.cncf.io/selected=flux) is an open-source project that’s currently being incubated by the Cloud Native Computing Foundation. It enables Kubernetes cluster to adopt a [GitOps](https://gaunacode.com/gitops) workflow for deployments. Terraform can get you most of the way there. But, ultimately, there’s some **glue code** needed.

This is a quick guide on how to do it through Azure DevOps, Azure CLI, Helm 3, and AKS.

### Background

Here’s the [official documentation](https://docs.fluxcd.io/en/1.18.0/tutorials/get-started-helm.html) on how to install Flux using Helm. It also gives you instructions on how to install the Helm operator. The Helm operator watches for [declarative YAML](https://github.com/gaunadevops/flux-get-started/blob/master/releases/redis.yaml) based declaration on what Helm charts should be installed on the cluster.

### Azure DevOps

Step zero, you’ll want to ensure that the running agent has Helm 3 installed.

    - task: HelmInstaller@1
      inputs:
        helmVersionToInstall: 'latest'
    

#### The Prep

First, you’ll want to use the Azure CLI task (`AzureCLI@2`). We’ll be using this to manually connect to the AKS cluster to issue `kubectl` and `helm` commands from the script.

    - task: AzureCLI@2
      displayName: Install Fluxctl
      inputs:
        azureSubscription: '[your azure service connection]'
        scriptType: 'bash'
        scriptLocation: 'inlineScript'
        inlineScript: |
          set -e
          ## script will go here
    

`set -e` will make the build fail if there’s an error in the inline script.

Next, you’ll want to install `fluxctl`.

    sudo snap install fluxctl --classic
    

Then, connect to the AKS cluster. If you’re running from an agent that’s already has working `kubectl` commands, then you won’t need this step. The purpose of the following command is to be able to use `kubectl` and `helm` command line.

    az aks get-credentials -n $CLUSTER_NAME -g $RESOURCE_GROUP_NAME
    

For me, the `CLUSTER_NAME` and `RESOURCE_GROUP_NAME` variables come from Terraform outputs.

Then, you’ll be ready to install Flux.

#### Finally installing Flux

First, create the flux namespace.

    kubectl apply -f flux.yaml
    

Where the contents of the `flux.yaml` file are

    apiVersion: v1
    kind: Namespace
    metadata:
      name:  flux
    

With this approach, we can apply this configuration file and it won’t fail if the namespace already exist.

Next, use Helm to install Flux.

    helm repo add fluxcd https://charts.fluxcd.io
    
    helm upgrade -i flux fluxcd/flux \
            --set git.url=$(ManifestsRepoUrl) \
            --namespace flux \
            --wait
    

_Note:_ If you’re using Azure Container Registry, then you’ll want to set `registry.acr.enabled` to `true`. This way, Flux will be able to authenticate against Azure Container Registry and have [automated upgrades](https://helm.workshop.flagger.dev/helm/#automated-upgrade)

`$(ManifestsRepoUrl)` is the variable that points to the Git repo URL for the main repository to be used by Flux.

Next, install the helm operator.

    helm upgrade -i helm-operator fluxcd/helm-operator \
            --set git.ssh.secretName=flux-git-deploy \
            --namespace flux \
            --set helm.versions=v3 \
            --wait
    

Since I am not using Helm v2, I am specific about only using Helm 3 by specifying the `helm.versions` value in the Helm chart.

Lastly, you’ll want to get the SSH public key the flux operator so that it can interact with the Git repository. For this, we’ll use `fluxctl` to get the “identity.”

    STAGING_SSH_PUBLIC_KEY=$(fluxctl identity --k8s-fwd-ns flux)
    echo "##vso[task.setvariable variable=Staging.Flux.SshPublicKey;issecret=true]$STAGING_SSH_PUBLIC_KEY"
    

That’s it!

As shown above, I am also assigning the public ssh key to a pipeline variable. This later allows me to configure GitHub with a new deploy key for the repo being watched.

### By the way

Here’s what it looks like all together

    - task: AzureCLI@2
      displayName: Install Fluxctl
      inputs:
        azureSubscription: '[azure service connection]'
        scriptType: 'bash'
        scriptLocation: 'inlineScript'
        inlineScript: |
          set -e
    
          CLUSTER_NAME=$(cat $(TerraformCluster.jsonOutputVariablesPath) | jq '.cluster_name.value' -r)
          RESOURCE_GROUP_NAME=$(cat $(TerraformCluster.jsonOutputVariablesPath) | jq '.resource_group_name.value' -r)
          
          echo "installing fluxctl"
          sudo snap install fluxctl --classic
    
          echo "acquiring credentials for cluster"
          az aks get-credentials -n $CLUSTER_NAME -g $RESOURCE_GROUP_NAME
    
          echo "ensuring flux namespace exists"
          kubectl apply -f k8s/flux.yml
    
          echo "installing flux. adding fluxcd helm repo"
          helm repo add fluxcd https://charts.fluxcd.io
    
          echo "installing flux. installing the main operator"
          
          helm upgrade -i flux fluxcd/flux \
            --set git.url=$(ManifestsRepoUrl) \
            --namespace flux
    
          echo "installing flux. installing the helm operator"
          helm upgrade -i helm-operator fluxcd/helm-operator \
            --set git.ssh.secretName=flux-git-deploy \
            --namespace flux \
            --set helm.versions=v3
          
          sleep 5
          
          echo "acquiring public ssh key for flux"
          STAGING_SSH_PUBLIC_KEY=$(fluxctl identity --k8s-fwd-ns flux)
          echo "##vso[task.setvariable variable=Staging.Flux.SshPublicKey;issecret=true]$STAGING_SSH_PUBLIC_KEY"
