Skip to content

Commit 4f42b2c

Browse files
docs: Add WASM function support documentation
Add comprehensive documentation for WASM function support in kpt, covering how to run, develop, and deploy WASM functions. Closes #4296 Signed-off-by: Surbhi <agarwalsurbhi1807@gmail.com>
1 parent 731ce7c commit 4f42b2c

1 file changed

Lines changed: 324 additions & 0 deletions

File tree

Lines changed: 324 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,324 @@
1+
---
2+
title: "Using WASM Functions"
3+
linkTitle: "Using WASM Functions"
4+
weight: 5
5+
description: >
6+
How to run, develop, and deploy WebAssembly (WASM) functions with kpt.
7+
---
8+
9+
WASM functions are an alternative to container-based KRM functions. They're faster to start, smaller to distribute, and run in a sandboxed environment.
10+
11+
## Why use WASM functions?
12+
13+
{{< warning type=warning title="Note" >}}
14+
WASM support in kpt is currently in alpha and not ready for production use. The API and behavior may change in future releases.
15+
{{< /warning >}}
16+
17+
WASM functions have some advantages over container-based functions:
18+
19+
- Faster startup - no container runtime needed
20+
- Smaller size - WASM modules are typically much smaller than container images
21+
- Better security - sandboxed execution with no host access by default
22+
- More portable - run anywhere WASM is supported
23+
- Lower resource usage
24+
25+
## Running WASM functions
26+
27+
WASM support is an alpha feature. You need to use the `--allow-alpha-wasm` flag to enable it.
28+
29+
### With `fn render`
30+
31+
Add the WASM function to your Kptfile pipeline:
32+
33+
```yaml
34+
# Kptfile
35+
apiVersion: kpt.dev/v1
36+
kind: Kptfile
37+
metadata:
38+
name: my-package
39+
pipeline:
40+
mutators:
41+
- image: gcr.io/my-org/my-wasm-fn:v1.0.0
42+
configMap:
43+
key: value
44+
```
45+
46+
```shell
47+
kpt fn render my-package --allow-alpha-wasm
48+
```
49+
50+
kpt will detect the function as WASM if the OCI image has a `js/wasm` platform manifest.
51+
52+
### With `fn eval`
53+
54+
Run WASM functions imperatively:
55+
56+
```shell
57+
kpt fn eval my-package --allow-alpha-wasm -i gcr.io/my-org/my-wasm-fn:v1.0.0 -- key=value
58+
```
59+
60+
### Using local WASM files
61+
62+
You can run local `.wasm` files with the `--exec` flag:
63+
64+
```shell
65+
kpt fn eval my-package --allow-alpha-wasm --exec ./my-function.wasm
66+
```
67+
68+
You can also declare local WASM files in your `Kptfile`:
69+
70+
```yaml
71+
# Kptfile
72+
apiVersion: kpt.dev/v1
73+
kind: Kptfile
74+
metadata:
75+
name: my-package
76+
pipeline:
77+
mutators:
78+
- exec: ./functions/my-function.wasm
79+
```
80+
81+
```shell
82+
kpt fn render my-package --allow-alpha-wasm --allow-exec
83+
```
84+
85+
Note: Using local WASM files makes your package less portable since the file needs to exist on every system.
86+
87+
## Publishing WASM functions
88+
89+
### Push a WASM module
90+
91+
Compress and push a WASM module to an OCI registry:
92+
93+
```shell
94+
kpt alpha wasm push ./my-function.wasm gcr.io/my-org/my-wasm-fn:v1.0.0
95+
```
96+
97+
What this does:
98+
1. Compresses the WASM file into a tar archive
99+
2. Creates an OCI image with `js/wasm` platform
100+
3. Pushes to the registry
101+
102+
### Pull a WASM module
103+
104+
Download and decompress a WASM module:
105+
106+
```shell
107+
kpt alpha wasm pull gcr.io/my-org/my-wasm-fn:v1.0.0 ./my-function.wasm
108+
```
109+
110+
Useful for:
111+
- Testing WASM functions locally
112+
- Inspecting modules
113+
- Offline caching
114+
115+
## Developing WASM functions
116+
117+
WASM functions follow the [KRM Functions Specification](https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md). They receive a `ResourceList` as input and return a `ResourceList` as output.
118+
119+
### What you need
120+
121+
- A language that compiles to WASM (Go, Rust, etc.)
122+
- WASM build toolchain
123+
- KRM functions SDK
124+
125+
### Example: Go WASM function
126+
127+
Here's how to build a Go KRM function for WASM. You need two files - one for regular builds and one for WASM:
128+
129+
`main.go` (regular build):
130+
131+
```go
132+
//go:build !(js && wasm)
133+
134+
package main
135+
136+
import (
137+
"os"
138+
139+
"github.com/kptdev/krm-functions-sdk/go/fn"
140+
)
141+
142+
func main() {
143+
if err := fn.AsMain(fn.ResourceListProcessorFunc(process)); err != nil {
144+
os.Exit(1)
145+
}
146+
}
147+
148+
func process(rl *fn.ResourceList) (bool, error) {
149+
for i := range rl.Items {
150+
// Your transformation logic
151+
rl.Items[i].SetAnnotation("processed-by", "my-fn")
152+
}
153+
return true, nil
154+
}
155+
```
156+
157+
`main_js.go` (WASM build):
158+
159+
```go
160+
//go:build js && wasm
161+
162+
package main
163+
164+
import (
165+
"syscall/js"
166+
167+
"github.com/kptdev/krm-functions-sdk/go/fn"
168+
)
169+
170+
func main() {
171+
if err := run(); err != nil {
172+
panic(err)
173+
}
174+
}
175+
176+
func run() error {
177+
resourceList := []byte("")
178+
179+
js.Global().Set("processResourceList", resourceListWrapper(&resourceList))
180+
js.Global().Set("processResourceListErrors", resourceListErrors(&resourceList))
181+
182+
// Keep the program running
183+
<-make(chan bool)
184+
return nil
185+
}
186+
187+
// process applies the same transformation logic as in the non-WASM build.
188+
func process(rl *fn.ResourceList) (bool, error) {
189+
for i := range rl.Items {
190+
// Your transformation logic
191+
rl.Items[i].SetAnnotation("processed-by", "my-fn")
192+
}
193+
return true, nil
194+
}
195+
196+
func transform(input []byte) ([]byte, error) {
197+
return fn.Run(fn.ResourceListProcessorFunc(process), input)
198+
}
199+
200+
func resourceListWrapper(resourceList *[]byte) js.Func {
201+
return js.FuncOf(func(this js.Value, args []js.Value) any {
202+
if len(args) != 1 {
203+
return "Invalid number of arguments"
204+
}
205+
input := args[0].String()
206+
output, err := transform([]byte(input))
207+
*resourceList = output
208+
if err != nil {
209+
return "unable to process: " + err.Error()
210+
}
211+
return string(output)
212+
})
213+
}
214+
215+
func resourceListErrors(resourceList *[]byte) js.Func {
216+
return js.FuncOf(func(this js.Value, args []js.Value) any {
217+
rl, err := fn.ParseResourceList(*resourceList)
218+
if err != nil {
219+
return ""
220+
}
221+
errors := ""
222+
for _, r := range rl.Results {
223+
if r.Severity == "error" {
224+
errors += r.Message
225+
}
226+
}
227+
return errors
228+
})
229+
}
230+
```
231+
232+
### Build for WASM
233+
234+
```shell
235+
GOOS=js GOARCH=wasm go build -o my-function.wasm .
236+
```
237+
238+
### Test locally
239+
240+
```shell
241+
kpt fn eval ./test-package --allow-alpha-wasm --exec ./my-function.wasm
242+
```
243+
244+
### Publish
245+
246+
Push to a registry:
247+
248+
```shell
249+
kpt alpha wasm push ./my-function.wasm gcr.io/my-org/my-wasm-fn:v1.0.0
250+
251+
# Test the published version
252+
kpt fn eval ./test-package --allow-alpha-wasm -i gcr.io/my-org/my-wasm-fn:v1.0.0
253+
```
254+
255+
## Complete example
256+
257+
From development to deployment:
258+
259+
```shell
260+
# 1. Write your function code (main.go and main_js.go)
261+
262+
# 2. Build
263+
GOOS=js GOARCH=wasm go build -o my-function.wasm .
264+
265+
# 3. Test locally
266+
kpt fn eval ./test-package --allow-alpha-wasm --exec ./my-function.wasm
267+
268+
# 4. Publish
269+
kpt alpha wasm push ./my-function.wasm gcr.io/my-org/my-wasm-fn:v1.0.0
270+
271+
# 5. Use in a package
272+
cat <<EOF > Kptfile
273+
apiVersion: kpt.dev/v1
274+
kind: Kptfile
275+
metadata:
276+
name: my-package
277+
pipeline:
278+
mutators:
279+
- image: gcr.io/my-org/my-wasm-fn:v1.0.0
280+
EOF
281+
282+
# 6. Render
283+
kpt fn render my-package --allow-alpha-wasm
284+
```
285+
286+
## Limitations
287+
288+
### Alpha status
289+
290+
WASM support is alpha, which means:
291+
- API may change
292+
- Requires `--allow-alpha-wasm` flag
293+
- Some features may be limited
294+
295+
### Security
296+
297+
WASM functions run in a sandbox:
298+
- No network access
299+
- No filesystem access (except input/output resources)
300+
- Can't execute system commands
301+
302+
This is more secure but also more restrictive.
303+
304+
### Performance
305+
306+
- Faster startup than containers
307+
- CPU-intensive operations may be slower
308+
- Different memory patterns
309+
- Benchmark if performance is critical
310+
311+
### Compatibility
312+
313+
Not all container functions can convert to WASM:
314+
- Functions needing network access
315+
- Functions with complex dependencies
316+
- Platform-specific code
317+
318+
## See also
319+
320+
- [KRM Functions Specification](https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md)
321+
- [Functions Catalog](https://catalog.kpt.dev/)
322+
- [kpt alpha wasm push](../../../reference/cli/alpha/wasm/push/)
323+
- [kpt alpha wasm pull](../../../reference/cli/alpha/wasm/pull/)
324+
- [WASM function examples](https://github.com/kptdev/krm-functions-catalog/tree/main/functions/go)

0 commit comments

Comments
 (0)