azure-pipelineshelmfile

How to implement helmfile into my azure pipeline?


I have created a Node application for which I want to automate the deployment. Up till now I only automated the building process, i.e. install dependencies, create the docker image and push to the Azure Container Registry. This works perfectly fine and corresponds to the code below which is not commented away. In the current process I still need to

  1. manually change the image tag in my helmfile configuration and
  2. manually perform a helmfile -environment=<my-environment> sync.

My struggle is in the second part, for I believe the first part is easily implemented when I have a setup for the second.

In the source directory of the repository I have the helmfile.yaml which could be called immediately after the build. This is what I tried to achieve with the below setup which is commented. My thoughts were to have a container on which helfmile is already installed, e.g. cablespaghetti/helmfile-docker, then connect to the K8s cluster using the Azure kubectl task to do so, followed by executing the helmfile sync command. This approach failed as I got a Docker exec fail with exit code 1, probably because the specified container uses the ENTRYPOINT approach, which is not allowed in the Azure Pipeline.

The approach however feels somewhat cumbersome, as if I am missing a much simpler approach to 'simply' perform a helmfile sync command. How can I get this to work?

trigger:
- dev

resources:
- repo: self

variables:
  # Container registry service connection established during pipeline creation
  dockerRegistryServiceConnection: <service-connection>
  imageRepository: <node-app-image>
  containerRegistry: <registry-name>
  dockerfilePath: '$(Build.SourcesDirectory)/Dockerfile'
  tag: '$(Build.BuildId)'
  
  # Agent VM image name
  vmImageName: 'ubuntu-latest'

  ## This was an approach I tried but failed, because the below image is not suitable
  # helmfileImageName: 'cablespaghetti/helmfile-docker:3.3.4.1'
  # azureSubscriptionEndpoint: <endpoint>
  # azureResourceGroup: <resource-group>
  # kubernetesCluster: <cluster-name>
  # stage: <stage>

stages:
- stage: Build
  displayName: Build and push stage
  jobs:  
  - job: Build
    displayName: Build
    pool:
      vmImage: $(vmImageName)
    steps:
    - task: NodeTool@0
      inputs:
        versionSpec: '13.x'
      displayName: 'Install Node.js'
    - script: |
        yarn install
        yarn run build
      displayName: 'yarn install'
    - task: Docker@2
      displayName: Build and push an image to container registry
      inputs:
        command: buildAndPush
        repository: $(imageRepository)
        dockerfile: $(dockerfilePath)
        containerRegistry: $(dockerRegistryServiceConnection)
        tags: |
          $(tag)
## Attempted deploy stage - still missing here is using the above $(tag) to select the correct image
# - stage: Deploy
#   displayName: Deploy with helmfile
#   jobs:  
#   - job: Deploy
#     displayName: Deploy
#     container: cablespaghetti/helmfile-docker:3.3.4.1
#     steps:
#     - task: Kubernetes@1
#       displayName: kubectl login
#       inputs:
#         connectionType: Azure Resource Manager
#         azureSubscriptionEndpoint: $(azureSubscriptionEndpoint)
#         azureResourceGroup: $(azureResourceGroup)
#         kubernetesCluster: $(kubernetesCluster)
#         useClusterAdmin: $(useClusterAdmin)
#         command: login
#     - script: |
#         helmfile -environment=$(stage) sync

Solution

  • Since the helmfile is not preinstalled in the pipeline agent. You can manually install helmfile with a script task. Check below example:

    - bash: |
       
       curl -L https://github.com/roboll/helmfile/releases/download/v0.135.0/helmfile_linux_amd64 > helmfile
        
       chmod +x helmfile
         
      displayName: 'Install helm'
    

    Above bash task will install hemlfile in the default working directory(You can change the file path to install it to a different folder). Then you can use the helmfile command like this ./helmfile -environment=<my-environment> sync in the following script task. See below:

    - bash: |
       az login --service-principal -u "$(AZURE_SERVICE_PRINCIPAL_USER)" -p "$(AZURE_SERVICE_PRINCIPAL_PW_OR_CERT)" --tenant "$(AZURE_SERVICE_PRINCIPAL_TENANT)"
       az aks get-credentials --resource-group "$(AZURE_RESOURCE_GROUP)" --name "$(CLUSTER_NAME)"
           
       ./helmfile -environment=<my-environment> sync
    
      displayName: 'helmfile  sync'