Guide to Setting Up Flux on Kubernetes

Setting up Flux on Kubernetes is a straightforward process, but you will need a few prerequisites before you start. Flux operates via a CLI that interacts with your cluster and bootstraps itself directly into your Git repository.

Here is the step-by-step guide to installing and setting up Flux.

Prerequisites

Before running any commands, ensure you have:

  1. A Kubernetes cluster (Minikube, EKS, GKE, KIND, etc.) and your kubectl context pointed to it.
  2. A Git Provider account (GitHub, GitLab, Bitbucket) and a Personal Access Token (PAT) with repository read/write permissions.

Step 1: Install the Flux CLI

The Flux CLI is used to bootstrap the cluster and manage your GitOps pipeline.

On macOS / Linux (via Homebrew):

Bash

brew install fluxcd/tap/flux
On Linux (via Bash script):

Bash

curl -s https://fluxcd.io/install.sh | sudo bash
On Windows (via Chocolatey):

DOS

choco install flux

Verify the installation by running:

Bash

flux --version

Step 2: Pre-check Your Cluster

Before installing Flux on your cluster, verify that your Kubernetes environment meets all requirements (like the correct version and API permissions):

Bash

flux check --pre

If everything returns a green checkmark, you are ready to bootstrap!

Step 3: Bootstrap Flux

The bootstrap command is where the magic happens. It performs several actions simultaneously:

  1. Creates a private Git repository if it doesn’t exist (or uses an existing one).
  2. Generates the Flux control plane manifests (deployments, CRDs, etc.).
  3. Commits those manifests to your Git repository.
  4. Configures the cluster to watch that exact folder in Git.
Example for GitHub:

First, export your GitHub personal access token so the CLI can authenticate:

Bash

export GITHUB_TOKEN=ghp_your_actual_token_here

Now, run the bootstrap command:

Bash

flux bootstrap github \
--owner=your-github-username \
--repository=fleet-infra \
--branch=main \
--path=./clusters/my-cluster \
--personal
What just happened?
  • Flux created a repository named fleet-infra on your GitHub account.
  • It installed components like the source-controller and kustomize-controller inside a new namespace called flux-system in your cluster.
  • It configured your cluster to continuously sync with ./clusters/my-cluster in that repository.

Step 4: Verify the Installation

To ensure Flux is up and running inside your cluster, run:

Bash

flux check

You can also use standard kubectl to see the running pods:

Bash

kubectl get pods -n flux-system

Step 5: Deploying Your First App (The GitOps Way)

Now that Flux is watching your repository, never use kubectl apply manually again. To deploy an application, you simply push a manifest to your Git repo.

  1. Clone your newly created repository to your local machine:Bashgit clone https://github.com/your-github-username/fleet-infra.git cd fleet-infra
  2. Create a Kubernetes deployment manifest inside the watched directory (./clusters/my-cluster/podinfo.yaml):YAMLapiVersion: apps/v1 kind: Deployment metadata: name: podinfo namespace: default spec: replicas: 2 selector: matchLabels: app: podinfo template: metadata: labels: app: podinfo spec: containers: - name: podinfo image: ghcr.io/stefanprodan/podinfo:6.0.0 ports: - containerPort: 9898
  3. Commit and push the file:Bashgit add . git commit -m "Add podinfo deployment" git push origin main

Within 5 minutes (or immediately if you run flux reconcile kustomization flux-system), Flux will detect the change and deploy podinfo to your cluster.

Flux uses a dedicated Notification Controller to offload its events natively to external systems. The process works by pairing a Provider (where the alert goes, e.g., Slack/Discord Webhook) with an Alert (which specific cluster actions trigger the notification).

Here is how to set it up for either platform.

Step 1: Create a Kubernetes Secret for your Webhook

First, you need to grab the Webhook URL from your platform:

  • Slack: Create an app in the Slack API console, enable Incoming Webhooks, and create a webhook for your channel.
  • Discord: Go to Channel Settings → Integrations → Webhooks → Create Webhook, and copy the URL.

Once you have the URL, create a Kubernetes secret in the flux-system namespace. Choose one option below:

