GitOps with Kubernetes: Managing Application using GitLab and Argo CD

Adil Shehzad
9 min readApr 9, 2022

Evolution to GitOps

Managing everyday tasks, which include infrastructure configuration and software deployment. Infrastructure configurations mean that computer resources prepare to enable the software application to operate correctly, and software deployment is the process of taking a particular version of a software application and making it ready to run on the computing infrastructure. Managing these two processes is the core of GitOps. Before we dig into how this management is done in GitOps, however, it is useful to understand the traditional Ops and how GitOps is helping us out.

Traditional Ops

In the traditional IT Operations model, the development team is responsible for delivering new versions of a software application to a quality assurance team that tests the new version and then delivers it to an operation team for deployment. It becomes very difficult for a traditional operating model to support an increasingly compressed released cycle.
The operation team is responsible for infrastructure configuration and deployment of new software changes. The operation team’s primary focus is to ensure the reliability resilience and security of the system running the software. This requires a lot of specialized knowledge.


DevOps is both an organizational structure and mindset change with an emphasis on automation. An operations team is no longer responsible for deployment and operations, the application
the development team takes on these responsibilities.

The benefits of DevOps include

  1. Better collaboration between development and operations
    2. Improved product quality
    3. More frequently releases
    4. Reducing time for new features.


GitOps is the operational framework that allows us to take the best practices used for application development to infrastructure automation. In practice, GitOps is achieved by combining Infrastructure as Code(IaC), Git Repositories, PR/MR, and CI/CD Pipelines.

GitHub (along with GitLab, Bitbucket, and so on) is central to the modern software development life cycle, so it seems natural that it is also used for systems operation and management.

Quick Intro: Kubernetes

At the highest level, Kubernetes is the

  1. A Cluster for running application
  2. An Orchestration of cloud-native microservice applications

Masters & Nodes

The Kubernetes cluster is made up of master and nodes. These are the Linux machines that you can host on your on-premise server or public cloud, i.e., AWS.

Masters (Control Plane)

Collection of system services that make up the control plane of the cluster. Let's look at the different services that make up the control plane.

  1. API Server
  2. Cluster Store
  3. The Controller Manager
  4. The Scheduler
  5. The Cloud Control Manager

API Server

API Server is the grand central station of Kubernetes. All communication between all the components goes through the API Server. It exposes a Restful API that you post YAML configuration files to over HTTPS. These YAML files which we sometimes call manifest contain the desired state of your application. Desired states include container image, port to expose, and pod replicas to run.

The Cluster Store(etcd)

The cluster store is only a stateful part of the control plane, and it persistently stores the entire configuration and state of the cluster, As such, it is a vital component of the cluster. The cluster store is currently based on etcd a popular distributed database.

The Controller Manager

The controller manager implements all the background control loops that monitor the cluster and respond to events. It’s a controller of the controller, meaning it spawns all the independent control loops and monitors them.

The Scheduler

At a very high level, the scheduler watches the API Server for new works tasks and assigns them to appropriate health nodes. Behind the scene, it implements the logic that filters out nodes incapable of running the task and then ranks the capable nodes. The ranking system is complex, but the node with the highest-ranking score is selected to run the task.

The Cloud Control Manager

If you are using a cluster on a supported public cloud platform such as AWS, Azure, GCP, etc., your control plane will be running a cloud controller manager. Its job is to manage integrations with underlying cloud technologies and services such as instances, load-balancer, and storage.


Nodes are the workers of a Kubernetes cluster. At a high-level node, do three things:
1. watch the API Server for new work assignments
2. Execute new work assignments
3. Report back to the control plane.


The kubelet is the star of the show on every node. It’s the main Kubernetes agent, and it runs on every node in the cluster. When you join a new node to a cluster, the process installs a kubelet onto the node, the kubelet is responsible for registering the node with the cluster.


The last piece of the node puzzle is Kube-proxy. This runs on every node in the cluster, and it is responsible for local cluster networking. For example, it makes sure each node gets its unique IP address, and IPVS rules to handle routing and load balancing of traffic on the pod network.

Pod & Containers

In the VMware world, the atomic unit of scheduling is the virtual machine. In the docker world, it is a container and in the Kubernetes world, it is the pod. The Kubernetes Pod is a construct for running one or more containers.


