GKE: Contour values, exposed by LoadBalancer on the reserved IP

The homelab binds Envoy to node ports 80/443 with hostPort, because
VMware bridging over Wi-Fi never made a LoadBalancer IP reachable
(claude.md issue #6). Here it is a real cloud load balancer, and since
the nodes have no public IPs it is the single inbound path to the
cluster.

envoy.service.loadBalancerIP pins it to the address Terraform reserved,
which is what makes DNS work: every hostname here is
<name>.35.238.248.203.nip.io, so an unpinned Service would take a fresh
ephemeral address and point every hostname at nothing.

That field is deprecated upstream (Kubernetes 1.24). GKE's replacement
annotation is not a drop-in — it takes the address resource's name, and
on an external Service also requires spec.loadBalancerClass:
networking.gke.io/l4-regional-external, changing which controller
programs the load balancer. GKE still honours the field, so this is the
smaller change.

contour.ingressClass.name is pinned to "contour" because every Ingress
in this cluster names that class; the chart default derives a name from
the release instead. Envoy stays a DaemonSet, which is what makes the
chart's default externalTrafficPolicy: Local (real client IPs) correct.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LEsTefWWifp4ikvhHF5s6N
This commit is contained in:
Mukul Sharma
2026-09-12 13:43:27 +05:30
co-authored by Claude Opus 5
parent 66c30cfaf4
commit cdc6d9167c
@@ -0,0 +1,64 @@
contour:
# GKE counterpart of helm-overrides/k8s-admin-prd-ase1/contour. Same
# official projectcontour chart (0.7.0, see helm-templates/contour), but
# exposed the opposite way.
#
# The homelab binds Envoy to node ports 80/443 with hostPort, because
# VMware bridging over Wi-Fi never made a LoadBalancer IP reachable
# (claude.md issue #6). None of that applies here: this is a real cloud
# load balancer on the reserved address, and it is the ONE inbound path
# into the cluster now that the nodes have no public IPs of their own.
contour:
replicaCount: 1
# Ingress objects across this cluster say `ingressClassName: contour`,
# so the class must be created under exactly that name. The chart's
# default is an empty string, which derives a name from the release.
ingressClass:
name: contour
create: true
default: true
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
memory: 192Mi
envoy:
# DaemonSet (the chart default): one Envoy per node, which pairs with
# externalTrafficPolicy: Local below — every node the load balancer can
# send to is running a proxy that can serve the request locally.
kind: daemonset
service:
type: LoadBalancer
# The reserved address from Terraform (module.network's
# google_compute_address). Every hostname in this deployment is
# <name>.35.238.248.203.nip.io, so this pin is what makes DNS work at
# all — an unpinned Service takes a fresh ephemeral IP and every
# hostname points at nothing.
#
# spec.loadBalancerIP is deprecated upstream (Kubernetes 1.24), and
# GKE's replacement is the annotation
# networking.gke.io/load-balancer-ip-addresses. That annotation is NOT
# a drop-in: it takes the address resource's NAME rather than the
# address, and on an external Service it also requires
# spec.loadBalancerClass: networking.gke.io/l4-regional-external,
# which changes which controller programs the load balancer. GKE still
# honours this field, so the deprecated-but-working one is the smaller
# change; revisit if a GKE upgrade ever stops honouring it.
loadBalancerIP: "35.238.248.203"
# Chart default, kept deliberately: preserves the real client IP
# instead of replacing it with a node's address. Valid here precisely
# because Envoy is a DaemonSet.
externalTrafficPolicy: Local
resources:
requests:
cpu: 50m
memory: 96Mi
limits:
memory: 256Mi