Skip to content

Instantly share code, notes, and snippets.

@scottrigby
Last active February 3, 2023 20:12
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scottrigby/e835157370763de7609db0c73558ffa9 to your computer and use it in GitHub Desktop.
Save scottrigby/e835157370763de7609db0c73558ffa9 to your computer and use it in GitHub Desktop.
Introduction to GitOps & The Flux Family of Projects

Introduction to GitOps & The Flux Family of Projects

Set up local cluster and Flux CLI

  1. Install Flux CLI and Kind:

    $ brew reinstall flux kind
    $ kind --version
    kind version 0.11.1
    $ flux --version
    flux version 0.16.2
  2. Create local demo cluster

    $ kind create cluster --name flux
    (took 37s)

Set up for Flux with GitHub as source

  1. Make Personal Access Token for creating repositories

    1. Check all permissions under repo
    2. Copy PAT to buffer
  2. Export env vars locally

    $ read -s GITHUB_TOKEN
    [paste PAT]
    $ export GITHUB_TOKEN=$GITHUB_TOKEN

Bootstrap Flux both for your source and in cluster

  1. Simple bootstrap:

    $ flux bootstrap github \
    --owner scottrigby \
    --personal \
    --private \
    --repository flux-demo \
    --path=clusters
    ► connecting to github.com
    ✔ repository "https://github.com/scottrigby/flux-demo" created
    ► cloning branch "main" from Git repository "https://github.com/scottrigby/flux-demo.git"
    ✔ cloned repository
    ► generating component manifests
    ✔ generated component manifests
    ✔ committed sync manifests to "main" ("8122eb8f6cd0c520a757aafde01462946e2b07e8")
    ► pushing component manifests to "https://github.com/scottrigby/flux-demo.git"
    ► installing components in "flux-system" namespace
    ✔ installed components
    ✔ reconciled components
    ► determining if source secret "flux-system/flux-system" exists
    ► generating source secret
    ✔ public key: ssh-rsa ****
    ✔ configured deploy key "flux-system-main-flux-system-./clusters" for "https://github.com/scottrigby/flux-demo"
    ► applying source secret "flux-system/flux-system"
    ✔ reconciled source secret
    ► generating sync manifests
    ✔ generated sync manifests
    ✔ committed sync manifests to "main" ("06360186166df1ebbba33b5be07bea60b77e39f1")
    ► pushing sync manifests to "https://github.com/scottrigby/flux-demo.git"
    ► applying sync manifests
    ✔ reconciled sync configuration
    ◎ waiting for Kustomization "flux-system/flux-system" to be reconciled
    ✔ Kustomization reconciled successfully
    ► confirming components are healthy
    ✔ source-controller: deployment ready
    ✔ kustomize-controller: deployment ready
    ✔ helm-controller: deployment ready
    ✔ notification-controller: deployment ready
    ✔ all components are healthy
    (took 1m12s)
  2. Show GitRespository CR representing the instructions for Flux to sync the Git repo with the cluster

$ kubectl get gitrepositories.source.toolkit.fluxcd.io -A
NAMESPACE     NAME          URL                                         READY   STATUS                                                            AGE
flux-system   flux-system   ssh://git@github.com/scottrigby/flux-demo   True    Fetched revision: main/06360186166df1ebbba33b5be07bea60b77e39f1   7m33s
  1. Clone the newly created git repo to your local workspace

    $ cd ~/code/github.com/scottrigby
    $ git clone git@github.com:scottrigby/flux-demo.git
    $ cd flux-demo
    $ tree
    .
    └── clusters
        └── flux-system
            ├── gotk-components.yaml
            ├── gotk-sync.yaml
            └── kustomization.yaml
    
    2 directories, 3 files

    We now have a git repo hooked up to our cluster and syncing regularly, without using kubectl apply. I can drop manifests directly into this repository, and they'll show up automatically in my cluster.

