Shoulder.dev Logo Shoulder.dev

Getting Started with FluxCD

Scenario: A developer wants to get started with FluxCD and begin managing Kubernetes deployments using its controller. In this example, we will follow the FluxCD getting started guide (https://fluxcd.io/docs/get-started/) to set up a FluxCD controller and configure it to manage a simple application deployment.

First, let’s understand the FluxCD project structure. FluxCD is an open-source GitOps tool for Kubernetes that automates deployments and manages applications. The project consists of various components, including the FluxCD controller, action workflows, and various utilities.

The FluxCD controller is responsible for synchronizing the desired state of your applications with the actual state in your Kubernetes cluster. It achieves this by monitoring your Git repositories for changes and applying the changes to your cluster accordingly.

To get started, we need to install the FluxCD controller in our Kubernetes cluster. However, since we’re assuming the project is already installed, we’ll skip the installation process and focus on managing a simple application deployment.

  1. Create a new directory for our application and initialize a new Git repository:
$ mkdir my-app && cd my-app
$ git init
  1. Create a new file named action.yml in the my-app directory. This file will define the actions that FluxCD should perform when it detects changes in the repository.
apiVersion: flux.tools/v1beta2
kind: GitRepository
metadata:
name: my-app
namespace: my-namespace
spec:
url: https://github.com/username/my-app.git
interval: 30s
ref:
branch: main
path: .
syncPolicy:
automated:
pr: {}
secretRef:
name: my-secret
key: my-token
postSync:
- action:
apiVersion: batch/v1
kind: Job
metadata:
name: my-job
spec:
template:
spec:
containers:
- name: my-container
image: my-image:latest
ports:
- containerPort: 80

This action.yml file defines a Git repository named my-app and sets up a job to be run after a successful synchronization. The job pulls an image named my-image:latest and runs a container listening on port 80.

  1. Commit the action.yml file to the repository:
$ git add action.yml
$ git commit -m "Add FluxCD action for my-app"
  1. Create a new file named flux.sh in the root directory of the project. This script will be used to bootstrap the FluxCD controller and configure it to manage our application.
#!/bin/bash

# Install FluxCD
curl -s https://raw.githubusercontent.com/fluxcd/install/master/install-flux.sh | sh

# Configure FluxCD to manage our application
kubectl apply -f action.yml
  1. Make the flux.sh script executable and run it:
$ chmod +x flux.sh
$ ./flux.sh

This script installs FluxCD using the official installation script and applies the action.yml file to configure it to manage our application.

  1. Verify that FluxCD has successfully synchronized the changes by checking the status of the job:
$ kubectl get jobs my-job -n my-namespace
NAME          TYPE        AGE   STATUS    REASON   RESTARTS   AGE   IP           PORT(S)       NODENAME
my-job        Job        1m    Succeeded  Success  0          1m    <IP-ADDRESS>   80           <NODE-NAME>
  1. Test the application by visiting its IP address in a web browser.

Tests:

To verify the answer, you can perform the following tests:

  1. Check that the FluxCD controller is running and synchronizing changes from the Git repository:
$ kubectl get pods -n flux-system
NAME                                 READY   STATUS    RESTARTS   AGE
flux-controller-gitops-controller-0   1/1     Running   0          10m
  1. Verify that the application is running and accessible:
$ kubectl get pods my-job -n my-namespace
NAME          TYPE        AGE   STATUS    REASON   RESTARTS   AGE   IP           PORT(S)       NODENAME
my-job        Job        1m    Succeeded  Success  0          1m    <IP-ADDRESS>   80           <NODE-NAME>

$ curl <IP-ADDRESS>:80
<HTML output>
  1. Make a change to the action.yml file and verify that FluxCD applies the change to the cluster:
$ git checkout action.yml
$ git commit -am "Update image to version 1.2.3"
$ git push origin main

$ kubectl get pods my-job -n my-namespace
NAME          TYPE        AGE   STATUS    REASON   RESTARTS   AGE   IP           PORT(S)       NODENAME
my-job        Job        2m    Succeeded  Success  0          2m    <IP-ADDRESS>   80           <NODE-NAME>

$ curl <IP-ADDRESS>:80
<HTML output with updated version number>