Kubernetes GitOps with FluxCD - Part 1 - Initial Setup

Table of Contents

GitOps practice enables us to define our infrastructure as code in a declarative manner. It serves as an audited single source of truth for our cloud/cluster state, providing benefits like:

  • Version control and audit trails for infrastructure changes
  • Automated reconciliation between desired and actual states
  • Improved security through encrypted credentials and access control
  • Simplified rollback capabilities
  • Enhanced collaboration through Git workflows

FluxCD is a CNCF graduated project that enables GitOps practices in the Kubernetes ecosystem. It automates the deployment, monitoring, and reconciliation of cluster resources based on Git repositories.

This post covers the initial setup and core functionality of FluxCD in a Kubernetes cluster.

1. Setup Git dependencies

Lets start by creating git repository in Github.

Next, we need to generate a fine-grained access token that FluxCD will use to interact with our repository. These tokens provide more granular control over repository permissions compared to classic personal access tokens.

We’ll keep Read and write permission for Administration, Contents access and Read-only for Metadata access limited to repository we created above and permissions as recommeded by official FluxCD documentation for this initial setup.

2. Setup Flux CLI

Lets start by installing FluxCD cli

sudo zypper in flux2-cli

Next step is to export github token and user details variables.

export GITHUB_TOKEN=******
export GITHUB_USER=*****

For this post we are using locally VM hosted k3s cluster, lets check if we have access to same with kubectl.

# 1. Point to specific cluster we are setting up
export KUBECONFIG=~/.kube/local.config
# 2. Check for access and version
kubectl version

Let’s check same with Flux cli if it has access as well.

flux check --pre

3. Bootstrap FluxCD

We are going to install all components including extra for image automation.

flux bootstrap github \
    --owner=$GITHUB_USER \
    --repository=k8s-gitops \
    --branch=main \
    --path=./cluster/default \
    --read-write-key \
    --components source-controller,kustomize-controller,helm-controller,notification-controller \
    --components-extra image-reflector-controller,image-automation-controller \
    --personal

Lets verify Flux setup step by step.

  1. Bootstrap has created one deployment key in Github repository and stored as flux-system/flux-secret

Let’s verify deployment key in Github

Let’s verify secret with kubectl -n flux-system get secrets

  1. Flux has initialized the repository with initial commit having definition of components at cluster/default as specified bootstrap command.

  1. FluxCD reconclided with Git repository and installed the components in flux-system namespace, lets verify same with kubectl

4. Verify installation

Lets verify our installation by creating a sample deployment.

apps/nginx/deployment.yaml

apiVersion: apps/v1
metadata:
  name: nginx-deployment
  namespace: default
kind: Deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "50m"
          limits:
            memory: "64Mi"
            cpu: "50m"

apps/nginx/kustomization.yaml

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

cluster/default/nginx.yaml

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: nginx
  namespace: flux-system
spec:
  interval: 5m
  path: ./apps/nginx
  prune: true
  retryInterval: 2m
  sourceRef:
    kind: GitRepository
    name: flux-system
  targetNamespace: default
  timeout: 3m
  wait: true

The Kustomization resource has several important fields:

  • interval: How often Flux should reconcile this resource (5m = 5 minutes)
  • path: Directory containing the Kubernetes manifests
  • prune: Whether Flux should delete resources that are no longer defined in Git
  • retryInterval: How long to wait between retries if reconciliation fails
  • wait: Whether Flux should wait for resources to be ready before completing reconciliation
  • timeout: Maximum time to wait for reconciliation

Lets push these changes and wait for reconciliation to finish.

Lets verify if nginx is deployed

5. What if

One of the core goals of GitOps is ensuring that our cluster’s state always matches the resources defined in our git repository. This continuous reconciliation process is what makes GitOps powerful for maintaining system consistency.

To demonstrate this functionality, we’ll delete our nginx deployment using kubectl and observe how Flux’s reconciliation process automatically restores it to the desired state defined in Git. This showcases the “self-healing” capability of the GitOps approach.

In screen above:

  1. First step is to verify the deployment with kubectl get deployments to check if nginx is up and running
  2. Second step is to delete deployment with kubectl delete deployment/nginx-deployment
  3. 3rd step to confirm nginx deployment is deleted with kubectl get deployment
  4. 4th step is to watch over FluxCD reconciliation to kick in
  5. 5th step to verify that nginx is re-deployed post Flux’s reconciliation

What next ?

Future posts will explore advanced GitOps patterns with FluxCD, including:

  • Helm chart automation
  • Image update automation
  • Notification and alerting configuration
  • Secrets management with SOPS

Stay tuned for each of these topics.

References