Option A: For Slack
kubectl create secret generic slack-webhook-url \
--namespace=flux-system \
--from-literal=address=https://hooks.slack.com/services/T0000/B0000/XXXXXX
Option B: For Discord
kubectl create secret generic discord-webhook-url \
--namespace=flux-system \
--from-literal=address=https://discord.com/api/webhooks/123456/XXXXXX

Step 2: Define the Flux Provider

The Provider object points directly to the secret you just created and identifies the backend type. Choose the YAML corresponding to your platform and add it to your cluster (or commit it to your Git repository directory).

Option A: Slack Provider (provider-slack.yaml)
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Provider
metadata:
name: slack-provider
namespace: flux-system
spec:
type: slack
channel: '#devops-alerts' # Optional: overrides default webhook channel
secretRef:
name: slack-webhook-url
Option B: Discord Provider (provider-discord.yaml)
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Provider
metadata:
name: discord-provider
namespace: flux-system
spec:
type: discord
secretRef:
name: discord-webhook-url

Step 3: Define the Flux Alert

The Alert object links your Git repositories and applications to the Provider. It controls what triggers an alert. You can listen for errors only, or all information events.

Create an alert.yaml manifest that references your provider (adjust name: slack-provider to name: discord-provider if needed):

apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
name: cluster-alert
namespace: flux-system
spec:
# 1. Reference the provider you made in Step 2
providerRef:
name: slack-provider # Or discord-provider
# 2. Filter severity: choose 'info' for all updates, or 'error' for failures only
eventSeverity: info
# 3. Choose which resources to listen to ('*' means all resources of this type)
eventSources:
- kind: GitRepository
name: '*'
- kind: Kustomization
name: '*'
- kind: HelmRelease
name: '*'

Apply your chosen provider and alert manifests using kubectl apply -f <filename>.yaml (or push them to Git if you are following standard GitOps flow).

Step 4: Test the Setup

To verify everything works and force an immediate sync event to trigger a chat alert, tell Flux to manually reconcile:

flux reconcile kustomization flux-system --with-source

Within a few seconds, you should see a richly formatted message appear in your chat channel outlining the commit hash, the status, and what components synchronized successfully.

Argo CD vs Flux: Choosing the Right GitOps Tool for Kubernetes

Both Argo CD and Flux implement the GitOps model for Kubernetes:

Git → Desired State → Kubernetes

The biggest difference is their philosophy:

  • Argo CD focuses on application delivery with a rich user experience.
  • Flux focuses on lightweight, Kubernetes-native automation.

For enterprise Kubernetes platforms, both are excellent choices, but they’re optimized for different priorities.


High-Level Architecture

Argo CD
                Git Repository
                      |
          +-----------+-----------+
          |                       |
      Helm Charts            Kustomize
          |                       |
          +-----------+-----------+
                      |
               Argo Repo Server
                      |
             Application Controller
                      |
               Kubernetes API Server
                      |
              Kubernetes Resources

One main controller coordinates deployments.


Flux
             Git Repository
                   |
          Source Controller
                   |
      +------------+------------+
      |            |            |
Kustomize    Helm Controller   Image Controller
Controller
      |            |            |
      +------------+------------+
                   |
          Kubernetes API Server
                   |
          Kubernetes Resources

Flux uses several small controllers that each have a single responsibility.


Feature Comparison

FeatureArgo CDFlux
GitOps
Excellent Web UI⭐⭐⭐⭐⭐⭐⭐
CLIExcellentExcellent
Multi-clusterExcellentExcellent
HelmNativeNative
KustomizeNativeNative
Drift DetectionExcellentExcellent
Automatic ReconciliationYesYes
RollbackEasyGit-based
Progressive DeliveryVia integrations (e.g. Argo Rollouts)Via integrations (e.g. Flagger)
Learning CurveEasierMore Kubernetes knowledge required

User Experience

Argo CD

One of its biggest strengths is its UI.

You can immediately see:

  • Applications
  • Sync status
  • Health status
  • Deployment history
  • Resource tree
  • Live manifest diff

Example:

Payments
✓ Synced
✓ Healthy
Frontend
⚠ OutOfSync
Database
✓ Healthy

Operations teams often like this because troubleshooting is visual.


Flux

Flux has no comparable built-in dashboard.

Most operations use:

  • kubectl
  • flux CLI
  • logs
  • monitoring dashboards

This appeals to teams that already work primarily from the command line.


Deployment Model

