SealSkin

vpn_kube

VPN gateways on Kubernetes: a hub pod per profile and endpoint, and a spoke beside every session.

A Docker node puts its sessions on an internal network beside the gateway; pods have no such network, and a session pod may land on any node. So on Kubernetes the gateway is a hub: a pod per profile and endpoint, owned by the server like a session pod, that holds the one tunnel to the provider and a WireGuard interface of its own behind a ClusterIP Service. A session pod gets a native sidecar from the same image (spoke mode) that connects to the hub over the pod network with a key pair of its own, makes that the pod's default route, keeps the cluster's networks (vpn_local_cidrs) on the pod's own route, and lets nothing else out. The hub forwards the spokes into the tunnel and answers their DNS. One hub carries every session of the deployment that picked its endpoint, wherever the pods run, so the provider's connection is spent once per endpoint in use.

The hub's rendered files are a Secret the pod mounts: the profile's files, the hub's private key, and the spokes' peers, which the server also adds to the running hub through pods/exec so a session does not wait on the kubelet's Secret sync. A hub that restarts reads its peers from the file, and a hub pod that failed or was evicted is created again over the same Secret and Service, so the spokes of its sessions reconnect with the keys they have. The hub's objects carry the server's instance in their names and labels, so two servers in one namespace keep hubs of their own. Spoke addresses are taken from vpn_hub_subnet, the hub at .1, each session's from a hash of its id.

attributelogger
= logging.getLogger(__name__)
attributeHUB_PORT
= 51820
attributeCOMPONENT
= 'vpn-gateway'
attributeREADY_TIMEOUT
= 300
attributeGONE_TIMEOUT
= 60
attributeINSTANCE_CHARS
= 24