Streamlined Application Deployment in Kubernetes with Flux and GitOps
Why Flux ?
Flux is an open-source continuous delivery and GitOps automation tool designed for Kubernetes. It facilitates the automated deployment and management of applications within a Kubernetes cluster. Flux operates on the principle of GitOps, which means it uses Git repositories as the source of truth for defining the desired state of your cluster.
Here’s how Flux works:
- Desired State in Git: You define the desired state of your Kubernetes cluster by storing YAML manifests (such as deployment configurations, services, etc.) in a Git repository.
- Continuous Synchronization: Flux continuously monitors this Git repository for changes. Whenever it detects a new commit, it automatically synchronizes the state of your Kubernetes cluster with the state defined in the repository.
- Automated Deployments: If there are any changes in the Git repository, Flux will apply those changes to the cluster. It can handle tasks like deploying new versions of applications, scaling services, and managing other Kubernetes resources.
- Automated Rollbacks: If there are any issues with the new deployment, Flux can automatically rollback to the previous known good state, ensuring a reliable and consistent cluster.
- Observability and Feedback: Flux provides observability features, allowing you to monitor the deployment process, track revisions, and view deployment history.
Source Controller:
The main role of the source management component is to provide a common interface for artifacts acquisition. The source API defines a set of Kubernetes objects that cluster admins and various automated operators can interact with to offload the Git and Helm repositories operations to a dedicated controller.
Kustomize Controller:
The kustomize-controller is a Kubernetes operator, specialized in running continuous delivery pipelines for infrastructure and workloads defined with Kubernetes manifests and assembled with Kustomize.
Helm Controller:
The Helm Controller is a Kubernetes operator, allowing one to declaratively manage Helm chart releases with Kubernetes manifests.
The desired state of a Helm release is described through a Kubernetes Custom Resource named HelmRelease
. Based on the creation, mutation or removal of a HelmRelease
resource in the cluster, Helm actions are performed by the controller.
Notification controller:
The Notification Controller is a Kubernetes operator, specialized in handling inbound and outbound events.
The controller handles events coming from external systems (GitHub, GitLab, Bitbucket, Harbor, Jenkins, etc) and notifies the GitOps toolkit controllers about source changes.
The controller handles events emitted by the GitOps toolkit controllers (source, kustomize, helm) and dispatches them to external systems (Slack, Microsoft Teams, Discord, Rocker) based on event severity and involved objects.
Flux brings several benefits to Kubernetes environments:
- Version Control: Using Git as the source of truth ensures that all changes are tracked, providing a clear history of deployments.
- Automation and Efficiency: Flux automates the deployment process, reducing the manual effort required to manage applications.
- Consistency and Reliability: GitOps principles ensure that the cluster state is always aligned with the desired state, minimizing drift and errors.
- Rollback Capabilities: Flux enables easy rollbacks in case of deployment issues, improving resilience.
Objectives of this article
- Bootstrap Flux on a Kubernetes Cluster.
- Deploy a sample application using Flux.
Install the Flux CLI
The flux
command-line interface (CLI) is used to bootstrap and interact with Flux.
To install the CLI with Homebrew run:
brew install fluxcd/tap/flux
Export your credentials
Export your GitHub personal access token and username:
export GITHUB_TOKEN=<your-token>
export GITHUB_USER=<your-username>
Check your Kubernetes cluster
Check you have everything needed to run Flux by running the following command:
flux check — pre
The output is similar to:
► checking prerequisites
✔ kubernetes 1.28.0 >=1.25.0
✔ prerequisites checks passed
Install Flux onto your cluster
For information on how to bootstrap using a GitHub org, Gitlab and other git providers, see Installation.
Run the bootstrap command:
flux bootstrap github \
--owner=amit17133129 \ --repository=mac-repo \
--path=app-cluster
—personal
The output is similar to:
► connecting to github.com
► cloning branch "main" from Git repository "https://github.com/amit17133129/mac-repo.git"
✔ cloned repository
► generating component manifests
✔ generated component manifests
✔ component manifests are up to date
► installing components in "flux-system" namespace
✔ installed components
✔ reconciled components
► determining if source secret "flux-system/flux-system" exists
► generating source secret
✔ public key: ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBFX6fzL6HPPjI8lJ4Lzz7VDEERjZc40MGWErwdwHv9tFMsN2KwqVkMDJpBwasWvHqiRVL/EbnO39Ek1iRskRVt9cV/6/6TwhLAfNDE2b8enHyJ3cXu4OGk2xGs7wfYUExg==
✔ configured deploy key "flux-system-main-flux-system-./app-cluster" for "https://github.com/amit17133129/mac-repo"
► applying source secret "flux-system/flux-system"
✔ reconciled source secret
► generating sync manifests
✔ generated sync manifests
✔ sync manifests are up to date
► applying sync manifests
✔ reconciled sync configuration
◎ waiting for Kustomization "flux-system/flux-system" to be reconciled
✔ Kustomization reconciled successfully
► confirming components are healthy
✔ helm-controller: deployment ready
✔ kustomize-controller: deployment ready
✔ notification-controller: deployment ready
✔ source-controller: deployment ready
✔ all components are healthy
The bootstrap command above does the following:
- Creates a git repository
mac-repo
on your GitHub account. - Adds Flux component manifests to the repository.
- Deploys Flux Components to your Kubernetes Cluster.
- Configures Flux components to track the path
app-cluster/
in the repository.
If you check the resources of flux-system namespace you will be seeing that flux is installed in the respective namespace.
kubectl get all -n flux-system
The output is similar to:
NAME READY STATUS RESTARTS AGE
pod/helm-controller-5494f66c7f-nc5vb 1/1 Running 0 79s
pod/kustomize-controller-5c4bf4459b-bj7rw 1/1 Running 0 79s
pod/notification-controller-5646f6df46-dkwjc 1/1 Running 0 79s
pod/source-controller-df74bddd4-84zhs 1/1 Running 0 79s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/notification-controller ClusterIP 10.100.235.146 <none> 80/TCP 80s
service/source-controller ClusterIP 10.100.37.0 <none> 80/TCP 80s
service/webhook-receiver ClusterIP 10.100.133.229 <none> 80/TCP 79s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/helm-controller 1/1 1 1 79s
deployment.apps/kustomize-controller 1/1 1 1 79s
deployment.apps/notification-controller 1/1 1 1 79s
deployment.apps/source-controller 1/1 1 1 79s
NAME DESIRED CURRENT READY AGE
replicaset.apps/helm-controller-5494f66c7f 1 1 1 80s
replicaset.apps/kustomize-controller-5c4bf4459b 1 1 1 80s
replicaset.apps/notification-controller-5646f6df46 1 1 1 80s
replicaset.apps/source-controller-df74bddd4 1 1 1 80s
Clone the git repository
Clone the mac-repo
repository to your local machine:
git clone https://github.com/$GITHUB_USER/mac-repo
cd mac-repo
Add podinfo repository to Flux
This example uses a public repository github.com/stefanprodan/podinfo, podinfo is a tiny web application made with Go.
- Create a GitRepository manifest pointing to podinfo repository’s master branch:
flux create source git mac-repo --url=https://github.com/amit17133129/mac-repo --branch=main --interval=30s --export > ./app-cluster/source.yaml
The output is similar to:
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: mac-repo
namespace: flux-system
spec:
interval: 30s
ref:
branch: main
url: https://github.com/amit17133129/mac-repo
Now create a basic application file using the kubectl command or create the manifests and save the file in deployment folder.
kubectl -n dev-namespace create deploy dev-app --image=nginx:latest --dry-run -o yaml > ./dev-app.yaml
The output is similar to:
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: dev-app
name: dev-app
namespace: dev-namespace
spec:
replicas: 1
selector:
matchLabels:
app: dev-app
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: dev-app
spec:
containers:
- image: nginx:latest
name: nginx
resources: {}
status: {}
Now lets create the service of the above deployment.
kubectl -n dev-namespace expose deployment dev-app --type=LoadBalancer --port=80 --dry-run -o yaml > ./dev-app-svc.yaml
The output is similar to:
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: dev-app
name: dev-app
namespace: dev-namespace
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: dev-app
type: LoadBalancer
status:
loadBalancer: {}
Now push the code to the github repo.
flux create kustomization dev-app --source=mac-repo --path="./deployment" --prune=true --interval=1m --wait=true --health-check-timeout=3m --export > ./app-cluster/dev-app.yaml
The files architecture should look like below.
.
├── app-cluster
│ ├── dev-app.yaml
│ ├── flux-system
│ │ ├── gotk-components.yaml
│ │ ├── gotk-sync.yaml
│ │ └── kustomization.yaml
│ └── source.yaml
├── deployment
│ ├── dev-app-svc.yaml
│ └── dev-app.yaml
└── ReadMe.md
Watch Flux sync the application
Now you can the kustomization status. You will see that the dev-app kustomization is under Reconciliation.
watch flux get kustomizations
The output is similar to:
Every 2.0s: flux get kustomizations Tue Sep 19 13:35:16 2023
NAME REVISION SUSPENDED READY MESSAGE
dev-app False Unknown Reconciliation in progress
flux-system main@sha1:7e00c75b False True Applied revision: main@sha1:7e00c75b
After sometime you will get that the dev-app kustomization is applied successfully.
Every 2.0s: flux get kustomizations Tue Sep 19 13:38:11 2023
NAME REVISION SUSPENDED READY MESSAGE
dev-app main@sha1:7e00c75b False True Applied revision: main@sha1:7e00c75b
flux-system main@sha1:7e00c75b False True Applied revision: main@sha1:7e00c75b
Now you can check the resources under dev-namespace
.
kubectl get all -n dev-namespace
The output is similar to:
NAME READY STATUS RESTARTS AGE
pod/dev-app-5ddcdc5b97-sws4c 1/1 Running 0 4m20s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/dev-app LoadBalancer 10.100.245.133 a89ce36260c2f44618f197b16cc9002f-1695850056.eu-west-1.elb.amazonaws.com 80:31364/TCP 70s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/dev-app 1/1 1 1 4m21s
NAME DESIRED CURRENT READY AGE
replicaset.apps/dev-app-5ddcdc5b97 1 1 1 4m21s
Conclusion:
Flux in Kubernetes is a game-changer for modern deployment workflows. By embracing GitOps principles, it allows teams to manage their applications in a declarative, version-controlled manner. This not only brings efficiency and automation to the deployment process but also enhances the overall reliability and consistency of Kubernetes clusters.
With Flux, you can confidently deploy applications, track changes, and even perform seamless rollbacks when needed. Its integration with Git repositories as the source of truth ensures that your cluster’s state aligns perfectly with your desired configurations.
Whether you’re a DevOps engineer, a Kubernetes administrator, or a developer, Flux empowers you to take control of your Kubernetes deployments, enabling smoother operations and faster iterations. Embrace Flux to experience a more robust and automated approach to managing your applications in Kubernetes. Happy deploying!