Deploy Applications using Flux on Vultr Kubernetes Engine

Updated on November 12, 2023
Deploy Applications using Flux on Vultr Kubernetes Engine header image

Introduction

Flux is an open-source continuous delivery (CD) tool used for automating application delivery pipelines to Kubernetes clusters. Flux uses the GitOps principle to automatically synchronize changes in a Git repository to a Kubernetes cluster. It updates your application depending on your Git repository state.

To deploy applications to a Kubernetes cluster, Flux uses a declarative configuration file. Additionally, all the configuration files are stored in your application repository. This makes it easier to manage all application code and configurations.

Flux offers a range of features that make it an ideal choice for implementing GitOps workflows in Kubernetes environments. These include:

  • GitOps Workflow
  • Declarative Configuration
  • Automated Synchronization
  • Rollback and Recovery
  • Multi-Environment Support
  • Notifications and Alerts
  • Cluster State Monitoring

This article explains how you can deploy applications in a Vultr Kubernetes Engine (VKE) cluster using Flux.

Prerequisites

Before you begin:

Install Flux CLI

To interact with Flux installations on your server, install the Flux CLI tool. The command line tool allows you to manage and configure Flux together with its resources in your Kubernetes cluster. Install Flux CLI on your management server as described in the steps below.

  1. Download the Flux CLI installation script

     $ wget https://toolkit.Fluxcd.io/install.sh
  2. Run the script to install the Flux CLI tool

     $ sudo bash install.sh

    When successful, your output should look like the one below

     [INFO]  Downloading metadata https://api.github.com/repos/fluxcd/flux2/releases/latest
     [INFO]  Using 2.1.2 as release
     [INFO]  Downloading hash https://github.com/fluxcd/flux2/releases/download/v2.1.2/flux_2.1.2_checksums.txt
     [INFO]  Downloading binary https://github.com/fluxcd/flux2/releases/download/v2.1.2/flux_2.1.2_linux_amd64.tar.gz
     [INFO]  Verifying binary download
     [INFO]  Installing flux to /usr/local/bin/flux
  3. Verify the installed Flux CLI version

     $ flux --version

    Output:

     flux version 2.1.2

Configure GIT

  1. Verify that Git is available on your server

     $ git --version

    The git version should display in your output like the one below:

     git version 2.39.2
  2. Configure Git with your email address

     $ git config --global user.email "example-user@gmail.com"
  3. Set up your Git user name

     $ git config --global user.name "Example User"
  4. Verify your Git information

     $ git config --list --show-origin

    Output.

     file:/home/user/.gitconfig      user.email=example-user@gmail.com
     file:/home/user/.gitconfig      user.name=example user
  5. Export your active GitHub username as an environment variable on your server

     $ export GITHUB_USER="example-user"

    The environment variable value allows Flux to connect to your private GitHub repository and the perform necessary operations

  6. Export your GitHub personal access token as an environment variable

     $ export GITHUB_TOKEN="example-token"

    The GITHUB_TOKEN value allows Flux to authenticate and write files to your GitHub repository

Bootstrapping FluxCD Toolkit Components

Flux uses these toolkit components to add a CD pipeline to the cluster. During the bootstrapping process, Flux automatically creates the GitHub repository if it does not exist and uploads the Flux toolkit components. Bootstrap the flux toolkit to your Kubernetes cluster as described below.

  1. View cluster nodes and verify that Kubectl has access to your Kubernetes cluster

     $ kubectl get nodes
  2. Verify that Flux is compatible with your Kubernetes cluster

     $ flux check --pre

    Output:

     ► checking prerequisites
     ✔ Kubernetes 1.28.2 >=1.25.0-0
     ✔ prerequisites checks passed
  3. Bootstrap Flux to your Kubernetes cluster using a GitHub repository. Replace flux-example with your actual private repository name

     $ flux bootstrap github --owner=$GITHUB_USER --repository=flux-example --path=clusters/lab --personal

    The above command creates the flux-system namespace, the necessary configuration files, and installs flux to your cluster. When successful, your log output should look like the one below.

     ► connecting to github.com
     ✔ repository "https://github.com/example-user/flux-example" created
     ► cloning branch "main" from Git repository "https://github.com/example-user/flux-example.git"
     ✔ cloned repository
     ► 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
  4. Verify that new resources are available in the flux-system namespace

     $ kubectl get pods -n flux-system

    Output:

     NAME                                      READY   STATUS    RESTARTS   AGE
     helm-controller-674b78f654-7mhrt          1/1     Running   0          58s
     kustomize-controller-6d95f95b78-5t2xz     1/1     Running   0          58s
     notification-controller-76dc5d768-g7pkp   1/1     Running   0          58s
     source-controller-86d9c8fd4f-lkfdb        1/1     Running   0          58s
  5. Visit your GitHub repository and verify that new configuration manifest files are available in the clusters directory

    Verify GitHub repository

Deploy a Sample Application

