Waypoint proxy
Enforce Layer 7 policies for the apps in your ambient mesh by using kgateway as a waypoint proxy.
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 set up kgateway as a waypoint proxy for multiple apps in your ambient mesh. To demonstrate the Layer 7 capabilities of the waypoint proxy, you deploy the three sample apps client
, httpbin2
, and httpbin3
to your cluster. The client
app sends in-mesh traffic to httpbin2
and httpbin3
. To apply Layer 7 policies, you create HTTPRoute resources for the httpbin2
and httpbin3
apps that define the policies that you want to apply to each app. Because the HTTPRoute is scoped to a particular service, when the client
app sends a request to that service, only the policies that are defined for that service are enforced by the waypoint proxy.
parentRef
section. This way, the policies that are defined in the HTTPRoute are automatically applied to all services in the waypoint proxy namespace.
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.
Deploy sample apps
Install the httpbin2, httpbin3, and curl client sample apps into the httpbin namespace. You use these sample apps to demonstrate the Layer 7 capabilities of the waypoint proxy.
-
Create the httpbin namespace.
kubectl create ns httpbin
-
Deploy the httpbin2, httpbin3, and client sample apps.
kubectl apply -f - <<EOF apiVersion: v1 kind: ServiceAccount metadata: name: httpbin2 namespace: httpbin --- apiVersion: v1 kind: Service metadata: name: httpbin2 namespace: httpbin labels: app: httpbin2 service: httpbin2 spec: ports: - name: http port: 8000 targetPort: http protocol: TCP appProtocol: http selector: app: httpbin2 --- apiVersion: apps/v1 kind: Deployment metadata: name: httpbin2 namespace: httpbin spec: replicas: 1 selector: matchLabels: app: httpbin2 version: v1 template: metadata: labels: app: httpbin2 version: v1 spec: serviceAccountName: httpbin2 containers: - name: httpbin image: mccutchen/go-httpbin:v2.14.0 command: [ go-httpbin ] args: - "-max-duration" - "600s" # override default 10s - -use-real-hostname ports: - name: http containerPort: 8080 protocol: TCP livenessProbe: httpGet: path: /status/200 port: http readinessProbe: httpGet: path: /status/200 port: http env: - name: K8S_MEM_LIMIT valueFrom: resourceFieldRef: divisor: "1" resource: limits.memory - name: GOMAXPROCS valueFrom: resourceFieldRef: divisor: "1" resource: limits.cpu EOF
kubectl apply -f - <<EOF apiVersion: v1 kind: ServiceAccount metadata: name: httpbin3 namespace: httpbin --- apiVersion: v1 kind: Service metadata: name: httpbin3 namespace: httpbin labels: app: httpbin3 service: httpbin3 spec: ports: - name: http port: 8000 targetPort: http protocol: TCP appProtocol: http selector: app: httpbin3 --- apiVersion: apps/v1 kind: Deployment metadata: name: httpbin3 namespace: httpbin spec: replicas: 1 selector: matchLabels: app: httpbin3 version: v1 template: metadata: labels: app: httpbin3 version: v1 spec: serviceAccountName: httpbin3 containers: - name: httpbin image: mccutchen/go-httpbin:v2.14.0 command: [ go-httpbin ] args: - "-max-duration" - "600s" # override default 10s - -use-real-hostname ports: - name: http containerPort: 8080 protocol: TCP livenessProbe: httpGet: path: /status/200 port: http readinessProbe: httpGet: path: /status/200 port: http env: - name: K8S_MEM_LIMIT valueFrom: resourceFieldRef: divisor: "1" resource: limits.memory - name: GOMAXPROCS valueFrom: resourceFieldRef: divisor: "1" resource: limits.cpu EOF
kubectl apply -f - <<EOF apiVersion: v1 kind: ServiceAccount metadata: name: client namespace: httpbin --- apiVersion: v1 kind: Service metadata: name: client namespace: httpbin labels: app: client service: client spec: ports: - name: http port: 8000 targetPort: 80 selector: app: client --- apiVersion: apps/v1 kind: Deployment metadata: name: client namespace: httpbin spec: replicas: 1 selector: matchLabels: app: client version: v1 template: metadata: labels: app: client version: v1 spec: serviceAccountName: client containers: - image: nicolaka/netshoot:latest imagePullPolicy: IfNotPresent name: netshoot command: ["/bin/bash"] args: ["-c", "while true; do ping localhost; sleep 60;done"] EOF
-
Verify that all apps are deployed successfully.
kubectl get pods -n httpbin
Example output:
NAME READY STATUS RESTARTS AGE client-87678cb44-dclfs 1/1 Running 0 87m httpbin2-58dcc755ff-ngq2f 1/1 Running 0 92m httpbin3-77bbdd9b6b-8d8hq 1/1 Running 0 70m
-
Label the
httpbin
andkgateway-system
namespaces to add the httpbin2, httpbin3, and client apps, and the gateway proxy to the ambient mesh.kubectl label ns httpbin istio.io/dataplane-mode=ambient kubectl label ns kgateway-system istio.io/dataplane-mode=ambient
Create a waypoint proxy
You use the kgateway-waypoint
GatewayClass to deploy kgateway as a waypoint proxy in your cluster.
-
Create a waypoint proxy in the httpbin namespace. Note that creating a waypoint proxy does not automatically enforce Layer 7 policies for the apps in your cluster. To assign a waypoint, you must label your apps. You learn how to label your apps in a later step.
kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: kgateway-waypoint namespace: httpbin spec: gatewayClassName: kgateway-waypoint listeners: - name: proxy port: 15088 protocol: istio.io/PROXY EOF
-
Wait for the waypoint proxy to deploy successfully.
kubectl -n httpbin rollout status deploy kgateway-waypoint
Example output:
deployment "kgateway-waypoint" successfully rolled out
-
Label the httpbin2 and httpbin3 apps to use the waypoint proxy that you created.
kubectl -n httpbin label svc httpbin2 istio.io/use-waypoint=kgateway-waypoint kubectl -n httpbin label svc httpbin3 istio.io/use-waypoint=kgateway-waypoint
-
Send a request from the client app to httpbin2 and httpbin3. Verify that the request succeeds.
kubectl -n httpbin exec deploy/client -- curl -s http://httpbin2:8000/get kubectl -n httpbin exec deploy/client -- curl -s http://httpbin3:8000/get
Example output for httpbin2:
{ "args": {}, "headers": { "Accept": [ "*/*" ], "Host": [ "httpbin2:8000" ], "User-Agent": [ "curl/8.7.1" ], "X-Envoy-Expected-Rq-Timeout-Ms": [ "15000" ], "X-Forwarded-Proto": [ "http" ], "X-Request-Id": [ "590a6a48-60f8-4ec0-92d1-fcb629b97e0d" ] }, "method": "GET", "origin": "10.XX.X.XX:34059", "url": "http://httpbin2:8000/get" }
Enforce L7 policies with the waypoint
In this step, you explore how to apply header modification policies to your sample apps. These policies are enforced by the Gloo Gateway waypoint proxy that you created earlier. You can add other Layer 7 policies to the waypoint proxy. For more information, see the traffic management, security, and resiliency guides.
Header control
Use the Kubernetes Gateway API to define header manipulation rules that you apply to the httpbin apps, including adding, setting, and removing request headers.
-
Create an HTTPRoute resource for the httpbin2 app with the following request header modifications rules:
- Add the
App: httpbin2
header to all requests. - Set the
User-Agent
header tocustom
. If the User-Agent header is not present, it is added to the request. - Remove the
X-Remove
header from the request.
Note that the HTTPRoute specifies the httpbin2 service in the
parentRefs
section. This setting instructs the waypoint proxy to enforce these policies for the httpbin2 app only.kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httpbin2 namespace: httpbin spec: parentRefs: - name: httpbin2 kind: Service group: "" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: httpbin2 port: 8000 filters: - type: RequestHeaderModifier requestHeaderModifier: add: - name: App value: httpbin2 set: - name: User-Agent value: custom remove: - X-Remove EOF
- Add the
-
Create an HTTPRoute for the httpbin3 app with the following request header modifications rules:
- Add the
App: httpbin3
header to all requests.
kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httpbin3 namespace: httpbin spec: parentRefs: - name: httpbin3 kind: Service group: "" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: httpbin3 port: 8000 filters: - type: RequestHeaderModifier requestHeaderModifier: add: - name: App value: httpbin3 EOF
- Add the
-
Use the client sample app to send a request to the httpbin2 app. Verify that you see the
App: httpbin2
andUser-Agent: custom
headers, and that theX-Remove
was not added to the respones.kubectl -n httpbin exec deploy/client -- curl -s http://httpbin2:8000/get \ -H "X-Remove: this header"
Example output:
Console output1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
{ "args": {}, "headers": { "Accept": [ "*/*" ], "App": [ "httpbin2" ], "Host": [ "httpbin2:8000" ], "User-Agent": [ "custom" ], "X-Client": [ "curl" ], "X-Envoy-Expected-Rq-Timeout-Ms": [ "15000" ], "X-Forwarded-Proto": [ "http" ], "X-Request-Id": [ "4ef6b82d-6388-4be9-bb2c-b3077beafee8" ] }, "method": "GET", "origin": "10.XX.X.XX:33737", "url": "http://httpbin2:8000/get" }
-
Send the same request to the httpbin3 app. Verify that you see the
App: httpbin3
header andX-Remove
headers, and that theUser-Agent
header is not changed tocustom
.kubectl -n httpbin exec deploy/client -- curl -s http://httpbin3:8000/get \ -H "X-Remove: this header"
Example output:
Console output1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
{ "args": {}, "headers": { "Accept": [ "*/*" ], "Host": [ "httpbin3:8000" ], "App": [ "httpbin3" ], "User-Agent": [ "curl/8.7.1" ], "X-Envoy-Expected-Rq-Timeout-Ms": [ "15000" ], "X-Forwarded-Proto": [ "http" ], "X-Remove": [ "this header" ], "X-Request-Id": [ "8a32f44f-55ab-4ff7-8b77-16d18739ae02" ] }, "method": "GET", "origin": "10.XX.X.XX:53569", "url": "http://httpbin3:8000/get" }
Transformations
Use kgateway’s TrafficPolicy to apply a transformation policy to the httpbin2 app.
-
Create a TrafficPolicy that applies a transformation policy to the httpbin2 app. In this example, the base64-encoded value from the
x-base64-encoded
header is decoded and added to thex-base64-decoded
header, starting from the 11th character.kubectl apply -f- <<EOF apiVersion: gateway.kgateway.dev/v1alpha1 kind: TrafficPolicy metadata: name: transformation namespace: httpbin spec: targetRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: httpbin2 transformation: response: set: - name: x-base64-decoded value: '{{ substring(base64_decode(request_header("x-base64-encoded")), 11) }}' EOF
-
Use the client app to send a request to the httpbin2 app and include a base64-encoded value of
transformation test
in the requestx-base64-encoded
header. Verify that you get back a 200 HTTP response code, and that the decoded value is added to thex-base64-decoded
response header, starting from the 11th character.kubectl -n httpbin exec deploy/client -- curl -vik http://httpbin2:8000/headers \ -H "x-base64-encoded: dHJhbnNmb3JtYXRpb24gdGVzdA=="
Example output:
Console output1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
< HTTP/1.1 200 OK ... access-control-allow-credentials: true access-control-allow-origin: * content-type: application/json; charset=utf-8 content-length: 544 x-envoy-upstream-service-time: 0 x-base64-decoded: ion test server: envoy { "headers": { "Accept": [ "*/*" ], "App": [ "httpbin2" ], "Host": [ "httpbin2:8000" ], "User-Agent": [ "custom" ], "X-Base64-Encoded": [ "dHJhbnNmb3JtYXRpb24gdGVzdA==" ], "X-Envoy-Expected-Rq-Timeout-Ms": [ "15000" ], "X-Envoy-External-Address": [ "10.0.74.217" ], "X-Forwarded-For": [ "10.0.74.217" ], "X-Forwarded-Proto": [ "http" ], "X-Request-Id": [ "4b6444cc-b631-49c9-b2b4-f71ec479925f" ] } }
-
Optional: Remove the TrafficPolicy that you created in this guide.
kubectl delete TrafficPolicy transformation -n httpbin
Cleanup
Delete the resources that you created in this guide.
kubectl delete HTTPRoute httpbin3 -n httpbin
kubectl delete HTTPRoute httpbin2 -n httpbin
kubectl delete gateway kgateway-waypoint -n httpbin
kubectl delete serviceaccount httpbin2 -n httpbin
kubectl delete service httpbin2 -n httpbin
kubectl delete deployment httpbin2 -n httpbin
kubectl delete serviceaccount httpbin3 -n httpbin
kubectl delete service httpbin3 -n httpbin
kubectl delete deployment httpbin3 -n httpbin
kubectl delete serviceaccount client -n httpbin
kubectl delete service client -n httpbin
kubectl delete deployment client -n httpbin
kubectl delete TrafficPolicy transformation -n httpbin