In this guide we will show you how you can run self-hosted Azure Pipeline agents on the cheap and with minimal maintenance using Gigahatch Managed Kubernetes, starting at just 4.87€ per month.
To follow along, you will need the following:
To start with, we need to create a cluster to run our agents. If you already have one, you can skip this step.
Create cluster
.AZP Agents
and choose a node size. For this example we will be using one replica of the smallest SharedI1 with 2 CPUs and 4GB RAM. If you need more power for your agents, or you would like to run multiple of them, you can use larger node sizes.Create Cluster
and wait a few minutes for your cluster to be created.After your cluster has finished creating, click the Get Kubeconfig
button. This will download a yaml
file that you need to connect to your cluster. Save it somewhere secure and open your terminal. Now you need to tell your kubectl
cli where to find this file. The easiest way is to set it as the KUBECONFIG
environment variable.
In bash this looks like so:
export KUBECONFIG='PATH_TO_YAML'
In powershell this looks like so:
$env:KUBECONFIG = "PATH_TO_YAML"
# Or if its in the current directory:
$env:KUBECONFIG = "$(Get-Location)\<NAME_OF_YAML>.yaml"
If you would rather not use the environment variable, you can pass it as the --kubeconfig
flag to the kubectl
cli.
For example:
kubectl --kubeconfig 'PATH_TO_YAML' get nodes
To check if you can access the cluster, run:
kubectl get nodes
You should now get a list of nodes like so:
NAME STATUS ROLES AGE VERSION
41488847-47e9-4f03-90df-7fb5f7f8e15f-l2ljs-qx8mf Ready <none> 37s v1.31.0+k3s1
9b43501b-f5d8-4cce-bdab-b5fdcb777325-control-plane-n67gv Ready control-plane,etcd,master 3m56s v1.31.0+k3s1
If this doesn’t work, try using the cli flag.
We will now create the agent pool and PAT (Personal Access Token) that the agents will use to run.
Agent pools
in the left sidebar. You should now see a list of Agent pools.Add pool
in the top left.Pool to link: New
and Pool type: self-hosted
.Kubernetes
.Create
.Now we need to create the Personal Access Token (PAT) that the agents will use to authenticate with your Azure DevOps.
User settings
(the icon with a person and a gear) and click Personal access tokens
.New Token
and enter a name for your token so you remember what it is for. I chose Kubernetes Agents
.Custom defined
for the Scopes
.Show all scopes
that we have to click to see the scope we need.Agent Pools
-> Read & manage
.Now we can create the agents in the cluster. First of all, we need to save the PAT in a kubernetes secret. To do this, run the following command:
kubectl create secret generic azp --from-literal=azp-token='<PAT_FROM_AZURE_DEVOPS_HERE>'
Make sure to pass the --kubeconfig
flag if not using the environment variable.
You can now close the sidebar in Azure DevOps.
Then we can create the kubernetes deployment that will actually run the agent. Create a deployment.yaml
file with the following content:
apiVersion: apps/v1
kind: Deployment
metadata:
name: azp-agent
spec:
selector:
matchLabels:
app: azp-agent
replicas: 1 # Number of agents to create
strategy:
rollingUpdate:
maxSurge: 0 # No more instances than replicas will be created at a time
maxUnavailable: 1 # Only one agent will be updated at a time
type: RollingUpdate
template:
metadata:
labels:
app: azp-agent
spec:
containers:
- name: azp-agent
image: ghcr.io/gigahatch/azp-agent:ubuntu-24.04
resources:
limits:
memory: '1536Mi' # Depending on the node size, you might need to increase this
cpu: '1500m' # Depending on the node size, you might need to increase this
env:
- name: AZP_URL
value: https://dev.azure.com/<YOUR_ORGANISATION> # <- Add your organisation URL here
- name: AZP_POOL
value: Kubernetes # <- Add the name of the agent pool here
- name: AZP_TOKEN
valueFrom:
secretKeyRef:
name: azp
key: azp-token
Make sure that:
replicas
property in the file.1500m
means 1.5 CPUs and 1536Mi
means 1.5GB RAM.RollingUpdate
with a max of 0 surge and 1 unavailable. This means that only one agent will be updated at a time.If you want to run docker commands in the container, you will have to disable some security features. Add
securityContext:
privileged: true
to your container definition. Your yaml should now look like this:
apiVersion: apps/v1
kind: Deployment
metadata:
name: azp-agent
spec:
selector:
matchLabels:
app: azp-agent
replicas: 1 # Number of agents to create
strategy:
rollingUpdate:
maxSurge: 0 # No more instances than replicas will be created at a time
maxUnavailable: 1 # Only one agent will be updated at a time
type: RollingUpdate
template:
metadata:
labels:
app: azp-agent
spec:
containers:
- name: azp-agent
image: ghcr.io/gigahatch/azp-agent:ubuntu-24.04
resources:
limits:
memory: '1536Mi'
cpu: '1500m'
env:
- name: AZP_URL
value: https://dev.azure.com/<YOUR_ORGANISATION>
- name: AZP_POOL
value: Kubernetes
- name: AZP_TOKEN
valueFrom:
secretKeyRef:
name: azp
key: azp-token
securityContext:
privileged: true # <- Add this
This will basically make the agent run like a normal process on the system, with no sandboxing. It is probably best if you only use this in a cluster solely dedicated to your build agents.
Now run the following command to create the deployment in the cluster:
kubectl apply -f deployment.yaml
It should print out deployment.apps/azp-agent created
. Wait a bit and run this to check if the agent was created successfully.
kubectl get pods
It should print out something like this:
NAME READY STATUS RESTARTS AGE
azp-agent-557fdcc78f-kr6kn 1/1 Running 0 4m38s
Now go back to your Azure DevOps agent pools, click on the agent pool you created previously and click on the Agents
tab. You should now see an agent. Now we can run jobs on our cluster.
To run the pipeline on the new agent pool, just change the pool
property in the pipeline yaml to the following:
pool: Kubernetes # Or whatever name you gave to the Agent Pool
Now try running your pipeline. The first time it runs, you will probably have to give it access to the agent pool, so just refresh the page on the pipeline run a few times until the banner appears to give it access.
You have now successfully setup your Azure Pipeline Agents on Gigahatch Managed Kubernetes. If you have any questions or are stuck somewhere, please write us at info@gigahatch.ch. We look forward to hearing from you.