Engineering

GitOps Tools: A Hands-On Guide to ArgoCD, FluxCD, and More

April 24, 2025
Ankur Khurana
Neel Punatar

Cloud-native infrastructure is all about performance, adaptability, and resilience– all that GitOps can offer. GitOps is a methodology that applies Infrastructure as a Code (IaC) principles to Continuous Deployment (CD) and operations. Before GitOps, IaC existed independently. 

GitOps follows a declarative approach where it uses Git as a single source of truth— meaning Git serves as an authoritative and version-controlled repository for all infrastructure and application deployments.  It also improves deployment speed and reliability a lot– as much as 50% reduction in deployment time. 

Before GitOps, deployments were often prone to configuration drifts, security risks, and complex rollbacks due to undocumented manual updates such as ad-hoc hotfixes or direct changes through the cloud’s console. More problems arose when companies had to scale their project across multiple clusters, requiring ad-hoc scripts and workarounds. 

Gitops tools

GitOps is not an experimental trend now–it's a widely adopted best practice for cloud-native infrastructure, automating deployments and regulating consistency. GitOps tools like ArgoCD, FluxCD, and Jenkins X make implementing GitOps easier, helping organizations deploy infrastructure scale Kubernetes workloads efficiently while maintaining full control.

Understanding GitOps Tools & Their Core Principles

The GitOps method stores application and infrastructure as code in Git repositories, which automation tools implement for target environment deployment. 

GitOps strongly recommends version control, which enables a complete and transparent audit trail of all changes for people who have permission to review.

Let’s understand the major principles that GitOps works on:

  • Declarative Infrastructure as Code (IaC)
  • Automated Reconciliation: Continuous Sync with the Cluster
  • Drift Detection & Automated Rollbacks
  • Flexibility & Security

GitOps vs Release Management?

Many developers often confuse GitOps with release management. While GitOps automated deployments, release management involves approvals, progressive rollouts, and governance - areas where enterprise tools like Spinnaker shine. GitOps and release management complement each other rather than compete.

Prerequisite: Setting Up Kubernetes in Docker Desktop

To get started, let’s make sure that you have Docker on your system. We are using Kubernetes in Docker; you can also use minikube along with Docker. Also, Docker Desktop has a built-in Kubernetes feature, so you don’t need Minikube.

For enabling GitOps Kubernetes in Docker Desktop:

  • Open your Docker Desktop.
  • Click on Settings and then go to Kubernetes. Here, enable the toggle and then click on the ‘Apply and Restart’ button. 
  • Wait for some time and use the command kubectl cluster-info to check if it’s running.

Output:

kubectl cluster-info
Kubernetes control plane is running at https://127.0.0.1:6443 CoreDNS is running at https://127.0.0.1:6443/api/v1/namespaces/kube-system/services/kube-dns dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. echoindia@ECHOs-MacBook-Air-

Setting Up GitOps with ArgoCD

ArgoCD is one of the best GitOps tools that provides users with a UI-driven approach to automate Kubernetes deployments. It does this by continuously syncing Git with the cluster. You can use Helm, Kustomize and raw YAML, which makes it quite flexible even for complex deployments.  Let’s have a look at how to set up ArgoCD GitOps platform

Step 1: Install ArgoCD

Now that you have your kubernetes running, the first thing is to install the ArgoCD. You can either apply the manifest directly or use Helm ( better version control).

  • Option 1: Install ArgoCD using Helm Chart

Helm provides better customization and flexibility. For using ArgoCD helm chart, you need to use the following commands:

helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
helm install argocd argo/argo-cd --namespace argocd --create-namespace

  • Option 2: Install ArgoCD using YAML Manifests

Open your terminal and then copy this command:

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

Output:

kubectl create namespace argocd kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifest
s/install.yaml

namespace/argocd created customresourcedefinition.apiextensions.k8s.io/applicationsets.argoproj.io created customresourcedefinition.apiextensions.k8s.io/appprojects.argoproj.io created serviceaccount/argocd-application-controller created

