> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Demo Multi Service Application Gateway

> Demo deploying a Kubernetes coffee app, configuring an NGINX Fabric Gateway and HTTPRoute to expose and route HTTP requests for subdomains like cafe.example.com

Welcome to demo two. In this walkthrough we take the first steps with the Gateway API and the NGINX Fabric Gateway implementation. You'll deploy a simple app, expose it with a Kubernetes Service, create a Gateway that accepts `*.example.com`, and attach an HTTPRoute so external requests reach the app.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/QZ7pWzRtYdnRAGco/images/Gateway-API-with-NGINX-Fabric-Gateway/Core-Gateway-API-Resources/Demo-Multi-Service-Application-Gateway/multi-service-application-gateway-demo-slide.jpg?fit=max&auto=format&n=QZ7pWzRtYdnRAGco&q=85&s=c0729d79a29ed8a3c48e9dc15fcd2530" alt="A presentation slide reading &#x22;Multi-Service Application Gateway&#x22; on the left and a large turquoise shape on the right with the word &#x22;Demo.&#x22; A small &#x22;© Copyright KodeKloud&#x22; label appears in the bottom-left." width="1920" height="1080" data-path="images/Gateway-API-with-NGINX-Fabric-Gateway/Core-Gateway-API-Resources/Demo-Multi-Service-Application-Gateway/multi-service-application-gateway-demo-slide.jpg" />
</Frame>

## Application and Service

This demo uses a simple "coffee" application deployed as a Deployment and exposed via a ClusterIP Service named `coffee`.

Key Service details:

* Service name: `coffee`
* Service port: `80`
* Target container port: `8080`
* Protocol: `TCP`
* Service port name: `http`

Verify the Deployment and Service:

```bash theme={null}
kubectl get deployments
kubectl get services
```

## Gateway manifest

Create a Gateway to accept HTTP on port 80. The Gateway references a `GatewayClass` (`nginx`) so the underlying implementation (control plane + data plane) knows which controller to use. The listener restricts hostnames to `*.example.com`, allowing routes to match subdomains such as `cafe.example.com`.

```yaml theme={null}
# gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: gateway
spec:
  gatewayClassName: nginx
  listeners:
  - name: http
    port: 80
    protocol: HTTP
    hostname: "*.example.com"
```

Apply the Gateway and inspect status:

```bash theme={null}
kubectl apply -f gateway.yaml
kubectl get gateway
kubectl get pods
```

Example terminal output after creating the Gateway:

```bash theme={null}
$ kubectl apply -f gateway.yaml
gateway.gateway.networking.k8s.io/gateway created

$ kubectl get gateway
NAME      CLASS   ADDRESS        PROGRAMMED   AGE
gateway   nginx   10.96.56.153   True         10s

$ kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
coffee-5b9c74f9d9-9rf2f            1/1     Running   0          3m
gateway-nginx-5f9d4c4ff-2d7zp      0/1     Running   0          20s
```

When the Gateway is created, the implementation spins up a data-plane pod (for example `gateway-nginx-...`) that receives translated configuration from the Gateway API control plane. Wait for that pod to reach `Running` before testing.

<Callout icon="lightbulb" color="#1CB2FE">
  The Gateway's `hostname` (for example `*.example.com`) limits which Host header / SNI values are accepted. Routes (HTTPRoute) that target a specific hostname like `cafe.example.com` must match a hostname allowed by the Gateway.
</Callout>

## HTTPRoute manifest

Create an HTTPRoute that binds to the `gateway` listener (section `http`) and routes requests with the `/coffee` path prefix to the `coffee` Service on port `80`.

```yaml theme={null}
# coffee-route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: coffee
spec:
  parentRefs:
  - name: gateway
    sectionName: http
  hostnames:
  - "cafe.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /coffee
    backendRefs:
    - name: coffee
      port: 80
```

Apply the HTTPRoute and verify the configured resources:

```bash theme={null}
kubectl apply -f coffee-route.yaml
kubectl get httproute
kubectl get gateway
kubectl get pods
kubectl get svc
```

Example terminal output:

```bash theme={null}
$ kubectl apply -f coffee-route.yaml
httproute.gateway.networking.k8s.io/coffee created

$ kubectl get httproute
NAME     HOSTNAMES             AGE
coffee   ["cafe.example.com"]  12s

$ kubectl get gateway
NAME     CLASS   ADDRESS       PROGRAMMED  AGE
gateway  nginx   10.96.56.153  True        2m30s

$ kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
coffee-5b9c74f9d9-9rf2f            1/1     Running   0          5m
gateway-nginx-5f9d4c4ff-2d7zp      1/1     Running   0          3m

$ kubectl get svc
NAME           TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)         AGE
coffee         ClusterIP   10.96.197.88   <none>        80/TCP           5m
gateway-nginx  NodePort    10.96.56.153   <none>        80:31437/TCP     3m
kubernetes     ClusterIP   10.96.0.1      <none>        443/TCP          26m
```

## Testing with curl

In a local lab environment we often don't have real DNS for `cafe.example.com`, so we use `curl --resolve` to override DNS and send the correct Host header. You can reach the Gateway either by port-forwarding the Gateway service to localhost or by hitting the NodePort exposed by the Gateway.

Port-forward example (forward service port 80 to local 8080):

```bash theme={null}
kubectl port-forward svc/gateway-nginx 8080:80
```

Then request the `/coffee` path while preserving the Host header:

```bash theme={null}
curl --resolve cafe.example.com:8080:127.0.0.1 http://cafe.example.com:8080/coffee
```

Alternatively, target the NodePort shown in `kubectl get svc` (31437 in the example):

```bash theme={null}
curl --resolve cafe.example.com:31437:127.0.0.1 http://cafe.example.com:31437/coffee
```

The Gateway implementation will accept the Host header `cafe.example.com` and route `/coffee` to the `coffee` Service.

Successful request example (same curl command as above):

```bash theme={null}
curl --resolve cafe.example.com:8080:127.0.0.1 http://cafe.example.com:8080/coffee
```

Example response body returned by the coffee application (fields vary by app):

```text theme={null}
Server address: 10.244.0.7:8080
Server name: coffee-5b9c74f9d9-9rf2f
Date: 11/Apr/2026:19:58:03 +0000
URI: /coffee
Request ID: 6af36e55-15ba-1173-5d84-b62a58833a5b
```

If you request a path that does not match any configured route (for example `/coffee123`), the Gateway proxy returns a 404:

```bash theme={null}
curl --resolve cafe.example.com:8080:127.0.0.1 http://cafe.example.com:8080/coffee123
```

Example 404 response from the proxy (NGINX):

```html theme={null}
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
```

## Quick resource summary

| Resource | Purpose | Example / Command |
| - | - | - |
| Deployment | Runs the coffee app | `kubectl get deployments` |
| Service (ClusterIP) | Internal service for pods | `name: coffee`, `port: 80 -> targetPort: 8080` |
| Gateway | Listens for external traffic, implemented by `GatewayClass` | `gateway.yaml` (above) |
| HTTPRoute | Routes requests (host + path) to backends | `coffee-route.yaml` (above) |
| Test access | Local testing using Host header override | `curl --resolve cafe.example.com:8080:127.0.0.1 http://cafe.example.com:8080/coffee` |

## Summary

* Deployed the `coffee` application and exposed it via a ClusterIP Service.
* Created a Gateway that listens on HTTP port 80 and accepts `*.example.com`.
* Attached an HTTPRoute for `cafe.example.com` and routed `/coffee` requests to the `coffee` Service.
* Tested end-to-end routing locally with `curl --resolve` (or via NodePort / port-forward).

References

* Gateway API: [https://gateway-api.sigs.k8s.io/](https://gateway-api.sigs.k8s.io/)
* Kubernetes documentation: [https://kubernetes.io/docs/](https://kubernetes.io/docs/)
* NGINX documentation: [https://docs.nginx.com/](https://docs.nginx.com/)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/gateway-api-with-nginx-fabric-gateway/module/4c755491-684e-4113-bddb-c202ad926bff/lesson/e220a257-8599-440a-a656-1cbc4efbd716" />

  <Card title="Practice Lab" icon="flask-conical" cta="Learn more" href="https://learn.kodekloud.com/user/courses/gateway-api-with-nginx-fabric-gateway/module/4c755491-684e-4113-bddb-c202ad926bff/lesson/92d9a2de-668b-4af2-8dae-8ab826ab093b" />
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.