Extend waypoints with Lua scripts

Istio provides the ability to extend waypoint proxies using inline Lua scripts via the TrafficExtension API. In ambient mode, TrafficExtension resources must be attached to a waypoint proxy using targetRefs.

Before you begin

  1. Set up Istio by following the ambient mode Getting Started guide.

  2. Deploy the Bookinfo sample application.

  3. Add the default namespace to the ambient mesh.

  4. Deploy the curl sample app as a test source:

    Zip
    $ kubectl apply -f @samples/curl/curl.yaml@

At a gateway

Get the gateway name:

$ kubectl get gateway
NAME               CLASS            ADDRESS                                            PROGRAMMED   AGE
bookinfo-gateway   istio            bookinfo-gateway-istio.default.svc.cluster.local   True         42m

Create a TrafficExtension targeting the bookinfo-gateway with a Lua parity filter. The filter reads an x-number request header and adds an x-parity response header indicating whether the value is odd or even. The value is stored in dynamic metadata during request processing so it is available when writing the response header:

$ kubectl apply -f - <<EOF
apiVersion: extensions.istio.io/v1alpha1
kind: TrafficExtension
metadata:
  name: parity-at-gateway
spec:
  targetRefs:
    - kind: Gateway
      group: gateway.networking.k8s.io
      name: bookinfo-gateway
  phase: STATS
  lua:
    inlineCode: |
      function envoy_on_request(request_handle)
        local number = tonumber(request_handle:headers():get("x-number"))
        if number == nil then return end
        local parity = number % 2 == 0 and "even" or "odd"
        request_handle:streamInfo():dynamicMetadata():set(
          "envoy.filters.http.lua", "parity", parity)
      end
      function envoy_on_response(response_handle)
        local meta = response_handle:streamInfo():dynamicMetadata():get(
          "envoy.filters.http.lua")
        if meta == nil then return end
        response_handle:headers():add("x-parity", meta["parity"])
      end
EOF

Verify the traffic via the gateway

$ kubectl exec deploy/curl -- curl -s -o /dev/null -D - -H "x-number: 4" "http://bookinfo-gateway-istio.default.svc.cluster.local/productpage" | grep x-parity
x-parity: even

At a waypoint, for all services in a namespace

Deploy a waypoint proxy

Follow the waypoint deployment instructions to deploy a waypoint proxy in the bookinfo namespace:

$ istioctl waypoint apply --enroll-namespace --wait

Verify traffic reaches the service:

$ kubectl exec deploy/curl -- curl -s -w "%{http_code}" -o /dev/null http://productpage:9080/productpage
200

Get the waypoint gateway name:

$ kubectl get gateway
NAME               CLASS            ADDRESS                                            PROGRAMMED   AGE
bookinfo-gateway   istio            bookinfo-gateway-istio.default.svc.cluster.local   True         23h
waypoint           istio-waypoint   10.96.202.82                                       True         21h

Create a TrafficExtension targeting the waypoint:

$ kubectl apply -f - <<EOF
apiVersion: extensions.istio.io/v1alpha1
kind: TrafficExtension
metadata:
  name: parity-at-waypoint
spec:
  targetRefs:
    - kind: Gateway
      group: gateway.networking.k8s.io
      name: waypoint
  phase: STATS
  lua:
    inlineCode: |
      function envoy_on_request(request_handle)
        local number = tonumber(request_handle:headers():get("x-number"))
        if number == nil then return end
        local parity = number % 2 == 0 and "even" or "odd"
        request_handle:streamInfo():dynamicMetadata():set(
          "envoy.filters.http.lua", "parity", parity)
      end
      function envoy_on_response(response_handle)
        local meta = response_handle:streamInfo():dynamicMetadata():get(
          "envoy.filters.http.lua")
        if meta == nil then return end
        response_handle:headers():add("x-parity", meta["parity"])
      end
EOF

Verify the traffic via the waypoint proxy

$ kubectl exec deploy/curl -- curl -s -o /dev/null -D - -H "x-number: 7" http://productpage:9080/productpage | grep x-parity
x-parity: odd

At a waypoint, for a specific service

Remove the namespace-wide filter and replace it with one that targets only the reviews service:

$ kubectl delete trafficextension parity-at-waypoint

Create a TrafficExtension targeting the reviews service directly so that the filter applies only to traffic destined for that service:

$ kubectl apply -f - <<EOF
apiVersion: extensions.istio.io/v1alpha1
kind: TrafficExtension
metadata:
  name: parity-for-reviews
spec:
  targetRefs:
    - kind: Service
      group: ""
      name: reviews
  match:
  - mode: SERVER
  phase: STATS
  lua:
    inlineCode: |
      function envoy_on_request(request_handle)
        local number = tonumber(request_handle:headers():get("x-number"))
        if number == nil then return end
        local parity = number % 2 == 0 and "even" or "odd"
        request_handle:streamInfo():dynamicMetadata():set(
          "envoy.filters.http.lua", "parity", parity)
      end
      function envoy_on_response(response_handle)
        local meta = response_handle:streamInfo():dynamicMetadata():get(
          "envoy.filters.http.lua")
        if meta == nil then return end
        response_handle:headers():add("x-parity", meta["parity"])
      end
EOF

Verify the traffic targeting the service

$ kubectl exec deploy/curl -- curl -s -o /dev/null -D - -H "x-number: 3" http://reviews:9080/reviews/1 | grep x-parity
x-parity: odd

Cleanup

  1. Remove TrafficExtension resources:

    $ kubectl delete trafficextension parity-at-gateway parity-for-reviews
  2. Follow the ambient mode uninstall guide to remove Istio and sample test applications.

Was this information useful?
Do you have any suggestions for improvement?

Thanks for your feedback!