Ingress

Use kgateway as the ingress gateway for your ambient mesh.

About ambient mesh

Solo.io and Google collaborated to develop ambient mesh, a new “sidecarless” architecture for the Istio service mesh. Ambient mesh uses node-level ztunnels to route and secure Layer 4 traffic between pods with mutual TLS (mTLS). Waypoint proxies enforce Layer 7 traffic policies whenever needed. To onboard apps into the ambient mesh, you simply label the namespace the app belongs to. Because no sidecars need to be injected in to your apps, ambient mesh significantly reduces the complexity of adopting a service mesh.

To learn more about ambient, see the ambient mesh documentation.

About this guide

In this guide, you learn how to use kgateway as the ingress gateway to route traffic to the httpbin app that is part of an ambient service mesh.

This guide assumes that you run your ambient mesh in a single cluster and want to use kgateway as the ingress gateway to protect your ambient mesh services.

kgateway as an ingress gateway to your ambient mesh

Before you begin

  1. Follow the Get started guide to install kgateway.

  2. Follow the Sample app guide to create an API gateway proxy with an HTTP listener and deploy the httpbin sample app.

  3. Get the external address of the gateway and save it in an environment variable.

    export INGRESS_GW_ADDRESS=$(kubectl get svc -n kgateway-system http -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}")
    echo $INGRESS_GW_ADDRESS  
    kubectl port-forward deployment/http -n kgateway-system 8080:8080

Step 1: Set up an ambient mesh

Set up an ambient mesh in your cluster to secure service-to-service communication with mutual TLS by following the ambientmesh.io quickstart documentation.

Step 2: Set up kgateway for ingress

To set up kgateway as the ingress gateway for your ambient mesh, you simply add all the namespaces that you want to secure to your ambient mesh, including the namespace that your gateway proxy is deployed to.

  1. Add the kgateway-system and httpbin namespaces to your ambient mesh. Use the same command to add other namespaces in your cluster.

    kubectl label ns kgateway-system istio.io/dataplane-mode=ambient
    kubectl label ns httpbin istio.io/dataplane-mode=ambient
  2. Send a request to the httpbin app and verify that you get back a 200 HTTP response code. All traffic from the gateway is automatically intercepted by a ztunnel that is co-located on the same node as the gateway. The ztunnel collects Layer 4 metrics before it forwards the request to the ztunnel that is co-located on the same node as the httpbin app. The connection between ztunnels is secured via mutual TLS.

    curl -i http://$INGRESS_GW_ADDRESS:8080/headers -H "host: www.example.com:8080"

    Example output:

    HTTP/1.1 200 OK
    ...
    {
     "headers": {
       "Accept": [
         "*/*"
        ],
        "Host": [
          "www.example.com:8080"
        ],
        "User-Agent": [
          "curl/8.7.1"
        ],
        "X-Envoy-Expected-Rq-Timeout-Ms": [
          "15000"
        ],
        "X-Forwarded-Proto": [
          "http"
        ],
       "X-Request-Id": [
          "929c334b-e611-4aba-9bc6-ad6b2450db26"
        ]
      }
    }
    
    1. Port-forward the http pod on port 8080.

      kubectl port-forward deployment/http -n kgateway-system 8080:8080
    2. Send a request to the httpbin app and verify that you get back a 200 HTTP response code.

      curl -i localhost:8080/headers -H "host: www.example.com"

      Example output:

      HTTP/1.1 200 OK
      ...
      {
      "headers": {
      "Accept": [
      "*/*"
      ],
      "Host": [
         "www.example.com:8080"
      ],
      "User-Agent": [
         "curl/8.7.1"
      ],
      "X-Envoy-Expected-Rq-Timeout-Ms": [
         "15000"
      ],
      "X-Forwarded-Proto": [
         "http"
      ],
      "X-Request-Id": [
         "929c334b-e611-4aba-9bc6-ad6b2450db26"
      ]
       }
      }

      <button class=“hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50” title=“Copy code”

  3. Verify that traffic between the gateway proxy and the httpbin app is secured via mutual TLS. Because traffic in an ambient mesh is intercepted by the ztunnels that are co-located on the same node as the sending and receiving service, you can check the logs of the ztunnels.

    1. Find the NODE that the httpbin app runs on.

      kubectl get pods -n httpbin -o wide

      Example output:

      NAME                       READY   STATUS    RESTARTS   AGE   IP           NODE                                                  NOMINATED NODE   READINESS GATES
      httpbin-54cf575757-hdv8t   3/3     Running   0          22h   10.XX.X.XX   gke-ambient-default-pool-bb9a8da5-bdf4   <none>           <none>
    2. Find the ztunnel that runs on the same node as the httpbin app.

      kubectl get pods -n istio-system -o wide | grep ztunnel
    3. Check the logs of that ztunnel instance and verify that the source and destination workloads have a SPIFFE ID.

      kubectl logs <ztunnel-instance> -n istio-system

      Example output:

      2025-03-19T17:32:42.762545Z	info	http access	request complete	src.addr=10.0.71.117:42468 src.workload="http-9db6c8995-l54dw" src.namespace="kgateway-system" src.identity="spiffe://cluster.local/ns/kgateway-system/sa/http" dst.addr=10.0.65.144:15008 dst.hbone_addr=10.0.65.144:8080 dst.service="httpbin.httpbin.svc.cluster.local" dst.workload="httpbin-577649ddb-7nc8p" dst.namespace="httpbin" dst.identity="spiffe://cluster.local/ns/httpbin/sa/httpbin" direction="inbound" method=GET path="/headers" protocol=HTTP1 response_code=200 host="www.example.com:8080" user_agent="curl/8.7.1" request_id="4c5fc679-c5cd-4721-8735-51bcdbea6e0f" duration="0ms"
      2025-03-19T17:32:46.810472Z	info	access	connection complete	src.addr=10.0.71.117:42468 src.workload="http-9db6c8995-l54dw" src.namespace="kgateway-system" src.identity="spiffe://cluster.local/ns/kgateway-system/sa/http" dst.addr=10.0.65.144:15008 dst.hbone_addr=10.0.65.144:8080 dst.service="httpbin.httpbin.svc.cluster.local" dst.workload="httpbin-577649ddb-7nc8p" dst.namespace="httpbin" dst.identity="spiffe://cluster.local/ns/httpbin/sa/httpbin" direction="inbound" bytes_sent=1290 bytes_recv=550 duration="6742ms"

Next

Now that you set up kgateway as the ingress gateway for your ambient mesh, you can further control and secure ingress traffic with Policies.