mirror of
https://github.com/alibaba/higress.git
synced 2026-03-08 10:40:48 +08:00
feat: 使用多阶段构建优化 wasm-go 构建流程 (#192)
This commit is contained in:
@@ -1,2 +1,17 @@
|
||||
FROM scratch
|
||||
COPY main.wasm plugin.wasm
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}
|
||||
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=<your-wasm-go-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 \
|
||||
.
|
||||
@@ -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
|
||||
<summary>输出结果</summary>
|
||||
<pre><code>
|
||||
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
|
||||
</code></pre>
|
||||
</details>
|
||||
@@ -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 <your_registry_hub>/request-block:1.0.0 .
|
||||
docker build -t <your_registry_hub>/request-block:1.0.0 -f <your_dockerfile> .
|
||||
docker push <your_registry_hub>/request-block:1.0.0
|
||||
```
|
||||
|
||||
@@ -92,7 +90,6 @@ spec:
|
||||
```
|
||||
|
||||
使用 `kubectl apply -f <your-wasm-plugin-yaml>` 使资源生效。
|
||||
|
||||
资源生效后,如果请求url携带 `swagger.html`, 则这个请求就会被拒绝,例如:
|
||||
|
||||
```bash
|
||||
@@ -152,4 +149,3 @@ spec:
|
||||
```
|
||||
|
||||
所有规则会按上面配置的顺序一次执行匹配,当有一个规则匹配时,就停止匹配,并选择匹配的配置执行插件逻辑。
|
||||
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Output</summary>
|
||||
<pre><code>
|
||||
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
|
||||
</code></pre>
|
||||
</details>
|
||||
|
||||
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 <your_registry_hub>/request-block:1.0.0 .
|
||||
docker build -t <your_registry_hub>/request-block:1.0.0 -f <your_dockerfile> .
|
||||
docker push <your_registry_hub>/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://<your_registry_hub>/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 <your-wasm-plugin-yaml>`,
|
||||
the request will be blocked if the string `swagger.html` in the url.
|
||||
|
||||
```bash
|
||||
curl <your_gateway_address>/api/user/swagger.html
|
||||
|
||||
Reference in New Issue
Block a user