Wasm
Envoy supports execution of Wasm plugins: the Wasm modules written against the Proxy-Wasm specification, which defines an extension interface through which the modules can implement custom extension logic. Currently, the Proxy-Wasm ABI (Application Binary Interface) version 0.2.1 is recommended. Wasm offers a portable and compact binary executable format that can be compiled once from a variety of languages (C++, Rust) and run anywhere. Please see the sandbox example for instructions on how to create and deploy a Wasm module.
Envoy provides several extension points at which Wasm plugins can be invoked:
As an HTTP filter
As a StatsSink
As an AccessLogger
As a background service
The particular functions that Envoy invokes on a Wasm plugin depend on the extension point at which it is configured.
Contexts, plugins, and VMs
A Wasm context refers to the interface implementation between the host (Envoy) and the guest (Wasm bytecode). For an HTTP filter, there are two types of contexts: a root context (context with ID 0) represents the configuration-only context, and a per-request context that is created once per each request.
A Wasm VM refers to the execution instance of a Wasm bytecode module. Multiple VMs can be created for the same bytecode
when using the vm_id
field, and they each would have separate per-VM memory. The opposite is also true, the same VM
can contain multiple implementations for different extensions (plugins), to be used in different contexts. VM sharing
optimizes the runtime overhead and reduces the total binary size of the bytecode since the extensions can share the
code.
A Wasm plugin is the link between the context and the VM. It identifies which Wasm VM to use for a context, which extension to invoke within the Wasm VM execution instance (via the root_id field value), and how to route the configuration call to the extension during the xDS update.
Execution model for filters
At runtime, the Wasm modules are executed inline in the worker threads via a series of stream callbacks as defined by the ABI. The worker threads operate independently and do not share the Wasm execution instances and their runtime memory. Asynchronous or blocking operations are delegated to Envoy to perform; upon completion, Envoy then invokes a separate completion callback on the plugin.
At configuration time, the Wasm modules are loaded into the Wasm engine on the main thread. A separate Wasm execution instance is spawned for each combination of the module binary and the vm_id field value. The instance receives the Wasm configuration for each plugin via a callback, possibly repeatedly for each xDS listener encapsulating the Wasm filter. If the callback accepts the configuration, the main execution instance is cloned to each worker thread.
Note that this configuration model is distinct for the Wasm filter. Unlike a regular HTTP filter that is instantiated independently for each xDS listener, xDS listeners share the same main Wasm execution instance across xDS updates.
Envoy Attributes
Wasm ABI exposes Envoy-specific host attributes via the dedicated proxy_get_property interface stub. These are the standard attributes and the values are returned via the type-specific binary serialization.
Foreign functions
Envoy offers additional functionality over the Proxy-Wasm ABI via proxy_call_foreign_function binary interface:
verify_signature
verifies cryptographic signatures.compress
applieszlib
compression.uncompress
applieszlib
decompression.declare_property
creates a placeholder filter state object with the type information.set_envoy_filter_state
set a filter state object.clear_route_cache
updates the selected route.expr_create
compiles a CEL expression for evaluation.expr_evalute
evaluates a compiled CEL expression.expr_delete
deletes a compiled CEL expression.
Wasm runtime
Envoy Wasm can be configured to use one of several Wasm
runtime implementations: V8
, WAMR
, or Wasmtime
, as long as the runtime is included in the Envoy
distribution. There is also a special pseudo-Wasm runtime, called the “Null VM”, in which Wasm plugin code is compiled
to native (non-Wasm) code and statically linked directly into the Envoy binary.