A teaching-first, single-cluster GitOps setup: Talos Linux + Argo CD with an app-of-apps layout, MetalLB pre-installed for real LoadBalancer IPs on bare metal, a demo app, and a progressive docs/ walkthrough with a CLAUDE.md tutor persona and guided bootstrap checklist. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
92 lines
4.3 KiB
Markdown
92 lines
4.3 KiB
Markdown
# 08 — Growing up: what to add next
|
|
|
|
Everything up to here is deliberately minimal — enough to understand the
|
|
whole loop, nothing more. This doc is a map of the natural next steps, each
|
|
with why you'd want it and roughly what it involves. None of it is built
|
|
for you; each is its own project once you're ready.
|
|
|
|
## More nodes
|
|
|
|
Right now, one machine is both control plane and worker
|
|
(`allowSchedulingOnControlPlanes: true` in
|
|
[`talos/patch-controlplane.yaml`](../talos/patch-controlplane.yaml)). That's
|
|
a single point of failure: if that machine dies, the cluster is gone.
|
|
|
|
To grow beyond it:
|
|
|
|
1. Boot a second machine from the Talos ISO, same as the first.
|
|
2. Generate a **worker** config instead of a control-plane one — you
|
|
already have `_out/worker.yaml` from
|
|
[`docs/02-talos-bootstrap.md`](02-talos-bootstrap.md), unused until now.
|
|
3. `talosctl apply-config --insecure --nodes <NEW_NODE_IP> --file _out/worker.yaml`
|
|
4. `kubectl get nodes` should show two nodes shortly after.
|
|
|
|
For real resilience against a control-plane node failing (not just adding
|
|
worker capacity), you'd want an odd number of control-plane nodes — 3 is
|
|
the normal minimum — because etcd (the cluster's data store) uses majority
|
|
voting to agree on state, and majority voting needs an odd number to avoid
|
|
ties. That's a bigger step than this doc covers in detail; ask Claude when
|
|
you're actually ready to take it.
|
|
|
|
## Ingress
|
|
|
|
Right now, thanks to MetalLB ([`docs/05-metallb.md`](05-metallb.md)), the
|
|
demo app gets its own dedicated IP address
|
|
(see [`apps/demo/service.yaml`](../apps/demo/service.yaml)). That's a real
|
|
improvement over NodePort, but it doesn't scale past a handful of apps
|
|
either: every app still needs its own IP address out of a pool that's only
|
|
so big, and there's no way to route by hostname (`app1.example.com` vs
|
|
`app2.example.com` sharing one IP on port 443).
|
|
|
|
An **Ingress controller** is itself just another app you'd deploy the same
|
|
way as anything else in this repo (see
|
|
[`docs/07-adding-new-apps.md`](07-adding-new-apps.md)) — commonly as a
|
|
Helm-based app, since most ingress controllers are distributed that way,
|
|
same as MetalLB. It typically sits behind one single MetalLB
|
|
`LoadBalancer` Service (one IP, total, for every app), and you add an
|
|
`Ingress` resource per app instead of giving each one its own
|
|
`LoadBalancer` Service — trading "one IP per app" for "one IP, many
|
|
hostnames."
|
|
|
|
## cert-manager
|
|
|
|
Once you have Ingress and real hostnames, you'll want HTTPS. `cert-manager`
|
|
is the standard tool for this — it watches for certificate requests and
|
|
automatically obtains and renews them (commonly via Let's Encrypt). Also
|
|
just another app in this repo's structure once you get there.
|
|
|
|
## Secrets management
|
|
|
|
**This repo is public. Never commit a plaintext secret, credential, token,
|
|
or private key to it — anyone can read your Git history, forever, even if
|
|
you delete the file in a later commit.**
|
|
|
|
Kubernetes' own `Secret` resource does not encrypt anything — it just
|
|
base64-encodes data, which is not encryption, only encoding (trivially
|
|
reversible by anyone). None of the manifests in this repo need secrets yet,
|
|
which is exactly why this hasn't come up so far. When you add something
|
|
that does (a database password, an API key), you need one of:
|
|
|
|
- **[Sealed Secrets](https://github.com/bitnami-labs/sealed-secrets)** —
|
|
encrypts a secret using a key that only your cluster holds, producing a
|
|
`SealedSecret` file that's safe to commit; the cluster decrypts it into a
|
|
normal Secret on the fly.
|
|
- **[SOPS](https://github.com/getsops/sops)** (often paired with Argo CD via
|
|
a plugin) — encrypts values inside a normal-looking YAML file using a key
|
|
from a system like age or a cloud KMS, decrypted at sync time.
|
|
|
|
Either is a reasonable choice; don't improvise your own approach. Ask
|
|
Claude to walk you through setting one up when you have a real secret to
|
|
manage — it's a short, well-trodden path once you're at that point.
|
|
|
|
> **Ask Claude:** if you're about to commit anything you're even slightly
|
|
> unsure about, paste it (or describe it) and ask first. Cheaper than a
|
|
> `git filter-branch` later.
|
|
|
|
## Where to go from here
|
|
|
|
You've now seen the whole shape: Talos underneath, Argo CD watching Git,
|
|
app-of-apps organizing what it manages. Everything in this doc is more of
|
|
the same pattern — a new app, a new file, a push. Pick whichever expansion
|
|
is actually useful to you and start there.
|