← Back to DevBytes

Troubleshooting Gateway API: Common Issues and Fixes

Troubleshooting Gateway API: Common Issues and Fixes

The Kubernetes Gateway API has become the standard way to configure ingress and service mesh traffic in modern clusters. However, because it introduces a multi-resource model — Gateways, GatewayClasses, HTTPRoutes, TLSRoutes, and more — troubleshooting can feel overwhelming when something does not work as expected. This tutorial walks you through the most common issues developers encounter when adopting Gateway API, explains why they happen, and shows you how to fix them with practical commands and configuration examples.

What Is the Gateway API?

Gateway API is a set of Kubernetes CRDs that provide a more expressive, role-oriented, and portable alternative to the older Ingress resource. Instead of a single Ingress object, the model is split into three layers:

This separation is powerful, but it also means a single broken link in the chain can prevent traffic from flowing. Understanding where to look is half the battle.

Why Troubleshooting Matters

Unlike Ingress, where a misconfiguration usually surfaces as a 404 or 503, Gateway API failures can be silent. A Route may be accepted by the controller but never produce a valid backend binding. A Gateway may report Programmed=True while listeners are actually down. Without a systematic approach, you can spend hours guessing. The fixes below follow the same diagnostic flow used by maintainers of controllers like Envoy Gateway, Istio, and the NGINX Gateway Fabric.

1. Gateway Stuck in "Not Accepted" State

The most common first symptom is a Gateway that never becomes ready. The status.conditions field is your primary diagnostic tool. Start by inspecting it:

kubectl describe gateway my-gateway -n production

Look for the Accepted and Programmed conditions. A typical failure looks like this:

Conditions:
  Type        Status  Reason                Message
  Accepted    False   InvalidParameters     listener "https" references missing TLS secret
  Programmed  False   Pending               waiting for controller to reconcile

Common Causes

Fix: Verify the GatewayClass and Controller

kubectl get gatewayclass
kubectl get pods -n gateway-system

If the GatewayClass exists but its controllerName does not match the controller you deployed, the Gateway will never be reconciled. For example, Envoy Gateway uses gateway.envoyproxy.io/gatewayclass-controller. Make sure your Gateway references the correct class:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: my-gateway
  namespace: production
spec:
  gatewayClassName: envoy-gateway
  listeners:
    - name: http
      protocol: HTTP
      port: 80

2. HTTPRoute Not Receiving Traffic

Your Gateway is healthy, but requests to your domain return 404 or never reach the backend. The issue is almost always in the attachment between the HTTPRoute and the Gateway.

Diagnosing with Route Status

kubectl get httproute my-route -n production -o yaml

Check the parents section in status. A healthy Route shows:

parents:
  - controllerName: gateway.envoyproxy.io/gatewayclass-controller
    conditions:
      - type: Accepted
        status: "True"
        reason: Accepted
      - type: ResolvedRefs
        status: "True"
        reason: ResolvedRefs

If Accepted is False, the Route is not attached. The most frequent cause is a mismatch in the parentRefs section.

Fix: Correct parentRefs and SectionName

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: my-route
  namespace: production
spec:
  parentRefs:
    - name: my-gateway
      namespace: production
      sectionName: http
  hostnames:
    - api.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: api-service
          port: 8080

Common mistakes to check:

3. Cross-Namespace ReferenceGrant Issues

Gateway API intentionally blocks cross-namespace references unless a ReferenceGrant explicitly permits them. This is a security feature, not a bug. If your Route in namespace frontend references a Gateway in gateway-system, you need a grant.

Symptom

The Route status shows ResolvedRefs=False with reason RefNotPermitted.

Fix: Create a ReferenceGrant

apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-frontend-to-gateway
  namespace: gateway-system
spec:
  from:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      namespace: frontend
  to:
    - group: gateway.networking.k8s.io
      kind: Gateway

Note that the ReferenceGrant must live in the target namespace — the namespace of the resource being referenced, not the namespace of the resource making the reference. This is the single most common mistake developers make.

The same pattern applies to TLS certificate Secrets. If a Gateway in gateway-system references a TLS Secret in certs, the grant goes in the certs namespace:

apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-gateway-tls
  namespace: certs
spec:
  from:
    - group: gateway.networking.k8s.io
      kind: Gateway
      namespace: gateway-system
  to:
    - group: ""
      kind: Secret

4. TLS Listener Not Terminating HTTPS

When HTTPS requests fail with certificate errors or connection resets, the problem usually lies in the TLS configuration block of the listener.

Common Causes

Fix: Validate the Secret and Listener

