Skip to main content

Command Palette

Search for a command to run...

Configuring Automated Deployment to a Kubernetes Cluster Using GitOps Flux CD

Deploy an application on a Kubernetes Cluster using Flux and GitOps principles

Updated
5 min read

Demonstration video

Step 1: Install Git

sudo apt update && sudo apt install -y git

git --version

git config --global user.name "Your Name"

git config --global user.email "your@email.com"

Step 2: Create a GitHub Repository

Create a GitHub Repository to track all the cluster configuration files.


Step 3: Install the Flux CLI

Run the following command to install flux cli on your node:

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

Check the installation:

flux --version

Step 4: Create a GitHub Personal Access Token

GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)

Click Generate new token (classic), add a note for what the token is for (like homelab-gitops).
Select scopes for: repo and click Generate token. And then Copy the token.

Export the token value as an environment variable in your cluster:

export GITHUB_TOKEN=<token>

Step 5: Install Flux and Its Components Using Flux Bootstrap

Flux can bootstrap itself and link our cluster to our Git repository.

This is how flux bootstrap command works:

  • Uses the GitHub Personal Access Token (PAT) to connect to the GitHub repository.

  • Clones the GitHub repository and switches to the main branch.

  • Generates manifests (YAML files) for all the required Flux components.

  • Commits and pushes the Flux system manifests to the repository at
    clusters/my-cluster/flux-system

  • Installs Flux components in our cluster in the flux-system namespace.

  • Outputs the public key that will be used as the deploy key in the cluster. Flux uses this deploy key to continuously access our repository (instead of the PAT) to pull the state of the cluster.

Run this on cluster:

flux bootstrap github \
  --token-auth=false \
  --owner=<GITHUB_USERNAME> \
  --repository=<REPO_NAME> \
  --branch=main \
  --path=clusters/my-cluster \
  --read-write-key=true \
  --components-extra='image-reflector-controller,image-automation-controller'

Command explanation:
--token-auth=false : this means Flux will Use PAT only once, Create SSH deploy key and Use SSH afterwards.

--owner=<GITHUB_USERNAME> : Specifies the owner of the GitHub repository.

--repository=<REPO_NAME> : The GitHub repository name where Flux will store the GitOps configuration.

--branch=main : Specifies the Git branch Flux will watch and sync from.

--path=clusters/my-cluster : Defines where inside the repo the cluster manifests are located. Flux installs itself using the manifests inside this folder. my-cluster is our cluster name. We can include multiple clusters under the clusters folder.

--read-write-key=true : Write access is required so Flux Image Automation can automatically update image tags in the manifests.

--components-extra='image-reflector-controller,image-automation-controller' : This installs additional Flux controllers which are not installed by default for automatic container image updates.

Verify that Flux components are running:

k get pods -n flux-system

Get the status of the GitRepository sources:

## List all Git repositories and their status
flux get sources git

Step 6: Structure the repository

We'll follow Flux’s recommended repository structure, organizing our files into separate directories for apps, base configurations, environment-specific configurations (staging, production) and infrastructure configurations (configs, controllers).

We'll use the monorepo approach. Run this locally:

git clone <GITHUB_REPO_URL>

cd <REPO_NAME>

## Create the directory structure for applications and infrastructure
mkdir -p apps/{base,staging,production}
mkdir -p infrastructure/{configs,controllers}

Step 7: Deploy an Application using Flux

Let us use GitOps to deploy the mealie application.

We will create several YAML files:

  • namespace.yaml: a dedicated namespace for the application

  • deployment.yaml: kubernetes deployment for the application

  • kustomization.yaml files: Here we'll define resources and configurations for the application

  • apps.yaml: This tells Flux to look at the apps/staging directory

Create a mealie directory for our mealie application at apps/base. Then go to apps/base/mealie directory and create these yaml files:

namespace.yaml :

apiVersion: v1
kind: Namespace
metadata:
  name: mealie

deployment.yaml :

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: mealie
  name: mealie
  namespace: mealie
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mealie
  template:
    metadata:
      labels:
        app: mealie
    spec:
      containers:
      - image: ghcr.io/mealie-recipes/mealie:v3.12.0
        name: mealie
        ports:
        - containerPort: 9000

kustomization.yaml :

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

Now go to the apps/staging directory and create a mealie directory for our mealie application. And under apps/staging/mealie directory create:

kustomization.yaml :

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: mealie
resources:
  - ../../base/mealie

Then Go to clusters/my-cluster directory and create the apps.yaml file.

apps.yaml :

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: apps
  namespace: flux-system
spec:
  interval: 60s
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./apps/staging
  prune: true
  wait: true

Now commit and push these newly created files to our GitHub repo.

git add .
git commit -m "Add mealie application manifests"
git push origin main

Flux will detect these changes and automatically apply the manifests to the cluster.


This is how our repo structure would look like:

clusters/
  my-cluster/
    flux-system/
    apps.yaml

apps/
  base/
    mealie/
      deployment.yaml
      namespace.yaml
      kustomization.yaml
  staging/
    mealie/
      kustomization.yaml
  production/

infrastructure/
  controllers/
  configs/

Let's understand the path Flux follows to deploy our application:

  1. Flux reads the clusters/my-cluster directory.

  2. Finds and applies our apps.yaml file.

  3. The apps.yaml file tells Flux to look at the apps/staging directory.

  4. Finds our Mealie application kustomization file.

  5. Applies the resources we defined in the base configuration.

             apps.yaml   
            
                ▼
            
           apps/staging
               
                ▼
             
             apps/base
  
                ▼
            
          mealie manifests
      (deployment, namespace)

Step 8: Verify that Flux Applied the Application Manifests

After pushing the changes, Flux will pull the updated configuration and apply the resources to the cluster.

Check the Flux Kustomizations:

flux get kustomizations

Also Check the resources created by Flux:

k get ns
k get all -n mealie

If everything worked correctly, you should see the Mealie namespace, Mealie pod and deployment running in that namespace.