Flux stores your application and all configuration files in your GitHub repository flux-example. Each time you make changes in your application, Flux automatically applies the changes to your Kubernetes cluster. Deploy a sample-app application to your cluster using Flux to test the tool operations.

  1. Clone your GitHub repository flux-example

     $ git clone https://github.com/example-user/flux-example.git

    When prompted enter your GitHub username and the Personal Access Token as your password to successfully clone the repository.

  2. Navigate to the flux-example directory

     $ cd flux-example
  3. Create a new kustomization configuration file that directs flux where to find your Git application definition

     $ flux create kustomization sample-app --target-namespace=sample-app --source=flux-system --path="./clusters/lab/kustomize" --prune=true --interval=7m  --export > ./clusters/lab/static-kustomization.yaml
  4. Create a new kustomize sub-directory in the cluster/lab directory

     $ mkdir -p clusters/lab/kustomize
  5. Using a text editor such as Nano, create a namespace manifest file for your application

     $ nano clusters/lab/kustomize/namespace.yaml
  6. Add the following configurations to the file.

     apiVersion: v1
     kind: Namespace
     metadata:
       name: sample-app

    Save and close the file.

  7. Create a new kustomization.yaml file to define your namespace

     $ nano clusters/lab/kustomize/kustomization.yaml
  8. Add the following configurations to the file

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

    Save and close the file.

  9. Add the new files to your local repository

     $ git add .
  10. Commit changes to your repository

    $ git commit -m "first commit"

    Output:

    [main 7bd053b] first commit
    3 files changed, 22 insertions(+)
    create mode 100644 clusters/lab/kustomize/kustomization.yaml
    create mode 100644 clusters/lab/kustomize/namespace.yaml
    create mode 100644 clusters/lab/static-kustomization.yaml
  11. Push changes to the flux-example GitHub repository

    $ git push

    Output:

    Enumerating objects: 11, done.
    Counting objects: 100% (11/11), done.
    Delta compression using up to 4 threads
    Compressing objects: 100% (6/6), done.
    Writing objects: 100% (8/8), 841 bytes | 841.00 KiB/s, done.
    Total 8 (delta 0), reused 0 (delta 0), pack-reused 0
    To https://github.com/example-user/flux-example.git
       e48763f..7bd053b  main -> main
  12. Flux now detects the changes in the flux-example repository and applies every change to your cluster. View cluster namespaces to verify the operations

    $ kubectl get ns

    Verify that the sample-app namespace is available in your cluster as created in your repository:

    NAME              STATUS   AGE
    default           Active   6m19s
    flux-system       Active   4m59s
    kube-node-lease   Active   6m19s
    kube-public       Active   6m19s
    kube-system       Active   6m19s
    sample-app        Active   10s
  13. Create a new deployment.yaml file to deploy the sample-app application

    $ nano clusters/lab/kustomize/deployment.yaml
  14. Add the following configurations to the file.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sample-app
      namespace: sample-app
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: sample-app
      template:
        metadata:
          labels:
            app: sample-app
        spec:
          containers:
            - image: mstruebing/static-sample:1666603774
              imagePullPolicy: IfNotPresent
              name: sample-app

    Save and close the file.

  15. Create a new service.yaml file to expose your application on port 80

    $ nano clusters/lab/kustomize/service.yaml
  16. Add the following configurations to the file

    apiVersion: v1
    kind: Service
    metadata:
      name: sample-app
      namespace: sample-app
    spec:
      ports:
        - name: http
          port: 80
          protocol: TCP
          targetPort: 80
      selector:
        app: sample-app

    Save and close the file.

  17. Edit the kustomization.yaml configuration file and define your new manifest files

    $ nano clusters/lab/kustomize/kustomization.yaml
  18. Add new - deployment.yaml and - service.yaml directives to the file within the resources: group

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

    Save and close the file.

  19. Apply the changes to your local repository

    $ git add .
  20. Commit the changes

    $ git commit -m "second commit"

    Output:

    [main 0dd5888] second commit
    4 files changed, 53 insertions(+)
    create mode 100644 clusters/lab/kustomize/deployment.yaml
    create mode 100644 clusters/lab/kustomize/ingress.yaml
    create mode 100644 clusters/lab/kustomize/service.yaml
  21. Push all changes to the flux-example GitHub repository

    $ git push

    Output:

    Enumerating objects: 14, done.
    Counting objects: 100% (14/14), done.
    Delta compression using up to 4 threads
    Compressing objects: 100% (7/7), done.
    Writing objects: 100% (9/9), 1.19 KiB | 1.19 MiB/s, done.
    Total 9 (delta 0), reused 0 (delta 0), pack-reused 0
    To https://github.com/example-user/flux-example.git
       7bd053b..0dd5888  main -> main
  22. View the newly deployed resources in your cluster to verify that Flux synchronizes all changes

    $ kubectl get pods,service,deployment -n sample-app

    Your output should look like the one below:

    NAME                              READY   STATUS    RESTARTS   AGE
    pod/sample-app-75f89b9785-ndg9l   1/1     Running   0          28s
    
    NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
    service/sample-app   ClusterIP   10.108.93.122   <none>        80/TCP    28s
    
    NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/sample-app   1/1     1            1           28s
  23. View the cluster pod and verify that your application is ready and running

    $ kubectl get pods -n sample-app

    Output:

    NAME                          READY   STATUS    RESTARTS   AGE
    sample-app-75f89b9785-ndg9l   1/1     Running   0          6m48s

Verify the Application Deployment

Your sample application is now deployed on the Kubernetes using Flux. To verify that the application is running correctly, test access to the service port 80 as described below.

  1. Verify that the application service is available

     $ kubectl get svc -n sample-app

    Output:

     NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
     sample-app   ClusterIP   10.108.93.122   <none>        80/TCP    48s
  2. Using port forwarding, redirect the service port 80 to your host port 8000

     $ kubectl port-forward svc/sample-app 8000:80 -n sample-app --address 0.0.0.0 

    The above command forwards the cluster port 80 to your host port 8000 and accepts connections from all server interfaces

    Output:

     Forwarding from 127.0.0.1:8000 -> 80
     Forwarding from [::1]:8000 -> 80
  3. Using a web browser of your choice, access your host port 8000 using your Server IP

     http://SERVER-IP:8000

    Verify that your sample application displays correctly in your browser

    Access sample application

Conclusion

You have deployed a sample application using Flux on a Vultr Kubernetes Engine cluster. Every time you add new manifest files to your integrated repository, Flux writes the changes to your cluster. You can now use Flux to automate your application deployment processes to achieve a more efficient, and version-controlled application deployment process.