kubectl get secret tls-cert -n production -o jsonpath='{.type}'

The output must be kubernetes.io/tls. A generic Opaque Secret will not work. Verify the listener configuration:

listeners:
  - name: https
    protocol: HTTPS
    port: 443
    tls:
      mode: Terminate
      certificateRefs:
        - kind: Secret
          name: tls-cert
          namespace: production
    hostname: api.example.com

If you are using cert-manager to issue certificates, confirm the Certificate resource has a Ready=True condition before expecting the Gateway to serve traffic:

kubectl get certificate tls-cert -n production

5. BackendRefs Pointing to Non-Existent Services

A Route can be Accepted by the Gateway but still fail to route if the backend Service does not exist or has no matching port. The ResolvedRefs condition catches this.

Diagnosis

kubectl get httproute my-route -n production \
  -o jsonpath='{.status.parents[*].conditions[?(@.type=="ResolvedRefs")]}'

A failure shows status: False with reason BackendNotFound or InvalidKind.

Fix: Verify the Service Exists and the Port Matches

kubectl get svc api-service -n production -o wide

Ensure the port in backendRefs matches a port defined on the Service, not a named port string. Gateway API requires the integer port number:

backendRefs:
  - name: api-service
    port: 8080
    weight: 100

If you are using a ServiceImport from a multi-cluster service mesh, confirm the GatewayClass controller supports that backend type. Not all controllers do.

6. Controller Logs and Debugging

When status conditions do not reveal the problem, controller logs are the next stop. Each controller has its own logging conventions, but the general approach is the same.

Envoy Gateway

kubectl logs -n envoy-gateway-system -l control-plane=envoy-gateway --tail=200

NGINX Gateway Fabric

kubectl logs -n nginx-gateway -l app=nginx-gateway --tail=200

Istio Gateway API

kubectl logs -n istio-system -l app=istiod --tail=200 | grep gateway

Look for reconciliation errors, webhook rejections, or RBAC denials. A common log pattern is failed to reconcile Gateway followed by a specific reason. Increase log verbosity if needed:

kubectl -n envoy-gateway-system set env deployment/envoy-gateway \
  GATEWAY_CONTROLLER_LOG_LEVEL=debug

7. Webhook Admission Errors

Gateway API installs validating and mutating webhooks. If the webhook service is unavailable, applying any Gateway API resource will fail with an error like:

Error from server (InternalError): error when creating "gateway.yaml":
Internal error occurred: failed calling webhook "validate.gateway.networking.k8s.io"

Fix: Check the Webhook Service and Certificates

kubectl get validatingwebhookconfigurations
kubectl get pods -n gateway-system
kubectl get svc -n gateway-system

Ensure the webhook pod is running and the certificate mounted in the webhook configuration matches the serving certificate. If you installed Gateway API with Helm, a failed cert rotation is a frequent culprit. Restart the controller pod to force re-registration:

kubectl rollout restart deployment gateway-controller -n gateway-system

8. Best Practices for Avoiding Common Pitfalls

Most Gateway API issues stem from a small set of recurring mistakes. Adopt these practices to minimize troubleshooting time:

9. A Quick Diagnostic Checklist

When traffic is not flowing, work through this checklist in order:

  1. Is the Gateway Accepted=True and Programmed=True?
  2. Does the HTTPRoute show Accepted=True and ResolvedRefs=True?
  3. Do the parentRefs namespace and sectionName match the Gateway?
  4. Do the Route hostnames overlap with the listener hostname?
  5. If cross-namespace, does a ReferenceGrant exist in the target namespace?
  6. Does the backend Service exist with a matching port number?
  7. For HTTPS, is the TLS Secret present, correctly typed, and valid for the hostname?
  8. Are the controller pods running and healthy?

Following this sequence will resolve the vast majority of Gateway API issues without needing to dig into controller internals.

Conclusion

Troubleshooting the Kubernetes Gateway API becomes straightforward once you internalize its layered model and learn to read status conditions as your primary signal. Most failures boil down to mismatched references, missing ReferenceGrants, invalid TLS Secrets, or backend Services that do not exist. By systematically checking the Accepted, Programmed, and ResolvedRefs conditions, verifying cross-namespace grants, and inspecting controller logs when status is silent, you can quickly pinpoint and resolve issues. As the Gateway API ecosystem matures and more controllers implement the standard conformance tests, the debugging experience will only improve — but the fundamentals covered in this tutorial will remain the backbone of any effective troubleshooting workflow.

— Ad —

Google AdSense will appear here after approval

← Back to all articles