Retire gluetun gateway Deployment (ADR-0015: node tunnel validated + conformance-green)
Prepared on a feature branch for operator review — NOT merged/pushed (retiring the running fallback needs explicit approval). The node-level host OpenVPN tunnel steered by Cilium Egress Gateway is validated end-to-end and gated by green conformance (egress-class + vpn-killswitch). A Gluetun pod's tun0 was never steerable by Cilium egress gateway (the reason ADR-0015 moved the tunnel to the node), so gluetun serves no steering role. The now-unused pia-* SOPS secrets are retained pending a separate cleanup (creds are host-side in the Ansible vault). Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
0753b2ac96
commit
7b7982e28d
2 files changed
+7
-129
No files matched your search
@@ -1,126 +0,0 @@
|
|||||||
---
|
|
||||||
# Gluetun — the single shared in-cluster VPN egress gateway (ADR-0013): PIA over OpenVPN-UDP, with
|
|
||||||
# Gluetun's built-in kill-switch/firewall (fail-closed), health checks, auto-reconnect. `vpn`-class
|
|
||||||
# pods are steered through this gateway (see README.md "Egress steering").
|
|
||||||
#
|
|
||||||
# CUSTOM-PROVIDER mode (DECISIONS-LOG "Phase 3 VPN — custom .ovpn"): gluetun's PIA-provider server
|
|
||||||
# selection random-picks server IPs, many of which don't answer this cluster's flows (intermittent
|
|
||||||
# TLS timeouts — verified by packet capture: the pod CAN complete a full handshake, only against
|
|
||||||
# responsive servers). So we feed gluetun the operator's own PIA `.ovpn`, which pins a known-healthy
|
|
||||||
# Stockholm server IP (gluetun's custom parser requires an IP `remote`, not a hostname). Trade-off:
|
|
||||||
# custom mode loses gluetun's PIA-native port forwarding (Phase-6/qBittorrent concern) — revisit then.
|
|
||||||
#
|
|
||||||
# Credentials: `pia-credentials` SOPS Secret (username/password) → OPENVPN_USER/OPENVPN_PASSWORD (the
|
|
||||||
# .ovpn uses auth-user-pass). Config: `pia-custom-ovpn` SOPS Secret (key `pia.ovpn`), mounted at
|
|
||||||
# /config/pia.ovpn. Both operator-provisioned.
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: gluetun
|
|
||||||
namespace: vpn-egress
|
|
||||||
labels:
|
|
||||||
app: gluetun
|
|
||||||
spec:
|
|
||||||
replicas: 1 # ONE shared tunnel (ADR-0013). Active/standby is a later enhancement.
|
|
||||||
strategy:
|
|
||||||
type: Recreate # a tunnel is a singleton — never run two overlapping during a rollout
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: gluetun
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: gluetun
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: gluetun
|
|
||||||
image: qmcgaw/gluetun:v3.41.3 # pinned; Renovate bumps.
|
|
||||||
securityContext:
|
|
||||||
capabilities:
|
|
||||||
add: ["NET_ADMIN"] # required for the tunnel + firewall
|
|
||||||
env:
|
|
||||||
- name: VPN_SERVICE_PROVIDER
|
|
||||||
value: "custom" # custom .ovpn — see header + DECISIONS-LOG
|
|
||||||
- name: VPN_TYPE
|
|
||||||
value: "openvpn"
|
|
||||||
- name: OPENVPN_CUSTOM_CONFIG
|
|
||||||
value: "/config/pia.ovpn" # the operator's PIA .ovpn (pia-custom-ovpn Secret, IP remote)
|
|
||||||
# PIA username/password for the .ovpn's auth-user-pass (pia-credentials SOPS Secret):
|
|
||||||
- name: OPENVPN_USER
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: pia-credentials
|
|
||||||
key: username
|
|
||||||
- name: OPENVPN_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: pia-credentials
|
|
||||||
key: password
|
|
||||||
# Pod MTU is 1450 (Cilium VXLAN: 1500 − 50 encap). Shrink OpenVPN's tun-mtu so data-channel
|
|
||||||
# packets fit (the .ovpn likely defaults to 1500). Hardcoded strings (int-coercion gotcha).
|
|
||||||
- name: OPENVPN_MTU
|
|
||||||
value: "1300"
|
|
||||||
- name: OPENVPN_MSSFIX
|
|
||||||
value: "1300"
|
|
||||||
- name: FIREWALL
|
|
||||||
value: "on" # KILL-SWITCH: block all egress except the tunnel (fail-closed, R-NET-06)
|
|
||||||
- name: FIREWALL_OUTBOUND_SUBNETS
|
|
||||||
value: "${CLUSTER_POD_CIDR}" # allow steered client pods (pod CIDR) to route out via the tunnel
|
|
||||||
- name: DOT
|
|
||||||
value: "off" # DNS via cluster CoreDNS, not Gluetun's DoT
|
|
||||||
ports:
|
|
||||||
- name: control
|
|
||||||
containerPort: 8000 # Gluetun control API (health + tunnel-state lookup)
|
|
||||||
livenessProbe:
|
|
||||||
# EXEC (localhost) not httpGet: once the tunnel redirects the default route via tun0, the pod's
|
|
||||||
# response to a kubelet HTTP probe would egress the tunnel and never return → probe times out →
|
|
||||||
# needless restarts. A local wget stays on lo, unaffected by the VPN routing.
|
|
||||||
exec:
|
|
||||||
command: ["/bin/sh", "-c", "wget -qO- http://127.0.0.1:8000/v1/vpn/status | grep -q running"]
|
|
||||||
initialDelaySeconds: 30
|
|
||||||
periodSeconds: 30
|
|
||||||
timeoutSeconds: 5
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 50m
|
|
||||||
memory: 64Mi
|
|
||||||
limits:
|
|
||||||
memory: 160Mi
|
|
||||||
volumeMounts:
|
|
||||||
- name: tun
|
|
||||||
mountPath: /dev/net/tun
|
|
||||||
- name: gluetun-data
|
|
||||||
mountPath: /gluetun # gluetun runtime state
|
|
||||||
- name: custom-ovpn
|
|
||||||
mountPath: /config # the .ovpn (read-only)
|
|
||||||
readOnly: true
|
|
||||||
volumes:
|
|
||||||
- name: tun
|
|
||||||
hostPath:
|
|
||||||
path: /dev/net/tun
|
|
||||||
type: CharDevice
|
|
||||||
- name: gluetun-data
|
|
||||||
emptyDir: {}
|
|
||||||
- name: custom-ovpn
|
|
||||||
secret:
|
|
||||||
secretName: pia-custom-ovpn
|
|
||||||
items:
|
|
||||||
# operator's secret keys the .ovpn by filename; map it to /config/pia.ovpn
|
|
||||||
- key: sweden-aes-128-cbc-udp-ip.ovpn
|
|
||||||
path: pia.ovpn
|
|
||||||
---
|
|
||||||
# Control API Service — used for tunnel-state health/alerting (ADR-0013 "alert on tunnel state").
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: gluetun-control
|
|
||||||
namespace: vpn-egress
|
|
||||||
labels:
|
|
||||||
app: gluetun
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
app: gluetun
|
|
||||||
ports:
|
|
||||||
- name: control
|
|
||||||
port: 8000
|
|
||||||
targetPort: 8000
|
|
||||||
@@ -3,7 +3,11 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
|||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
- namespace.yaml
|
- namespace.yaml
|
||||||
- gluetun-gateway.yaml
|
# gluetun-gateway.yaml RETIRED 2026-08-24 (ADR-0015): the node-level host tunnel is validated +
|
||||||
|
# conformance-green (egress-class + vpn-killswitch pass live); a Gluetun *pod* can't be a Cilium
|
||||||
|
# egress-gateway target anyway. Steering now flows through the node tun0 via egress-steering.yaml.
|
||||||
|
# NOTE: pia-credentials/pia-custom-ovpn secrets below are now UNUSED (creds are host-side in the
|
||||||
|
# Ansible vault per docs/07) — retained temporarily, pending a follow-up cleanup change.
|
||||||
- pia-credentials.sops.yaml
|
- pia-credentials.sops.yaml
|
||||||
- pia-custom-ovpn.sops.yaml # operator-provisioned: the PIA .ovpn (custom-provider mode). See README.
|
- pia-custom-ovpn.sops.yaml # (was gluetun's PIA .ovpn; superseded host-side — see note above)
|
||||||
- egress-steering.yaml # ADR-0015: steer egress-class=vpn pods to the node tun0 (host tunnel validated 2026-08-24)
|
- egress-steering.yaml # ADR-0015: steer egress-class=vpn pods to the node tun0 (validated 2026-08-24)
|
||||||
Reference in new issue
Block a user