--- # kube_vip role defaults — control-plane HA VIP for the k3s kube-API. # # kube-vip runs as a DaemonSet on the control-plane nodes and floats a single # virtual IP (kube_vip_address) that always points at the current leader, giving # the kube-apiserver a stable failover endpoint (an operator port-forward fronts # it at 192.168.1.49:6443). It is CONTROL-PLANE ONLY (svc_enable=false): Cilium # owns Service LoadBalancing (L2 pool .53-.60), so kube-vip must not touch # Services or the two would fight over ARP for LoadBalancer IPs. # The floating control-plane VIP. Defined in group_vars/all.yml so k3s_server's # tls-san list and this role stay in parity; this default is the fallback. kube_vip_address: "192.168.1.49" # Image pinned deliberately — a version bump is a code change (verified tag on # ghcr.io). v1.2.3 is the current stable release (k8s-1.36 catch-up from v0.8.9). kube_vip_version: "v1.2.3" kube_vip_image: "ghcr.io/kube-vip/kube-vip:{{ kube_vip_version }}" kube_vip_namespace: "kube-system" kube_vip_port: 6443 # Empty => auto-detected per host (the interface holding 192.168.1.5x); override # only if detection is wrong. kube_vip_interface: "" # How long to wait for the VIP to actually ANSWER on kube_vip_port after the manifest is # written (seconds). This is a real gate, not cosmetics: since 2026-09-06 Cilium's # k8sServiceHost is this VIP (k3s_apiserver_endpoint), and playbooks/site.yml runs this role # immediately before cilium.yml — so if the VIP never comes up, the run must stop HERE with # a clear message rather than proceed to install a CNI pointed at an address nothing # answers. On a cold cluster the budget covers k3s's deploy controller applying the # manifest, the ghcr.io image pull and leader election; on an already-running cluster the # check returns immediately. kube_vip_wait_timeout: 300 # Leader-election tuning (seconds) — a snappy failover without thrashing. kube_vip_lease_duration: 15 kube_vip_renew_deadline: 10 kube_vip_retry_period: 2 # k3s auto-deploy manifests dir: k3s applies anything here on start, so kube-vip # is reproducible and independent of Flux/Helm. # # THE PATH FOLLOWS --data-dir. k3s reads auto-deploy manifests from # /server/manifests, so this must be derived from the cluster-wide # k3s_data_dir (roles/k3s_server turns the same variable into --data-dir), not from the # literal /var/lib/rancher/k3s. Dev leaves k3s_data_dir unset outside roles/k3s_server's # own defaults, so the fallback below reproduces dev's existing path exactly; prod sets # k3s_data_dir: /data/k3s in group_vars/k3s_prod, where the old hardcoded path was simply # not the directory k3s watches — the manifest would have been written and silently never # applied, and the control-plane VIP would never have come up. kube_vip_manifest_path: >- {{ k3s_data_dir | default('/var/lib/rancher/k3s') }}/server/manifests/kube-vip.yaml