Argo CD

Application is the central concept.

Application
|
Git Repository
|
Namespace

One Application usually represents one deployable workload.


Flux

Everything is represented as Kubernetes Custom Resources.

Example:

GitRepository
|
Kustomization
|
Deployment

This feels very “Kubernetes-native.”


Multi-Cluster

Argo CD

A common enterprise architecture:

           Git

            |
      Argo CD Cluster

      /      |      \
 AKS Prod  EKS Dev  OCP QA

One central installation manages many clusters.


Flux

Flux is commonly installed into each cluster:

Git
|
+-----------------------+
| | |
Flux Flux Flux
AKS EKS GKE

Each cluster reconciles itself independently.

This distributed approach reduces dependency on a central control plane.


Security

Both support:

  • Git over SSH
  • HTTPS repositories
  • OIDC
  • Kubernetes RBAC
  • Secret management integrations

Flux has a smaller attack surface because it exposes fewer services.

Argo CD’s UI and API require additional security hardening but provide operational convenience.


Git Repository Structure

Argo CD
apps/
payment/
frontend/
monitoring/
platform/
ingress/
cert-manager/
argocd/
applications/

Flux
clusters/
production/
kustomization.yaml
infrastructure/
applications/
monitoring/

Flux repository layouts often emphasize environment-specific reconciliation.


Progressive Delivery

Argo CD

Frequently paired with:

  • Argo Rollouts

Supports:

  • Canary deployments
  • Blue/Green deployments
  • Automated rollback
  • Traffic shifting

Flux

Frequently paired with:

  • Flagger

Supports similar deployment strategies while remaining GitOps-driven.


Enterprise Operations

Argo CD shines when:
  • Developers want visibility
  • Operations teams prefer a UI
  • Many application teams deploy frequently
  • Platform engineers need simple troubleshooting
  • Management wants deployment dashboards

Common in:

  • Financial services
  • Telecommunications
  • Retail
  • SaaS companies

Flux shines when:
  • Platform engineers prefer declarative Kubernetes resources
  • Automation is prioritized over graphical interfaces
  • Minimal components are desired
  • Teams already manage everything through kubectl

Often chosen by organizations emphasizing Kubernetes-native operations.


Performance

Both scale well into hundreds or thousands of applications.

Flux’s modular controllers can make very large deployments easier to distribute, while Argo CD’s centralized controller simplifies operational visibility. Proper sizing, reconciliation intervals, and repository organization matter more than the choice of tool for most environments.


Which Would I Choose?

Given the types of environments you’ve been working with—OpenShift, AKS, EKS, GKE, enterprise platform engineering, Terraform, and GitOps—I’d generally recommend:

Choose Argo CD if you want:
  • A powerful UI
  • Easier troubleshooting
  • Centralized multi-cluster management
  • A shorter learning curve for application teams
Choose Flux if you want:
  • A highly Kubernetes-native architecture
  • Minimal operational overhead
  • Everything managed as Kubernetes resources
  • GitOps controllers embedded in each cluster

Recommendation for Enterprise Platforms

For organizations running multiple Kubernetes distributions (such as OpenShift, AKS, EKS, and GKE) with many development teams, Argo CD is the more common choice because of its operational visibility, centralized management, and mature ecosystem.

Flux is an excellent alternative when the platform engineering team prefers a fully Kubernetes-native approach and is comfortable operating primarily through Kubernetes APIs and the CLI.

For senior Platform Engineer or Cloud Architect interviews, it’s valuable to understand both tools, but you’ll encounter Argo CD more frequently in enterprise GitOps discussions, while Flux is especially popular in Kubernetes-native and cloud-native platform teams.

Quick Guide to Bootstrapping Flux on Kubernetes

Setting up and bootstrapping Flux on a Kubernetes cluster is best done using the Flux CLI. The bootstrap process is highly elegant: it installs the Flux controllers on your cluster, configures them to watch a specific Git repository, generates an SSH deployment key, and saves its own architecture manifests right back into that Git repository (so Flux becomes self-managing).

Here is the production-ready guide to installing and bootstrapping Flux.

Prerequisites

Before starting, ensure you have:

  1. A running Kubernetes cluster and your local terminal configured with cluster access (e.g., kubectl get nodes works).
  2. A Personal Access Token (PAT) from your Git provider (GitHub, GitLab, Bitbucket) with repository creation and management permissions.

