homelab/manifests/multus/20-canary.yaml
Nik Afiq e980fcb755
Some checks failed
validate / lint (push) Failing after 1s
feat: add Multus manifests for VPN VLAN 50 (manual sync)
CRD, RBAC, thick-plugin DaemonSet (nik-debian only, k3s CNI paths,
digest-pinned), the VLAN 50 NAD (macvlan bridge on enp1s0.50), the
shared pod egress-guard script, a temporary canary pod, and the
not-yet-deployed browser-vpn-proxy workload (kept in reserved/, outside
this Application's non-recursive source path).

Referenced by argocd/apps/multus.yaml (already pushed) but not deployed
by it — that Application has no syncPolicy.automated, so this still
needs an explicit selective sync per resource.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 18:07:40 +09:00

84 lines
2.9 KiB
YAML

# Apply: kubectl apply -f manifests/multus/20-canary.yaml
# Delete when done: kubectl delete -f manifests/multus/20-canary.yaml
# Description: TEMPORARY canary pod for Phase 5 validation (plan.md) —
# proves eth0/net1 routing, kill-switch failure modes, and the netns
# egress guard before qBittorrent/JDownloader are touched. Not a
# long-lived resource; delete it once the Phase 5 validation matrix has
# run. sync-wave 2 — after Multus (0) and the NAD (1).
#
# *** DO NOT SYNC/APPLY until: ***
# - Phases 0-4 have actually been applied and verified live (this file
# is drafted alongside them, not proof they work).
# - The user has explicitly approved running the canary specifically —
# per this task's own gates, Argo CD sync of this file needs the same
# explicit go-ahead as any other live change, even though the
# multus.yaml Application it lives under is manual-sync-only anyway.
#
# Image: nicolaka/netshoot:v0.11 — a widely-used network-debugging image
# (iproute2 + iptables + curl/dig/tcpdump). Tag not independently
# verified against a live pull; confirm it still resolves before
# applying, same caveat as the Multus image tag in 02-daemonset.yaml.
apiVersion: v1
kind: Pod
metadata:
name: vlan50-canary
namespace: downloads
labels:
app: vlan50-canary
annotations:
argocd.argoproj.io/sync-wave: "2"
k8s.v1.cni.cncf.io/networks: |
[{"name": "vlan50", "namespace": "downloads", "interface": "net1", "ips": ["10.10.50.100/24"]}]
spec:
nodeSelector:
kubernetes.io/hostname: nik-debian
restartPolicy: Never
# Same reasoning as qbittorrent.yaml/jdownloader.yaml: no cluster
# DNS/CoreDNS resolution needed, single Technitium resolver, routed via
# net1 so Technitium sees the real VLAN 50 source.
dnsPolicy: None
dnsConfig:
nameservers:
- "10.10.40.53"
initContainers:
- name: vlan50-egress-guard
image: nicolaka/netshoot:v0.11
command: ["/bin/sh", "/scripts/guard.sh"]
env:
- name: VLAN50_GATEWAY
value: "10.10.50.1"
- name: TECHNITIUM_IP
value: "10.10.40.53"
- name: POD_CIDR
value: "10.42.0.0/16"
- name: SERVICE_CIDR
value: "10.43.0.0/16"
- name: NODE_IP
value: "10.10.40.20"
securityContext:
capabilities:
drop: ["ALL"]
add: ["NET_ADMIN"]
volumeMounts:
- name: guard-script
mountPath: /scripts
containers:
- name: netshoot
image: nicolaka/netshoot:v0.11
command: ["sleep", "infinity"]
securityContext:
capabilities:
drop: ["ALL"]
resources:
requests:
cpu: 20m
memory: 32Mi
limits:
cpu: 200m
memory: 128Mi
volumes:
- name: guard-script
configMap:
name: vlan50-egress-guard-script
defaultMode: 365 # octal 0555, r-xr-xr-x — yamllint here forbids octal literals