Introduction
아래의 golang 공식 SDK를 기준으로 proxy-wasm plugin을 빌드하는 방법과, 추가로 Istio 환경에서 배포 및 테스트하는 방법에 대해 설명한다.
상기 SDK는 다양한 내용을 포함하지만, 여기서 참조한 내용은 다음과 같다.
•
다양한 예제(examples 폴더 내) 중 Helloworld: 주요 기능(REQ/RES header, query string, path, body 변경, 주기적 실행(timer) 등)에 대한 예제 제공. 본 가이드는 주기적으로 로그를 뱉는 helloworld 만을 다루지만, 빌드 방법은 타 예제에 대해서도 동일하다.
•
빌드를 위한 전체 절차: 기본 빌드 방법 및 Makefile 기반한 자동화 및 구체 실행 절차
참고로, 이 SDK는 Proxy-Wasm 자체에 대한 상세 설명()도 함께 제공하는데, Proxy-Wasm root 문서(
WebAssembly-in-Envoy.md) 보다도 훨씬 더 자세하여 지금껏 보았던 그 어떤 문서보다 났다.
Proxy-Wasm overview는 동일 주제에 대한 요약이다.

Prerequisite
•
golang 설치
•
docker 설치
•
OCI Image repository(e.g. dockerhub)
참고로 SDK의 README 가이드는 envoy 역시 설치를 요구하지만, macOS에 (brew를 통해) 설치되는 envoy는 default WASM runtime인 V8이 빠져있기에 실행이 안되기에 해당 step은 제외하였다. 따라서 테스트는 별도 Istio 기반의 istio-proxy에서 교체하였다. 그러므로 테스트를 위해서는 아래가 필요하다.
•
k8s 환경 내 동작하는 istio-proxy
Proxy-Wasm Build 방법 요약
golang 빌드 방법과 동일하되, 단지 환경 변수 몇 개만 특이할 뿐이다. 아래는 SDK README에 나와있는 설명으로, my-plugin.wasm 이란 Proxy-Wasm 모듈 생성 방법이다.
❯ go mod init main.go
❯ go mod tidy
❯ env GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o my-plugin.wasm main.go
Bash
복사
Helloworld를 통한 Proxy-Wasm 생성부터 동작 확인까지
앞선 Proxy-Wasm Build 방법 요약은 코드가 있을 때의 이야기이고, SDK에 코드까지 예제로 마련되어 있으니 이를 그대로 따르면 된다. 아래 설명은 이를 기반으로 하되, 추가된 내용은 OCI image 생성 및 등록, Istio WasmPlugin 을 통한 설치 및 동작 확인 방법 뿐이다(3, 4, 5번).
1.
Proxy-Wasm golang sdk git cloning 및 해당 directory로 이동
❯ git clone git@github.com:proxy-wasm/proxy-wasm-go-sdk.git
...
❯ cd proxy-wasm-go-sdk
YAML
복사
2.
Helloworld example 빌드하기: root의 README.md의 Build and run Examples 섹션 중 마지막 make run name=helloworld 만 제외하고 그대로 실행
•
제외한 사항은 실행 기반 테스트이다. 이유는 envoy 사전 설치가 필요하고, 나아가 macOS에 (brew를 통해) 설치되는 envoy는 default WASM runtime인 V8이 빠져있기에 실행이 안되기 때문이다.
•
정상 실행 완료 시 examples/helloworld directory root에 main.wasm이 생성된다.
•
전체 명령, 순서 및 로그
❯ make build.examples
go: downloading github.com/tidwall/gjson v1.14.1
go: downloading github.com/tidwall/pretty v1.2.0
go: downloading github.com/tidwall/match v1.1.1
go: downloading github.com/tidwall/gjson v1.14.3
❯ cd examples/helloworld
❯ env GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o main.wasm main.go
❯ go test
2025/06/13 10:06:27 proxy_info_log: OnPluginStart from Go!
2025/06/13 10:06:27 proxy_info_log: It's 1749776787541691000: random value: 1927470619330703026
2025/06/13 10:06:27 proxy_info_log: OnTick called
2025/06/13 10:06:28 proxy_info_log: OnPluginStart from Go!
2025/06/13 10:06:28 proxy_info_log: It's 1640995200000000000: random value: 15261016922882481856
2025/06/13 10:06:28 proxy_info_log: OnTick called
2025/06/13 10:06:28 proxy_info_log: OnPluginStart from Go!
2025/06/13 10:06:29 proxy_info_log: OnPluginStart from Go!
PASS
ok github.com/proxy-wasm/proxy-wasm-go-sdk/examples/helloworld 1.943s
❯ make build.example name=helloworld
make: *** No rule to make target `build.example'. Stop.
❯ cd ../../
❯ make build.example name=helloworld
❯ ls examples/helloworld/main.wasm
examples/helloworld/main.wasm
Bash
복사
3.
main.wasm 에 대한 OCI image 생성 및 repository에 push하기
•
단계 요약: Dockerfile 생성 → docker build → push image
•
전체 명령, 순서 및 로그(<repositiory_path_prefix> 는 적당한 값으로 바꾸어야 한다)
❯ cd examples/helloworld
❯ echo -e "FROM scratch\nCOPY main.wasm /plugin.wasm" > Dockerfile
❯ docker build -t <repositiory_path_prefix>/helloworld:latest .
[+] Building 0.0s (5/5) FINISHED docker:desktop-linux
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 115B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 70B 0.0s
=> CACHED [1/1] COPY main.wasm /plugin.wasm 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:f870044bcbf0f4552bc4602f7467701ac7f9021e2aa8ae3e7c2e9d19e2387931 0.0s
=> => naming to docker.io/anyflow/helloworld:latest 0.0s
What's next:
View a summary of image vulnerabilities and recommendations → docker scout quickview
❯ docker push anyflow/helloworld:latest
The push refers to repository [docker.io/anyflow/helloworld]
9232c8380bb3: Layer already exists
latest: digest: sha256:803aa4497b9e5d4be466b9294b0c9242688c5263113f8680fcdb2518a2b1c287 size: 526
Bash
복사
4.
Istio WasmPlugin 작성하기
istio-proxy에 설치하기 위해서는 WasmPlugin 이 필요하다(EnvoyFilter 도 가능하지만 훨씬 복잡하다). WasmPlugin 에 대해서는 다음을 참고한다.
apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
name: helloworld-dockebi
namespace: service
spec:
selector:
matchLabels:
app: dockebi
url: <repositiory_path_prefix>/helloworld:latest
imagePullPolicy: Always
phase: STATS
failStrategy: FAIL_OPEN
match:
- mode: CLIENT
YAML
복사
5.
설치 및 정상 동작 확인하기
•
참고: helloworld는 매초마다 아래와 같은 로그를 찍는 plugin이다. 본 로그를 확인하기 위해서는 istio-proxy wasm log level을 info로 낮추어야 한다.
2025-06-13T01:53:35.328060Z info envoy wasm external/envoy/source/extensions/common/wasm/context.cc:1137 wasm log: OnTick called thread=43
2025-06-13T01:53:35.327997Z info envoy wasm external/envoy/source/extensions/common/wasm/context.cc:1137 wasm log: It's 1749779615327973000: random value: 2630350579687050147 thread=42
YAML
복사
•
전체 명령, 순서 및 로그
# wasm 로그 level 변경
❯ istioctl pc log -n <namespace name> <pod name> --level wasm:info
<pod name>.<namespace name>:
active loggers:
...
udp: warning
wasm: info
websocket: warning
...
# WasmPlugin 적용
❯ kubectl apply -f <wasmplugin YAML path>
wasmplugin.extensions.istio.io/helloworld-dockebi created
# 로그 확인
❯ kubectl logs -n <namespace name> <pod name> -c istio-proxy -f
...
2025-06-13T02:49:57.143963Z info envoy wasm external/envoy/source/extensions/common/wasm/context.cc:1137 wasm log: It's 1749782997143929000: random value: 11197525585411950461 thread=42
2025-06-13T02:49:57.143994Z info envoy wasm external/envoy/source/extensions/common/wasm/context.cc:1137 wasm log: OnTick called thread=42
2025-06-13T02:49:57.227731Z info envoy wasm external/envoy/source/extensions/common/wasm/context.cc:1137 wasm log: It's 1749782997227681000: random value: 661078671923516041 thread=43
2025-06-13T02:49:57.227774Z info envoy wasm external/envoy/source/extensions/common/wasm/context.cc:1137 wasm log: OnTick called thread=43
Bash
복사