1. Install the Flux CLI

The Flux CLI is used to bootstrap the platform and manage day-to-day operations.

For macOS/Linux (via Homebrew):
brew install fluxcd/tap/flux
For Linux (via Bash Script):
curl -s https://fluxcd.io/install.sh | sudo bash

Verify the Installation:

Ensure the CLI is installed and check if your cluster meets the technical prerequisites:

Bash

flux --version
flux check --pre

2. Export your Git Provider Token

Flux needs your API token to automatically create the Git repository (if it doesn’t exist) and register the secure SSH deploy keys.

For GitHub:

Bash

export GITHUB_TOKEN=ghp_YourPersonalAccessTokenHere
For GitLab:

Bash

export GITLAB_TOKEN=glpat-YourPersonalAccessTokenHere

3. Run the Flux Bootstrap Command

The bootstrap command handles the entire initialization process. Run the command that matches your Git provider.

Option A: Bootstrapping with GitHub

Bash

flux bootstrap github \
--owner=your-github-username-or-org \
--repository=fleet-infra \
--branch=main \
--path=clusters/my-cluster \
--personal

(Note: Remove the --personal flag if you are deploying to a GitHub Organization instead of a personal account.)

Option B: Bootstrapping with GitLab

Bash

flux bootstrap gitlab \
--owner=your-gitlab-username-or-group \
--repository=fleet-infra \
--branch=main \
--path=clusters/my-cluster
What just happened behind the scenes?
  1. Flux connected to your Git account and created a private repository called fleet-infra.
  2. It generated an SSH key pair, saved the private key inside the cluster as a secret, and uploaded the public key as a Deploy Key to your Git repository.
  3. It generated the Kubernetes manifests for the Flux GitOps Toolkit controllers and pushed them directly into your fleet-infra repository under the clusters/my-cluster/flux-system/ path.
  4. It applied those manifests to your cluster, spinning up the flux-system namespace.

4. Verify the Setup

Check your cluster to ensure all the modular micro-controllers are up and running:

Bash

kubectl get pods -n flux-system

Expected Output:

Plaintext

NAME READY STATUS RESTARTS AGE
helm-controller-76797b5bf-mxm44 1/1 Running 0 2m
image-automation-controller-58bf4-x8f4z 1/1 Running 0 2m
image-reflector-controller-7cc89-k4pqp 1/1 Running 0 2m
kustomize-controller-584746f46-j5zdf 1/1 Running 0 2m
notification-controller-7548c-m5w5v 1/1 Running 0 2m
source-controller-557fc77b7-pcc7b 1/1 Running 0 2m

You can also use the Flux CLI to verify that the cluster is successfully tracking your Git repository:

Bash

flux get sources git

5. Your First GitOps Deployment

Now that Flux is installed, you never use kubectl apply manually again. To deploy something, you commit it to Git.

On your local machine, pull down your newly created fleet-infra repository:

Bash

git clone https://github.com/your-username/fleet-infra.git
cd fleet-infra

Create a manifest file for a web server inside your cluster tracking directory (clusters/my-cluster/podinfo.yaml):

YAML

apiVersion: v1
kind: Namespace
metadata:
name: demo
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
namespace: demo
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
Commit and Push to Git:

Bash

git add .
git commit -m "Add demo web server deployment"
git push origin main

Within a minute, Flux’s Source Controller will notice the new commit, and the Kustomize Controller will deploy the Nginx web server into your cluster.

To watch Flux pull the changes immediately without waiting for the next automated polling cycle, run:

Bash

flux reconcile kustomization flux-system --with-source

Deploy ITRS Analytics with Flux: A GitOps Blueprint

To deploy the ITRS Analytics platform (formerly known as Geneos/ITRS Insights or Capacity Planner components) using Flux, you will want to leverage Flux’s native Helm Controller. ITRS packages its platform components as Helm charts, making the HelmRepository and HelmRelease Custom Resource Definitions (CRDs) the best practice for this architecture.

Here is a complete, production-ready GitOps blueprint to deploy the ITRS Analytics stack using a structured, declarative Flux pipeline.

1. Directory Structure

Add the following files to your private GitOps repository under your cluster management path:

Plaintext

