Initial commit: GitOps Starter Pack
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>
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
# 00 — What is all this?
|
||||
|
||||
You're comfortable with servers, SSH, config files, and the command line.
|
||||
You've probably never touched Kubernetes. This doc gives you the mental
|
||||
model before you type a single command — everything after this builds on
|
||||
it.
|
||||
|
||||
## The problem this stack solves
|
||||
|
||||
Say you run a few services on a server. The traditional way: SSH in,
|
||||
install things, edit config files by hand, restart services, and remember
|
||||
what you did (or don't, and regret it later). It works, but nothing
|
||||
records *why* the server looks the way it does — the truth lives only on
|
||||
that one machine, in your head, and in shell history if you're lucky.
|
||||
|
||||
This stack solves that by making a **Git repository** the single source of
|
||||
truth for "what should be running," and using software to continuously make
|
||||
the real cluster match it. You stop making changes by hand. You edit a file,
|
||||
push it, and a robot applies it for you — the same way every time, with a
|
||||
record of every change in `git log`.
|
||||
|
||||
## The five pieces, in plain terms
|
||||
|
||||
**Kubernetes** is software that runs on one or more machines and manages
|
||||
containers for you: starts them, restarts them if they crash, and moves
|
||||
them to a different machine if one dies (once you have more than one — see
|
||||
[`docs/08-growing-up.md`](08-growing-up.md)). You describe the end state you
|
||||
want ("run one copy of this"); Kubernetes' job is to make that true and keep
|
||||
it true. This is what people mean by **declarative**: you state the
|
||||
destination, not the steps to get there.
|
||||
|
||||
**Talos Linux** is the operating system your machine runs. It's built for
|
||||
exactly one purpose — running Kubernetes — and nothing else. There's no SSH,
|
||||
no shell, no package manager to fiddle with by hand. You configure it by
|
||||
sending it a config file over the network (a "machine config"), the same
|
||||
declarative idea as Kubernetes itself, just one layer lower. Less to
|
||||
install, less to secure, less that can drift out of a known state.
|
||||
|
||||
**Argo CD** is the piece that watches a Git repository — this one — and
|
||||
continuously makes the cluster match whatever it finds there. This is
|
||||
called **GitOps**: Git isn't just where your config *lives*, it's where
|
||||
change *happens*. You don't run `kubectl apply` for day-to-day changes;
|
||||
you edit a file, commit, push, and Argo CD does the applying.
|
||||
|
||||
**App of apps** is the pattern this repo uses to organize what Argo CD
|
||||
manages. Rather than one Application resource pointing at everything, one
|
||||
Application — the app-of-apps — watches a folder (`apps/`) full of *other*
|
||||
Application definitions, each pointing at its own small piece. Add a new
|
||||
app by adding a new file — see
|
||||
[`docs/07-adding-new-apps.md`](07-adding-new-apps.md).
|
||||
|
||||
**MetalLB** solves a specific problem: on a cloud provider, asking for a
|
||||
public IP address for a service is one API call away; on your own bare
|
||||
metal machine, nothing hands those out automatically. MetalLB runs inside
|
||||
the cluster and fills that gap, so apps here can get a real, dedicated IP
|
||||
address on your network instead of an awkward fixed port. It's pre-installed
|
||||
in this repo, not a "next step" — see [`docs/05-metallb.md`](05-metallb.md).
|
||||
|
||||
## Architecture — the shape of what you'll build
|
||||
|
||||
```
|
||||
┌─────────────────────────┐
|
||||
│ Git repository (this │
|
||||
│ repo, on GitHub) │
|
||||
│ │
|
||||
│ apps/demo.yaml │
|
||||
│ apps/demo/*.yaml │──┐
|
||||
│ apps/metallb.yaml │ │ watched by
|
||||
│ apps/metallb/* │ │
|
||||
└─────────────────────────┘ │
|
||||
▼
|
||||
┌───────────────────┐
|
||||
│ Argo CD │ runs inside the cluster
|
||||
│ (installed once, │
|
||||
│ imperatively) │
|
||||
└─────────┬──────────┘
|
||||
│ applies manifests
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ Talos Linux node │
|
||||
│ (control plane + worker, │
|
||||
│ single node) │
|
||||
│ │
|
||||
│ ┌────────────┐ ┌──────────┐ │
|
||||
│ │demo │ metallb- │ │
|
||||
│ │namespace: │ system: │ │
|
||||
│ │nginx Pod ⇄ │ hands out │ │
|
||||
│ │Service │ a real IP │ │
|
||||
│ │(LoadBalancer)◄─address to │ │
|
||||
│ │ │ that Service│ │
|
||||
│ └────────────┘ └──────────┘ │
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
Everything below the Git repo is a *consequence* of what's in Git. If the
|
||||
box labelled "Talos Linux node" burned to the ground and you rebuilt it from
|
||||
scratch, replaying this repo against it would recreate everything except the
|
||||
raw OS bootstrap (docs/02), the one-time Argo CD install (docs/03), and the
|
||||
handful of network-specific addresses you choose in docs/05 — all
|
||||
deliberately kept outside the loop, since something has to start it and
|
||||
nothing in Git can know your LAN's IP layout for you.
|
||||
|
||||
## The reconciliation loop
|
||||
|
||||
This is the mechanism that makes GitOps actually work, not just a nice
|
||||
diagram. Argo CD repeats this forever, by default every few minutes (and
|
||||
instantly, if you ask it to):
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ 1. Read desired state from Git │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ 2. Read actual state from the cluster │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ 3. Diff them │
|
||||
│ │ │
|
||||
│ ┌────┴────┐ │
|
||||
│ │ │ │
|
||||
│ no diff diff found │
|
||||
│ │ │ │
|
||||
│ │ ▼ │
|
||||
│ │ 4. Apply the change so the │
|
||||
│ │ cluster matches Git │
|
||||
│ │ │ │
|
||||
│ └────┬─────┘ │
|
||||
│ ▼ │
|
||||
│ wait, then repeat │
|
||||
│ │
|
||||
└────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
"Reconciliation" just means step 3 and 4: noticing a difference between what
|
||||
should exist and what does, and fixing it. This loop is also what makes
|
||||
Argo CD self-healing — if someone changes the cluster by hand (`kubectl edit`
|
||||
during an emergency, say), the very next loop notices the drift from Git and
|
||||
reverts it. Git wins, always. That's the whole point.
|
||||
|
||||
> **Ask Claude:** before moving on, try asking "why does Git winning matter —
|
||||
> what goes wrong without it?" It's worth being able to answer in your own
|
||||
> words before you start building.
|
||||
|
||||
## What's next
|
||||
|
||||
Continue to [`docs/01-prerequisites.md`](01-prerequisites.md), or jump
|
||||
straight to [`docs/checklist.md`](checklist.md) if you'd rather work through
|
||||
a condensed step-by-step list with Claude alongside you.
|
||||
Reference in New Issue
Block a user