customresourcedefinition.apiextensions.k8s.io/applications.argoproj.io created
serviceaccount/argocd-applicationset-controller created
serviceaccount/argocd-dex-server created
serviceaccount/argocd-notifications-controller created
serviceaccount/argocd-redis created serviceaccount/argocd-repo-server created
serviceaccount/argocd-server created role.rbac.authorization.k8s.io/argocd-application-controller created role.rbac.authorization.k8s.io/argocd-applicationset-controller created role.rbac.authorization.k8s.io/argocd-dex-server created role.rbac.authorization.k8s.io/argocd-notifications-controller created role.rbac.authorization.k8s.io/argocd-redis created

You can verify if it’s installed properly. Just run this command: kubectl get pods -n argocd

If the pods aren’t in Running state, check their logs and describe the pod to address the issue:

kubectl logs -n argocd <pod-name>
kubectl describe pod -n argocd <pod-name>

Here, you have to change the <pod-name> with your pod.

Step 2: Post Forward ArgoCD Server

Now, we will expose the ArgoCD UI by running the following command:

kubectl port-forward svc/argocd-server -n argocd 8080:443

You can use any other port. The port will start running at https://localhost:8080, and you can access the ArgoCD UI at this port.

Note: This method only exposes the UI locally. For production environments, it is recommended to set up Ingress or LoadBalancer services instead of relying on port forwarding.

Output:

kubectl port-forward svc/argocd-server -n argocd 8080:443
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
Handling connection for 8080
Handling connection for 8080

Gitops tools

Step 3: Get the Initial Admin Password

Your port is running successfully, but you need to log in to the ArgoCD UI. You can get the password by using this command in your terminal:

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

Use admin as the username and this password to log in. The UI will look something like this:

Gitops tools

You can connect your git repo and then get started after this. 

Gitops tools

Step 4: Create your App and Make your First Deployment with ArgoCD

With Argo CD successfully set up, you can now create and deploy your applications using declarative GitOps principles. Define your application manifests in a Git repository, connect it to Argo CD, and automate deployments seamlessly.

Setting Up GitOps with FluxCD

If you want ArgoCD alternatives that are more lightweight than FluxCD is the one. FluxCD follows a pull deployment model that helps to reduce external access to the cluster, improving security. However, FluxCD still needs some access mechanisms like Webhook Triggers.  Let’s see how you can set up FluxCD:

Important prerequisites other than Kubernetes:

  • A GitHub repository – This is for storing and managing Kubernetes manifests.
  • GitHub Personal Access Token (PAT) – With repository access for authentication.

Step 1: Installing Flux CLI

To get started, we will need GitOps Flux CLI installation first.  I am using MacOS here; you can see other commands too:

For macOS (Homebrew)

brew install fluxcd/tap/flux

For Linux

curl -s https://fluxcd.io/install.sh | sudo bash

For Windows (Using Chocolatey)

curl -s https://fluxcd.io/install.sh | sudo bash
choco install fluxcd

For checking if Flux CLI is successfully installed, use flux --version

Output:

brew install fluxcd/tap/flux
==> Auto-updating Homebrew... Adjust how often this is run with HOMEBREW_AUTO_UPDATE_SECS or disable with HOMEBREW_NO_AUTO_UPDATE. Hide these hints with HOMEBREW_NO_ENV_HINTS (see man brew').
==> Homebrew collects anonymous analytics.


Read the analytics documentation (and how to opt-out) here: https://docs.brew.sh/Analytics No analytics have been recorded yet (nor will be during this 'brew' run).

==> Homebrew is run entirely by unpaid volunteers. Please consider donating: https://github.com/Homebrew/brew#donations
==> Auto-updated Homebrew! Updated 1 tap (homebrew/core).
==> New Formulae cloudfoundry-cli


You have 6 outdated formulae installed.

Tapping fluxcd/tap
Cloning into '/opt/homebrew/Library/Taps/fluxcd/homebrew-tap'
remote: Enumerating objects: 690, done.
remote: Counting objects: 100% (229/229), done. remote: Compressing objects: 100% (146/146), done.
remote: Total 690 (delta 119), reused 170 (delta 83), pack-reused 461 (from 1) Receiving objects: 100% (690/690), 104.93 KiB | 1.69 MiB/s, done.
Resolving deltas: 100% (342/342), done. Tapped 7 formulae (22 files, 156.5KB).
==> Fetching fluxcd/tap/flux

Step 2: Bootstrap Flux into Your Kubernetes Cluster

Next, we need to set up the environment variables for GitHub authentication. For this, you need to copy these commands and paste into your terminal:

You have to change the <your-token> and <your-github-username> with yours respectively.

export GITHUB_TOKEN=<your-token>
export GITHUB_USER=<your-github-username>

Now, bootstrap Flux will connect with your GitHub repository. Use this command:

flux bootstrap github \
  --owner=$GITHUB_USER \
  --repository=FluxCD \
  --branch=main \
  --path=fluxCdCluster \
  --personal

Output:

flux bootstrap github --owner=shiw0712echo
--repository=ArgoCD --branch=main
--path=clusters/my-cluster -personal
connecting to github.com
cloning branch "main" from Git repository "https://github.com/shiw0712echo/ArgoCD.git"
cloned repository generating component manifests
generated component manifests
committed component manifests to "main" ("6ad6d413993ac2952ff97566569c3e378e6bf509") pushing component manifests to "https://github.com/shiw0712echo/ArgoCD.git

The path here is the location of your yaml files. You can create your own directory and use that in this path. This command will install Flux system components in Kubernetes and start syncing configurations from your Git repo. 

Step 3: Configure Git Repository Source

We’ll need a git repository definition to fetch the manifest from your repo. For this, you need to create a gitrepository.yaml file inside your repository. 

I’m using my repo FluxCD to carry this out. 

apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: FluxCD
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/shiw0712echo/ArgoCD.git
  ref:
    branch: main
  secretRef:
    name: flux-system

Change the name and the URL of your github repo. 

Note: If your repo is private, We need a secret for authentication. The secretRef can be removed if your repo is public.

Create it using this command:

kubectl create secret generic flux-system \
  --namespace=flux-system \
  --from-literal=username=<your-github-username>
\
  --from-literal=password=<your-github-token>

Replace <your-github-userName> and <your-github-token> with your own github username and github token here. 

Output:

kubectl create secret generic flux-system
--namespace=flux-system --from-literal=username=shiw@712echo
--from-literal=password=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
secret/flux-system created

Step 4: Define Kubernetes Manifests in GitHub

Next, we need to define the Kubernetes manifest in our github repository. We do this because Flux applies Kubernetes configurations stored in a Git repo. Let’s see how to organize the structure accordingly.

Now you need to define Kustomization, service, and example deployment inside the path=fluxCdCluster  as defined earlier.

  • Create service.yaml file:

apiVersion: v1
kind: Service
metadata:
  name: flux-app
  namespace: default
spec:
  selector:
    app: flux-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP

  • Create deployment.yaml file:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flux-app
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: flux-app
  template:
    metadata:
      labels:
        app: fluxCd-app
    spec:
      containers:
      - name: flux-app        image: nginx
        ports:
        - containerPort: 80

Commit these changes and push it to your git repo. Next, we’ll create a Kustomization resource that tracks and applies the manifests. 

  • Kustomization.yaml file

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - service.yaml

Now, you need to apply this configuration:

kubectl apply -f kustomization.yaml

Check if Flux is successfully connected to your repo. Use this command:

flux get kustomizations

Output:

NAME REVISION SUSPENDED READY MESSAGE
my-app-kustomization main@sha1:c9dcaa50 False True Applied revision: main@sha1:c9dcaa50

If your output shows READY=True, then your connection is successful. 

Step 5: Verify Deployment

To check if your connection is successful, check if the pods are running:

kubectl get pods -A

Output:

NAMESPACE NAME READY STATUS AGE
flux-system helm-controller-69bdd59d4c-t55vn 1/1 Running 7m
flux-system kustomize-controller-66877fbf9-6561 1/1 Running 7m
flux-system notification-controller-6cf45ccc8-dwjk2 1/1 Running 7m
flux-system source-controller-777974d9ff-fatos 1/1 Running 7m
kube-system coredns-7c65d6cfc9-drznj 1/1 Running 7685s
kube-system coredns-7c65d6cfc9-snapd 1/1 Running 172m
kube-system etcd-docker-desktop 1/1 Running 172m

Now check the service:

kubectl get svc

If the pod is running, Flux CD has successfully deployed your application. 

Output:|

Services

NAME TYPE CLUSTER-IP PORT(S) EXTERNAL-IP AGE
kubernetes ClusterIP 10.96.0.1 443/TCP <none> 3h11m
my-app-service ClusterIP 10.103.209.176 80/TCP <none> 19m

Deployments

NAME READY UP-TO-DATE AVAILABLE AGE
my-app 2/2 2 2 21m


kubectl port-forward svc/my-app-service 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
Handling connection for 8080
Handling connection for 8080

Your service is of type ClusterIP i.e, it is accessible only inside the cluster. So, you need to port-forward it to access it from your local machine:

Use this command: 

kubectl port-forward svc/fluxCD-app 8080:80

You can change the port number as per your preference. Now open your browser and visit http://localhost:8080. If your application is running, you’ll see the UI or the response like this : 

nginx Gitops tools

You have now successfully set up FluxCD and deployed your first application!

Setting Up GitOps with Jenkins X

Jenkins X is primarily a CI/CD tool that uses GitOps, automating both deployments and environment promotions via Git. It focuses more on CI/CD workflows and integrates with Tekton pipelines, creating preview environments for pull requests and reducing manual interventions, making it a great choice for teams needing full GitOps automation. Let’s see how to set it up.

Step 1: Install Jenkins X

To install the latest version of Jenkins X, use this command in your terminal:

  • MacOs

brew install --no-quarantine --cask jenkins-x/jx/jx

  • Linux

curl -L https://github.com/jenkins-x/jx/releases/download/v3.11.52/jx-linux-amd64.tar.gz | tar xzv
chmod +x jx
sudo mv jx /usr/local/bin

  • Windows

Click on this link (downloading a binary).

Then, copy the jx binary to any directory of your choice on your $PATH.

You can check it by using the command jx version. 

Output:

version: 3.11.52
shaCommit: 83bca73eb044c9114aaca12854d789e5676049c2
buildDate: Wed Feb 19 15:37:33 UTC 2025
goVersion: 1.23.2
branch: main
gitTreeState: clean

Step 2: Install Git Operator

Since we are using Jenkins X 3.x, it uses a git operator that manages all the installing and upgrading of Jenkins X or any other environment components. 

jx admin operator

This will:

  • Install Jenkins X components in your Kubernetes cluster.
  • Set up GitOps Pipelines for CI/CD.

Make sure you have a Github token. If not, please generate one from here

Output:

git clone URL is https://github.com/shiw0712echo/JenkinsXCreate.git
now verifying we have a valid git username and token so that we can clone the git repository inside kubernetes…
? Enter Bot Git username the Kubernetes operator will use to clone the environment git repository shiw0712echo
WARNING: validation failures in YAML file /Users/echoindia/Desktop/ArgoCD/jenkins-x-boot-config/JenkinsXCreate/jx-requirements.ym

1: (root): Additional property gitops is not allowed, cluster: Additional property gitUrl is not allowed To work with git provider https://github.com we need an API Token Please click this URL and generate a token
https://github.com/settings/tokens/new?scopes=repo,read:user,read:org,user:email,admin:repo_hook,delete_repo,write:packages,read:
packages,write:discussion,workflow
Then COPY the token and enter it below:
? Enter Bot Git token the Kubernetes operator will use to clone the environment git repository [? for help] ************ git username is shiw0712echo for URL https://github.com/shiw0712echo/JenkinsXCreate.git and we have a valid password running command:

/Users/echoindia/.jx3/plugins/bin/helm-3.6.2 upgrade --install \
-set url=https://github.com/****/JenkinsXCreate.git \
-set username=**** \
-set password=**** --namespace jx-git-operator --create-namespace jxgo jxgh/jx-git-operator

waiting for the Git Operator to be ready in namespace jx-git-operator... pod jx-git-operator-7565dc5649-wq77j has status Pending pod jx-git-operator-7565dc5649-wq77j has status Ready the Git Operator is running in pod ix-ait-operator-7565dc5649-wa77÷
waiting for boot Job pod with selector app=ix-boot in namespace ix-qit-operator…

Now, to check if the installation is successful, let’s verify it using the command: kubectl get pods -n jx

If it's in Running Status, then we are good to go. 

Gitops tools

Step 4: Access Jenkins X

To launch the Jenkins X UI in our browser, we need to run our next command:

jx UI

If the UI doesn’t open, check the port and forward it. Then, access http://localhost:8080 in your browser.

kubectl port-forward svc/jx-pipelines-visualizer 8080:80 -n jx

Step 5: Create & Deploy a Project

We have installed and run Jenkins X UI successfully. You can now create your projects and deploy them easily. Jenkins X automates CI/CD pipelines for your applications. Use this command to create a new project:

jx project create

Follow the on-screen prompts to set up a Git repository and initialize a project.

Then, to deploy a sample app:

jx create quickstart

This action will generate the code, push it to GitHub, and trigger an automated CI/CD pipeline. You are good to go now!

Best Practices for Production Deployments

When you're setting up GitOps tools, you also have to ensure that it's free from any vulnerabilities.

This keeps the system protected and helps us scale our product whenever needed. Here are some GitOps best practices that should be followed for production deployments: 

Security

GitOps workflows need strong security measures. Teams should implement RBAC in ArgoCD and FluxCD to ensure that users have only the necessary permissions. Some more security measures that teams can use are:

  • Git commit signing (GPG)- to verify code authenticity, preventing unauthorized access.
  • SOPS (Secrets OPerationS), Sealed Secrets, or HashiCorp Vault- to encrypt sensitive data
  • Kubernetes NetworkPolicies- for network security enforcement to restrict pod-to-pod communication.
  • Audit Logging- to track all changes and track suspicious activity in deployments. 

Flexibility 

It's obvious that the infrastructure will grow at some point. As this happens, it becomes important to manage multiple clusters and teams efficiently. You can use ArgoCD’s ApplicationSet or FluxCD’s Cluster API to automate multi-cluster deployments. 

And for multi-tenancy and multiple environments, teams can enforce namespace-based RBAC and make use of kustomize overlays to manage environment-specific configurations.

Monitoring

Workability depends on how well you can monitor your GitOps system. Connect Prometheus and Grafana to monitor deployment status and detect both system health problems and syncing difficulties instantly. 

ArgoCD will send you notifications through Slack, Teams, or email to fix deployment problems immediately. You can trace and resolve system problems better through gathered data stored in Elasticsearch or Loki services.

Now, tools like ArgoCD and FluxCD automate deployments and enforce consistency, but they also introduce a lot of friction. Making even a small change - like adjusting resource limits, updating an environment variable, or scaling replicas - often means modifying your YAML configurations, committing changes to Git, and waiting for reconciliation. This works well for large-scale deployment automation, but it slows DevOps teams down when they need quick, controlled updates without breaking any GitOps workflows.

Kapstan: A Much More Simpler Way to Manage Your GitOps Deployments

Kapstan bridges this gap. Instead of forcing developers and DevOps engineers to interact solely through Git and Kubernetes manifests, it provides a UI-driven experience that automates deployments, scaling, and configuration management, all while keeping Git as the source of truth. It doesn’t replace ArgoCD or FluxCD but simplifies everyday operations, allowing teams to move faster without bypassing any GitOps principles.

The process of deploying a containerized service with Kapstan is pretty simple. Instead of writing YAML or scripting kubectl commands, a service can be created directly from the Kapstan’s UI. 

The user starts by selecting Container Service, entering details like the image repository, tag, and optional startup commands, and clicking Confirm. 

Gitops tools

Unlike traditional GitOps tools, where changes need to be committed and reconciled separately, Kapstan applies configurations automatically while still maintaining version control.

Gitops tools

Once the container service is defined, scaling and resource allocation are just as easy. Kapstan allows teams to configure CPU limits, memory allocation, and scaling preferences without modifying Kubernetes manifests. Users can choose manual scaling or enable auto-scaling, ensuring workloads adjust dynamically based on demand. Readiness and liveness probes can also be configured directly in the UI, helping ensure smooth rollouts without editing YAML configuration files.

Gitops tools

With everything configured, deployment is just one click away. Kapstan provides the service, applies GitOps-friendly changes, and immediately provides monitoring insights. Logs, metrics, and deployment history are accessible in the same interface, reducing the need to switch between multiple tools. If an update is needed, changes can be applied through the UI and automatically synced to Git, ensuring the GitOps model remains intact without unnecessary complexity.

Gitops tools

For teams that want GitOps without constant YAML interaction, Kapstan is a practical alternative. It enables developers to self-serve deployments and configurations while maintaining governance and security. Instead of slowing down operations with manual Git commits for every small change, teams can move fast while still keeping GitOps principles intact. It’s not about replacing ArgoCD or FluxCD - it’s about making them more usable for day-to-day work.

To learn more about Kapstan’s capabilities, check out its documentation.

Conclusion

GitOps tools like ArgoCD, FluxCD, and others have revolutionized infrastructure and application management by enabling continuous delivery of automated, version-controlled deployments. By leveraging Git as the single source of truth, these tools ensure consistency, security, and scalability in modern DevOps workflows.

Frequently Asked Questions 

  1. What is the major advantage of GitOps?

The major advantage of GitOps is that it provides a declarative and automated approach to infrastructure management and application management, ensuring consistency, reliability, and easy rollbacks using Git as the single source of truth.

  1. What is GitOps vs DevOps?

GitOps is a subset of DevOps that focuses on using Git as the central control mechanism for managing infrastructure and deployments, while DevOps is a broader practice that combines development and operations to streamline the software development lifecycle and delivery.

  1. What are the three core practices of GitOps?

The three core practices of GitOps are declarative infrastructure configuration (defining infrastructure as code), version control with Git (storing all changes in Git), and automated reconciliation (ensuring the actual state matches the desired state).

  1. Is GitHub Actions GitOps?

GitHub Actions can be part of a GitOps workflow but is primarily a CI/CD automation tool. GitOps requires continuous reconciliation, which is typically handled by tools like ArgoCD or Flux.

  1. Is GitOps a CI/CD tool?

No, GitOps is a methodology, not a tool. It leverages CI/CD tools but focuses on declarative configuration and automated reconciliation to maintain the desired state of infrastructure and applications.

  1. Can I use GitOps for non-Kubernetes environments?

Yes, while GitOps is widely used for Kubernetes, it can also be applied to non-Kubernetes environments, such as cloud native applications managing cloud infrastructure, databases, or VMs, using tools like Terraform or Pulumi.

Ankur Khurana
Principal Engineer @ Kapstan. Ankur brings over ten years of expertise in designing and constructing complex systems. He prefers to solve problems by applying first principles and enjoys exploring emerging technologies.

Simplify your DevEx with a single platform

Schedule a demo