├── clusters/production/
│ ├── infrastructure-source.yaml # Points to your Git repo
│ └── itrs-analytics-pipeline.yaml # Ties the Helm Release to the cluster
└── apps/itrs-analytics/
├── helm-repo.yaml # Declares the ITRS Chart repository
├── helm-release.yaml # App configuration, sizing, and values
└── secret-itrs-creds.yaml # (Encrypted/Vaulted) Image pull & license secrets

2. Step-by-Step Manifest Configuration

Step A: Declare the ITRS Helm Repository (apps/itrs-analytics/helm-repo.yaml)

This tells Flux’s Source Controller where to securely pull the official, certified ITRS Analytics charts.

YAML

apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: itrs-charts
namespace: flux-system
spec:
interval: 2h0m
url: https://itrs-group.github.io/helm-charts # Official ITRS repository URL
# If your enterprise agreement requires authenticated chart registry access:
# secretRef:
# name: itrs-registry-credentials
Step B: Define the Deployment and Values (apps/itrs-analytics/helm-release.yaml)

The HelmRelease resource dictates the version, target namespace, and custom application properties (like persistent storage, licensing, and database clustering settings for the analytics engine).

YAML

apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: itrs-analytics
namespace: monitoring
spec:
interval: 15m
chart:
spec:
chart: itrs-analytics # Substitutes with specific sub-component if installing standalone (e.g., obcerv, geneos)
version: '>=1.0.0 <2.0.0' # Safely tracks patches without accidentally breaking major upgrades
sourceRef:
kind: HelmRepository
name: itrs-charts
namespace: flux-system
install:
remediation:
retries: 3
upgrade:
remediation:
retries: 3
# Application-specific values matching ITRS requirements
values:
global:
enterpriseLicenseKey: "ITRS-ANALYTICS-PROD-LICENSE-XYZ"
persistence:
enabled: true
storageClass: "gp3-encrypted" # Or your platform standard (e.g., odf-ceph-rbd)
size: 100Gi
analyticsEngine:
replicaCount: 3
resources:
limits:
cpu: "4"
memory: 8Gi
requests:
cpu: "2"
memory: 4Gi
ingress:
enabled: true
className: openshift-default
hosts:
- host: itrs-analytics.apps.your-company.com
paths:
- path: /
pathType: ImplementationSpecific
Step C: The Orchestration Layer (clusters/production/itrs-analytics-pipeline.yaml)

To apply these manifests cleanly, use a Flux Kustomization resource at the root cluster directory. This tells Flux to evaluate the manifests in the apps/itrs-analytics path and execute them sequentially.

YAML

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: deploy-itrs-analytics
namespace: flux-system
spec:
interval: 10m
path: ./apps/itrs-analytics
prune: true # Ensures if you pull the platform, Kubernetes resources clean up cleanly
sourceRef:
kind: GitRepository
name: flux-system # Assumes the default root Git source created during 'flux bootstrap'
targetNamespace: monitoring

3. Handling Credentials and License Keys Securely

As an Architect/SRE best practice, never store raw credentials or license values directly inside your Git repository. To inject your actual ITRS credentials safely alongside this configuration, use one of the following GitOps-compliant patterns:

  1. Sealed Secrets: Encrypt your raw license secrets into a SealedSecret manifest that can only be decrypted by your target cluster’s controller.
  2. External Secrets Operator (Recommended): Use a Vault provider (HashiCorp Vault, AWS Secrets Manager, CyberArk) and map it using a SecretStore to sync the key directly into the monitoring namespace under the name itrs-registry-credentials.

4. Deploying and Verifying the Fleet

Commit and push your files to your Git control branch. To force Flux to immediately reconcile instead of waiting for the internal timer intervals, run the following command via the Flux CLI:

Bash

flux reconcile kustomization deploy-itrs-analytics --with-source
Verifying the Status

Verify the pipeline health and Helm lifecycle status directly from your terminal:

Bash

# Check that Flux has successfully built the source
flux get helmreleases -n monitoring
# Check the running pods of the platform
kubectl get pods -n monitoring -l app.kubernetes.io/name=itrs-analytics

When successful, your output will show a True condition for READY, indicating that Flux has fully automated the lifecycle management, storage provisioning, and endpoint configurations for your ITRS stack.