Skip to content

Commit 31d6261

Browse files
Merge pull request #162 from ajaymuppeda/feature/website
Feature/website
2 parents 78f5a4c + d473520 commit 31d6261

30 files changed

+1553
-8
lines changed
Lines changed: 374 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,374 @@
1+
# ⎈ Azure DevOps — Self Hosted Agents on Kubernetes — PART-1 ⎈
2+
#### *Unlocking Efficiency and Scalability for Your CI/CD Workflows🚀*
3+
4+
![img](./img/linux-agent.png.webp)
5+
6+
7+
Are you tired of wrestling with manual agent management, lengthy pipeline queues, or soaring infrastructure costs in your Azure DevOps setup? Look no further! In this comprehensive series of guides, we’ll explore how leveraging Kubernetes for self-hosted agents can revolutionize your CI/CD processes. Say goodbye to operational headaches and hello to streamlined, efficient pipelines.
8+
9+
### Introduction
10+
11+
If you find yourself grappling with the management of Azure DevOps self-hosted agents or experiencing prolonged wait times in pipeline queues, or perhaps facing higher costs associated with agent infrastructure, or struggling with the setup and maintenance of self-hosted agent environments, then Kubernetes presents an optimal solution to address these challenges.
12+
13+
Furthermore, the absence of Kubernetes orchestration complicates the setup of diverse environments for running pipelines on self-hosted agents. Organizations may struggle to configure and manage different agent environments for testing, staging, and production, resulting in inconsistency and potential deployment issues. Additionally, without the scalability and elasticity provided by Kubernetes, organizations may experience bottlenecks and delays due to long queue times in Azure DevOps pipelines, leading to decreased productivity and slower time-to-market.
14+
15+
In summary, without leveraging Kubernetes for Azure DevOps self-hosted agents, organizations may face a myriad of challenges including operational inefficiencies, pipeline delays, increased costs, and complexity in environment management. Embracing Kubernetes as a solution offers scalability, flexibility, cost-effectiveness, and streamlined operations, enabling organizations to optimize their CI/CD workflows and accelerate software delivery.
16+
17+
### Challenges with Traditional Self-Hosted Agents
18+
19+
- Management overhead: The manual effort required to provision, configure, and manage self-hosted agents.
20+
21+
- Queue times: Prolonged wait times in pipeline queues due to limited agent capacity.
22+
23+
- Cost implications: Inefficient resource utilization leading to increased infrastructure costs.
24+
25+
- Environment setup complexities: Difficulties in configuring and managing diverse environments for running pipelines.
26+
27+
### Benefits of using the Kubernetes for Self-Hosted Agents
28+
29+
**Key features:** Scalability, flexibility, portability, and automated management.
30+
31+
- **Benefits for CI/CD:** Enabling dynamic scaling, resource optimization, and simplified management of agent infrastructure.
32+
- **Scalability:** Ability to scale agent capacity up or down based on workload demands.
33+
- **Flexibility:** Customizable agent configurations and support for diverse environments.
34+
- **Cost-effectiveness:** Efficient resource utilization leading to reduced infrastructure costs.
35+
- **Simplified management:** Automated deployment, scaling, and maintenance of agent infrastructure.
36+
37+
### Prerequisites
38+
39+
- Kubernetes environment.
40+
- Azure Devops active account.
41+
- Docker environment
42+
43+
### Getting Started: Setting Up Azure DevOps Self-Hosted Agents on Kubernetes
44+
45+
Let’s start setting up these Azure DevOps Self-Hosted Agents on Kubernetes by following the below steps one by one.
46+
47+
- **Building Docker images:** Building Docker images containing Azure Pipelines Agent software.
48+
- **Configuring Azure DevOps:** Setting up agent pools and generating Personal Access Tokens (PATs).
49+
- **Deploying agent pods:** Using Kubernetes manifests to deploy agent pods in the cluster.
50+
- **Registering agents:** Configuring agent pods to register themselves with Azure DevOps using PATs.
51+
52+
#### Building Docker Images:
53+
54+
Assume you have Docker environment is ready to build the required docker images.
55+
56+
1. Open the target CLI to run docker commands
57+
58+
2. Create a new directory.
59+
```yaml
60+
mkdir azsh-linux-agent/
61+
```
62+
63+
3. Change the directory to newly created.
64+
```yaml
65+
cd azsh-linux-agent/
66+
```
67+
4. Create the Dockerfile with below content, name it as **azsh-linux-agent.dockerfile**
68+
```yaml
69+
FROM ubuntu:22.04
70+
71+
RUN apt update
72+
RUN apt upgrade -y
73+
RUN apt install -y curl git jq libicu70
74+
75+
# Also can be "linux-arm", "linux-arm64".
76+
ENV TARGETARCH="linux-x64"
77+
78+
WORKDIR /azp/
79+
80+
COPY ./start.sh ./
81+
RUN chmod +x ./start.sh
82+
83+
RUN useradd agent
84+
RUN chown agent ./
85+
USER agent
86+
# Another option is to run the agent as root.
87+
# ENV AGENT_ALLOW_RUNASROOT="true"
88+
89+
ENTRYPOINT ./start.sh
90+
```
91+
92+
5. Create a **start.sh** file using below content, which will be used by the above docker file.
93+
94+
```yaml
95+
#!/bin/bash
96+
set -e
97+
98+
if [ -z "${AZP_URL}" ]; then
99+
echo 1>&2 "error: missing AZP_URL environment variable"
100+
exit 1
101+
fi
102+
103+
if [ -z "${AZP_TOKEN_FILE}" ]; then
104+
if [ -z "${AZP_TOKEN}" ]; then
105+
echo 1>&2 "error: missing AZP_TOKEN environment variable"
106+
exit 1
107+
fi
108+
109+
AZP_TOKEN_FILE="/azp/.token"
110+
echo -n "${AZP_TOKEN}" > "${AZP_TOKEN_FILE}"
111+
fi
112+
113+
unset AZP_TOKEN
114+
115+
if [ -n "${AZP_WORK}" ]; then
116+
mkdir -p "${AZP_WORK}"
117+
fi
118+
119+
cleanup() {
120+
trap "" EXIT
121+
122+
if [ -e ./config.sh ]; then
123+
print_header "Cleanup. Removing Azure Pipelines agent..."
124+
125+
# If the agent has some running jobs, the configuration removal process will fail.
126+
# So, give it some time to finish the job.
127+
while true; do
128+
./config.sh remove --unattended --auth "PAT" --token $(cat "${AZP_TOKEN_FILE}") && break
129+
130+
echo "Retrying in 30 seconds..."
131+
sleep 30
132+
done
133+
fi
134+
}
135+
136+
print_header() {
137+
lightcyan="\033[1;36m"
138+
nocolor="\033[0m"
139+
echo -e "\n${lightcyan}$1${nocolor}\n"
140+
}
141+
142+
# Let the agent ignore the token env variables
143+
export VSO_AGENT_IGNORE="AZP_TOKEN,AZP_TOKEN_FILE"
144+
145+
print_header "1. Determining matching Azure Pipelines agent..."
146+
147+
AZP_AGENT_PACKAGES=$(curl -LsS \
148+
-u user:$(cat "${AZP_TOKEN_FILE}") \
149+
-H "Accept:application/json;" \
150+
"${AZP_URL}/_apis/distributedtask/packages/agent?platform=${TARGETARCH}&top=1")
151+
152+
AZP_AGENT_PACKAGE_LATEST_URL=$(echo "${AZP_AGENT_PACKAGES}" | jq -r ".value[0].downloadUrl")
153+
154+
if [ -z "${AZP_AGENT_PACKAGE_LATEST_URL}" -o "${AZP_AGENT_PACKAGE_LATEST_URL}" == "null" ]; then
155+
echo 1>&2 "error: could not determine a matching Azure Pipelines agent"
156+
echo 1>&2 "check that account "${AZP_URL}" is correct and the token is valid for that account"
157+
exit 1
158+
fi
159+
160+
print_header "2. Downloading and extracting Azure Pipelines agent..."
161+
162+
curl -LsS "${AZP_AGENT_PACKAGE_LATEST_URL}" | tar -xz & wait $!
163+
164+
source ./env.sh
165+
166+
trap "cleanup; exit 0" EXIT
167+
trap "cleanup; exit 130" INT
168+
trap "cleanup; exit 143" TERM
169+
170+
print_header "3. Configuring Azure Pipelines agent..."
171+
172+
./config.sh --unattended \
173+
--agent "${AZP_AGENT_NAME:-$(hostname)}" \
174+
--url "${AZP_URL}" \
175+
--auth "PAT" \
176+
--token $(cat "${AZP_TOKEN_FILE}") \
177+
--pool "${AZP_POOL:-Default}" \
178+
--work "${AZP_WORK:-_work}" \
179+
--replace \
180+
--acceptTeeEula & wait $!
181+
182+
print_header "4. Running Azure Pipelines agent..."
183+
184+
chmod +x ./run.sh
185+
186+
# To be aware of TERM and INT signals call ./run.sh
187+
# Running it with the --once flag at the end will shut down the agent after the build is executed
188+
./run.sh "$@" & wait $!
189+
```
190+
191+
6. Let’s build the docker image using below command.
192+
```yaml
193+
docker build --tag "azsh-linux-agent:tag" --file "./azsh-linux-agent.dockerfile" .
194+
```
195+
196+
7. Now push the above docker image to your target repository.
197+
### Configuring Azure DevOps
198+
**Create Agent Pool**
199+
200+
- In your Azure DevOps organization, navigate to “Project Settings” > “Agent Pools”.
201+
- Create a new agent pool or use an existing one for your Kubernetes agents.
202+
- Click on the “New agent pool” button to create a new pool, or select an existing one.
203+
204+
**Create PAT Token**
205+
206+
- Click on “**User Settings**” from top-right corner of the page.
207+
- Select “**Personal access tokens**” from the dropdown menu.
208+
- Generate a Personal Access Token (PAT) with the appropriate scope for registering agents, and save it for next steps.
209+
210+
**Deploying agent pods**
211+
212+
Imagine you’ve got your Kubernetes cluster ready to roll. If not, don’t worry — we’ve got you covered. Even if you’re new to Kubernetes, setting up Azure DevOps agents on your behalf is a breeze. Simply follow along with the steps outlined in this guide, and you’ll be up and running in no time!
213+
214+
Create a **azsh-linux-agent-deployment.yaml** file using below content.
215+
```yaml
216+
apiVersion: apps/v1
217+
kind: Deployment
218+
metadata:
219+
name: azsh-linux
220+
namespace: az-devops
221+
labels:
222+
app: azsh-linux-agent
223+
spec:
224+
replicas: 1
225+
selector:
226+
matchLabels:
227+
app: azsh-linux-agent
228+
template:
229+
metadata:
230+
labels:
231+
app: azsh-linux-agent
232+
spec:
233+
containers:
234+
- name: kubepodcreation
235+
image: anvesh35/azsh-linux-agent:02062024
236+
env:
237+
- name: AZP_URL
238+
valueFrom:
239+
secretKeyRef:
240+
name: azdevops
241+
key: AZP_URL
242+
- name: AZP_TOKEN
243+
valueFrom:
244+
secretKeyRef:
245+
name: azdevops
246+
key: AZP_TOKEN
247+
- name: AZP_POOL
248+
valueFrom:
249+
secretKeyRef:
250+
name: azdevops
251+
key: AZP_POOL
252+
volumeMounts:
253+
- mountPath: /var/run/docker.sock
254+
name: docker-volume
255+
volumes:
256+
- name: docker-volume
257+
hostPath:
258+
path: /var/run/docker.sock
259+
```
260+
Create a **azsh-linux-agent-secret.yaml** file using below content. This secret will help us to authenticate our kubernetes pods with Azure devops.
261+
262+
```yaml
263+
apiVersion: v1
264+
data:
265+
AZP_POOL: <agent-pool-name>
266+
AZP_TOKEN: <PAT-token>
267+
AZP_URL: <https://dev.azure.com/username>
268+
kind: Secret
269+
metadata:
270+
name: azdevops
271+
namespace: az-devops
272+
type: Opaque
273+
```
274+
275+
Here replace your agent-pool-name with your newly created Agent Pool name, PAT-Token with PAT token, and AZP_URL with your Azure devops portal URL.
276+
277+
Now create a new namespace for azure devops self-hosted agents in your kubernetes cluster.
278+
```yaml
279+
kubectl create namespace az-devops
280+
```
281+
Let’s deploy the deployment using below command.
282+
```yaml
283+
kubectl apply -f azsh-linux-agent-deployment.yaml
284+
```
285+
Let’s create the secret to authenticate our agent pods to azure devops using below command.
286+
```yaml
287+
kubectl apply -f azsh-linux-agent-secret.yaml
288+
```
289+
290+
Verify the newly created pods and secrets status using below command.
291+
```yaml
292+
kubectl get pods -n az-devops
293+
kubectl get secret -n az-devops
294+
```
295+
```yaml
296+
kubectl get pods -n az-devops
297+
NAME READY STATUS RESTARTS AGE
298+
azdevops-deployment-b684fd756-nmn54 1/1 Running 0 21h
299+
300+
kubectl get secret -n az-devops
301+
NAME TYPE DATA AGE
302+
azdevops Opaque 3 21h
303+
```
304+
305+
Now the pods are up and running, let’s check in our Azure Devops Portal for our self-hosted agents in our agent pool.
306+
307+
308+
That’s it your agents are online now you can run your pipelines based on your number of replicas.
309+
310+
### Running your first Azure DevOps pipeline on Kubernetes Self-Hosted agents
311+
Lets create a new sample pipeline using below steps.
312+
313+
Create a new file in **/pipelines/sample-pipeline.yaml** path in your azure devops repository using below content.
314+
315+
```yaml
316+
trigger: none
317+
318+
pool: <agent-pool>
319+
320+
resources:
321+
repositories:
322+
- repository: templates
323+
displayname: templates from devops
324+
type: git
325+
name: <projectname>/<repositoryname>
326+
ref: <branch>
327+
328+
stages:
329+
- stage: Deploy
330+
jobs:
331+
- deployment: helloWorld
332+
displayName: 'Agent Setup'
333+
strategy:
334+
runOnce:
335+
deploy:
336+
steps:
337+
#Branch Checkout
338+
- checkout: self
339+
persistCredentials: true
340+
341+
# Hello World program
342+
- template: /scripts/kubernetes/hello-world.yaml@templates
343+
```
344+
Create the script **/scripts/kubernetes/hello-world.yaml** to run the sample program on self-hosted agent on kubernetes.
345+
```yaml
346+
347+
steps:
348+
- bash: |
349+
echo "Hello, Welcome to Anvesh World!"
350+
displayName: 'Hello World'
351+
352+
```
353+
354+
Now create a new pipeline using below steps.
355+
Select the project where you want to create the YAML pipeline.
356+
357+
1. Click on the “Pipelines” menu option in the left sidebar.
358+
2. You should see a button labeled “New pipeline” on the Pipelines page.
359+
3. Click on it to start creating a new pipeline.
360+
4. Choose the repository where your code is located. Azure DevOps supports Git repositories, GitHub repositories, and others.
361+
5. Choose where your YAML file is located(i.e., /pipelines/sample-pipeline.yaml)
362+
6. Now save the pipeline.
363+
7. should see your pipeline listed in the Pipelines page of your Azure DevOps project. You can review the pipeline configuration and manually trigger a run to test it.
364+
365+
That’s it! You’ve successfully created a YAML pipeline in Azure DevOps and ran it using self hosted agent from kubernetes.
366+
367+
![img](./img/sample-pipeline.png.webp)
368+
369+
370+
## Best Practices and Tips
371+
- **Resource management:** Setting resource limits and requests for agent pods to ensure efficient resource utilization.
372+
- **Monitoring and logging:** Implementing monitoring and logging solutions to track agent performance and troubleshoot issues.
373+
- **Automation:** Leveraging automation tools and scripts for seamless deployment and configuration of agent infrastructure.
374+
- Will discuss all these in upcoming parts.

0 commit comments

Comments
 (0)