feat(P7): doctor ingress + docs + integration tests (REQ-177,178,179)
New 'orca doctor ingress' command: verifies podman orca-traefik
container running, nft DNAT+SNAT, /etc/traefik/dynamic exists,
step-ca root CA present.
UAT signoff script: replaced assertion 36 (systemd → podman
container), added assertions 40-46 (nft table, DNAT, SNAT, dynamic
dir, step-ca CA, traefik.yml, doctor ingress pass).
docs/ingress.md: R-024 podman traefik section — three topologies,
container config, nft ruleset, doctor ingress, Dockerfile.traefik.
TLS model updated (drop certResolver, tls:{} for v0.14, mTLS v0.15).
ARCHITECTURE.md: v0.14 deltas section — R-024, three topologies,
nft emitter changes, TLS model, migration 0009, new CLI.
Integration tests (tests/ingress_bootstrap_test.go): nft postrouting
+ DNATTarget, priority -10, traefik TLS model (tls:{} no
certResolver), image ref resolution, floating-IP LXC provisioning
commands (pct create with hwaddr/ip/gw/features), MAC generation.
---ci---
project: orca
phase: 7
milestone: v0.14
status: execute
---/ci---
This commit is contained in:
@@ -872,3 +872,70 @@ scheduler.Schedule(spec, nodes) → emitter.Render(unit) → sshpush.Deploy(targ
|
||||
- IPv6 `net.JoinHostPort` in all SSH dial paths.
|
||||
- Explicit timeouts on all SSH commands.
|
||||
- Root SIGINT/SIGTERM handler for clean exit on non-watch commands.
|
||||
|
||||
## v0.14 Deltas — Ingress Bootstrap Completeness (R-024)
|
||||
|
||||
### R-024: Traefik as Podman Container
|
||||
|
||||
Traefik runs exclusively as a podman container, deployed from the
|
||||
custom `orca-traefik` image (published per release via `Dockerfile.traefik`
|
||||
+ `scripts/release.sh` + `.coreci.yml container-publish-traefik`).
|
||||
|
||||
The v0.13 binary+systemd install (`internal/traefik/install.go`) is
|
||||
replaced by an idempotent podman container reconciler
|
||||
(`EnsureTraefikContainerLocal`/`Remote`). The container runs with
|
||||
`--network host`, `--restart=unless-stopped`, and volume mounts for
|
||||
`traefik.yml` (static config), `dynamic` (dynamic config), and
|
||||
`step-ca-root.crt` (future mTLS). No SELinux `:Z` flag.
|
||||
|
||||
### Three Ingress Topologies
|
||||
|
||||
1. **Linux** (`orca init` / `orca node join --type linux`):
|
||||
host → nft DNAT → podman traefik (host network).
|
||||
`internal/ingress/bootstrap.go` → `BootstrapLocalIngress` /
|
||||
`BootstrapRemoteIngress`.
|
||||
|
||||
2. **Proxmox Native** (`--ingress-mode native`, default):
|
||||
PVE host → nft DNAT (target = LXC bridge IP) → LXC
|
||||
(`--features nesting=1,keyctl=1,fuse=1`) → podman traefik.
|
||||
`internal/proxmox/bootstrap.go` → `provisionNativeIngressLXC`.
|
||||
|
||||
3. **Proxmox Floating-IP** (`--ingress-mode floating-ip`):
|
||||
LXC owns the floating IP (`net0 bridge=vmbr0,hwaddr=<mac>,
|
||||
ip=<floating-ip>/<prefix>,gw=<gateway>`) → nft inside LXC →
|
||||
podman traefik. The ingress LXC is registered as a `linux` node
|
||||
(name=`ingress`) so `orca job run` pushes traefik dynamic config.
|
||||
`internal/proxmox/ingress_lxc.go` → `ProvisionIngressLXC`.
|
||||
|
||||
### nft Emitter Changes
|
||||
|
||||
`internal/emitter/nft.go`:
|
||||
- `DNATTarget` field (C-51: validated via `net.ParseIP`). Default
|
||||
`127.0.0.1`; proxmox native uses LXC bridge IP.
|
||||
- `EnableSNAT` field + postrouting masquerade chain: `ip saddr
|
||||
127.0.0.0/8 oifname != "lo" masquerade` (research Topic 1).
|
||||
- Input/forward chain priority shifted from `filter` (=0) to `-10`
|
||||
(research Topic 2: pve-firewall coexistence — avoids same-priority
|
||||
undefined evaluation order).
|
||||
|
||||
### TLS Model
|
||||
|
||||
v0.14 drops `certResolver: orca` from the dynamic config (traefik v3.3
|
||||
only supports `acme`/`tailscale` resolvers, not CA-file-based). The
|
||||
dynamic config emits `tls: {}` (traefik default cert). Real mTLS via
|
||||
`tls.certificates` + `tls.options.default.clientAuth.caFiles` is
|
||||
deferred to v0.15 (grill G-003, confidence 0.55 < 0.60).
|
||||
|
||||
### Migration 0009
|
||||
|
||||
`ALTER TABLE nodes ADD COLUMN ingress_mode TEXT NOT NULL DEFAULT '';`
|
||||
Values: `""` (legacy), `"native"`, `"floating-ip"`. `IngressMode` field
|
||||
on `model.Node`.
|
||||
|
||||
### New CLI
|
||||
|
||||
- `orca doctor ingress` — verifies podman container running, nft
|
||||
DNAT+SNAT, dynamic dir, step-ca root CA.
|
||||
- `--ingress-mode` flag on `orca node join --type proxmox`.
|
||||
- `--floating-ip`, `--gateway`, `--mac`, `--net-prefix` flags for
|
||||
floating-IP mode.
|
||||
|
||||
Reference in New Issue
Block a user