diff --git a/plugins/wasm-go/Dockerfile b/plugins/wasm-go/Dockerfile index 9b084e059..8aae062ca 100644 --- a/plugins/wasm-go/Dockerfile +++ b/plugins/wasm-go/Dockerfile @@ -1,2 +1,17 @@ -FROM scratch -COPY main.wasm plugin.wasm \ No newline at end of file +ARG BUILDER=higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/wasm-go-builder:go1.19-tinygo0.26.0 +FROM $BUILDER as builder + +ARG PLUGIN_NAME=hello-world + +WORKDIR /workspace + +COPY . . + +WORKDIR /workspace/extensions/$PLUGIN_NAME + +RUN go mod tidy +RUN tinygo build -o /main.wasm -scheduler=none -target=wasi ./main.go + +FROM scratch as output + +COPY --from=builder /main.wasm plugin.wasm diff --git a/plugins/wasm-go/DockerfileBuilder b/plugins/wasm-go/DockerfileBuilder index 78064ddeb..ba0756c41 100644 --- a/plugins/wasm-go/DockerfileBuilder +++ b/plugins/wasm-go/DockerfileBuilder @@ -1,40 +1,84 @@ -FROM ubuntu as builder +# The Dockerfile for wasm-go builder only support amd64 and arm64 yet. +# If you want to build on another architecture, the following information may be helpful. +# +# - arch: amd64 \ +# base image: docker.io/ubuntu +# go_url: https://golang.google.cn/dl/go1.20.1.linux-amd64.tar.gz" +# tinygo_url: https://github.com/tinygo-org/tinygo/releases/download/v0.26.0/tinygo_0.26.0_amd64.deb +# +# - arch: arm64 +# base image: docker.io/ubuntu +# go_url: https://golang.google.cn/dl/go1.20.1.linux-arm64.tar.gz +# tinygo_url: https://github.com/tinygo-org/tinygo/releases/download/v0.26.0/tinygo_0.26.0_arm64.deb +# +# - arch: armel +# base image: build yourself +# go_url: install from source code +# tinygo_url: build yourself +# +# - arch: i386 +# base image: build yourself +# go_url: https://dl.google.com/go/go1.20.1.linux-386.tar.gz +# tinygo_url: build yourself +# +# - arch: mips64el +# base image: build your self +# go_url: https://dl.google.com/go/go1.20.1.linux-386.tar.gz +# tinygo_url: build your self +# +# - arch: ppc64el +# base image: build your self +# go_url: https://dl.google.com/go/go1.20.1.linux-ppc64le.tar.gz +# tinygo_url: build your self +# +# - arch: s390x +# base image: docker.io/ubuntu +# go_url: https://dl.google.com/go/go1.20.1.linux-s390x.tar.gz +# tinygo_url: build your self +# +# - arch: armhf +# base image: build your self +# go_url: https://golang.google.cn/dl/go1.20.1.linux-armv6l.tar.gz +# tinygo_url: https://github.com/tinygo-org/tinygo/releases/download/v0.26.0/tinygo_0.26.0_armhf.deb + +ARG BASE_IMAGE=docker.io/ubuntu +FROM $BASE_IMAGE -ARG THIS_ARCH -ARG PLUGIN_NAME ARG GO_VERSION ARG TINYGO_VERSION -ARG this_arch=${THIS_ARCH:-amd64} -ARG plugin_name=${PLUGIN_NAME:-hello-world} -ARG go_version=${GO_VERSION:-1.19} -ARG tinygo_version=${TINYGO_VERSION:-0.26.0} - -ARG go_pkg_name=go$go_version.linux-$this_arch.tar.gz -ARG tinygo_pkg_name=tinygo_${tinygo_version}_$this_arch.deb - +LABEL go_version=$GO_VERSION tinygo_version=$TINYGO_VERSION RUN apt-get update \ && apt-get install -y wget build-essential \ && rm -rf /var/lib/apt/lists/* -RUN wget https://golang.google.cn/dl/$go_pkg_name -RUN rm -rf /usr/local/go && tar -C /usr/local -xzf $go_pkg_name -ENV PATH=$PATH:/usr/local/go/bin -RUN wget https://github.com/tinygo-org/tinygo/releases/download/v$tinygo_version/$tinygo_pkg_name -RUN dpkg -i $tinygo_pkg_name -ENV export PATH=$PATH:/usr/local/bin +RUN arch="$(dpkg --print-architecture)"; arch="${arch##*-}"; \ + go_url=; \ + tinygo_url=; \ + go_version=${GO_VERSION:-1.19}; \ + tinygo_version=${TINYGO_VERSION:-0.26.0}; \ + echo "arch: '$arch'"; \ + echo "go go_version: '$go_version'"; \ + echo "tinygo_version: '$tinygo_version'"; \ + case "$arch" in \ + 'amd64') \ + go_url="https://golang.google.cn/dl/go$go_version.linux-amd64.tar.gz"; \ + tinygo_url="https://github.com/tinygo-org/tinygo/releases/download/v$tinygo_version/tinygo_${tinygo_version}_amd64.deb"; \ + ;; \ + 'arm64') \ + go_url="https://golang.google.cn/dl/go$go_version.linux-arm64.tar.gz"; \ + tinygo_url="https://github.com/tinygo-org/tinygo/releases/download/v$tinygo_version/tinygo_${tinygo_version}_arm64.deb"; \ + ;; \ + *) echo >&2 "error: unsupported architecture '$arch' "; exit 1 ;; \ + esac; \ + echo "go_url: '$go_url'"; \ + echo "tinygo_url: '$tinygo_url'"; \ + wget -O go.tgz "$go_url" --progress=dot:giga; \ + wget -O tinygo.deb "$tinygo_url" --progress=dot:giga; \ + echo "Download complete"; \ + rm -rf /usr/local/go && tar -C /usr/local -xzf go.tgz && rm -rf go.tgz; \ + dpkg -i tinygo.deb && rm -rf tinygo.deb -WORKDIR /workspace - -COPY . . - -WORKDIR /workspace/extensions/$plugin_name - -RUN go mod tidy -RUN tinygo build -o /main.wasm -scheduler=none -target=wasi ./main.go - -FROM scratch - -COPY --from=builder /main.wasm plugin.wasm +ENV PATH=$PATH:/usr/local/go/bin:/usr/local/bin diff --git a/plugins/wasm-go/Makefile b/plugins/wasm-go/Makefile index 9904ac3cd..a3ec58743 100644 --- a/plugins/wasm-go/Makefile +++ b/plugins/wasm-go/Makefile @@ -4,17 +4,29 @@ BUILD_TIME := $(shell date "+%Y%m%d-%H%M%S") COMMIT_ID := $(shell git rev-parse --short HEAD 2>/dev/null) IMG ?= ${REGISTRY}${PLUGIN_NAME}:${BUILD_TIME}-${COMMIT_ID} +.DEFAULT: build: DOCKER_BUILDKIT=1 docker build --build-arg PLUGIN_NAME=${PLUGIN_NAME} \ - --build-arg THIS_ARCH=${THIS_ARCH} \ - --build-arg GO_VERSION=${GO_VERSION} \ - --build-arg TINYGO_VERSION=${TINYGO_VERSION} \ - -t ${IMG} \ - -f DockerfileBuilder \ - --output extensions/${PLUGIN_NAME} . + -t ${IMG} \ + --output extensions/${PLUGIN_NAME} \ + . @echo "" @echo "image: ${IMG}" @echo "output wasm file: extensions/${PLUGIN_NAME}/plugin.wasm" build-push: build - docker push ${IMG} \ No newline at end of file + docker push ${IMG} + +# builder: +# To build a wasm-go-builder image. +# If you want to use Go/TinyGo with another version, please modify GO_VERSION/TINYGO_VERSION. +# After your wasm-go-builder image is built, you can use --build-arg BUILDER= to build plugin image. +builder: + docker buildx build --platform linux/amd64,linux/arm64 \ + --build-arg BASE_IMAGE=docker.io/ubuntu \ + --build-arg GO_VERSION=1.19 \ + --build-arg TINYGO_VERSION=0.26.0 \ + -f DockerfileBuilder \ + -t wasm-go-builder:go1.19-tinygo0.26.0 \ + --push \ + . \ No newline at end of file diff --git a/plugins/wasm-go/README.md b/plugins/wasm-go/README.md index c9ba077ca..843f9bb7f 100644 --- a/plugins/wasm-go/README.md +++ b/plugins/wasm-go/README.md @@ -2,9 +2,9 @@ ## 介绍 -此 SDK 用于开发 Higress 的 Wasm 插件 +此 SDK 用于使用 Go 语言开发 Higress 的 Wasm 插件。 -## 使用 Docker 快速构建 +## 使用 Higress wasm-go builder 快速构建 使用以下命令可以快速构建 wasm-go 插件: @@ -16,15 +16,11 @@ $ PLUGIN_NAME=request-block make build 输出结果

 DOCKER_BUILDKIT=1 docker build --build-arg PLUGIN_NAME=request-block \