Deploy using only Git

  1. Create a default namespace directory in Git to help with organization (files can be organized however you like)

    mkdir -p clusters/default
  2. Add a frontend app deployment in the default namespace in Git (https://github.com/stefanprodan/podinfo/blob/master/deploy/bases/frontend/deployment.yaml)

    $ curl -O https://raw.githubusercontent.com/stefanprodan/podinfo/master/deploy/bases/frontend/deployment.yaml
    $ cp deployment.yaml clusters/default
    
    $ tree
    .
    └── clusters
        ├── default
        │   └── deployment.yaml
        └── flux-system
            ├── gotk-components.yaml
            ├── gotk-sync.yaml
            └── kustomization.yaml
    
    3 directories, 4 files
    
  3. From this point on, you are doing GitOps by interacting with your Desired State source:

    $ git add clusters/default/deployment.yaml
    $ git commit -m "Deploy a new frontend app"
    $ git push
    Enumerating objects: 7, done.
    Counting objects: 100% (7/7), done.
    Delta compression using up to 8 threads
    Compressing objects: 100% (3/3), done.
    Writing objects: 100% (5/5), 1.62 KiB | 1.62 MiB/s, done.
    Total 5 (delta 0), reused 0 (delta 0), pack-reused 0
    To github.com:scottrigby/flux-demo.git
      0636018..c401836  main -> main

    Note the old and new commit SHA.

  4. Poke reconciliation for faster demo (in a non-local cluster you may automate this with a webhook for the same effect)

    $ flux reconcile source git flux-system
    ► annotating GitRepository flux-system in flux-system namespace
    ✔ GitRepository annotated
    ◎ waiting for GitRepository reconciliation
    ✔ GitRepository reconciliation completed
    ✔ fetched revision main/c401836af99f60a64786033d4643b1edac5305c3
    (took 4s)
    
    $ k get deploy -n default
    NAME       READY   UP-TO-DATE   AVAILABLE   AGE
    frontend   1/1     1            1           2m33s

    Note it fetched the new commit SHA.

  5. Show the GitRepository CR is at the new commit SHA

$ kubectl get gitrepositories.source.toolkit.fluxcd.io -A
NAMESPACE     NAME          URL                                         READY   STATUS                                                            AGE
flux-system   flux-system   ssh://git@github.com/scottrigby/flux-demo   True    Fetched revision: main/c401836af99f60a64786033d4643b1edac5305c3   30m

Show automated applying

We have a separate application, called Kustomization Controller, which is able to apply plain manifests or Kustomize directories to your cluster.

  1. Get the Kustomize CR that's syncing our Git source to the cluster:
$ kubectl get kustomizations.kustomize.toolkit.fluxcd.io -A
NAMESPACE     NAME          READY   STATUS                                                            AGE
flux-system   flux-system   True    Applied revision: main/c401836af99f60a64786033d4643b1edac5305c3   49m

$ kubectl get kustomizations.kustomize.toolkit.fluxcd.io -A -o yaml
...
spec:
  force: false
  interval: 10m0s
  path: ./clusters
  prune: true
  sourceRef:
    kind: GitRepository
    name: flux-system
  validation: client
...
  1. Suspend reconciliation of a Kustomization
$ flux suspend kustomization flux-system -n flux-system
► suspending kustomizations flux-system in flux-system namespace
✔ kustomizations suspended

$ kubectl get kustomizations.kustomize.toolkit.fluxcd.io -A -o yaml
...
spec:
  force: false
  interval: 10m0s
  path: ./clusters
  prune: true
  sourceRef:
    kind: GitRepository
    name: flux-system
  suspend: true
  validation: client
...

Note that the suspend key is now added with a value of true. It is generally not advisable to commit suspend: false to your CR, because this would make suspending during incident management more difficult by platform teams in a break glass scenario.

This suspend of the Kustomization is separate from the syncing of the GitRepository, which is still ready and syncing to the cluster. You can also suspend the GitRepository, and other Custom Resources managed by Flux. See flux suspend --help for more.

  1. Resume reconciliation of a resource
$ flux resume kustomization flux-system -n flux-system
► resuming kustomizations flux-system in flux-system namespace
✔ kustomizations resumed
◎ waiting for Kustomization reconciliation
✔ Kustomization reconciliation completed
✔ applied revision main/c401836af99f60a64786033d4643b1edac5305c3

The magic of GitOps here is that I don't need to use kubectl apply and I have a deployment just by pushing to Git. I can be confident that the revision is correct because Git provides a complete audit log, and the flux CLI and controllers clearly surface exactly what is happening including which revision is applied.

Cleanup

  1. Delete local cluster

    kind delete cluster --name flux
  2. Delete demo repo & PAT from GitHub

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment