WebAssembly (Wasm) is an open standard, binary instruction format to enable high-performing web apps. Gloo Mesh integrates with Wasm filters by using Gloo Mesh policies. Add a Wasm filter to the Envoy sidecar proxy, for use cases such as customizing the endpoints and thresholds for your workloads.

NOTE FOR TESTING so WASM might not work for regular workloads since they don’t have a sidecar to enable. However, maybe you can modify the gateway workload’s sidecar and apply the policy to the gateway. Then any traffic that passes through it gets the filter applied.

In this guide, you set up a sample Wasm filter that is hosted in Solo’s public Google Container Registry. The filter adds a custom header to the response from the ratings service in the Bookinfo application. To set up the filter, you complete two main steps.

  1. Enable the Envoy sidecar to fetch Wasm filters.
  2. Apply a Wasm deployment policy to the ratings workload.

Before you begin

  1. Complete the multicluster getting started guide to set up the following testing environment.

    • Three clusters along with environment variables for the clusters and their Kubernetes contexts.
    • The Gloo meshctl CLI, along with other CLI tools such as kubectl and istioctl.
    • The Gloo management server in the management cluster, and the Gloo agents in the workload clusters.
    • Istio installed in the workload clusters.
    • A simple Gloo workspace setup.
  2. Install Bookinfo and other sample apps.
  3. Optional: Create your own Wasm filter to extend Envoy gateway functionality. To easily refer to your filter in the Wasm deployment policy, store your Wasm filter in an OCI-compliant registry, such as Docker Hub or Amazon ECR.

Enable the Envoy sidecar to fetch Wasm filters

To apply Wasm filters, you must enable the Envoy sidecar proxies on your workloads to fetch Wasm filters from an Envoy cluster. The Envoy cluster is defined in the static bootstrap configuration. You can perform a one-time operation to add the gloo-mesh-agent as an Envoy cluster in the Envoy bootstrap.

  1. Create a config map that defines the gloo-mesh-agent as the Envoy cluster to bootstrap your workloads’ Envoy sidecar proxies with.

      cat <<EOF | kubectl apply --context ${REMOTE_CONTEXT1} -n bookinfo -f -
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: gloo-mesh-custom-envoy-bootstrap
      namespace: bookinfo
    data:
      custom_bootstrap.json: |
        {
          "static_resources": {
            "clusters": [{
              "name": "gloo_mesh_agent_cluster",
              "type" : "STRICT_DNS",
              "connect_timeout": "1s",
              "lb_policy": "ROUND_ROBIN",
              "load_assignment": {
                "cluster_name": "gloo_mesh_agent_cluster",
                "endpoints": [{
                  "lb_endpoints": [{
                    "endpoint": {
                      "address":{
                        "socket_address": {
                          "address": "gloo-mesh-agent.gloo-mesh.svc.cluster.local",
                          "port_value": 9977
                        }
                      }
                    }
                  }]
                }]
              },
              "circuit_breakers": {
                "thresholds": [
                  {
                    "priority": "DEFAULT",
                    "max_connections": 100000,
                    "max_pending_requests": 100000,
                    "max_requests": 100000
                  },
                  {
                    "priority": "HIGH",
                    "max_connections": 100000,
                    "max_pending_requests": 100000,
                    "max_requests": 100000
                  }
                ]
              },
              "upstream_connection_options": {
                "tcp_keepalive": {
                  "keepalive_time": 300
                }
              },
              "max_requests_per_connection": 1,
              "http2_protocol_options": { }
            }]
          }
        }
    EOF
      
  2. Patch the ratings-v1 deployment to include the custom Envoy sidecar boostrap configuration.

      kubectl patch deployment -n bookinfo ratings-v1 --context ${REMOTE_CONTEXT1} \
      --patch='{"spec":{"template": {"metadata": {"annotations": {"sidecar.istio.io/bootstrapOverride": "gloo-mesh-custom-envoy-bootstrap"}}}}}' \
      --type=merge
      

Great job! Your ratings-v1 workload’s Envoy sidecar is ready to accept Wasm filters. You can repeat these steps for any workloads that you want to apply a Wasm filter to.

Apply the Wasm filter

Your Wasm filter configuration is stored in an OCI-compliant registry, and your workload’s Envoy sidecar is enabled for Wasm filters. Now you can start to modify traffic by creating a Wasm deployment policy. The policy includes a reference to the filter image that you want to apply. You apply Wasm deployment policies at the workload level.

In this example, you use a filter that adds a custom header to the response from the ratings service in the Bookinfo application. You can also make your own filters.

  1. Test your Bookinfo setup before applying the Wasm filter.

    1. Create a temporary curl pod in the bookinfo namespace, so that you can test the app setup.

        kubectl run -it -n bookinfo --context $REMOTE_CONTEXT1 curl \
        --image=curlimages/curl:7.73.0 --rm  -- sh
        
    2. Send a request to the ratings app.

        curl http://ratings:9080/ratings/1 -v
        

      In the output, note the response headers.

      *   Trying 10.96.31.140:9080...
      * Connected to ratings (10.96.31.140) port 9080 (#0)
      > GET /ratings/1 HTTP/1.1
      > Host: ratings:9080
      > User-Agent: curl/7.73.0-DEV
      > Accept: */*
      >
      * Mark bundle as not supporting multiuse
      < HTTP/1.1 200 OK
      < content-type: application/json
      < date: Wed, 11 May 2022 17:00:40 GMT
      < x-envoy-upstream-service-time: 104
      < server: envoy
      < transfer-encoding: chunked
      <
      * Connection #0 to host ratings left intact
      {"id":1,"ratings":{"Reviewer1":5,"Reviewer2":4}}
            
    3. Exit the temporary pod. The pod is automatically deleted.

        exit
        
  2. Create the Wasm deployment policy. Note: Change cluster-1 as needed to your cluster’s actual name (value of $CLUSTER_NAME).

      cat <<EOF | kubectl apply --context ${REMOTE_CONTEXT1} -f-
    apiVersion: extensions.policy.gloo.solo.io/v2
    kind: WasmDeploymentPolicy
    metadata:
      annotations:
        cluster.solo.io/cluster: ""
      name: wasm-deployment-policy
      namespace: bookinfo
    spec:
      applyToWorkloads:
      - selector:
          cluster: cluster-1
          labels:
            app: ratings
          namespace: bookinfo
      config:
        filters:
        - filterContext: SIDECAR_INBOUND
          wasmImageSource:
            wasmImageTag: gcr.io/solo-public/docs/assemblyscript-test:istio-1.8
    EOF
      

    Review the following table to understand this configuration. For more information, see the API docs.

    SettingDescription
    applyToWorkloadsConfigure which workloads to apply the policy to by using labels. Workloads can be apps that have injected sidecars, such as deployments or stateful sets, or standalone proxies, such as gateways. If omitted, the policy applies to all workloads in the workspace. Note: Change cluster-1 as needed to your cluster’s actual name (value of $CLUSTER_NAME).
    filtersSpecify the details of the Wasm filter to apply. If you have multiple Wasm filters, you can also add a weight field at the same level as filters to specify the order in which the filters are applied. In this example, no weight field is set because only one Wasm filter is applied.
    filterContextSpecify what context the filter is attached to: any workload context (ANY), a gateway (GATEWAY), inbound traffic to a sidecar proxy (SIDECAR_INBOUND), or outbound traffic from a sidecar (SIDECAR_OUTBOUND). By default, the value is ANY to permit any context. In this example, the filter is applied only to the context of SIDECAR_INBOUND traffic.
    wasmImageSourceSpecify where to pull the Wasm image to use for the filter. In this example, the image is hosted in Solo’s public Google Container Registry.
    insertBeforeFilterSpecify before which filter in the Envoy HTTP filter chain you want to insert your filter. Note that not all filters might be applied to a particular workload. In the example, this field is not set, so the filter defaults to being inserted before the envoy.router filter.
  3. Verify that the Wasm deployment policy is created. In the output, check the status field.

      kubectl get wasmdeploymentpolicy -n bookinfo -o yaml --context $REMOTE_CONTEXT1
      

    If you do not see a status:

    • Check for other policies that might block the ratings app.
    • Check the management server logs for errors related to WasmDeploymentPolicy, wasm, or the image gcr.io/solo-public/docs/assemblyscript-test:istio-1.8.
  4. Verify that the Wasm deployment policy works.

    1. Create a temporary curl pod again.

        kubectl run -it -n bookinfo --context $REMOTE_CONTEXT1 curl \
        --image=curlimages/curl:7.73.0 --rm  -- sh
        
    2. Re-send a request to the ratings app.

        curl http://ratings:9080/ratings/1 -v
        

      In the output, note that the new hello, world! header is added to the response.

      *   Trying 10.96.31.140:9080...
      * Connected to ratings (10.96.31.140) port 9080 (#0)
      > GET /ratings/1 HTTP/1.1
      > Host: ratings:9080
      > User-Agent: curl/7.73.0-DEV
      > Accept: */*
      >
      * Mark bundle as not supporting multiuse
        < HTTP/1.1 200 OK
        < content-type: application/json
        < date: Wed, 11 May 2022 17:09:10 GMT
        < x-envoy-upstream-service-time: 18
        < hello: world!
        < server: envoy
        < transfer-encoding: chunked
        <
      * Connection #0 to host ratings left intact
        {"id":1,"ratings":{"Reviewer1":5,"Reviewer2":4}}
            
    3. Exit the temporary pod. The pod is automatically deleted.

        exit
        
  5. Optional: Clean up the resources that you created.

      kubectl --context $REMOTE_CONTEXT1 -n bookinfo delete WasmDeploymentPolicy wasm-deployment-policy
    kubectl --context $REMOTE_CONTEXT1 -n bookinfo delete ConfigMap gloo-mesh-custom-envoy-bootstrap
    kubectl annotate deploy -n bookinfo ratings-v1 --context $REMOTE_CONTEXT1 sidecar.istio.io/bootstrapOverride-
      

Next steps

In this guide, you used Gloo Mesh Enterprise and the Wasm extension to enforce a Wasm filter on traffic to a service managed by Gloo Mesh.

Now that you know how to integrate Gloo Mesh Gateway with Wasm filters, you can create more complex filters.