-                               --build-arg THIS_ARCH= \
-                               --build-arg GO_VERSION= \
-                               --build-arg TINYGO_VERSION= \
-                               -t request-block:20230213-170844-ca49714 \
-                               -f DockerfileBuilder \
+                               -t request-block:20230223-173305-3b1a471 \
                                --output extensions/request-block .
-[+] Building 84.6s (16/16)                                                                                                                                                                                                                                                0.0s 
+[+] Building 67.7s (12/12) FINISHED
 
-image:            request-block:20230211-184334-f402f86
+image:            request-block:20230223-173305-3b1a471
 output wasm file: extensions/request-block/plugin.wasm
 
@@ -35,14 +31,11 @@ output wasm file: extensions/request-block/plugin.wasm ### 参数说明 -| 参数名称 | 可选/必须 | 默认值 | 含义 | -|------------------|-------|------------------------------------------|----------------------------------------------------------------------| -| `THIS_ARCH` | 可选的 | amd64 | 构建插件的机器的指令集架构,在非 amd64 架构的机器上构建时要手动指定。 | -| `PLUGIN_NAME` | 可选的 | hello-world | 要构建的插件名称。 | -| `REGISTRY` | 可选的 | 空 | 生成的镜像的仓库地址,如 `example.registry.io/my-name/`. 注意 REGISTRY 值应当以 / 结尾。 | -| `IMG` | 可选的 | 如不设置则根据仓库地址、插件名称、构建时间以及 git commit id 生成 | 生成的镜像名称。 | -| `GO_VERSION` | 可选的 | 1.19 | Go 版本号。 | -| `TINYGO_VERSION` | 可选的 | 0.26.0 | TinyGo 版本号。 | +| 参数名称 | 可选/必须 | 默认值 | 含义 | +|---------------|-------|-------------------------------------------|----------------------------------------------------------------------| +| `PLUGIN_NAME` | 可选的 | hello-world | 要构建的插件名称。 | +| `REGISTRY` | 可选的 | 空 | 生成的镜像的仓库地址,如 `example.registry.io/my-name/`. 注意 REGISTRY 值应当以 / 结尾。 | +| `IMG` | 可选的 | 如不设置则根据仓库地址、插件名称、构建时间以及 git commit id 生成。 | 生成的镜像名称。如非空,则会覆盖`REGISTRY` 参数。 | ## 本地构建 @@ -64,10 +57,15 @@ tinygo build -o main.wasm -scheduler=none -target=wasi ./extensions/request-bloc ### step2. 构建并推送插件的 docker 镜像 -使用这份简单的 [dockerfile](./Dockerfile). +使用这份简单的 Dockerfile + +```Dockerfile +FROM scratch +COPY main.wasm plugin.wasm +``` ```bash -docker build -t /request-block:1.0.0 . +docker build -t /request-block:1.0.0 -f . docker push /request-block:1.0.0 ``` @@ -92,7 +90,6 @@ spec: ``` 使用 `kubectl apply -f ` 使资源生效。 - 资源生效后,如果请求url携带 `swagger.html`, 则这个请求就会被拒绝,例如: ```bash @@ -152,4 +149,3 @@ spec: ``` 所有规则会按上面配置的顺序一次执行匹配,当有一个规则匹配时,就停止匹配,并选择匹配的配置执行插件逻辑。 - diff --git a/plugins/wasm-go/README_EN.md b/plugins/wasm-go/README_EN.md index 0bf876cfe..4958e4e30 100644 --- a/plugins/wasm-go/README_EN.md +++ b/plugins/wasm-go/README_EN.md @@ -1,37 +1,76 @@ ## Intro -This SDK is used to develop the WASM Plugins of Higress. -## Requirements +This SDK is used to develop the WASM Plugins for Higress in Go. -(need support Go's type parameters) +## Quick build with Higress wasm-go builder + +The wasm-go plugin can be built quickly with the following command: + +```bash +$ PLUGIN_NAME=request-block make build +``` + +
+Output +

