# FluxCD - We're going to implement a basic GitOps workflow with Flux - Pushing to `main` will automatically deploy to the clusters - There will be two clusters (`dev` and `prod`) - The two clusters will have similar (but slightly different) workloads --- ## Repository structure This is (approximately) what we're going to do: ``` @@INCLUDE[slides/k8s/gitopstree.txt] ``` --- ## Resource graph
flowchart TD H/D["charts/dockercoins--- ## Getting ready - Let's make sure we have two clusters - It's OK to use local clusters (kind, minikube...) - We might run into resource limits, though (pay attention to `Pending` pods!) - We need to install the Flux CLI ([packages], [binaries]) - **Highly recommended:** set up CLI completion! - Of course we'll need a Git service, too (we're going to use GitHub here) [packages]: https://fluxcd.io/flux/get-started/ [binaries]: https://github.com/fluxcd/flux2/releases --- ## GitHub setup - Generate a GitHub token: https://github.com/settings/tokens/new - Give it "repo" access - This token will be used by the `flux bootstrap github` command later - It will create a repository and configure it (SSH key...) - The token can be revoked afterwards --- ## Flux bootstrap .lab[ - Let's set a few variables for convenience, and create our repository: ```bash export GITHUB_TOKEN=... export GITHUB_USER=changeme export GITHUB_REPO=alsochangeme export FLUX_CLUSTER=dev flux bootstrap github \ --owner=$GITHUB_USER \ --repository=$GITHUB_REPO \ --branch=main \ --path=./clusters/$FLUX_CLUSTER \ --personal --private=false ``` ] Problems? check next slide! --- ## What could go wrong? - `flux bootstrap` will create or update the repository on GitHub - Then it will install Flux controllers to our cluster - Then it waits for these controllers to be up and running and ready - Check pod status in `flux-system` - If pods are `Pending`, check that you have enough resources on your cluster - For testing purposes, it should be fine to lower or remove Flux `requests`! (but don't do that in production!) - If anything goes wrong, don't worry, we can just re-run the bootstrap --- class: extra-details ## Idempotence - It's OK to run that same `flux bootstrap` command multiple times! - If the repository already exists, it will re-use it (it won't destroy or empty it) - If the path `./clusters/$FLUX_CLUSTER` already exists, it will update it - It's totally fine to re-run `flux bootstrap` if something fails - It's totally fine to run it multiple times on different clusters - Or even to run it multiple times for the *same* cluster (to reinstall Flux on that cluster after a cluster wipe / reinstall) --- ## What do we get? - Let's look at what `flux bootstrap` installed on the cluster .lab[ - Look inside the `flux-system` namespace: ```bash kubectl get all --namespace flux-system ``` - Look at `kustomizations` custom resources: ```bash kubectl get kustomizations --all-namespaces ``` - See what the `flux` CLI tells us: ```bash flux get all ``` ] --- ## Deploying with GitOps - We'll need to add/edit files on the repository - We can do it by using `git clone`, local edits, `git commit`, `git push` - Or by editing online on the GitHub website .lab[ - Create a manifest; for instance `clusters/dev/flux-system/blue.yaml` - Add that manifest to `clusters/dev/kustomization.yaml` - Commit and push both changes to the repository ] --- ## Waiting for reconciliation - Compare the git hash that we pushed and the one shown with `kubectl get ` - Option 1: wait for Flux to pick up the changes in the repository (the default interval for git repositories is 1 minute, so that's fast) - Option 2: use `flux reconcile source git flux-system` (this puts an annotation on the appropriate resource, triggering an immediate check) - Option 3: set up receiver webhooks (so that git updates trigger immediate reconciliation) --- ## Checking progress - `flux logs` - `kubectl get gitrepositories --all-namespaces` - `kubectl get kustomizations --all-namespaces` --- ## Did it work? -- - No! -- - Why? -- - We need to indicate the namespace where the app should be deployed - Either in the YAML manifests - Or in the `kustomization` custom resource (using field `spec.targetNamespace`) - Add the namespace to the manifest and try again! --- ## Adding an app in a reusable way - Let's see a technique to add a whole app (with multiple resource manifets) - We want to minimize code repetition (i.e. easy to add on multiple clusters with minimal changes) --- ## The plan - Add the app manifests in a directory (e.g.: `apps/myappname/manifests`) - Create a kustomization manifest for the app and its namespace (e.g.: `apps/myappname/flux.yaml`) - The kustomization manifest will refer to the app manifest - Add the kustomization manifest to the top-level `flux-system` kustomization --- ## Creating the manifests - All commands below should be executed at the root of the repository .lab[ - Put application manifests in their directory: ```bash mkdir -p apps/dockercoins/manifests cp ~/container.training/k8s/dockercoins.yaml apps/dockercoins/manifests ``` - Create kustomization manifest: ```bash flux create kustomization dockercoins \ --source=GitRepository/flux-system \ --path=./apps/dockercoins/manifests/ \ --target-namespace=dockercoins \ --prune=true --export > apps/dockercoins/flux.yaml ``` ] --- ## Creating the target namespace - When deploying *helm releases*, it is possible to automatically create the namespace - When deploying *kustomizations*, we need to create it explicitly - Let's put the namespace with the kustomization manifest (so that the whole app can be mediated through a single manifest) .lab[ - Add the target namespace to the kustomization manifest: ```bash echo "--- kind: Namespace apiVersion: v1 metadata: name: dockercoins" >> apps/dockercoins/flux.yaml ``` ] --- ## Linking the kustomization manifest - Edit `clusters/dev/flux-system/kustomization.yaml` - Add a line to reference the kustomization manifest that we created: ```yaml - ../../../apps/dockercoins/flux.yaml ``` - `git add` our manifests, `git commit`, `git push` (check with `git status` that we haven't forgotten anything!) - `flux reconcile` or wait for the changes to be picked up --- ## Installing with Helm - We're going to see two different workflows: - installing a third-party chart
(Helm chart)"] H/C["charts/color
(Helm chart)"] A/D["apps/dockercoins/flux.yaml
(HelmRelease)"] A/B["apps/blue/flux.yaml
(HelmRelease)"] A/G["apps/green/flux.yaml
(HelmRelease)"] A/CM["apps/cert-manager/flux.yaml
(HelmRelease)"] A/P["apps/kube-prometheus-stack/flux.yaml
(HelmRelease + Kustomization)"] A/T["traefik/flux.yaml
(HelmRelease)"] C/D["clusters/dev/kustomization.yaml
(Kustomization)"] C/P["clusters/prod/kustomization.yaml
(Kustomization)"] C/D --> A/B C/D --> A/D C/D --> A/G C/P --> A/D C/P --> A/G C/P --> A/T C/P --> A/CM C/P --> A/P A/D --> H/D A/B --> H/C A/G --> H/C A/P --> CHARTS & PV["apps/kube-prometheus-stack/manifests/configmap.yaml
(Helm values)"] A/CM --> CHARTS A/T --> CHARTS CHARTS["Charts on external repos"]