Skip to main content
Version: Next

GitOps with FluxCD

In this section, we will introduce how to use KubeVela to deliver in GitOps mode.

Please make sure you have enabled the fluxcd addon.

Watch the Git repositories and sync automatically

Preparing the configuration repository

GitOps will automatically synchronize the configuration in the repository to the cluster. First, we need a repository that stores all the configuration files you need: such as some Kubernetes native resources Deployment, Secret, ConfigMap, etc. Also, you can store KubeVela's Application in the repository.

Suppose in our repository, there is a folder called infrastructure, which has a KubeVela Application called server and a ConfigMap called server-config.

The directory structure of the repository is as follows:

├── infrastructure
   ├── server-config.yaml
   └── server.yaml

Deploy the following KubeVela GitOps application:

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: infra-gitops
spec:
components:
- name: database-config
type: kustomize
properties:
repoType: git
# replace it with your repo url
url: https://github.com/FogDong/KubeVela-GitOps-Infra-Demo
# replace it with your git secret if it's a private repo
# secretRef: git-secret
# the pull interval time, set to 10m since the infrastructure is steady
pullInterval: 10m
git:
# the branch name
branch: infra
# the path to sync
path: ./infrastructure

Check the status of this GitOps application:

$ vela status infra-gitops
About:

Name: infra-gitops
Namespace: default
Created at: 2022-06-30 14:52:33 +0800 CST
Status: running

Workflow:

mode: DAG
finished: true
Suspend: false
Terminated: false
Steps
- id:dgatat8jag
name:database-config
type:apply-component
phase:succeeded
message:

Services:

- Name: database-config
Cluster: local Namespace: default
Type: kustomize
Healthy
No trait applied

As you can see, the GitOps application is running successfully. At this point, the application continuously pulls the configuration from the repository and syncs across the cluster at 10-minute intervals.

Looking at the resources in the cluster, you can find that the server Application and the server-config ConfigMap have been automatically deployed.

$ vela ls
APP COMPONENT TYPE TRAITS PHASE HEALTHY STATUS CREATED-TIME
infra-gitops database-config kustomize running healthy 2022-06-30 14:52:33 +0800 CST
server server webservice running healthy Ready:1/1 2022-06-30 14:52:35 +0800 CST

$ kubectl get configmap
NAME DATA AGE
server-config 1 2m58s

Watch the image repositories and synchronize automatically

GitOps can also watch your image repository, get the latest image version, and update the configuration in your code repository with the latest version, so as to achieve the purpose of automatically updating the image.

Suppose the directory structure of our repository is as follows:

├── application
   └── my-app.yaml

The my-app.yaml in the application is as follows:

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: my-app
namespace: default
spec:
components:
- name: my-app
type: webservice
properties:
image: nginx # {"$imagepolicy": "default:image-gitops"}

Note that there is a # {"$imagepolicy": "default:image-gitops"} comment after the image field. KubeVela will update the corresponding image field through this annotation. default:image-gitops is the namespace and name of the GitOps application component we will deploy.

Deploy the following KubeVela GitOps application:

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: image-gitops
spec:
components:
- name: image-gitops
type: kustomize
properties:
repoType: git
# replace it with your repo url
url: https://github.com/FogDong/KubeVela-GitOps-Infra-Demo
# replace it with your git secret, GitOps will update the files in your repository with the latest image, which requires write permission
secretRef: git-secret
pullInterval: 1m
git:
# the branch name
branch: image
# the path to sync
path: ./application
imageRepository:
# replace it with your image url
image: ghcr.io/fogdong/test-fog
# if it's a private image registry, use `kubectl create secret docker-registry` to create the secret
# secretRef: imagesecret
filterTags:
# filter the image tag
pattern: '^master-[a-f0-9]+-(?P<ts>[0-9]+)'
extract: '$ts'
# use the policy to sort the latest image tag and update
policy:
numerical:
order: asc
# add more commit message
commitMessage: "Image: {{range .Updated.Images}}{{println .}}{{end}}"

After the application is deployed successfully, you can see that the my-app application has also been automatically deployed. At this point, the image in my-app is nginx:

$ vela ls
APP COMPONENT TYPE TRAITS PHASE HEALTHY STATUS CREATED-TIME
image-gitops image-gitops kustomize running healthy 2022-06-30 15:16:30 +0800 CST
my-app my-app webservice running healthy Ready:1/1 2022-06-30 15:16:31 +0800 CST

After a period of time, the imageRepository we configured will automatically pull the latest image we want and update the application image in the repository.

At this point, you can see a commit from kubevelabot in the config repository, which replaces the nginx image with the latest image from our own repository. Commits are prefixed with Update image automatically.. You can also append the information you want in the commitMessage field with {{range .Updated.Images}}{{println .}}{{end}}.

alt

Note that if you want to put the code and config in the same repository, you need to filter out the commit from KubeVela in CI configuration like below to avoid the repeat build of pipeline.

jobs:
publish:
if: "!contains(github.event.head_commit.message, 'Update image automatically')"

Re-check the Application in cluster, we can see that the image of the my-app has been updated after a while.

KubeVela polls the latest information from the code and image repo periodically (at an interval that can be customized):

  • When the Application file in the Git repository is updated, KubeVela will update the Application in the cluster based on the latest configuration.
  • When a new tag is added to the image registry, KubeVela will filter out the latest tag based on your policy and update it to Git repository. When the files in the repository are updated, KubeVela repeats the first step and updates the files in the cluster, thus achieving automatic deployment.

FAQ

How to control Application version in GitOps

Every time the spec of Application differs, the Application will re-run its workflow to deploy. If you want to strictly control the Application runs with your expected version, you can use Publish Version. With it, you can also viewing the history revisions, checking the differences across revisions, rolling back to the latest succeeded revision and re-publishing past revisions.

note

If you're using external policy or workflow in your Application, then your Application spec may not change if you have updated your policy or workflow. In this case, you can also use Publish Version to force re-trigger the deploy.

If you want to control the Application version in GitOps, you need to update the Publish Version in the Application in your CI to trigger the deploy.

note

Before update the PublishVersion, you need to setup a initial PublishVersion in your Application like:

metadata:
name: my-app
annotations:
app.oam.dev/publishVersion: <initial version>

You can checkout the example repo or setup the CI workflow to update it automatically like below:

name: Auto Commit
on:
push:
branches:
- '*'

jobs:
run:
name: Auto Commit
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v2

- name: Update publish version
id: update
run: |
VERSION=${GITHUB_SHA::8}
echo ::set-output name=VERSION::${VERSION}
# replace app.yaml with your app file name
sed -i "s|app.oam.dev/publishVersion: .*|app.oam.dev/publishVersion: $VERSION|" app.yaml

- name: Commit changes
uses: EndBug/add-and-commit@v7
with:
default_author: github_actions
add: '.'
message: "[ci skip] deploy from ${{ steps.update.outputs.VERSION }}"
signoff: true
# specify the branch you want to commit if need
# branch: main

This CI will use GitHub SHA as the PublishVersion and update it every time when you push to the branch. Note that this is an example of updating PublishVersion in GitHub Action, if you're using other CI tools, you can setup the CI like above.

More

You can also check out GitOps blog and video practice to better experience and use GitOps.