Most of the time you will deploy the pod indirectly via a higher controller which includes Deployment, Daemon Set and Statefulsets. For example, a deployment is a higher-level Kubernetes object that wraps around a particular pod and adds features such as scaling, zero downtime during updates, and rollback.


We learned that pods are mortal and can die. If they are managed via deployment or daemons set, they get replaced when they fail. But the replacement comes with totally different IP addresses. This also happens when you perform scaling operations. Scaling up to add new pods with new IP. This is where services come into play. Services Provide reliable networking for a set of Pods.

Installing Kubernetes (MiniKube) on Machine

I am skipping this, as installations guides are already out, and you can follow them accordingly to your operating system. Once you install the minikube on your system, you can use the following command to get your cluster details.

kubectl cluster-info

to get nodes, you can use the following command

kubectl get nodes

Installing Argo CD

Now we need to install the Argo CD to the machine, for this first we need to install an add-on using minikube for this you can use the following command

minikube addons enable ingress

Next, I’m going to install the Argo CD using Helm

Firstly we need to create a new namespace, for this, you can use the following command

kubectl create ns argocd

Go ahead and use the following commands to install Argo CD into your minikube cluster:

kubectl apply -n argocd -f

if help is not installed , please check out the official documentation :

Enable load balancer access in your minikube cluster by running the following command in a separate terminal:

minikube tunnel

Use the following command to open access to the good-server service and get the access URL:

kubectl patch svc argocd-server -n argocd -p ‘{“spec”: {“type”: “LoadBalancer”}}’

Make Sure you have installed ArgoCD CLI , otherwise download from official documentation :

As soon as Argo CD is installed, it has a preconfigured admin user. The initial admin password is autogenerated to be the Pod name of the Argo CD API server that can be retrieved using this command:

kubectl get pods -n argocd -l -o name | cut -d’/’ -f 2

Use the following command to get the Argo CD server URL and update the generated password using the Argo CD CLI:

argocd login <IP>:<PORT>argocd account update-password

URL can be easily gotten from the following URL

minikube service argocd-server -n argocd --url

However, i got the argoCD Password using this command

kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

GitLab Project SetUp

First of all, clone the repository, in this web-app demo it will display a text message and pod name next to it.

Now we need to set up the Repository, for this first we need to generate a token, which can be generated from the GitLab Settings. After token creation, save the token somewhere, now go back to your repository, from the left menu go to settings, CI/CD, and then look for the variables. Now you need to add variables.

  • CI_PUSH_TOKEN — the token
  • CI_USERNAME — the username of the token owner

Argo CD Application Setup

It's time to configure our applications in Kubernetes using GitOps. As I mentioned before, Argo CD comes with Argo CLI and Argo CD GUI. Here are the manifests which configure web apps for dev and prod environments.

The most important parts here are:

  • name — the name of our Argo CD application
  • namespace — must be the same as the Argo CD instance
  • project — project name where the application will be configured (this is the way to organize your applications in Argo CD)
  • repo URL — URL of our source code repository
  • target revision — the git branch you want to use
  • path — The path where Kubernetes manifests are stored inside the repository
  • destination — Kubernetes destination-related things (in this case the cluster is the same where Argo CD is hosted)

Now you need to create a new file and add the manifest to it. Once you have done using the following command to create the web app.

kubectl apply -f argocd.yml

Now, let check on Argo Cd, either our applications are created, for this use the following command

argocd app list

to check the age of both Argocd applications use the following command

-> kubectl get application -n argocd
web-app-dev 40m
web-app-prod 41m

GitLab CI Pipeline

The next step is to create the pipeline, which will automatically build our application, push it to the container registry and update Kubernetes manifests in desired environments.

The idea is, that developers are working on their branches. For each commit and push of their branch, the stage build will be triggered. When they merge their changes with the master branch, the full pipeline will be triggered. It will build the application, containerize it, push an image to the registry and automatically update Kubernetes manifests depending on the stage. In addition, deploying to Prod requires manual action from DevOps. Pipeline definition in GitLab CI is stored in the .gitlab-ci.yml file in the root directory of the project.

How Everything is Working?

The developer needs to push changes to the GitLab repository and this will trigger the Gitlab CI/Cd which will push an image to the GitLab Image Repository and this will be synced by ArgoCD and push changes to the Kubernetes Pods. This is how this workflow is followed.


I hope you learn the concepts of GitOps and its works using different tools. Let me know if you have any questions related to this blog. See you in the next blog.