wasme only supports up to Istio 1.9, while I am using Istio 1.14, so this post goes straight to tinygo for verification and learning.
1. Installing tinygo
Go v1.18+
1
2
| brew tap tinygo-org/tools
brew install tinygo
|
1
2
3
| tinygo version
tinygo version 0.27.0 darwin/amd64 (using go version go1.19.3 and LLVM version 15.0.0)
|
2. Creating the wasm-istio project
1
2
3
| mkdir wasm-istio
cd wasm-istio
go mod init wasm-istio
|
See https://github.com/shaowenchen/demo/blob/master/wasm-istio/main.go — the key part is the snippet below
1
2
3
4
5
6
7
8
9
| func (ctx *httpHeaders) OnHttpResponseHeaders(_ int, _ bool) types.Action {
proxywasm.LogInfof("adding header: %s=%s", ctx.headerName, ctx.headerValue)
// Add a hardcoded header
if err := proxywasm.AddHttpResponseHeader("hello", "world"); err != nil {
proxywasm.LogCriticalf("failed to set response constant header: %v", err)
}
...
}
|
- Compile to generate the wasm
1
| tinygo build -o plugin.wasm -scheduler=none -target=wasi -no-debug
|
3. Packaging and publishing to an image registry
1
2
| FROM scratch
COPY plugin.wasm ./
|
1
| docker build -t shaowenchen/wasm-istio:v1 .
|
1
| docker push shaowenchen/wasm-istio:v1
|
4. Publishing to Istio WasmPlugin
- Deploy a blog application
1
2
3
| kubectl label namespace default istio-injection=enabled --overwrite
kubectl create deploy blog --image=nginx
kubectl expose deploy blog --port 80
|
See https://github.com/shaowenchen/demo/blob/master/wasm-istio/blog.yaml for the gateway configuration
The blog application has the following labels
1
2
3
4
| kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
blog-64db778565-swdxg 2/2 Running 0 62s app=blog,pod-template-hash=64db778565,security.istio.io/tlsMode=istio,service.istio.io/canonical-name=blog,service.istio.io/canonical-revision=latest
|
- Create the following WasmPlugin object
1
2
3
4
5
6
7
8
9
10
11
| apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
name: add-header-hello-world
namespace: default
spec:
selector:
matchLabels:
app: blog
url: oci://docker.io/shaowenchen/wasm-istio:v1
phase: UNSPECIFIED_PHASE
|
matchLabels specifies the range of Pods the plugin applies to; note that WasmPlugin is a namespace-scoped object. phase specifies the stage at which the plugin applies. For other parameters, see https://istio.io/latest/docs/reference/config/proxy_extensions/wasm-plugin/ .
1
2
3
4
| kubectl get wasmplugins.extensions.istio.io
NAME AGE
add-header-hello-world 27s
|
1
2
3
4
5
6
| 2023-02-22T08:31:10.017446Z info ads Push debounce stable[75] 1 for config WasmPlugin/default/add-header-hello-world: 100.09877ms since last change, 100.098558ms since last push, full=true
2023-02-22T08:31:10.017744Z info ads XDS: Pushing:2023-02-22T08:31:10Z/49 Services:10 ConnectedEndpoints:3 Version:2023-02-22T08:31:10Z/49
2023-02-22T08:31:10.017990Z info ads LDS: PUSH for node:istio-egressgateway-7fcb98978c-ppkdx.istio-system resources:0 size:0B
2023-02-22T08:31:10.018241Z info ads LDS: PUSH for node:istio-ingressgateway-55b6cffcbc-w6lwv.istio-system resources:1 size:3.7kB
2023-02-22T08:31:10.020476Z info ads LDS: PUSH for node:blog-7cc68f9d6b-m9rpd.default resources:20 size:96.8kB
2023-02-22T08:31:10.066004Z info ads ECDS: PUSH request for node:blog-7cc68f9d6b-m9rpd.default resources:1 size:327B
|
If there are errors, it may be a permission problem accessing the image registry. Although WasmPlugin also supports S3 and file service addresses, an OCI-capable image registry is the better choice.
Configure the local hosts file to point the domain in the VirtualService to the IP of the host where the gateway runs. Then access it from the terminal and check the response headers:
1
2
3
4
5
6
7
8
9
10
11
12
| curl http://istio.chenshaowen.com:31990/ -I
HTTP/1.1 200 OK
server: istio-envoy
date: Wed, 22 Feb 2023 08:36:52 GMT
content-type: text/html
content-length: 615
last-modified: Tue, 13 Dec 2022 15:53:53 GMT
etag: "6398a011-267"
accept-ranges: bytes
x-envoy-upstream-service-time: 2
hello: world
|
At this point the response headers carry one extra key: value pair compared to before, namely hello: world.
5. References