Select Page
last updated on May 24, 2024
Share

Introduction

Jenkins is a popular CI (Continuous Integration) tool for automating, building, and testing projects. It divides the job into various pipeline stages for this process. Jenkins is extended sometimes as a CD (Continuous Deployment) server for getting projects deployed to the required environments such as testing, staging, production etc. 

Now, why extend a tool primarily developed for CI to CD, when modern CD tools like FluxCD make use of GitOps principles?

FluxCD makes sure that the services deployed to a kubernetes cluster are in line with the description provided in the manifest files committed in a Git repo. Thus every deployment whether new or upgraded is recorded as a series of Git commits. This gives one many advantages of version control and reliable-cum-faster deployments. To know more about how GitOps can help you, see What is GitOps.

Entrusting the responsibility of CD to Flux will give us a clear boundary between CI and CD. We understand that CI builds are unstable whereas deployment needs reliability. In this tutorial we will connect Jenkins with Flux and deploy an example application (docker image) to a kubernetes cluster.

Overview

Once the project is built to a tag, Jenkins tests it and deploys it to a container registry. In this example, let’s assume that Jenkins is using docker for containerization and pushes it to the docker hub. Of course the example is a container-tech antagonist and you are free to choose.

Flux deploys applications from a manifest file (in a Git repo) which refers to a specific version of image to be deployed, and makes sure that the deployed application remains true to the version and other information (eg: number of replicas) as specified in the manifest file. 

What we require is a way to automatically update the specific version inside the manifest file according to the version of image in the docker hub. In this way, whatever image Jenkins pushes with a specific tag, the information is committed to Git repo and image is further deployed (with certain rules) to a cluster. 

FluxCD provides us this feature with the name ‘auto image updation’

Prerequisites

  • A running kubernetes cluster with flux installed.
  • A flux client on our system to access the remote flux controllers.
  • A Jenkins pipeline pushing to an image hub.
  • Git installed on the system.

The automatic image updation feature is not installed by default when we bootstrap flux. 

It requires a special controller provided by flux, to install it:

Rerun bootstrap with `–components-extra=image-reflector-controller, image-automation-controller

or, apply these CRDs to cluster and bootstrap again.

				
					kubectl apply -f https://raw.githubusercontent.com/fluxcd/image-automation-controller/main/config/crd/bases/image.toolkit.fluxcd.io_imageupdateautomations.yaml
kubectl apply -f https://raw.githubusercontent.com/fluxcd/image-reflector-controller/main/config/crd/bases/image.toolkit.fluxcd.io_imagerepositories.yaml
kubectl apply -f https://raw.githubusercontent.com/fluxcd/image-reflector-controller/main/config/crd/bases/image.toolkit.fluxcd.io_imagepolicies.yaml

				
			

Refer, Flux Installation to know how to bootstrap flux on a cluster and also set up a flux client.

Working directory

An example for a working directory and explanation of the various terms is given below:

Working Directory:

				
					flux-test
	clusters
		my-cluster
			podinfo-deployment.yaml
			podinfo-policy.yaml
			podinfo-registry.yaml
			flux-system
				gotk-components.yaml
				gotk-sync.yaml
				Kustomization.yaml
				
			

podinfo-deployment.yaml – Specifies that flux should deploy a service named podinfo into the cluster.

podinfo-registry.yaml – Specifies a resource of type ImageRepository which points to the container registry in which new tags have to be scanned. The container registry will be the same in which jenkins pushes the tags.

podinfo-policy.yaml – Specifies the rules/policy by which a tag must adhere to if it has to be automatically pulled. It references an image repository.

flux-system-automation.yaml – Specifies a resource of type ImageUpdateAutomation. Through this, flux will know exactly in which file image version update is required, and what should be the commit message by executing the image policy files at a specific interval.

flux-system – Contains manifest files of flux components made by flux bootstrap command.

Next comes the steps to be followed for the demonstration. Make sure to change username, imagename, tag etc at your discrimination! I have used my personal project and logs as an example. 

Clone your Git repository

Clone your git repository using the command given below:

				
					sh
git clone https://github.com/<github user name>/flux-test
cd flux-test

				
			

Create a deployment of your service

Create a deployment of your service. Inside clusters/my-cluster create a file named, podinfo-deployment.yaml with tag reference. The image name must be the same as the one pushed by jenkins pipeline. I have used a fork of podinfo app by stefanprodan

				
					apiVersion: apps/v1
kind: Deployment
metadata:
  name: podinfo
  namespace: default
spec:
  selector:
    matchLabels:
      app: podinfo
  template:
    metadata:
      labels:
        app: podinfo
    spec:
      containers:
        - name: podinfod
          image: docker.io/utkarshopsmx/podinfo:1.0.0
          imagePullPolicy: IfNotPresent
          ports:
            - name: http
              containerPort: 9898
              protocol: TCP

				
			

You can either wait or force flux to pull and apply changes:

				
					flux reconcile kustomization flux-system --with-source
				
			

Check the podinfo deployed on your cluster:

				
					kubectl get deployment/podinfo -oyaml | grep 'image:'
				
			

Create an ImageRepository

Now, create an image repository. This will start the image scanning by flux system at regular intervals.

Either use the command:

				
					flux create image repository podinfo \
--image=docker.io/utkarshopsmx/podinfo \
--interval=5m \
--export > ./clusters/my-cluster/podinfo-registry.yaml

				
			

or copy-paste the below manifest:

				
					apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageRepository
metadata:
  name: podinfo
  namespace: flux-system
spec:
  image: docker.io/utkarshopsmx/podinfo
  interval: 5m0s
				
			

If the image is private (usually they are), create a Kubernetes secret in the same namespace as the ImageRepository by executing the below command:

				
					kubectl create secret docker-registry
				
			

Then configure Flux to use the credentials by referencing the Kubernetes secret in the ImageRepository:

				
					kind: ImageRepository
spec:
  secretRef:
    name: regcred

				
			

Commit and push the above changes.

Create an ImagePolicy

The next step is to create an ImagePolicy. In our case, flux will be informed as to which version of the image it should pull.

				
					flux create image policy podinfo \
--image-ref=podinfo \
--select-semver=1.0.x \
--export > ./clusters/my-cluster/podinfo-policy.yaml

				
			

Or copy-paste:

				
					apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImagePolicy
metadata:
  name: podinfo
  namespace: flux-system
spec:
  imageRepositoryRef:
    name: podinfo
  policy:
    semver:
      range: 1.0.x

				
			

Refer ImagePolicy Examples, to know about various policy examples.

Commit and push the above changes.

Force flux to reconcile by executing the below command:

				
					flux reconcile kustomization flux-system --with-source
				
			

Check if the `ImageRepository` has scanned the latest tag from registry:

				
					$ flux get image repository podinfo
NAME    LAST SCAN                       SUSPENDED       READY   MESSAGE
podinfo 2024-05-02T11:34:48+05:30       False           True    successful scan: found 2 tags

				
			

To see sample of tags scanned, execute the below command:

				
					kubectl -n flux-system describe imagerepositories podinfo
				
			

To find which image tag matches the policy semantice version range, execute the below  command:

				
					$ flux get image policy podinfo
NAME    LATEST IMAGE                            READY   MESSAGE
podinfo docker.io/utkarshopsmx/podinfo:1.0.2    True    Latest image tag for 'doker.io/utkarshopsmx/podinfo' resolved to 1.0.2

				
			

Configure Image Updates:

Edit the podinfo-deployment file to mark the tagline with the specific image policy. That policy will be used to update the image.

				
					image: doker.io/utkarshopsmx/podinfo:1.0.0 # {"$imagepolicy": "flux-system:podinfo"}
				
			

Now create an ImageUpdateAutomation to specify the Git Repository we need to write the image updates:

				
					flux create image update flux-system \
--interval=10m \
--git-repo-ref=flux-system \
--git-repo-path="./clusters/my-cluster" \
--checkout-branch=main \
--push-branch=main \
--author-name=fluxcdbot \
--author-email=fluxcdbot@users.noreply.github.com \
--commit-template="{{range .Changed.Changes}}{{print .OldValue}} -> {{println .NewValue}}{{end}}" \
--export > ./clusters/my-cluster/flux-system-automation.yaml

				
			

Or copy-paste:

				
					apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageUpdateAutomation
metadata:
  name: flux-system
  namespace: flux-system
spec:
  git:
    checkout:
      ref:
        branch: main
    commit:
      author:
        email: fluxcdbot@users.noreply.github.com
        name: fluxcdbot
      messageTemplate: '{{range .Changed.Changes}}{{print .OldValue}} -> {{println
        .NewValue}}{{end}}'
    push:
      branch: main
  interval: 5m0s
  sourceRef:
    kind: GitRepository
    name: flux-system
  update:
    path: ./clusters/my-cluster
    strategy: Setters

				
			

Commit and push the changes.

Testing our setup:

Run the Jenkins pipeline to push a new tag to docker hub. Either wait for some time to let flux update the changes or force flux to reconcile immediately.

Now check the latest version of your git repo and lookout for the image line in the deployment file.

You will see that the file has been updated:

				
					$ git pull && cat clusters/my-cluster/podinfo-deployment.yaml | grep "image:"
image: ghcr.io/stefanprodan/podinfo:1.0.2 # {"$imagepolicy": "flux-system:podinfo"}

				
			

Check the latest deployment in cluster:

				
					$ watch "kubectl get deployment/podinfo -oyaml | grep 'image:'"
image: ghcr.io/stefanprodan/podinfo:1.0.2

				
			

The manifest file was updated after, flux observed a new tag pushed by jenkins and finally deployed the tag to the cluster.

Additional changes

It’s recommended that the registry is private and to access the registry one can create a kubernetes secret and refer it in the policy:

				
					kubectl create secret docker-registry
kind: ImageRepository
spec:
  secretRef:
    name: regcred

				
			

Refer ImagePolicy Examples, to specify a range of versions to be scanned.

To revert an image upgrade (due to issues caused by the latest tag) specify exactly which tag should be deployed by editing the deployment file as shown below:

				
					policy:
  semver:
    range: 1.0.0

				
			

or by executing the following command:

				
					flux create image policy podinfo \
--image-ref=podinfo \
--select-semver=1.0.0

				
			

Execute the given commands to do the following actions:

  • To suspend flux pushing image updates:
				
					flux suspend image update flux-system
				
			
  • To resume the updates:
				
					flux resume image update flux-system
				
			

or specify in ImageUpdateAutomation:

				
					kind: ImageUpdateAutomation
metadata:
  name: flux-system
  namespace: flux-system
spec:
  suspend: true

				
			

If you want a push system rather than a pull system from flux so as to immediately deploy the latest tag, refer, Trigger image updates with webhooks.

If you want to push to different branch than the one specified in ImageUpdateAutomation:

				
					spec:  
  git:
    checkout:
      ref:
        branch: main
    push:
      branch: flux-image-updates

				
			

About OpsMx

OpsMx is a leading innovator and thought leader in the Continuous Delivery space. OpsMx’s Solution for Flux helps DevOps teams manage their Flux deployments at scale.

Talk to OpsMx’s FluxCD experts about any questions that you may have around Flux, GitOps-style deployments, Kubernetes, or DevSecOps. Our services enable the largest and most innovative companies to optimize their (GitOps) delivery pipelines.

0 Comments

Submit a Comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.