Table of Contents
The primary goal of this project is to exercise with Argo CD based GitOps deployment covering the full cycle - up to production via promotion, if you want to. Experimentation and production should not conflict.
The change process starts at localhost. Hence, we consider kind experience very important. Given that, some elements may be useful in CI context. Most things, should play nice productive environments as well.
Demo using opentofu bootstrapping a single node kind cluster showing deployments,statefulsets and daemonsets as they enter their desired state πͺπ©π°
- Speed : A fast cycle from localhost to production π
- Fail early and loud (notifications)
- Scalability
- Simplicity (yes, really)
- Composability
- Target
kind, vanillaKubernetesand Openshift includingcrc
Stage propagation is hard. Folders, branches, repos, ... you name it. All those come with pros and cons and it ends up being a tradeoff. Apparently, it is so hard that a dedicated project kargo was born to solve it. Long story short:
We have started using kargo, and we are trying the migration following effective processes for monorepos while using a single long lived branch (unchanged as we did before) and the "Rendered Config" pattern. Essential bits appear to be working with the kargo (environment/stage), and we may even get way without changing the folder structure.
We use single level environment staging with one cluster per environment. We do not use names and namespaces in this context, and we don't even dare to do multi-tenancy in a single cluster (OLMv1 drops it). This should help with isolation, loose coupling, support the cattle model and keep things simpler. We want cluster scoped staging. Using another nested level introduces issues ("Matrjoschka Architecture").
We prefer Pull over Push.
We focus on one "Platform Team" managing many clusters using a single repo. It should enable ArgoCD embedding for Application verticals.
Following the App of Apps pattern, our kind-olm root Application is at (envs/kind-olm). The root app kicks off various ApplicationSets covering similarly shaped (e.g. helm/kustomize) apps hosted in apps. Within that folder, we do not want Argo CD resources. This helps with separation and quick testing cycles.
OLM footprint has a bigger footprint than helm and it comes with its own set of issues as well. It is higher level and way more user friendly. With some components (e.g. Argo CD, Loki, LVM) helm is the second class citizen. With others (e.g. Rook), it's the opposite. We prefer first class citizens. Hence, we default to bring in OLM when it is not there initially (such as on kind).
We cover deployments of:
- Argo CD (self managed)
- Argo CD Notifications
- Argo-CD Image-Updater
- Argo Rollouts
- Argo Events
- Operator Lifecycle Management
- Kargo
- Kube-Prometheus
- Loki
- Velero
- Cert-Manager
- Sealed Secrets
- SOPS Secrets
- Submariner
- LitmusChaos
Beyond deployments, we feature:
miseaiming at a more uniform environment locally and in CImakebased tasks- Github Actions integration
- Prometheus Rule Unit Testing
- A bare bones alerting application in case want to send alerts to very custom receivers (like Matrix Chat Rooms)
- Open Cluster Management / Submariner multi-cluster setup (dormant)
- Kargo promotion pipelines β per-app Rendered Configs and whole-env
promotion to a second cluster (see
docs/kargo-promotion.md)
Some opinions first:
- YAML at scale is ... terrible. Unfortunately, there is no way around.
- CI/CD usually comes with horrible DX: β.. itβs this amalgamation of scripts in YAML tied together with duct tape.β
- CI/CD should enable basic inner loop local development. Should not be
git commit -m hoping-for-the-best && git push - Naming ... is hard
- Joining clusters is hard (e.g. Submariner)
- Beware of Magic π©πͺπ° (e.g. Argo CD helm release changes when Prometheus CRDs become available)
- Beware of helm shared values or kustomize base. We deploy
mainand shared bits kick in on all environments. - Versions/Refs: Pin or Float? It depends. We should probably pin things in critical environments and keep things floating a bit more elsewhere
- Don't try too hard modeling deps and ordering. Failing to start a few times can be perfectly fine. Honor this modeling your alerts.
- We should propagate to production frequently.
- Rebuilding whole things automatically from scratch matters a lot. Drift kicks in fast and it helps with Recovery.
- Bootstrapping OLM is painful - thanks god, there is a helm chart these days.
- Using Kubernetes bits in Terraform (e.g.
helm,kustomize,kubectl,kubernetesproviders), only use the bare minimum (because deps are painful) This is an example of how you may give instructions on setting up your project locally. To get a local copy up and running follow these simple example steps.
makekubectlmise(highly recommended)docker(if usingkind)opentofu(required to bring up a cluster)helm(only for the deprecated no-opentofu install path)
For basic demo purposes, you can use this public repo. If you want to run against your own, replace the git server reference with your own.
The root Makefile is the entrypoint. Run make for the full
list of targets; the Clusters section brings everything up from scratch
(kind cluster β cilium β Argo CD β root app) via the OpenTofu module in
./tf, which it drives for you:
make cluster-up # default hub cluster (helm flavor) - the usual entrypoint
make cluster-workload-up # optional second "workload" cluster (pull model)
make kargo-connect # wire the workload Kargo shard back to the hub
make cluster-down # tear the current cluster back downcluster-up picks the right tofu workspace and tfvars per cluster, so you
never touch tofu workspace directly. The OLM-preferring kind-olm flavor is
built the same way but in its own workspace with tf/terraform-batman.tfvars
(see tf/ for the underlying apply/quick-destroy engine, and
docs/kargo-promotion.md for the two-cluster
promotion flow).
Deprecated: install Argo CD into a pre-existing cluster (no OpenTofu)
Before OpenTofu was required, the root Makefile could install Argo CD into a
cluster you had already created (it did not create the kind cluster). Those
targets still exist but are deprecated β prefer make cluster-up:
make argocd-helm-install-basic argocd-apply-root boots the olm-less
kind-helm flavor (bringing in cert-manager, grafana-operator and the OCM
cluster-manager as helm charts), while
make argocd-olm-install-basic argocd-apply-root ENV=kind-olm boots the
OLM-preferring kind-olm flavor.
Our preferred approach to secrets is sealed-secrets (have a look at gen-keys.sh in case you'd like to use sops instead).
If using github, you may want to disable github actions and/or add a public deployment key.
gh repo deploy-key add ...
If you want to see what a target will do before running it, dry-run it first:
make -n cluster-up
Run it without -n once you feel confident to get the ball rolling.
The deployment will deploy a SealedSecret. It will fail during decryption, because we won't be sharing our key. It is meant to be used with Argo Notifications, so it is not critical for a basic demo. Feel free to introduce your own bootstrap secret.
We want lifecycle of things (Create/Destroy) to be as fast as possible. Pulling images can slow things down significantly. Contrary docker a host based solution (such as k3s), challenges are harder with kind. Make sure to understand your the defails of your painpoints before implementing your solution.
- Local Registry
- Pull-through Docker registry on Kind clusters (
registry:2supports only one registry per instnance) kind loadmay address some use cases- Remove everything in
kindinstalled by Argo CD (so we can rebuild from cached images).
The kind-olm and kind-helm environments deploy a bare, single-pod
Gitea (apps/infra/gitea) to
act as an in-cluster git remote for quick Argo CD sync experiments β edit,
push, sync without leaving the cluster or waiting on GitHub.
Admin credentials are the chart defaults β gitea_admin / r8sA8CPHD9!bt6d β
a local throwaway, fine for kind. Reach the UI/API from the host via
kubectl -n gitea port-forward svc/gitea-http 3000:3000Create a repo (make it public and Argo CD needs no repo credentials) and push:
curl -su 'gitea_admin:r8sA8CPHD9!bt6d' -X POST localhost:3000/api/v1/user/repos \
-H 'Content-Type: application/json' -d '{"name": "sync-lab", "auto_init": true}'
git clone 'http://gitea_admin:r8sA8CPHD9%21bt6d@localhost:3000/gitea_admin/sync-lab.git'From inside the cluster β i.e. as an Application repoURL β the same repo is
http://gitea-http.gitea.svc.cluster.local:3000/gitea_admin/sync-lab.git
Repositories and the sqlite database live on a small PVC, so they survive pod restarts β but they are pruned together with the gitea app itself.
For a scripted end-to-end pass of exactly this loop, run
tools/gitea-sync-demo.sh: it creates a repo,
pushes manifests, points a throwaway Application at it and verifies initial
sync, update, prune and self-heal before cleaning up after itself. The script
is deliberately imperative β everything it touches is ephemeral demo state
that is removed on exit, so the declarative rule ("edit manifests, commit, let
Argo CD sync") still holds for anything durable.
Tracked work items live in docs/TODO.md.
- Alert only if certain time passed
- Wildcards in Argo CD sourceNamespaces prevent resource creation
argcocdcli does not support apps with multiple sources.- Support configuration of HTTP_PROXY, HTTPS_PROXY and NO_PROXY for Gateway DaemonSet
- Appears there is not straight forward way to make OLM Deployments use one pod per Deployment/Replica
- Create a dry run tool for ConfigurationPolicy
- RFE Create tools to assist in Policy development
- Operator cannot be upgraded with the error "Cannot update: CatalogSource was removed" while the CatalogSource exists in OpenShift 4
- OLMv1 Design Decisions
- Kustomized Helm (Application plugin)
- Bootstrapping: ApplicationSets vs App-of-apps vs Kustomize
- Argo CD 2.10: ApplicationSet full templating
- viaduct-ai/kustomize-sops
- Introduction to GitOps with Argo CD
- 3 patterns for deploying Helm charts with Argo CD
- Self Managed Argo CD β App Of Everything
- Setting up Argo CD with Helm
- terraform-argocd-bootstrap
- Argo CD with Kustomize and KSOPS using Age encryption
- https://blog.devgenius.io/argocd-with-kustomize-and-ksops-2d43472e9d3b
- https://github.com/majinghe/argocd-sops
- https://dev.to/callepuzzle/secrets-in-argocd-with-sops-fc9
- Argo CD Application Dependencies
- Progressive Syncs (alpha)
- Custom Root CAs in OpenShift
- Finding: vind (vCluster in Docker) as a kind replacement β why we stay on
kindfor now
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature) - Commit your Changes (
git commit -m 'Add some AmazingFeature') - Push to the Branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Distributed under the MIT License. See LICENSE.txt for more information.
