Setting Up a Seamless Integration Pipeline with Azure DevOps

I'm a detail-oriented and innovative Solutions Architect / DevOps engineer, a team player, and solution-driven, with a keen eye for excellence and achieving business goals.
I have repeatedly demonstrated success in designing and launching new cloud infrastructure throughout Azure workloads. I'm passionate about the Cloud, DevOps, Well-Architected Infrastructure, Automation, Open-source, Collaboration, Community building, and knowledge sharing.
π¨βπ» Introduction
Welcome to the third part of the step-by-step implementation guide for deploying a Dockerized application on Azure Kubernetes Service (AKS) using ArgoCD and Azure DevOps. In this project series, We're on a journey of breaking down the complex process of creating a robust and efficient Kubernetes deployment pipeline into manageable steps.
In Part 3, I'll guide you through setting up a robust integration pipeline using Azure DevOps which ensures a smooth and automated integration process.
π Prerequisites:
Before we dive into setting up the pipeline, ensure that you have the following prerequisites in place:
Azure DevOps Organization Account: If you don't have one, you can sign up for free on the Azure DevOps website.
Docker Hub Account: If you don't have one already, you can create an account at Docker Hub.
An Application Code Repository - Todo-App Sample Repository (Our CI Journey begins here)
Fundamental Knowledge of Git, Kubernetes, and YAML syntax
It will be great to check out part 1 of this project series where I've provided the project's architecture and details about this series - Link Here
π Plan of Execution
Writing Kubernetes Manifest Files and Repository Setup
Application Code and Dockerfile Setup
Azure DevOps Project and Azure Pipelines Setup
βΈοΈ Step 1: Writing Kubernetes Manifest Files and Repository Setup
To kick things off, We'll be creating two files: deployment.yaml and service.yaml, which defines how your AKS cluster should be set up. Here's a snippet of what they might look like:
deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: todo-app-deployment
labels:
app: todo-app
spec:
replicas: 2
selector:
matchLabels:
app: todo-app
template:
metadata:
labels:
app: todo-app
spec:
containers:
- name: todo-app-container
image: joelplush/todo-app:v1
ports:
- containerPort: 80
service.yaml:
apiVersion: v1
kind: Service
metadata:
name: todo-app-service
spec:
selector:
app: todo-app
type: LoadBalancer
ports:
- port: 80
protocol: TCP
targetPort: 80
Once you've created your deployment and service configuration file, the next step is to push it to a dedicated GitHub repository. This repository will serve as our single source of truth for managing Kubernetes configurations and ensuring version control.
For a quick start, you can also fork and clone my Kubernetes manifest repository on GitHub. This will provide you with a ready-to-use repository to follow along with the guide and experiment with Kubernetes manifest files. Simply fork the repository to your GitHub account, clone it to your local environment, and you're ready to continue the guide.
π³ Step 2: Application Code and Dockerfile Setup
In this crucial step, we'll focus on preparing your application code and creating a Dockerfile. These components are the heart of your containerized application, and getting them right is essential for a successful deployment. Here's how to get started:
Application Code Setup:
Version Control: Ensure your application code is stored in a version-controlled repository, like GitHub, GitLab, or Bitbucket. This facilitates collaboration, version tracking, and seamless integration with your pipeline.
Convenient Option: For added convenience, you can use my sample todo application's GitHub repository. Simply fork and clone it. This repository features a Reactjs-based todo application, and it's accessible HERE. By forking and cloning, you'll have a pre-prepared application codebase to follow along with this guide.
Creating a Dockerfile:
Your Dockerfile holds an important role in the creation of containerized applications. Think of it as the blueprint for constructing a Docker image that packages your application along with its dependencies. Below is a snippet illustrating what your Dockerfile should look like:
# Build stage FROM node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # Final stage FROM nginx:latest COPY --from=builder /app/build /usr/share/nginx/html
This Dockerfile defines the build process for your application, starting with a Node.js environment for building and then packaging it into an Nginx-based image for serving.
π Step 3: Azure DevOps Project and Azure Pipelines Setup
Creating an Azure DevOps project is a fundamental step in setting up an efficient and automated integration pipeline for your application. Each project provides boundaries to isolate data from other projects. Now, let's jump into creating your Azure DevOps project.
Sign In to Azure DevOps
If you don't already have an Azure DevOps account, you can sign up for a free account on the Azure DevOps website or Sign in to your organization (
https://dev.azure.com/{yourorganization_name}). Once you're signed in, you're ready to start creating your project.Creating a New Project
Click on the "New Project" button. This will initiate the project creation window.

