Deploying Filters to Gloo
In this tutorial we’ll deploy an existing WebAssembly (WASM) module from the WebAssembly Hub directly to Envoy via Gloo installed to our kubernetes cluster.
Prepare environment
To get started, let’s deploy a sample service that we can call through Envoy. We’ll deploy the sample petstore API:
kubectl apply -f https://raw.githubusercontent.com/solo-io/gloo/master/example/petstore/petstore.yaml
You should now have the petstore running:
kubectl get po
NAME READY STATUS RESTARTS AGE
petstore-5dcf5d6b66-n8tjt 1/1 Running 0 2m20s
Deploying Envoy
In this tutorial, we’ll use Gloo Edge Enterprise, an API Gateway based on Envoy that has built-in wasm support. But these steps should also work for base Envoy.
First, install Gloo via the helm chart:
helm repo update
kubectl create ns gloo-system
helm install gloo-gateway glooe/gloo-ee --namespace gloo-system --set-string license_key=$GLOO_KEY
Gloo Edge will be installed to the gloo-system
namespace.
Gloo Edge Enterprise version 1.6.2
or greater is required. Check your installed version of Gloo with glooctl version
. You may obtain a license key with a free trial of the Enterprise edition, available here.
Create a Route
Lastly, we’ll create a route to be able to call our petstore
service. Let’s add a route using a Gloo VirtualService
:
Apply the virtual service manifest
cat <<EOF | kubectl apply -f -
apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
name: default
namespace: gloo-system
spec:
virtualHost:
domains:
- '*'
routes:
- matchers:
- prefix: /
routeAction:
single:
upstream:
name: default-petstore-8080
namespace: gloo-system
EOF
Next, we’ll get the Gloo Gateway’s external IP by running the following:
URL=$(kubectl get svc -n gloo-system gateway-proxy -o jsonpath='{.status.loadBalancer.ingress[*].ip}')
URL=$(minikube ip):$(kubectl get svc -n gloo-system gateway-proxy -o jsonpath='{.spec.ports[?(@.name == "http")].nodePort}')
Now let’s curl that URL:
curl -v $URL/api/pets
* Trying 35.184.102.75...
* TCP_NODELAY set
* Connected to 35.184.102.75 (35.184.102.75) port 80 (#0)
> GET /api/pets HTTP/1.1
> Host: 35.184.102.75
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: application/xml
< date: Tue, 10 Dec 2019 16:02:00 GMT
< content-length: 86
< x-envoy-upstream-service-time: 2
< server: envoy
<
[{"id":1,"name":"Dog","status":"available"},{"id":2,"name":"Cat","status":"pending"}]
If you’re able to get to this point, we are able to call to our petstore app through Gloo.
Deploying a WASM module from the Hub
If you don’t have wasme
installed, try the following or refer to the installation guide for getting the WebAssembly Hub CLI wasme
:
curl -sL https://run.solo.io/wasme/install | sh
export PATH=$HOME/.wasme/bin:$PATH
Let’s run wasme list
to see what’s available on the hub. Note that this may take a few minutes without a --search
option to limit the results.
wasme list --published --search jameshbarton/add-header
NAME TAG SIZE SHA UPDATED
webassemblyhub.io/jameshbarton/add-header v0.1 13.9 kB d696cba6 15 Jan 21 22:05 UTC
Let’s try deploying this filter to Gloo:
wasme deploy gloo webassemblyhub.io/jameshbarton/add-header:v0.1 --id=myfilter --config 'world'
This filter adds the header hello: <value>
to responses, where <value>
is the value of the --config
string.
The deployment should have added our filter to the Gloo Edge Gateway. Let’s check this with kubectl
:
kubectl get gateway -n gloo-system '-ojsonpath={.items[0].spec.httpGateway.options.wasm}'
{"filters":[{"image":"webassemblyhub.io/jameshbarton/add-header:v0.1","name":"add-header","rootId":"add_header"}]}
If we try our request again, we should see the hello: world
header was added by our filter:
curl -v $URL/api/pets
* Trying 34.73.225.160...
* TCP_NODELAY set
* Connected to 34.73.225.160 (34.73.225.160) port 80 (#0)
> GET /api/pets HTTP/1.1
> Host: 34.73.225.160
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: application/xml
< date: Fri, 20 Dec 2019 19:17:13 GMT
< content-length: 86
< x-envoy-upstream-service-time: 0
< hello: world
< location: envoy-wasm
< server: envoy
<
[{"id":1,"name":"Dog","status":"available"},{"id":2,"name":"Cat","status":"pending"}]
Note that deploying filters is dynamic and does not require restarting the proxy.
Cleaning up
We can clean up our filter with the wasme undeploy
command:
wasme undeploy gloo --id=myfilter
Then re-try the curl
:
curl -v $URL/api/pets
* Trying 34.73.225.160...
* TCP_NODELAY set
* Connected to 34.73.225.160 (34.73.225.160) port 80 (#0)
> GET /api/pets HTTP/1.1
> Host: 34.73.225.160
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: application/xml
< date: Fri, 20 Dec 2019 19:19:13 GMT
< content-length: 86
< x-envoy-upstream-service-time: 1
< server: envoy
<
[{"id":1,"name":"Dog","status":"available"},{"id":2,"name":"Cat","status":"pending"}]
* Connection #0 to host 34.73.225.160 left intact
Cool! We’ve just seen how easy it is to dynamically add and remove filters from Envoy using wasme
.
For more information and support using wasme
and the Web Assembly Hub, visit the Solo.io slack channel at
https://slack.solo.io.