Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 188 additions & 0 deletions documentation/content/en/book/04-using-functions/wasm-functions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
---
title: "Using WASM Functions"
linkTitle: "Using WASM Functions"
weight: 5
description: >
How to run, develop, and deploy WebAssembly (WASM) functions with kpt.
---

WASM functions are an alternative to container-based KRM functions. They're faster to start, smaller to distribute, and run in a sandboxed environment.
Comment thread
SurbhiAgarwal1 marked this conversation as resolved.

## Why use WASM functions?

{{< warning type=warning title="Note" >}}
WASM support in kpt is currently in alpha and not ready for production use. The API and behavior may change in future releases.
{{< /warning >}}

WASM functions have some advantages over container-based functions:

- Faster startup - no container runtime needed
- Smaller size - WASM modules are typically much smaller than container images
- Better isolation - sandboxed execution with limited host access
- More portable - run anywhere WASM is supported
- Lower resource usage

## Running WASM functions

WASM support is an alpha feature. You need to use the `--allow-alpha-wasm` flag to enable it.

Comment on lines +27 to +28
### With `fn render`

Add the WASM function to your Kptfile pipeline:

```yaml
# Kptfile
apiVersion: kpt.dev/v1
kind: Kptfile
metadata:
name: my-package
pipeline:
mutators:
- image: example.registry.io/my-org/my-wasm-fn:v1.0.0
configMap:
key: value
```

```shell
kpt fn render my-package --allow-alpha-wasm
```

kpt will use the WASM runtime for an OCI image if the `--allow-alpha-wasm` flag is present and the image has a `js/wasm` platform manifest.

### With `fn eval`

Run WASM functions imperatively:

```shell
kpt fn eval my-package --allow-alpha-wasm -i example.registry.io/my-org/my-wasm-fn:v1.0.0 -- key=value
```

### Using local WASM files

You can run local `.wasm` files with the `--exec` flag:

```shell
kpt fn eval my-package --allow-alpha-wasm --exec ./my-function.wasm
```
Comment on lines +60 to +66

You can also declare local WASM files in your `Kptfile`:

```yaml
# Kptfile
apiVersion: kpt.dev/v1
kind: Kptfile
metadata:
name: my-package
pipeline:
mutators:
- exec: ./functions/my-function.wasm
```

```shell
kpt fn render my-package --allow-alpha-wasm
```

Note: Using local WASM files makes your package less portable since the file needs to exist on every system.

## Publishing WASM functions

### Push a WASM module

Compress and push a WASM module to an OCI registry:

```shell
kpt alpha wasm push ./my-function.wasm example.registry.io/my-org/my-wasm-fn:v1.0.0
```

What this does:
1. Compresses the WASM file into a tar archive
2. Creates an OCI image with `js/wasm` platform
3. Pushes to the registry
Comment thread
SurbhiAgarwal1 marked this conversation as resolved.

### Pull a WASM module

Download and decompress a WASM module:

```shell
kpt alpha wasm pull example.registry.io/my-org/my-wasm-fn:v1.0.0 ./my-function.wasm
```

Useful for:
- Testing WASM functions locally
- Inspecting modules
- Offline caching

## Developing WASM functions

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.

### What you need

- A language that compiles to WASM (Go, Rust, etc.)
- WASM build toolchain
- KRM functions SDK

### Example: Go WASM function
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would avoid adding code examples to the docs and maybe ref/link to an example function instead


For a complete working example of a Go WASM function, see the [starlark function in the krm-functions-catalog](https://github.com/kptdev/krm-functions-catalog/tree/main/functions/go/starlark), which shows the two-file pattern (`run.go` for regular builds and `run_js.go` for WASM builds).

### Build for WASM

```shell
GOOS=js GOARCH=wasm go build -o my-function.wasm .
```

### Test locally

```shell
kpt fn eval ./test-package --allow-alpha-wasm --exec ./my-function.wasm
```

### Publish

Push to a registry:

```shell
kpt alpha wasm push ./my-function.wasm example.registry.io/my-org/my-wasm-fn:v1.0.0

# Test the published version
kpt fn eval ./test-package --allow-alpha-wasm -i example.registry.io/my-org/my-wasm-fn:v1.0.0
```

## Mixed pipelines

{{< note title="Limitation" >}}
Currently, enabling `--allow-alpha-wasm` will cause kpt to attempt to run all **image-based** functions in the pipeline using the WASM runtime. Mixed pipelines containing both WASM and standard container images are not yet fully supported. However, mixed pipelines with local `.wasm` files and standard executables are supported.
{{< /note >}}

## Limitations

### Security

WASM functions run in a sandboxed environment with restricted access. The current implementation using Wasmtime provides the following protections:
- No network access by default.
- Restricted filesystem access (functions cannot access host files outside the KRM interface).
- No ability to execute system commands.

These restrictions provide a higher level of isolation compared to traditional executables, though they may limit some use cases.

### Performance

- Faster startup than containers as no container runtime overhead is involved.
- CPU-intensive operations may be slower than native execution.
- Memory usage patterns differ from container-based functions.

### Compatibility

Not all container functions can convert to WASM, especially those needing:
- Host network access.
- Complex system dependencies.
- OS-specific features (e.g. syscalls not supported by WASI).

## See also

- [KRM Functions Specification](https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md)
- [Functions Catalog](https://catalog.kpt.dev/)
- [kpt alpha wasm push]({{< relref "/reference/cli/alpha/wasm/push" >}})
- [kpt alpha wasm pull]({{< relref "/reference/cli/alpha/wasm/pull" >}})
- [WASM function examples](https://github.com/kptdev/krm-functions-catalog/tree/main/functions/go)
2 changes: 1 addition & 1 deletion internal/fnruntime/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func NewRunner(
}
case f.Exec != "":
// If AllowWasm is true, we will use wasm runtime for exec field.
if opts.AllowWasm {
if opts.AllowWasm && strings.HasSuffix(f.Exec, ".wasm") {
wFn, err := NewWasmFn(&FsLoader{Filename: f.Exec})
if err != nil {
return nil, err
Expand Down
10 changes: 8 additions & 2 deletions internal/util/render/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,10 @@ func (pn *pkgNode) runValidators(ctx context.Context, hctx *hydrationContext, in
displayResourceCount = true
}
if function.Exec != "" && !hctx.runnerOptions.AllowExec {
return errAllowedExecNotSpecified
// WASM functions are sandboxed and don't require --allow-exec if --allow-alpha-wasm is set
if !(hctx.runnerOptions.AllowWasm && strings.HasSuffix(function.Exec, ".wasm")) {
return errAllowedExecNotSpecified
}
}
opts := hctx.runnerOptions
opts.SetPkgPathAnnotation = true
Expand Down Expand Up @@ -859,7 +862,10 @@ func fnChain(ctx context.Context, hctx *hydrationContext, pkgPath types.UniquePa
displayResourceCount = true
}
if function.Exec != "" && !hctx.runnerOptions.AllowExec {
return nil, errAllowedExecNotSpecified
// WASM functions are sandboxed and don't require --allow-exec if --allow-alpha-wasm is set
if !(hctx.runnerOptions.AllowWasm && strings.HasSuffix(function.Exec, ".wasm")) {
return nil, errAllowedExecNotSpecified
}
}
opts := hctx.runnerOptions
opts.SetPkgPathAnnotation = true
Expand Down