+DOCKER_BUILDKIT=1 docker build --build-arg PLUGIN_NAME=request-block \
+                               -t request-block:20230223-173305-3b1a471 \
+                               --output extensions/request-block .
+[+] Building 67.7s (12/12) FINISHED
+
+image:            request-block:20230223-173305-3b1a471
+output wasm file: extensions/request-block/plugin.wasm
+
+
+ +This command eventually builds a wasm file and a Docker image. +This local wasm file is exported to the specified plugin's directory and can be used directly for debugging. +You can also use `make build-push` to build and push the image at the same time. + +### Environmental parameters + +| Name | Optional/Required | Default | 含义 | +|---------------|-------------------|--------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------| +| `PLUGIN_NAME` | Optional | hello-world | The name of the plugin to build. | +| `REGISTRY` | Optional | empty | The regitstry address of the generated image, e.g. `example.registry.io/my-name/`. Note that the REGISTRY value should end with /. | +| `IMG` | Optional | If it is empty, it is generated based on the repository address, plugin name, build time, and git commit id. | The generated image tag will override the `REGISTRY` parameter if it is not empty. | + +## Build on local yourself + +You can also build wasm locally and copy it to a Docker image. This requires a local build environment: Go version: >= 1.18 TinyGo version: >= 0.25.0 -## Quick Examples +The following is an example of building the plugin [request-block](extensions/request-block). -Use the [request-block](example/request-block) as an example - -### step1. compile to wasm +### step1. build wasm ```bash -tinygo build -o main.wasm -scheduler=none -target=wasi ./example/request-block/main.go +tinygo build -o main.wasm -scheduler=none -target=wasi ./extensions/request-block/main.go ``` -### step2. build&push docker image +### step2. build and push docker image -Use this [dockerfile](./Dockerfile). +A simple Dockerfile: + +```Dockerfile +FROM scratch +COPY main.wasm plugin.wasm +``` ```bash -docker build -t /request-block:1.0.0 . +docker build -t /request-block:1.0.0 -f . docker push /request-block:1.0.0 ``` -### step3. create WasmPlugin resource +## Apply WasmPlugin API Read this [document](https://istio.io/latest/docs/reference/config/proxy_extensions/wasm-plugin/) to learn more about wasmplugin. +Create a WasmPlugin API resource: + ```yaml apiVersion: extensions.higress.io/v1alpha1 kind: WasmPlugin @@ -48,7 +87,8 @@ spec: url: oci:///request-block:1.0.0 ``` -If the url in request contains the `swagger.html`, the request will be blocked. +When the resource is applied on the Kubernetes cluster with `kubectl apply -f `, +the request will be blocked if the string `swagger.html` in the url. ```bash curl /api/user/swagger.html