Highly customizable GitOps pipeline built with Helm
APPENDIX: The end of Kustomize vs Helm argument
- Helm is a package manager for K8s
- "Package" is called "Chart" in Helm
WHAT: Auditability(Every change is git-trackable) / Security(less priv in CI) HOW: Pull desired state / Sync K8s resources Git → Cluster
flux
fetches git commits and reconsile K8s resources.helm-operator
reconcilesHelmRelease
resources to reconsile K8s resources.
- Fetches git commits to reconcile K8s resources
- Plug-in any K8s manifests builder (kustomize, helm, ksonnet, kubecfg, etc.)
PLUG: Wanna declaratively manage Argo CD projects? Use the community Helm chart
- Limited Customizability
- High Number of Total Moving-Parts
flux
and argocd
has limited extension points.
ex) argocd
supports custom "hooks".
- But the deployment is hard-coded to
kubectl apply
. - How to
helm install
it?
Worth maintaining both CI and CD systems separately? Your team size?
CI (lint, diff, test on PUSH): Travis, CircleCI, Concourse, Jenkins, Argo CI, ...
CD (deploy/sync/reconcile on PULL): Flux, Argo CD, Spinnaker, ...
- Flux
- Argo CD
- MISSING PIECE = Single customizable system that handles both CI and CD
brigade
is K8s scripting system- Basically CI system whose pipelines are written in JavaScript(Turing-Complete!)
https://github.com/brigadecore/brigade
-
brigade(an open, event-driven K8s scripting platform) as an universal workflow engine that runs both CI and GitOps/CD pipelines
-
helmfile to declaratively manage all the apps on K8s. Use whatever you like tho.
- Write the desired state of your cluster
- Edit & develop locally
- Push Git commit
- CI: Test on PR
- CD: Apply on commit to
master
-
Create a GitHub App for Brigade following this guide
-
Set envvars:
export NGROK_TOKEN=<Your ngrok token shown in https://dashboard.ngrok.com/get-started> export BRIGADE_GITHUB_APP_KEY=<Local path to the private key file for TLS client auth from the step 2> export BRIGADE_GITHUB_APP_ID=<App ID from the step 2> export BRIGADE_PROJECT_SECRET=<Webhook (shared) secret from the step 2> export SSH_KEY=$HOME/.ssh/id_rsa (Or whatever ssh private key you want Brigade to use while git-cloning private Git repos) export GITHUB_TOKEN=<Used for updating commit/pull request statuses>
SPOILER: We use this locally and remotely:
helmfile.yaml
:
releases:
- name: frontend
chart: flagger/podinfo
namespace: test
values:
- nameOverride: frontend
See helmfile.yaml for the full example.
a.k.a
helm upgrade --install \
frontend flagger/podinfo \
--set nameOverride=frontend`
Run:
# See what will be installed
$ helmfile diff
# Actually install all the things
$ helmfile apply
- Brigade Server
- Brigade GitHub App
- Brigade Project
- In-Cluster Ngrok Tunnel (GitHub Webhooks to Brigade GitHub App
- Other apps for demonstration purpose
Run:
$ git checkout -b change-blah
$ $EDITOR helmfile.yaml
(Again,) Run:
$ helmfile diff
$ helmfile apply
Run:
$ git add helmfile.yaml && \
git commit -m 'Change blah' && \
git push origin master
$ hub pull-request
So that Brigade
(Again) Runs:
$ helmfile diff
Review the PR on GitHub.
- Merge the pull request into
master
so that brigade
pulls the commit and applies it by (AGAIN!) running:$ helmfile apply
Voila! You've implemented GitOps.
The brigade
script looks like:
const { events, Job , Group} = require("brigadier")
const dest = "/workspace"
const image = "mumoshu/helmfile-gitops:dev"
events.on("push", (e, p) => {
console.log(e.payload)
var gh = JSON.parse(e.payload)
if (e.type == "pull_request") {
// Run "helmfile diff" for PRs
run("diff")
} else {
// Run "helmfile apply" for commits to master
run("apply")
}
});
See brigade.js for full example.
function run(cmd) {
var job = new Job(cmd, image)
job.tasks = [
"mkdir -p " + dest,
"cp -a /src/* " + dest,
"cd " + dest,
`helmfile ${cmd}`,
]
job.run()
}
Another GitOps solution that helps!
- Flux
- Argo CD
- Brigade (PROPOSED!)
Try youself!
https://gitpitch.com/mumoshu/helmfile-gitops
"The end of the "Kustomize vs Helm argument"
helm template mychart | kubectl apply -f
helm template mychart --outputs-dir manifests/ && (kustomize build | kubectl apply -f -)
When you want:
helm diff
: Preview changes before applyhelm test
: Run tests included in the charthelm stauts
: List helm-managed resources and the installation notehelm get values
: Which settings I used when installing this?
- (Optionally) Generate K8s manifests from Helm chart
- Patch K8s manifests with Kustomize (JSON Patch and Strategic-Merge Patch available)
- Install the patched manifests with Helm
Shameless Plug: https://github.com/mumoshu/helm-x
helm
:
$ helm install myapp mychart
helm-x
:
$ helm x install myapp mychart
Patch and diff/install/up whatever "as Helm chart":
$ helm x [diff|install|upgrade] --install myapp WHAT --version 1.2.4 \
-f values.yaml \
--strategic-merge-patch path/to/strategicmerge.patch.yaml \
--jsonpatch path/to/json.patch.yaml
WAHT can be:
- Helm chart
- Kustomization
- Directory containing K8s maniefsts
You've got everything!
- GitOps operator (Flux or Argo CD) OR Universal system for running CI and CD pipelines (brigade)
- Universal tool for deploying whatever (helm, kustomize, k8s manifests, helm-x, helmfile)
@mumoshu
AWS Container Hero
OSS enthusiast maintaining 10+ K8s-related OSS: