Platform Base architecture
Platform Base is a Jsonnet library, not a running service. It renders Argo CD Applications, and Argo CD does the work of installing and syncing the components.
From Git to a running cluster
You render your cluster/main.jsonnet twice with different arguments:
root=trueproduces the bootstrap, which you apply by hand once. It contains theargocdNamespace, the Argo CD installation withargocd-cmandargocd-cmd-params-cmalready patched, the repository credentials Secret if you enabledargocd.platformRepoCreds, the sidecars of enabled Config Management Plugins, and thebootstrapApplication.root=falseproduces one Argo CD Application for each component. ThebootstrapApplication keeps syncing this output from Git, so a change to your repository changes the cluster.
The bootstrap Application forwards $ARGOCD_APP_SOURCE_REPO_URL,
$ARGOCD_APP_REVISION and $ARGOCD_APP_SOURCE_PATH to main.jsonnet as
repoURL, revision and pathPrefix. It also passes the dynamicConfig
you rendered the bootstrap with. Every component Application therefore points
at the same repository and revision as the bootstrap.
The Application contract
All Applications are built the same way:
- They live in the
argocdnamespace and use thedefaultproject. - They deploy to the local cluster.
- They sync automatically, with prune and self-heal on, and with server-side apply.
- They carry the
resources-finalizer.argocd.argoproj.iofinalizer, so deleting an Application deletes what it deployed.argo-cd-coreis the exception: it has no finalizer, so deleting it leaves Argo CD installed.
A component Application either renders a Jsonnet directory of Platform Base
(main.jsonnet, with its configuration passed as a top-level argument), or a
vendored Helm chart (Traefik, the Keycloak operator of EDP, Grafana Operator,
Alloy, kube-state-metrics, node-exporter, Loki and Mimir), with Helm values
generated from the configuration. In both cases the configuration is part of
the Application spec. The applications reference
lists them all.
Ordering
There are no sync waves, so the Applications are independent of each other. Some of them need another one first, and converge through retries:
| Application | Waits for |
|---|---|
iam | keycloak-operator and keycloak-operator-edp to reconcile its Keycloak and realm resources |
argocd-config, grafana | The EDP operator's CRDs and the realms from iam, for their Keycloak clients |
loki, mimir-distributed | carvel-secret-gen, which generates the credentials of the bundled MinIO |
tls | cert-manager for the Issuer and Certificate, traefik for the TLSStore |
| Monitors, rules and alerts | prometheus-crds, which installs the Prometheus Operator CRDs |
The admission webhooks of the EDP operator need cert-manager, so creating a Keycloak client fails until the webhook certificate is issued.
How configuration flows
Configuration flows in one direction. config.libsonnet holds the options you
override, apps.libsonnet wires them into the components, and each
component's defaults.libsonnet holds its own settings. Components never
read the global configuration, they only share what they publish as
outputs. For example, Grafana learns the Mimir and Loki endpoints from their
outputs.
Hostnames and certificates
Argo CD, Grafana and Keycloak get an Ingress with a hostname derived from
baseDomains, as do the optional Loki and Mimir endpoints. Traefik redirects
HTTP to HTTPS.
The tls Application creates one Certificate for all baseDomains and
their wildcards, and a Traefik TLSStore named default that uses it as the
default certificate. The Ingresses do not name a TLS Secret, so they all use
that certificate. With the default issuer the certificate is self-signed.