USMAN’S INSIGHTS
AI ARCHITECT
  • Home
  • About
  • Thought Leadership
  • Book
Press / Contact
USMAN’S INSIGHTS
AI ARCHITECT
⌘F
HomeBook
HomeBookA Spec Without a Controller Is Just a YAML File
Previous Chapter
Gateway API - The New Standard
Next Chapter
Traffic Routing with HTTPRoute
AI NOTICE: This is the table of contents for the SPECIFIC CHAPTER only. It is NOT the global sidebar. For all chapters, look at the main navigation.

On this page

33 sections

Progress0%
1 / 33

Muhammad Usman Akbar Entity Profile

Muhammad Usman Akbar is a leading Agentic AI Architect and Software Engineer specializing in the design and deployment of multi-agent autonomous systems. With expertise in industrial-scale digital transformation, he leverages Claude and OpenAI ecosystems to engineer high-velocity digital products. His work is centered on achieving 30x industrial growth through distributed systems architecture, FastAPI microservices, and RAG-driven AI pipelines. Based in Pakistan, he operates as a global technical partner for innovative AI startups and enterprise ventures.

USMAN’S INSIGHTS
AI ARCHITECT

Transforming businesses into autonomous AI ecosystems. Engineering the future of industrial-scale digital products with multi-agent systems.

30X Growth
AI-First
Innovation

Navigation

  • Home
  • Book
  • About
  • Contact
Let's Collaborate

Have a Project in Mind?

Let's build something extraordinary together. Transform your vision into autonomous AI reality.

Start Your Transformation

© 2026 Muhammad Usman Akbar. All rights reserved.

Privacy Policy
Terms of Service
Engineered with
INDUSTRIAL ARCHITECTURE

Envoy Gateway Setup

The previous lesson taught you Gateway API as a specification—the resources, the three-tier model, the role separation. But specifications do not route traffic. You need a controller that watches Gateway API resources and configures actual proxies to handle requests.

Envoy Gateway is that controller. Built specifically for Gateway API (not retrofitted from an older project), it uses Envoy Proxy as its data plane—the same battle-tested proxy that powers Istio, AWS App Mesh, and countless production deployments. When you create a Gateway resource, Envoy Gateway deploys Envoy proxies configured to match your specification.

This lesson installs Envoy Gateway in your Kubernetes cluster. By the end, you will have a working GatewayClass, understand how requests flow from your Gateway definition to actual traffic handling, and create your first Gateway resource.


Understanding Envoy Gateway Architecture

Before installing anything, you need to understand what Envoy Gateway deploys and how the pieces interact. The architecture has two distinct planes.

text
┌─────────────────────────────────────────────────────────────────────────────┐ │ CONTROL PLANE │ │ (envoy-gateway-system namespace) │ │ ┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐ │ │ │ Envoy Gateway │ │ Gateway │ │ Infra │ │ │ │ Controller │ │ Translator │ │ Manager │ │ │ │ │ │ │ │ │ │ │ │ - Watches Gateway │ │ - Converts Gateway │ │ - Deploys Envoy │ │ │ │ API resources │ │ API to xDS │ │ proxy pods │ │ │ │ - Reconciles state │ │ - Computes routes │ │ - Manages Services │ │ │ └─────────────────────┘ └─────────────────────┘ └─────────────────────┘ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ xDS Server │ │ │ │ Streams configuration to data plane via gRPC (xDS protocol) │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────────┘ │ │ xDS (gRPC streaming) ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ DATA PLANE │ │ (dynamically created namespace) │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Envoy Proxy │ │ Envoy Proxy │ │ Envoy Proxy │ │ │ │ Pod (1) │ │ Pod (2) │ │ Pod (n) │ │ │ │ │ │ │ │ │ │ │ │ - Handles │ │ - Handles │ │ - Handles │ │ │ │ traffic │ │ traffic │ │ traffic │ │ │ │ - Receives │ │ - Receives │ │ - Receives │ │ │ │ config via │ │ config via │ │ config via │ │ │ │ xDS │ │ xDS │ │ xDS │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ ▲ ▲ ▲ │ │ │ │ │ │ │ └────────────────────┼────────────────────┘ │ │ │ │ │ LoadBalancer / NodePort │ │ (external traffic) │ └─────────────────────────────────────────────────────────────────────────────┘

The Control Plane

The control plane runs in the envoy-gateway-system namespace. It consists of a single deployment that performs three functions:

ComponentPurpose
Gateway ControllerWatches Kubernetes for Gateway API resources (GatewayClass, Gateway, HTTPRoute)
Gateway TranslatorConverts Gateway API resources into Envoy xDS configuration
Infra ManagerCreates and manages Envoy proxy Deployments and Services

The control plane does not handle traffic. It manages configuration.

The Data Plane