Provide a Project Name that reflects the purpose or name of your application or team. Choose a name that makes it easy to identify the project's content and purpose.
Select your Project Visibility. You can choose between "Public" and "Private" based on your project's requirements then Click the "Create" button to create your new project.

With your Azure DevOps project created, the next important phase is the configuration of your Azure Pipelines. Azure Pipelines will serve as the powerhouse automating multiple facets of our continuous integration process.
We'll start our journey by leveraging a starter template that streamlines the initial setup of Azure Pipelines. This template is designed to accelerate your configuration process and ensure you're up and running with minimal effort. Here's how to proceed:
Within your Azure DevOps project, navigate to the "Pipelines" section and Click on the "Create Pipeline" button to initiate the pipeline creation process. This action will launch a wizard to guide you through the setup.

In the wizard's initial steps, select GitHub as the location of your source code. You might be redirected to GitHub to sign in if you haven't already done so. Simply enter your GitHub credentials to proceed.

Once authenticated, you'll see a list of repositories. Here, you should choose the repository that houses your application code. At this point, you might be prompted to install the Azure Pipelines app from GitHub. If prompted, go ahead and select "Approve & install."

Next, since our needs are more specific you will need to Opt for the starter pipeline option in the configure tab.

This leads us to customize the provided
azure-pipelines.ymltemplate provided. But before configuring the pipeline we need to set up our Variables which will serve as a secret storehouse for our Docker Hub credentials and GitHub personal access token required in the pipeline.

It's crucial to ensure that the value you use for your
DOCKERHUB_PASSWORDis an access token with both READ and WRITE permissions. You can generate this access token by visiting https://hub.docker.com/settings/security. This token grants your pipeline the necessary privileges to interact with your Docker Hub repository securely.Now, let's get back to your pipeline configuration. Below is a snippet illustrating how your
azure-pipelines.ymlfile should be structured:trigger: - main pool: vmImage: ubuntu-latest name: v$(Rev:r) jobs: - job: LintAndTest displayName: 'Lint and Test React Code' steps: - script: | # Install dependencies npm install --save-dev eslint@7.x eslint-config-airbnb@18.x eslint-plugin-import@2.x eslint-plugin-jsx-a11y@6.x eslint-plugin-react@7.x eslint-plugin-react-hooks@4.x @babel/eslint-parser@7.x @babel/core@7.x @babel/plugin-syntax-jsx@7.x @babel/preset-env@7.x @babel/preset-react@7.x [ -f .eslintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.eslintrc.json [ -f .babelrc ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.babelrc npm install --save-dev stylelint@13.x stylelint-scss@3.x stylelint-config-standard@21.x stylelint-csstree-validator@1.x [ -f .stylelintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.stylelintrc.json # Run ESLint npx eslint . # Run Stylelint npx stylelint "**/*.{css,scss}" - job: BuildDockerImage displayName: 'Build and Push Docker Image' dependsOn: LintAndTest steps: - script: | buildtag="$(Build.BuildNumber)" echo $buildtag # Log in to Docker Hub echo $(DOCKERHUB_PASSWORD) | docker login -u $(DOCKERHUB_USERNAME) --password-stdin # Build Docker image docker build -t $(DOCKERHUB_USERNAME)/todo-app:$buildtag . # Push Docker image to Docker Hub docker push $(DOCKERHUB_USERNAME)/todo-app:$buildtag displayName: 'Build and Push Docker Image' - job: UpdateKubeManifest displayName: 'Update Kubernetes Manifest' dependsOn: BuildDockerImage steps: - script: | # Clone the Kubernetes manifest repository git clone https://$(GITHUB_PAT)@github.com/Joelayo/Week_4-Kubernetes-Manifests.git # Update the image tag in the Kubernetes manifest files buildtag="$(Build.BuildNumber)" cd Week_4-Kubernetes-Manifests sed -i "s/todo-app:.*/todo-app:$buildtag/g" kube-manifest/deployment.yaml # Commit and push changes using GitHub PAT git config user.email "$(GITHUB_EMAIL)" git config user.name "Joelayo" git add . git commit -m "Update image tag to $buildtag" git push origin main displayName: 'Update Kubernetes Manifest'This pipeline configuration automates linting, testing, Docker image creation and pushing, and Kubernetes manifest updates triggered by changes to the
mainbranch of the repository. Once you're done validating the code, save it and then run the pipeline.

With these elements in place, you're well on your way to streamlining your development and integration processes. Stay tuned for the next part of this project series, where we'll delve into continuous deployment with ArgoCD for seamless application updates in your AKS cluster. Thank you for reading!



