Ingress Best Practices
This list collects production-minded rules for exposing HTTP traffic with Ingress and Gateway API on Kubernetes.
It targets platform engineers and tech leads standardizing how apps reach the edge.
How to Use This List
Treat each group as a review gate for any new public endpoint.
Adopt the ones that fit your controller and cloud, and encode the rest as policy (OPA/Kyverno) or Helm chart defaults so they are enforced, not remembered.
Where a practice differs between Ingress and Gateway API, both are noted.
A - TLS and Encryption
Terminate TLS at the controller. Hold certificates on the ingress controller or Gateway listener so cert management is centralized and pods stay simple. Re-encrypt to the backend only when compliance requires in-cluster encryption.
Enforce a minimum TLS version. Require TLS 1.2 or higher and disable legacy protocols. In ingress-nginx set ssl-protocols in the ConfigMap; on Gateway API pin the listener's TLS options per controller.
Automate certificates with cert-manager. Never paste certs by hand. Use ACME or a corporate CA issuer so rotation and renewal happen automatically before expiry.
Redirect HTTP to HTTPS. Force ssl-redirect (or an HTTPRoute redirect filter) so plaintext requests are upgraded, but leave the ACME challenge path reachable for HTTP-01.
Use strong ciphers and HSTS. Prefer modern cipher suites and set Strict-Transport-Security so browsers refuse downgrades on future visits.
B - Controller Topology and Availability
Run one general controller per cluster. Avoid two controllers sharing an IngressClass; they duplicate load balancers and fight over objects. Scope any extra controller to its own class.
Bind objects explicitly with ingressClassName. Set the class on every Ingress instead of relying on the default. Explicit binding avoids silent orphaning when defaults change.
Run multiple controller replicas. Deploy at least two proxy replicas with a PodDisruptionBudget and topology spread so a node loss does not drop the edge.
Preserve the client source IP when needed. Use externalTrafficPolicy: Local or trust the proxy's X-Forwarded-For for logging, rate limiting, and geo rules.
Prefer controllers with dynamic reconfiguration. Under heavy Ingress churn, reload-on-change controllers can storm. Pick a data plane that hot-updates endpoints without full reloads.
C - Routing Correctness and Health
Gate backends with readiness probes. Only ready pods appear in EndpointSlices, so accurate probes stop the controller from sending traffic to cold or broken pods.
Order paths from specific to general. Place /api before / and use pathType: Prefix deliberately, since controllers match by longest prefix.
Set sane timeouts and body limits. Tune proxy read/send timeouts and proxy-body-size to match your app, so slow clients and large uploads fail predictably rather than hanging.
Watch object status. Use kubectl describe ingress or the Gateway API Accepted, ResolvedRefs, and Programmed conditions to confirm the controller actually accepted your config.
Keep TLS Secrets in the route's namespace. An Ingress references a Secret in its own namespace; for cross-namespace refs on Gateway API, add a ReferenceGrant.
D - Security and Isolation
Restrict traffic with NetworkPolicy. Apply default-deny policies and allow only the ingress controller to reach app pods on their service ports.
Add auth and rate limiting at the edge. Enforce authentication, WAF rules, and rate limits on the controller so bad traffic is dropped before it reaches pods.
Scope routes across teams cleanly. With Gateway API, let the platform team own the Gateway and listeners while app teams own HTTPRoute objects, gated by ReferenceGrant.
Do not expose internal services publicly. Use an internal IngressClass or private load balancer for admin and internal APIs, kept off the public listener.
Scan and pin controller images. Run scanned, digest-pinned, non-root controller images and keep the controller patched, since it is a high-value internet-facing target.
E - Delivery and Operations
Use weighted routes for safe rollouts. Split traffic with Gateway API backendRefs weights (or a canary annotation) and drive them with Argo Rollouts or Flagger for progressive delivery.
Manage ingress config in Git. Keep Ingress, Gateway, and issuer manifests in Git and reconcile with Argo CD or Flux so the edge is auditable and reproducible.
Standardize with Helm or Kustomize. Template common annotations, TLS blocks, and classes so every team ships consistent, policy-compliant ingress objects.
Enforce policy as code. Use Kyverno or OPA Gatekeeper to require TLS, a valid class, and namespace rules on every ingress object at admission time.
Observe the edge. Export controller metrics to Prometheus and traces to OpenTelemetry, and alert on 5xx rates, latency, and certificate expiry.
When You Are Done
You should have TLS terminated and automated, exactly one general controller with explicit class binding, health-gated routing, default-deny network policy, and GitOps-managed manifests under policy enforcement.
Re-run this list whenever you add a controller, adopt Gateway API, or onboard a new team to the shared edge.
FAQs
Where should TLS terminate? At the controller or Gateway listener by default. Re-encrypt to the backend only when in-cluster encryption is required by policy.
How do I enforce a minimum TLS version? Configure the controller's TLS settings, for example ssl-protocols in the ingress-nginx ConfigMap, and pin listener TLS options on Gateway API. Verify with a TLS scanner.
Can I run two ingress controllers? Yes, if each owns a distinct IngressClass or namespace. A common split is a public controller and an internal-only one.
Should I use Ingress or Gateway API? Use Ingress for simple host and path routing. Choose Gateway API for expressive routing, traffic splitting, and clean team role separation.
How do I stop traffic hitting unready pods? Define accurate readiness probes. Unready pods are removed from EndpointSlices, so the controller stops routing to them automatically.
Related
- How External Traffic Reaches Your Pods
- Ingress Basics
- Ingress Controllers
- TLS Certificates
- Gateway API
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).