Wasm

WebAssembly (Wasm) is an open standard, binary instruction format to enable high-performing web apps. Gloo Mesh Gateway 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.

In this guide, you set up a sample Wasm filter that is hosted in WebAssembly Hub. 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 example setup to install Gloo Mesh, Istio, and Bookinfo in your cluster.

  2. Create the Gloo Mesh resources for this policy in the management and workload clusters.

    The following files are examples only for testing purposes. Your actual setup might vary. You can use the files as a reference for creating your own tests.

    1. Download the following Gloo Mesh resources:
    2. Apply the files to your management cluster.
      kubectl apply -f kubernetes-cluster_gloo-mesh_cluster-1.yml --context ${MGMT_CONTEXT}
      kubectl apply -f kubernetes-cluster_gloo-mesh_cluster-2.yml --context ${MGMT_CONTEXT}
      kubectl apply -f workspace_gloo-mesh_anything.yml --context ${MGMT_CONTEXT}
      
    1. Download the following Gloo Mesh resources:
    2. Apply the files to your workload cluster.
      kubectl apply -f workspace-settings_bookinfo_anything.yml --context ${REMOTE_CONTEXT1}
      
  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 on WebAssembly Hub.

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 WebAssembly Hub, 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 make your own filters, such as with the wasme CLI tool.

  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.

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

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

    Setting Description
    applyToWorkloads Configure 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.
    filters Specify 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.
    filterContext Specify 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.
    wasmImageSource Specify where to pull the Wasm image to use for the filter. In this example, the image is hosted in WebAssembly Hub's OCI registry.
    insertBeforeFilter Specify 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 webassemblyhub.io/ilackarms/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
      

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. To store your filters, try out WebAssembly Hub and an open source CLI tool, wasme, provided by Solo.