Skip to content

Helm

Running Octopus Deploy Container With Kubernetes and Helm

When trying to run Kubernetes or Helm deployments from a local Octopus Deploy container, an error will be encountered because these tools aren’t available by default.

One solution to this problem is create a custom container that includes them. Below is an example of this.

FROM octopusdeploy/octopusdeploy:latest

RUN apt update
RUN apt install -y ca-certificates curl apt-transport-https
RUN curl -fsSLo /etc/apt/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
RUN curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | tee /usr/share/keyrings/helm.gpg > /dev/null
RUN echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | tee /etc/apt/sources.list.d/kubernetes.list
RUN echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | tee /etc/apt/sources.list.d/helm-stable-debian.list
RUN apt update
RUN apt install -y kubectl helm

To build the container, run the following command:

docker build --pull -t octopusdeploy-withkubectlandhelm .

Once created, follow the standard instructions on Octopus’ site, replacing the image name in the Docker Compose file with the custom container name. This:

image: octopusdeploy/octopusdeploy:${OCTOPUS_SERVER_TAG}

Becomes:

image: octopusdeploy-withkubectlandhelm

Pushing Helm Charts to a Container Registry

This article walks though building and then pushing a Helm chart to a container registry locally, Azure Container Registry (ACR) and Docker Hub.

Getting Local Container Registry Running

The easiest way to achieve this is using Docker. Once Docker is installed, running the following command will setup an auto-restarting on boot container.

docker run --name registry --env=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin --volume=/var/lib/registry -p 8880:5000 --restart=always -d registry:2

Once up and running, the list of charts can be accessed at http://localhost:8880/v2/_catalog although this will be blank when initially accessing it.

Building A Package

Building a package is the same as building for any Chart registry such as Chart Museum. The important thing is that the chart name is all lowercase. The recommended convention is lowercase, numbers and dashes, replacing other characters and spaces with hyphens e.g. MyShop.Checkout would become myshop-checkout. This value should be used in the name property of the Chart.yaml file, resulting in something similar to the following first few lines:

apiVersion: v2
name: myshop-checkout
version: 0.0.1-dev

Versioning

Most systems will only pull a new version of a chart if the version number has increased. A script to automate version numbering is advised but, for the purposes of this tutorial, the fixed value will be used.

Building Package

Assuming the above example chart is in a subfolder called MyShop.Checkout, run the following command to build a chart package called myshop-checkout-0.0.1-dev.tgz in the current folder:

helm package ./MyShop.Checkout

Pushing Package to Local Registry

Pushing to the local registry is straightforward as authentication is not required by default. Run the following command to add the above chart to the local registry:

helm push myshop-checkout-0.0.1-dev.tgz oci://localhost:8880/helm

This can then be checked by going to http://localhost:8880/v2/_catalog.

Pushing To Azure Container Registry (ACR)

The following PowerShell script will push the above example chart to an ACR. Subscription names and target registry will need updating per your settings.

$subscription = "Your Subscription Name"
$containerRegistry = "yourcontainerregistry"
$ociUrl = "$containerRegistry.azurecr.io/helm"

$currentAccount = (az account show | ConvertFrom-Json)
if (-not $currentAccount) {
    Write-Host "Attemping login..."

    az login
    az account set --subscription $subscription
} else {
    Write-Host "Logged in already as $($currentAccount.user.name)"
}

$helmUsername = "00000000-0000-0000-0000-000000000000"
$helmPassword = $(az acr login --name $containerRegistry --expose-token --output tsv --query accessToken)

Write-Output $helmPassword | helm registry login "$containerRegistry.azurecr.io" --username $helmUsername --password-stdin
}

helm push myshop-checkout-0.0.1-dev.tgz oci://$ociUrl

Pushing To Docker Hub

Firstly, if one doesn’t exist already, create a PAT with read/write permissions. Also, for any repositories that are to be deployed, create these if using a PAT without admin permissions. For example, if the repository will be called myshop-checkout, create a repository called myshop-checkout.

# login
$helmUsername = "docker-name"
$helmPassword = "your_docker_pat"

Write-Output $helmPassword | helm registry login "registry-1.docker.io" --username $helmUsername --password-stdin

$ociUrl = "registry-1.docker.io/$helmUsername"

helm push myshop-checkout-0.0.1-dev.tgz oci://$ociUrl

Running an Azure DevOps Build Agent in Kubernetes

The basics…

Firstly, create a new namespace called build-agents to hold the new agents and also create a PAT in Azure DevOps, ideally associated with a service principal.

kubectl create ns build-agents

If desired, add details about your Docker account if you wish to use your account for unlimited pulls.

kubectl create secret docker-registry dockerhub-account --docker-username=dockerhub-account-name --docker-password=dockerhub-account-password --docker-email= --namespace build-agents

In the above script, dockerhub-account will be the name of the secret in Kubernetes, dockerhub-account-name should be changed to your Docker Hub account name and dockerhub-account-password should be changed to your Docker Hub password or token.

Next create a simple YAML file with the following values:

buildagent-settings.yaml

image:
  pullPolicy: Always
  pullSecrets:
    - dockerhub-account

personalAccessToken: "your-ads-pat"

agent:
  organisationUrl: "https://dev.azure.com/your-org-name/"
  pool: "Default"
  dockerNodes: true

In the above file, you should change your-ads-pat to a Personal Access Token (PAT) you’ve generated which has “Read & manage” agent permissions. You should also change your-org-name to the name of your Azure DevOps organisation. If you wish to deploy the agent to a pool other than the "Default" one, you should also update pool. The image section can be completely removed or either of the sub-values if desired. If you’re not running Docker for your container hosting (Kubernetes 1.24+ will no longer use Docker as its container engine, using Containerd instead), set dockerNodes to false.

Once you are done, it’s time to install the first agent:

helm repo add jabbermouth https://helm.jabbermouth.co.uk
helm install -n build-agents -f buildagent-settings.yaml linux-agent-1 jabbermouth/AzureDevOpsBuildAgent

To add an additional build agent, simply run the following:

helm install -n build-agents -f buildagent-settings.yaml linux-agent-2 jabbermouth/AzureDevOpsBuildAgent

The container can be found on Docker Hub, the files used to build the container can be found on GitHub and the Helm chart code can also be found on GitHub.