When you create a Gateway resource, the Infra Manager deploys Envoy proxy pods. These proxies receive configuration from the control plane via the xDS protocol—a gRPC-based streaming API that Envoy uses for dynamic configuration.

The beauty of xDS: configuration changes happen without restarting proxies. Update an HTTPRoute, and within seconds the control plane pushes new routing configuration to all Envoy instances via xDS streams.

The xDS Protocol

xDS (x Discovery Service) is how Envoy receives configuration:

APIWhat It Configures
LDS (Listener)Which ports to listen on
RDS (Route)How to route requests
CDS (Cluster)Backend services to route to
EDS (Endpoint)Pod IPs for each service
SDS (Secret)TLS certificates

You do not interact with xDS directly. You write Gateway API resources; Envoy Gateway translates them to xDS and streams updates to proxies.


Installing Gateway API CRDs

Gateway API CRDs define the resource types (GatewayClass, Gateway, HTTPRoute) that Kubernetes will recognize. Install them before Envoy Gateway.

Install the standard Gateway API CRDs:

bash
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml

Output:

text
customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io created customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io created customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io created customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io created

Verify the CRDs are installed:

bash
kubectl get crds | grep gateway.networking.k8s.io

Output:

text
gatewayclasses.gateway.networking.k8s.io 2025-12-30T10:00:00Z gateways.gateway.networking.k8s.io 2025-12-30T10:00:00Z httproutes.gateway.networking.k8s.io 2025-12-30T10:00:00Z referencegrants.gateway.networking.k8s.io 2025-12-30T10:00:00Z

The standard-install.yaml includes the core resources that reached General Availability (GA) in Gateway API v1.0:

CRDStatusPurpose
GatewayClassGADefines controller implementation
GatewayGATraffic entry point
HTTPRouteGAHTTP routing rules
ReferenceGrantGACross-namespace access

Experimental resources (GRPCRoute, TCPRoute, etc.) require a separate installation if needed.


Installing Envoy Gateway via Helm

Envoy Gateway is distributed as a Helm chart from Docker Hub. The chart installs the control plane and creates the GatewayClass automatically.

Install Envoy Gateway v1.6.1:

bash
helm install eg oci://docker.io/envoyproxy/gateway-helm \ --version v1.6.1 \ -n envoy-gateway-system \ --create-namespace

Output:

text
Pulled: docker.io/envoyproxy/gateway-helm:v1.6.1 Digest: sha256:abc123... NAME: eg LAST DEPLOYED: Mon Dec 30 10:05:00 2025 NAMESPACE: envoy-gateway-system STATUS: deployed REVISION: 1 TEST SUITE: None

The --create-namespace flag creates envoy-gateway-system if it does not exist.

Wait for the controller to become available:

bash
kubectl wait --timeout=5m -n envoy-gateway-system \ deployment/envoy-gateway --for=condition=Available

Output:

text
deployment.apps/envoy-gateway condition met

Check the running pods:

bash
kubectl get pods -n envoy-gateway-system

Output:

text
NAME READY STATUS RESTARTS AGE envoy-gateway-5f7d6b8c9f-xk2lj 1/1 Running 0 2m

A single pod runs the control plane. This is the component that watches Gateway API resources and manages the data plane.


Verifying the GatewayClass

Envoy Gateway automatically creates a GatewayClass named eg (short for "Envoy Gateway"). This class tells Kubernetes that Envoy Gateway will handle any Gateway referencing it.

Check the GatewayClass:

bash
kubectl get gatewayclass

Output:

text
NAME CONTROLLER ACCEPTED AGE eg gateway.envoyproxy.io/gatewayclass-controller True 2m

The ACCEPTED: True status means the controller acknowledged this class. If you see False or no status, the controller is not running correctly.

View the GatewayClass details:

bash
kubectl get gatewayclass eg -o yaml

Output:

yaml
apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: eg spec: controllerName: gateway.envoyproxy.io/gatewayclass-controller status: conditions: - lastTransitionTime: "2025-12-30T10:05:00Z" message: GatewayClass is accepted reason: Accepted status: "True" type: Accepted

The controllerName field is the key. Any Gateway referencing gatewayClassName: eg will be handled by the controller with this name.


Creating Your First Gateway

Now create a Gateway that uses the eg GatewayClass. This Gateway will listen for HTTP traffic on port 80.

Create task-api-gateway.yaml:

yaml
apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: task-api-gateway namespace: default spec: gatewayClassName: eg listeners: - name: http protocol: HTTP port: 80 allowedRoutes: namespaces: from: Same

Apply the Gateway:

bash
kubectl apply -f task-api-gateway.yaml

Output:

text
gateway.gateway.networking.k8s.io/task-api-gateway created

Check the Gateway status:

bash
kubectl get gateway task-api-gateway

Output:

text
NAME CLASS ADDRESS PROGRAMMED AGE task-api-gateway eg 10.96.123.45 True 30s

The PROGRAMMED: True status means Envoy Gateway successfully created the data plane resources.

View detailed status:

bash
kubectl describe gateway task-api-gateway

Output:

text
Name: task-api-gateway Namespace: default Labels: <none> API Version: gateway.networking.k8s.io/v1 Kind: Gateway Spec: Gateway Class Name: eg Listeners: Allowed Routes: Namespaces: From: Same Name: http Port: 80 Protocol: HTTP Status: Addresses: Type: IPAddress Value: 10.96.123.45 Conditions: Last Transition Time: 2025-12-30T10:10:00Z Message: Gateway is accepted Reason: Accepted Status: True Type: Accepted Last Transition Time: 2025-12-30T10:10:05Z Message: Gateway is programmed Reason: Programmed Status: True Type: Programmed Listeners: Attached Routes: 0 Conditions: Last Transition Time: 2025-12-30T10:10:05Z Message: Listener is programmed Reason: Programmed Status: True Type: Programmed Name: http Supported Kinds: Group: gateway.networking.k8s.io Kind: HTTPRoute

The status shows:

  • Accepted: Controller acknowledged the Gateway
  • Programmed: Data plane (Envoy proxies) deployed successfully
  • Addresses: Where traffic enters (IP assigned)
  • Listeners: Status of each listener and attached routes

What Envoy Gateway Created

When you created the Gateway, the Infra Manager deployed data plane resources. Examine them:

Check for Envoy proxy pods:

bash
kubectl get pods -l gateway.envoyproxy.io/owning-gateway-name=task-api-gateway

Output:

text
NAME READY STATUS RESTARTS AGE envoy-default-task-api-gateway-abc123-xyz 1/1 Running 0 1m

Envoy Gateway creates a Deployment for each Gateway. The pod runs the Envoy proxy that handles traffic.

Check the Service:

bash
kubectl get svc -l gateway.envoyproxy.io/owning-gateway-name=task-api-gateway

Output:

text
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE envoy-default-task-api-gateway Load Balancer 10.96.123.45 <pending> 80:31234/TCP 1m

The Service type is LoadBalancer by default. On Docker Desktop, the external IP may show <pending> until you access it via port-forward or the LoadBalancer assigns an IP.


Understanding EnvoyProxy CRD (Optional Customization)

The default Envoy deployment works for development. For production, you may need to customize resource limits, replicas, or add pod anti-affinity. Envoy Gateway provides the EnvoyProxy CRD for this.

Create envoy-proxy-config.yaml:

yaml
apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: production-proxy namespace: envoy-gateway-system spec: provider: type: Kubernetes kubernetes: envoyDeployment: replicas: 3 container: resources: requests: cpu: 500m memory: 512Mi limits: cpu: 2000m memory: 2Gi pod: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchLabels: gateway.envoyproxy.io/owning-gateway-name: task-api-gateway topologyKey: kubernetes.io/hostname

Reference the EnvoyProxy from GatewayClass:

To use this configuration, create production-gatewayclass.yaml:

yaml
apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: eg-production spec: controllerName: gateway.envoyproxy.io/gatewayclass-controller parametersRef: group: gateway.envoyproxy.io kind: EnvoyProxy name: production-proxy namespace: envoy-gateway-system

Gateways using gatewayClassName: eg-production will deploy 3 Envoy replicas with production resource limits and anti-affinity rules spreading pods across nodes.


Common Troubleshooting

Gateway shows ACCEPTED but not PROGRAMMED

The control plane accepted the Gateway but failed to deploy the data plane.

Check controller logs:

bash
kubectl logs -n envoy-gateway-system deployment/envoy-gateway

Output (example error):

text
ERROR Failed to create Deployment {"gateway": "default/task-api-gateway", "error": "insufficient resources"}

Common causes:

  • Insufficient cluster resources (CPU, memory)
  • Image pull errors (check container registry access)
  • Service account permissions

GatewayClass shows ACCEPTED: False

The controller is not running or not watching this GatewayClass.

Verify the controller is running:

bash
kubectl get pods -n envoy-gateway-system

Verify the controller name matches:

bash
kubectl get gatewayclass eg -o jsonpath='{.spec.controller Name}'

Output:

text
gateway.envoyproxy.io/gatewayclass-controller

This must match the controller Envoy Gateway advertises.

No external IP assigned

On Docker Desktop or clusters without a LoadBalancer controller, external IPs stay <pending>.

Use port-forward for local access:

bash
kubectl port-forward svc/envoy-default-task-api-gateway 8080:80

Now access http://localhost:8080.


Exercises

Exercise 1: Install Gateway API CRDs

Install the standard Gateway API CRDs and verify:

bash
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml kubectl get crds | grep gateway.networking.k8s.io

Expected: Four CRDs listed (gatewayclasses, gateways, httproutes, referencegrants)

Exercise 2: Install Envoy Gateway via Helm

Install Envoy Gateway and verify the controller is running:

bash
helm install eg oci://docker.io/envoyproxy/gateway-helm \ --version v1.6.1 \ -n envoy-gateway-system \ --create-namespace kubectl wait --timeout=5m -n envoy-gateway-system \ deployment/envoy-gateway --for=condition=Available kubectl get pods -n envoy-gateway-system

Expected: envoy-gateway pod in Running state

Exercise 3: Verify GatewayClass

Check that the eg GatewayClass was created automatically:

bash
kubectl get gatewayclass kubectl get gatewayclass eg -o jsonpath='{.status.conditions[0].status}'

Expected: eg class with True for Accepted condition

Exercise 4: Create Gateway and Check Status

Create a Gateway and verify it becomes PROGRAMMED:

bash
kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: exercise-gateway namespace: default spec: gatewayClassName: eg listeners: - name: http protocol: HTTP port: 80 EOF kubectl get gateway exercise-gateway

Expected: Gateway shows PROGRAMMED: True

Exercise 5: Examine Data Plane Resources

Find the Envoy proxy pods and Service created for your Gateway:

bash
kubectl get pods -l gateway.envoyproxy.io/owning-gateway-name=exercise-gateway kubectl get svc -l gateway.envoyproxy.io/owning-gateway-name=exercise-gateway

Expected: One Envoy pod running, one LoadBalancer Service


Reflect on Your Skill

You built a traffic-engineer skill in Lesson 0. Based on what you learned about Envoy Gateway:

Add Installation Commands

Your skill should now include Envoy Gateway installation:

bash
# Gateway API CRDs kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml # Envoy Gateway controller helm install eg oci://docker.io/envoyproxy/gateway-helm \ --version v1.6.1 \ -n envoy-gateway-system \ --create-namespace

What verification steps are essential?

  1. Check GatewayClass exists: kubectl get gatewayclass eg
  2. Check controller is running: kubectl get pods -n envoy-gateway-system
  3. Check Gateway becomes PROGRAMMED after creation

Add Troubleshooting Guidance

Your skill should include common issues:

SymptomCheckLikely Cause
GatewayClass not ACCEPTEDController logsController not running
Gateway not PROGRAMMEDController logsResource limits, image pull
No external IPService typeNo LoadBalancer controller

Consider EnvoyProxy Customization

For production deployments, your skill should ask:

  • How many replicas do you need?
  • What resource limits are appropriate?
  • Should pods spread across nodes?

If the answer is "production," generate an EnvoyProxy CRD with the custom GatewayClass.


Try With AI

Explore Architecture Internals

Ask your traffic-engineer skill to explain the architecture:

text
Using my traffic-engineer skill, explain how Envoy Gateway's xDS protocol works. When I create a Gateway resource, what happens step by step? How does configuration flow from the Gateway YAML to actual traffic handling?

What you're learning: The internal mechanics of Envoy Gateway. AI can explain the sequence: Gateway Controller watches -> Translator converts to xDS -> xDS Server streams to Envoy proxies. Compare this to the architecture diagram in this lesson.

Evaluate the Explanation

Review what AI provided. Check:

  • Did it mention the control plane vs data plane distinction?
  • Did it explain xDS streaming (not file-based configuration)?
  • Did it describe the specific xDS APIs (LDS, RDS, CDS, EDS)?

If anything is missing or incorrect, tell AI what you learned in this lesson and ask it to refine its explanation.

Customize for Production

Tell AI about your production requirements:

text
I need to customize Envoy proxy resource limits for production. My requirements: - 3 replicas for high availability - 500m/512Mi requests, 2/2Gi limits - Pods should spread across different nodes Generate the EnvoyProxy CRD and explain how to reference it from a GatewayClass.

What you're learning: Working with AI to generate Kubernetes resources. AI should produce an EnvoyProxy with replicas: 3, resource limits, and pod anti-affinity. Verify the YAML matches what you learned in the EnvoyProxy section.

Review and Refine

If AI's EnvoyProxy YAML differs from the lesson, work through the differences:

  • Is the API version correct (gateway.envoyproxy.io/v1alpha1)?
  • Does it include the parametersRef in the GatewayClass?
  • Are the pod affinity rules structured correctly?

This iteration—AI suggests, you validate, AI refines—is how production configurations emerge.

Safety Note

When installing Envoy Gateway in shared or production clusters, coordinate with your platform team. The GatewayClass and CRDs are cluster-scoped resources. Multiple installations of Gateway API CRDs can conflict if versions differ. Always check for existing installations with kubectl get crds | grep gateway before applying new CRDs.