K3s part 5: Flux GitOps

Updated January 05, 2021 3 minutes

Flux is a Continuous Delivery platform for Kubernetes infrastructure. Flux will syncrhonize your git repository containing your YAML manifests, and automatically apply changes to your cluster. Manage your cluster via GitOps!

Install flux operators

Configure the git repository directory you created in part 1 along with other config variables:

FLUX_INFRA_DIR=${HOME}/git/flux-infra
CLUSTER=k3s.example.com
GITEA_USER=root
GIT_REMOTE=ssh://[email protected]${CLUSTER}:2222/${GITEA_USER}/flux-infra.git

Create the YAML manifests for flux:

mkdir -p ${FLUX_INFRA_DIR}/${CLUSTER}/flux-system
flux install --version=latest --arch=amd64 --export > \
  ${FLUX_INFRA_DIR}/${CLUSTER}/flux-system/gotk-components.yaml

Examine the gotk-components.yaml file, then apply to the cluster:

kubectl apply -f ${FLUX_INFRA_DIR}/${CLUSTER}/flux-system/gotk-components.yaml

Verify running pods:

kubectl get pods -n flux-system

Example output:

NAME                                       READY   STATUS    RESTARTS   AGE
source-controller-7c7b47f5f-ntlv6          1/1     Running   0          39s
helm-controller-6b9979865b-4vdff           1/1     Running   0          36s
notification-controller-596664f5f9-qt6jj   1/1     Running   0          31s
kustomize-controller-79948786c9-k4bzt      1/1     Running   0          38s

Commit and push the manifest to the remote git repository:

git -C ${FLUX_INFRA_DIR} add ${CLUSTER}
git -C ${FLUX_INFRA_DIR} commit -m "init ${CLUSTER} flux-system"
git -C ${FLUX_INFRA_DIR} push

Watch the infrastructure repository for changes

In the last step, we used kubectl apply to manually apply the manifest to the cluster. From now on, we’d like flux to monitor changes to the git repository, and apply the manifests automatically.

The flux GitRepository object defines the remote repository to peridoically pull and watch for changes. Create this for the flux-infra repo:

flux create source git flux-infra \
  --url=${GIT_REMOTE} \
  --ssh-key-algorithm=rsa \
  --ssh-rsa-bits=4096 \
  --branch=master \
  --interval=1m

This will output a public SSH key, which will be used to login to your remote git repository. You must copy the key and install it as a Deploy Key in the remote git repository settings. In Gitea add the deploy key under the repository Settings->Deploy Keys. The deploy key does not require write privileges. Once installed, press Y and Enter to continue.

The Kustomization object defines a job to apply the source code downloaded from a GitRepository, and apply it to the cluster. Create this for the flux-infra repo:

flux create kustomization ${CLUSTER} \
  --source=flux-infra \
  --path="./${CLUSTER}" \
  --prune=true \
  --interval=10m

Export configuration manifests:

flux export source git flux-infra > \
  ${FLUX_INFRA_DIR}/${CLUSTER}/flux-system/gotk-sync.yaml
flux export kustomization ${CLUSTER} >> \
  ${FLUX_INFRA_DIR}/${CLUSTER}/flux-system/gotk-sync.yaml

Create the kustomization.yaml file that lists all manifests to apply:

cat <<EOF > ${FLUX_INFRA_DIR}/${CLUSTER}/flux-system/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- gotk-components.yaml
- gotk-sync.yaml
EOF

Commit and push the changes to the remote git repository:

git -C ${FLUX_INFRA_DIR} add ${CLUSTER}
git -C ${FLUX_INFRA_DIR} commit -m "${CLUSTER}"
git -C ${FLUX_INFRA_DIR} push

If you add new manifests, make sure to edit kustomization.yaml to list them. Whenever you commit and push changes, the Kustomization job will automatically apply them.

Test it

Create a new manifest to create a namespace called tmp-namespace just for testing.

cat <<EOF > ${FLUX_INFRA_DIR}/${CLUSTER}/flux-system/tmp-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: tmp-namespace
EOF

Recreate the kustomization now with three manifests, including the tmp-namespace:

cat <<EOF > ${FLUX_INFRA_DIR}/${CLUSTER}/flux-system/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- gotk-components.yaml
- gotk-sync.yaml
- tmp-namespace.yaml
EOF

Commit and push the changes to the remote git repository:

git -C ${FLUX_INFRA_DIR} add ${CLUSTER}
git -C ${FLUX_INFRA_DIR} commit -m "${CLUSTER} flux-system"
git -C ${FLUX_INFRA_DIR} push

Within one minute, you should see the new tmp-namespace namespace.

# kubectl get ns tmp-namespace
NAME            STATUS   AGE
tmp-namespace   Active   20s

Now recreate the kustomization back to what it was, without the tmp-namespace manifest:

cat <<EOF > ${FLUX_INFRA_DIR}/${CLUSTER}/flux-system/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- gotk-components.yaml
- gotk-sync.yaml
EOF

Commit and push the changes to the remote git repository:

git -C ${FLUX_INFRA_DIR} add ${CLUSTER}
git -C ${FLUX_INFRA_DIR} commit -m "${CLUSTER} flux-system"
git -C ${FLUX_INFRA_DIR} push

In about another minute, the namespace will be gone:

# kubectl get ns tmp-namespace
Error from server (NotFound): namespaces "tmp-namespace" not found

Logs

To check the kustomize logs:

kubectl -n flux-system logs deployment/kustomize-controller


You can discuss this blog on Matrix (Element): #blog-rymcg-tech:enigmacurry.com

This blog is copyright EnigmaCurry and dual-licensed CC-BY-SA and MIT. The source is on github: enigmacurry/blog.rymcg.tech and PRs are welcome. ❤️