Prod inventory scaffolding for the three bare-metal nodes, and the become posture the operator ruled for production. BECOME: prod does NOT get dev's NOPASSWD sudo. Prod keeps a real sudo boundary and supplies the password to Ansible as an ansible-vault-encrypted `ansible_become_password` in inventory/group_vars/k3s_prod/vault.yml, mirroring the existing hypervisor and proxmox_hosts groups. The decrypting passphrase stays outside the repo (~/.config/home-k3s/ansible-vault-pass), so plays still run unattended with no plaintext secret in git. Committed here: README.md + vault.yml.example only — the operator creates the encrypted vault (`ansible-vault create`), as with every other vaulted group. PACKAGES BELONG IN THE ROLE (operator ruling): smartmontools is now declared in node_baseline_packages, not hand-installed on a node. Drive health tooling is a permanent part of a bare-metal node's baseline — dev nodes are VMs and never needed it. Same click-ops-never principle as the rest of the repo. ADDRESSING: nodes .10/.11/.12, reached DIRECTLY on the LAN (no pfSense NAT hop, unlike dev's 192.168.2.102:225x mapping), so ansible_host is the real node IP. kube-vip control-plane VIP is 192.168.2.9 — deliberately BELOW the nodes and OUTSIDE the Cilium LB pool (.20-.30) so kube-vip and LB-IPAM can never contend for an address. The ingress Gateway VIP (.20) and the LB pool are Flux/cluster-vars concerns and deliberately do not appear in Ansible. BLOCKED-BY-DESIGN: node_baseline_longhorn_device / node_baseline_etcd_device are present but set to an obviously invalid /dev/BLOCKED-... path pending the operator's disk-layout decision (node 1 is a single SATA SSD; the role's /dev/vdb,/dev/vdc defaults are virtio names that do not exist on bare metal). Leaving them unset would silently fall back to those equally-nonexistent defaults — a confusing failure that looks like a wiring bug. This fails just as hard and says exactly why. KNOWN FOLLOW-UP: roles/k3s_server and every node-host playbook hardcode the literal group names k3s_primary/k3s_secondary/k3s_servers, so the k3s_prod_* groups are not selected by them as-is. Harmless now (nothing can accidentally run against prod) but the "same roles, unchanged" reuse R-ENV-02 promises needs the target group parameterized before §6 of PROD-PROVISIONING.md can execute. Documented in hosts.ini and both READMEs. Serves: R-ENV-01, R-ENV-03, R-SEC-01. Task: T-7.1. Gate: MERGE GATE: PASS. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
100 lines
6.0 KiB
INI
100 lines
6.0 KiB
INI
# Static inventory — k3s node IPs ALIGNED with infra/tofu defaults (Proxmox migration IPs),
|
|
# but the SSH target is the pfSense NAT (see NAT HAND-OFF below) — this file is
|
|
# HAND-MAINTAINED and must NOT be regenerated from `tofu output -raw ansible_inventory`.
|
|
#
|
|
# k3s_primary = the --cluster-init server (embedded-etcd founder + Cilium k8sServiceHost).
|
|
# k3s_secondary = the two servers that join it. All three are servers (HA embedded etcd).
|
|
#
|
|
# NAT HAND-OFF (LIVE): the nodes live on the Proxmox LAN at 192.168.1.50/.51/.52, and
|
|
# Ansible reaches them over the pfSense NAT at 192.168.2.102, port-forwarded as
|
|
# 2250 -> 192.168.1.50:22, 2251 -> 192.168.1.51:22, 2252 -> 192.168.1.52:22.
|
|
# Therefore `ansible_host`/`ansible_port` below are the NAT SSH target (192.168.2.102:225x),
|
|
# and each node's REAL 192.168.1.x lives in the `k3s_node_ip` var — consumed for the k3s
|
|
# --node-ip, the API/tls-san endpoint (k3s_api_host), and general in-cluster parity.
|
|
# This file is HAND-MAINTAINED for the NAT: do NOT blindly regenerate it from
|
|
# tofu output -raw ansible_inventory
|
|
# because tofu has no knowledge of the pfSense NAT and would overwrite the mapping below.
|
|
|
|
[k3s_primary]
|
|
k3s-dev-1 ansible_host=192.168.2.102 ansible_port=2250 k3s_node_ip=192.168.1.50
|
|
|
|
[k3s_secondary]
|
|
k3s-dev-2 ansible_host=192.168.2.102 ansible_port=2251 k3s_node_ip=192.168.1.51
|
|
k3s-dev-3 ansible_host=192.168.2.102 ansible_port=2252 k3s_node_ip=192.168.1.52
|
|
|
|
[k3s_servers:children]
|
|
k3s_primary
|
|
k3s_secondary
|
|
|
|
# The hypervisor/workstation host itself (target of host-prereqs.yml). Its become
|
|
# (sudo) password comes from the vaulted group_vars/hypervisor/vault.yml.
|
|
[hypervisor]
|
|
localhost ansible_connection=local
|
|
|
|
# VPN egress-gateway node(s) — run the node-level split-tunnel OpenVPN + kill-switch
|
|
# (ADR-0015, playbooks/vpn.egress.gateway.yml). Initially just k3s-dev-3 (single gateway;
|
|
# add a second host here for Cilium Egress Gateway HA). Members are already defined above
|
|
# with their ansible_host under k3s_secondary; this group only tags the egress role target.
|
|
[vpn_egress_gateway]
|
|
k3s-dev-3
|
|
|
|
# The Proxmox HYPERVISOR host itself (NOT a k3s node) — target of playbooks/backup-s3.yml,
|
|
# which stands up the off-cluster versitygw S3 backup target for Velero + CNPG. Reached DIRECTLY
|
|
# over SSH as root (its own 192.168.2.102:22, the pfSense NAT to the host's 192.168.1.9), so
|
|
# it overrides the cluster-wide `ansible_user: k3s` from group_vars/all.yml. Distinct from the
|
|
# `hypervisor` group above (that is `localhost` for host-prereqs.yml, a different machine).
|
|
[proxmox_hosts]
|
|
proxmox ansible_host=192.168.2.102 ansible_port=22 ansible_user=root ansible_ssh_private_key_file=~/.ssh/home_network
|
|
|
|
# =============================================================================
|
|
# PROD (k3s-prod-*) — Phase 7 PREP ONLY. See infra/PROD-PROVISIONING.md (T-7.1,
|
|
# especially §5/§6) and DECISIONS-LOG.md "PHASE 7 OPENED" (2026-08-31). Node 1
|
|
# (`k3s-prod-1`, HP EliteDesk 800 G5 Mini) is on the bench and SSH-reachable; nodes 2
|
|
# and 3 have not arrived. This section is inventory/group_vars scaffolding only —
|
|
# nothing has been run against node 1, and the operator has decided the CLUSTER stays
|
|
# uninitialized (no k3s install, no --cluster-init) until all three nodes are present
|
|
# (decision #2 in the DECISIONS-LOG entry above) — no single-server-etcd window, no
|
|
# later member-add dance.
|
|
#
|
|
# KEY DIFFERENCE FROM DEV: prod sits DIRECTLY on the 192.168.2.x LAN — no pfSense NAT
|
|
# hop in front of it. Dev's `ansible_host` above is a NAT target (192.168.2.102:225x)
|
|
# that port-forwards to the node's real 192.168.1.x address, which is why dev also
|
|
# carries a separate `k3s_node_ip` per host. Prod needs no such split: `ansible_host`
|
|
# below IS already the node's real, routable address, so `k3s_node_ip` is set to the
|
|
# SAME value (kept explicit, not omitted, only so the k3s_server role's hostvar lookup
|
|
# — see the GAP note below — has something correct to find once that gap is closed).
|
|
# `ansible_port` is the node's own real sshd (22). See group_vars/k3s_prod/vars.yml for
|
|
# the k3s_api_host override that reflects this directly-reachable topology.
|
|
#
|
|
# GAP flagged for the PM, NOT fixed in this pass (inventory/group_vars only): the
|
|
# k3s_server role hardcodes the LITERAL group names `k3s_primary` / `k3s_secondary` /
|
|
# `k3s_servers` in roles/k3s_server/defaults/main.yml (tls-san SAN list) and
|
|
# roles/k3s_server/tasks/main.yml (node-token delegate_to), and every node-host
|
|
# playbook (node-baseline.yml, k3s.yml, cilium.yml, kube-vip.yml, verify.yml,
|
|
# flux-bootstrap.yml) declares `hosts: k3s_servers` / `k3s_primary` / `k3s_secondary`
|
|
# literally. Naming prod's groups k3s_prod_primary/k3s_prod_secondary — as this
|
|
# checklist and PROD-PROVISIONING.md §6 both call for — means those existing
|
|
# playbooks will NOT select prod hosts as they stand today. That's harmless right now
|
|
# (nothing can accidentally run against prod), but it means actually reusing the dev
|
|
# playbooks against prod later (the R-ENV-02 promise) needs either parametrizing the
|
|
# group name they target or some other mechanism — not yet designed, tracked here so
|
|
# it isn't lost before §6 is attempted for real.
|
|
# =============================================================================
|
|
|
|
[k3s_prod_primary]
|
|
k3s-prod-1 ansible_host=192.168.2.10 ansible_port=22 k3s_node_ip=192.168.2.10
|
|
|
|
[k3s_prod_secondary]
|
|
# Addresses for nodes 2/3 ARE decided (operator, 2026-08-31 — infra/PROD-PROVISIONING.md
|
|
# §0), but the nodes themselves are NOT yet racked/imaged/reachable. Left commented so
|
|
# no play can accidentally target a host that isn't there; uncomment each line only once
|
|
# that node is actually on the bench and answering SSH.
|
|
# k3s-prod-2 ansible_host=192.168.2.11 ansible_port=22 k3s_node_ip=192.168.2.11
|
|
# k3s-prod-3 ansible_host=192.168.2.12 ansible_port=22 k3s_node_ip=192.168.2.12
|
|
|
|
# Umbrella group group_vars/k3s_prod/ attaches to (mirrors dev's [k3s_servers:children]
|
|
# pattern; named to match the group_vars directory so Ansible auto-loads it).
|
|
[k3s_prod:children]
|
|
k3s_prod_primary
|
|
k3s_prod_secondary
|