Implementing GitOps with FluxCD for Kubernetes Applications
This guide provides a clear, standardized process for configuring FluxCD to manage Kubernetes applications using GitOps principles. It automates the deployment of application manifests from a Git repository to a staging namespace, utilizing a streamlined folder structure for simplicity and efficiency. The guide includes practical tests to validate GitOps functionality through an image tag update and pruning via replica adjustments, while preserving local Git integration for robust configuration management. Prerequisites Kubernetes Cluster: A running cluster, such as Kind, Minikube, AKS, or EKS. kubectl: Installed and configured to interact with the cluster. Flux CLI: Installed (e.g., curl -s https://fluxcd.io/install.sh | bash). Git: Installed for managing repositories. GitHub Account: Maintaining two repositories: /flux-config: Stores Flux configurations. /app-repo: Contains application manifests. GitHub Personal Access Token (PAT): Configured with repo scope permissions. Working Directory: /flux-config. Step 1: Set Up the Environment Create Working Directory: mkdir -p /flux-config cd /flux-config Initialize Git Repository: Set up a local Git repository for configuration management: git init git branch -M main Configure GitHub Credentials: Set environment variables for authentication, replacing and with your GitHub credentials: export GITHUB_USER= export GITHUB_TOKEN= Verify Cluster Compatibility: Confirm the cluster is ready for Flux: flux check --pre Expect confirmation of kubectl (version 1.26 or higher), cluster connectivity, and Flux CLI readiness. Resolve issues, such as setting kubeconfig with kubectl config use-context . Step 2: Create Folder Structure The folder structure is minimal, including only critical configuration files, with flux-system/ generated during setup. /flux-config/ ├── .git/ ├── clusters/ │ ├── staging/ │ │ ├── app-repo.yaml │ │ └── apps.yaml ├── flux-system/ (auto-generated) │ ├── gotk-components.yaml │ ├── gotk-sync.yaml │ └── kustomization.yaml Steps: Create directories: mkdir -p clusters/staging Create configuration files: touch clusters/staging/app-repo.yaml clusters/staging/apps.yaml Step 3: Configure Resources Define resources to monitor the application’s Git repository and deploy its manifests. Edit clusters/staging/app-repo.yaml: apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: my-app namespace: flux-system spec: interval: 1m url: https://github.com//app-repo ref: branch: main Instructs Flux to check the repository every minute for changes. Edit clusters/staging/apps.yaml: apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: my-app namespace: flux-system spec: interval: 5m sourceRef: kind: GitRepository name: my-app path: ./kubernetes/manifests prune: true targetNamespace: staging Configures Flux to apply manifests from kubernetes/manifests/ to the staging namespace, with pruning enabled to remove undefined resources, reconciling every five minutes. Step 4: Commit Configurations Add and commit configurations to the local repository: git add clusters/staging/ git commit -m "Add GitRepository and Kustomization for my-app" Step 5: Bootstrap Flux Initialize Flux to deploy its controllers and synchronize configurations with GitHub. Run Bootstrap: flux bootstrap github \ --owner=$GITHUB_USER \ --repository=flux-config \ --branch=main \ --path=clusters/staging \ --personal Creates or updates /flux-config. Installs Flux controllers (e.g., source-controller, kustomize-controller) in the flux-system namespace. Generates flux-system/ with gotk-components.yaml, gotk-sync.yaml, and kustomization.yaml. Pushes configurations to GitHub and sets Flux to monitor clusters/staging/. Verify Setup: Ensure Flux components are running: kubectl get pods -n flux-system Confirm pods like source-controller-... and kustomize-controller-... are active. Step 6: Configure Application Manifests Set up manifests in the application repository to define Kubernetes resources. Clone Application Repository: cd / mkdir temp-app cd temp-app git clone https://github.com//app-repo.git cd app-repo mkdir -p kubernetes/manifests Create kubernetes/manifests/deployment.yaml: apiVersion: apps/v1 kind: Deployment metadata: name: my-app namespace: staging spec: replicas: 1 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: containers: - name: my-app image: nginx

This guide provides a clear, standardized process for configuring FluxCD to manage Kubernetes applications using GitOps principles. It automates the deployment of application manifests from a Git repository to a staging
namespace, utilizing a streamlined folder structure for simplicity and efficiency. The guide includes practical tests to validate GitOps functionality through an image tag update and pruning via replica adjustments, while preserving local Git integration for robust configuration management.
Prerequisites
- Kubernetes Cluster: A running cluster, such as Kind, Minikube, AKS, or EKS.
- kubectl: Installed and configured to interact with the cluster.
-
Flux CLI: Installed (e.g.,
curl -s https://fluxcd.io/install.sh | bash
). - Git: Installed for managing repositories.
-
GitHub Account: Maintaining two repositories:
-
: Stores Flux configurations./flux-config -
: Contains application manifests./app-repo
-
-
GitHub Personal Access Token (PAT): Configured with
repo
scope permissions. -
Working Directory:
/flux-config
.
Step 1: Set Up the Environment
- Create Working Directory:
mkdir -p /flux-config
cd /flux-config
- Initialize Git Repository: Set up a local Git repository for configuration management:
git init
git branch -M main
-
Configure GitHub Credentials:
Set environment variables for authentication, replacing
and
with your GitHub credentials:
export GITHUB_USER=
export GITHUB_TOKEN=
- Verify Cluster Compatibility: Confirm the cluster is ready for Flux:
flux check --pre
- Expect confirmation of
kubectl
(version 1.26 or higher), cluster connectivity, and Flux CLI readiness. - Resolve issues, such as setting
kubeconfig
withkubectl config use-context
.
Step 2: Create Folder Structure
The folder structure is minimal, including only critical configuration files, with flux-system/
generated during setup.
/flux-config/
├── .git/
├── clusters/
│ ├── staging/
│ │ ├── app-repo.yaml
│ │ └── apps.yaml
├── flux-system/ (auto-generated)
│ ├── gotk-components.yaml
│ ├── gotk-sync.yaml
│ └── kustomization.yaml
Steps:
- Create directories:
mkdir -p clusters/staging
- Create configuration files:
touch clusters/staging/app-repo.yaml clusters/staging/apps.yaml
Step 3: Configure Resources
Define resources to monitor the application’s Git repository and deploy its manifests.
-
Edit
clusters/staging/app-repo.yaml
:
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: my-app
namespace: flux-system
spec:
interval: 1m
url: https://github.com//app-repo
ref:
branch: main
- Instructs Flux to check the repository every minute for changes.
-
Edit
clusters/staging/apps.yaml
:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: my-app
namespace: flux-system
spec:
interval: 5m
sourceRef:
kind: GitRepository
name: my-app
path: ./kubernetes/manifests
prune: true
targetNamespace: staging
- Configures Flux to apply manifests from
kubernetes/manifests/
to thestaging
namespace, with pruning enabled to remove undefined resources, reconciling every five minutes.
Step 4: Commit Configurations
Add and commit configurations to the local repository:
git add clusters/staging/
git commit -m "Add GitRepository and Kustomization for my-app"
Step 5: Bootstrap Flux
Initialize Flux to deploy its controllers and synchronize configurations with GitHub.
- Run Bootstrap:
flux bootstrap github \
--owner=$GITHUB_USER \
--repository=flux-config \
--branch=main \
--path=clusters/staging \
--personal
- Creates or updates
./flux-config - Installs Flux controllers (e.g.,
source-controller
,kustomize-controller
) in theflux-system
namespace. - Generates
flux-system/
withgotk-components.yaml
,gotk-sync.yaml
, andkustomization.yaml
. - Pushes configurations to GitHub and sets Flux to monitor
clusters/staging/
.
- Verify Setup: Ensure Flux components are running:
kubectl get pods -n flux-system
- Confirm pods like
source-controller-...
andkustomize-controller-...
are active.
Step 6: Configure Application Manifests
Set up manifests in the application repository to define Kubernetes resources.
- Clone Application Repository:
cd /
mkdir temp-app
cd temp-app
git clone https://github.com//app-repo.git
cd app-repo
mkdir -p kubernetes/manifests
-
Create
kubernetes/manifests/deployment.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: staging
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: nginx:1.14.2
ports:
- containerPort: 80
-
Create
kubernetes/manifests/service.yaml
:
apiVersion: v1
kind: Service
metadata:
name: my-app-service
namespace: staging
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
- Commit and Push:
git add .
git commit -m "Add my-app manifests"
git push origin main
Step 7: Create Namespace
Ensure the staging
namespace is present:
kubectl create namespace staging --dry-run=client -o yaml | kubectl apply -f -
Step 8: Verify Deployment
Confirm Flux has correctly applied the manifests.
- Check GitRepository:
flux get sources git my-app -n flux-system
- Expect
Ready: True
, indicating repository sync.
- Check Kustomization:
flux get kustomizations my-app -n flux-system
- Expect
Ready: True
, confirming manifest deployment.
- Verify Resources:
kubectl get deployments,services -n staging
- Expect a
my-app
deployment (1 replica,nginx:1.14.2
) andmy-app-service
.
Step 9: Test GitOps with Image Tag Update
Validate GitOps by updating the application’s image tag and confirming Flux applies the change.
-
Update Image Tag:
Edit
/temp-app/app-repo/kubernetes/manifests/deployment.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: staging
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: nginx:1.18.0
ports:
- containerPort: 80
- Commit and Push:
cd /temp-app/app-repo
git add kubernetes/manifests/deployment.yaml
git commit -m "Update my-app image to nginx:1.18.0"
git push origin main
- Reconcile (Optional): Accelerate the update:
flux reconcile kustomization my-app -n flux-system
- Verify Update: Inspect running pods:
kubectl get pods -n staging -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[0].image}{"\n"}{end}'
- Expect new pods running
nginx:1.18.0
, with oldnginx:1.14.2
pods terminated.
Step 10: Test Pruning with Replica Adjustment
Ensure pruning maintains the Git-defined state by introducing and correcting a configuration drift.
- Increase Replicas Manually: Modify the deployment:
kubectl scale deployment my-app -n staging --replicas=3
- Verify Increase:
kubectl get deployment my-app -n staging
- Expect 3 replicas.
-
Reconcile:
With
deployment.yaml
specifyingreplicas: 1
, Flux will revert the change:
flux reconcile kustomization my-app -n flux-system
- Verify Pruning:
kubectl get deployment my-app -n staging
- Expect 1 replica, confirming Git state enforcement.
Step 11: Troubleshoot
Address issues to ensure a reliable GitOps pipeline.
-
Bootstrap Issues:
- Verify
GITHUB_TOKEN
hasrepo
scope:curl -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user
. - Confirm network access and repository settings.
- Verify
-
GitRepository Problems:
- Validate repository URL and branch.
- Check status:
kubectl describe gitrepository my-app -n flux-system
.
-
Kustomization Errors:
- Ensure
path: ./kubernetes/manifests
exists inapp-repo
. - Review logs:
kubectl logs -n flux-system -l app=kustomize-controller
.
- Ensure
-
Update or Pruning Failures:
- Confirm
prune: true
inapps.yaml
. - Inspect events:
kubectl describe kustomization my-app -n flux-system
.
- Confirm
FluxCD: Transforming Kubernetes with GitOps
FluxCD redefines Kubernetes application management by leveraging GitOps, DevSecOps, CD pipeline, and DevOps principles. With a compact /flux-config
structure, it automates deployments, ensuring consistency, security, and collaboration for any application.
GitOps: FluxCD establishes Git as the single source of truth, synchronizing manifests from
. Updating an image from/app-repo nginx:1.14.2
to1.18.0
illustrates automated deployment, while pruning replicas from 3 to 1 enforces the declared state, enhancing traceability and control.DevSecOps: Security is integrated through Git’s access controls and Flux’s pull-based synchronization, reducing manual cluster interactions. Declarative configurations enable early validation, supporting DevSecOps’ emphasis on secure development and operations.
CD Pipeline: FluxCD’s continuous polling drives seamless updates, automating changes like image tag updates without manual intervention, accelerating delivery for modern applications.
DevOps: Centralized Git configurations unite development and operations teams, while automated synchronization and pruning minimize operational effort, reflecting DevOps’ focus on collaboration and efficiency.
FluxCD delivers a robust, secure, and automated GitOps framework, empowering teams to manage Kubernetes applications with confidence and precision.