Shoulder.dev Logo Shoulder.dev

Managing Stateful Applications with FluxCD

Scenario: A developer, named Alex, wants to manage stateful applications using FluxCD. Alex has a team that manages various applications, and they want to ensure that their applications are always in the desired state. They decide to use FluxCD’s GitOps workflow to manage stateful applications by syncing the desired state from a Git repository.

First, Alex sets up a Git repository for managing the configuration files of their stateful applications. He creates a new directory named stateful-apps and initializes a new Git repository:

$ mkdir stateful-apps
$ cd stateful-apps
$ git init

Next, Alex creates a new directory named my-app inside the stateful-apps directory. He will manage the configuration files for his application, my-app, in this directory.

$ mkdir my-app
$ cd my-app

Inside the my-app directory, Alex creates a new file named my-app-config.yaml that contains the desired state for his application:

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app:latest
ports:
- containerPort: 80

Alex commits and pushes the my-app-config.yaml file to the Git repository:

$ git add my-app-config.yaml
$ git commit -m "Initial commit: my-app configuration"
$ git push origin master

Now, Alex sets up FluxCD to watch the Git repository for changes and sync the desired state to the cluster. He creates a new file named flux-config.yaml in the root directory of the stateful-apps repository:

apiVersion: flux.tools/v1beta2
kind: GitRepository
metadata:
name: my-app-repo
namespace: my-namespace
spec:
url: https://github.com/my-username/stateful-apps.git
branch: master
directory:
path: my-app

---
apiVersion: flux.tools/v1beta2
kind: Kustomization
metadata:
name: my-app-kustomization
namespace: my-namespace
spec:
path: my-app
interval:
minutes: 5

The GitRepository resource tells FluxCD to watch the stateful-apps Git repository for changes, and the Kustomization resource tells FluxCD to apply the configuration files in the my-app directory every 5 minutes.

Alex creates a new file named flux-apply.yaml in the root directory of the stateful-apps repository and applies the configuration:

$ kubectl apply -f flux-config.yaml flux-apply.yaml

Now, whenever Alex makes changes to the configuration files in the Git repository, FluxCD will automatically sync the desired state to the cluster.

Tests:

  1. Verify that the StatefulSet is created and has the desired number of replicas by running:
$ kubectl get statefulsets my-app -n my-namespace
NAME         DESIRED   CURRENT   AGE
my-app       3         3         1m
  1. Make a change to the my-app-config.yaml file in the Git repository, commit and push the change.

  2. Verify that FluxCD syncs the change to the cluster by running:

$ kubectl get statefulsets my-app -n my-namespace -w
NAME         DESIRED   CURRENT   AGE
my-app       3         3         1m
my-app       3         2         1m
my-app       3         3         1m
  1. Verify that the logs in the FluxCD controller show the sync event by running:
$ kubectl logs flux-controller-manager -n flux-system
...
I0623 15:34:59.311333       1 flux.controller.syncer.k8s.io/syncer.go:112] Syncing source git://github.com/my-username/stateful-apps.git -> namespace: my-namespace, path: my-app
I0623 15:34:59.311333       1 flux.controller.syncer.k8s.io/syncer.go:118] Syncing source git://github.com/my-username/stateful-apps.git -> source: my-app/my-app-config.yaml
I0623 15:34:59.311333       1 flux.controller.syncer.k8s.io/syncer.go:125] Applying kustomization patch: my-app/my-app-config.yaml
I0623 15:34:59.311333       1 flux.controller.syncer.k8s.io/syncer.go:131] Syncing source git://github.com/my-username/stateful-apps.git -> source: my-app/my-app-config.yaml -> patch: my-app/my-app-config-patch.yaml
I0623 15:34:59.311333       1 flux.controller.syncer.k8s.io/syncer.go:137] Applying patch: my-app/my-app-config-patch.yaml
I0623 15:34:59.311333       1 flux.controller.syncer.k8s.io/syncer.go:143] Syncing source git://github.com/my-username/stateful-apps.git -> source: my-app/my-app-config.yaml -> patch: my-app/my-app-config-patch.yaml -> manifest: my-app/my-app-manifest.yaml
I0623 15:34:59.311333       1 flux.controller.syncer.k8s.io/syncer.go:150] Applying manifest: my-app/my-app-manifest.yaml
I0623 15:34:59.311333       1 flux.controller.syncer.k8s.io/syncer.go:156] Syncing source git://github.com/my-username/stateful-apps.git -> source: my-app/my-app-config.yaml -> patch: my-app/my-app-config-patch.yaml -> manifest: my-app/my-app-manifest.yaml -> kustomization: my-app/my-app-kustomization.yaml
I0623 15:34:59.311333       1 flux.controller.syncer.k8s.io/syncer.go:162] Applying kustomization: my-app/my-app-kustomization.yaml
I0623 15:34:59.311333       1 flux.controller.syncer.k8s.io/syncer.go:168] Syncing source git://github.com/my-username/stateful-apps.git -> source: my-app/my-app-config.yaml -> patch: my-app/my-app-config-patch.yaml -> manifest: my-app/my-app-manifest.yaml -> kustomization: my-app/my-app-kustomization.yaml -> kustomize: my-app/my-app-kustomize.yaml
I0623 15:34:59.311333       1 flux.controller.syncer.k8s.io/syncer.go:174] Applying kustomize: my-app/my-app-kustomize.yaml
I0623 15:34:59.311333       1 flux.controller.syncer.k8s.io/syncer