Skip to content

Commit 95ad8d4

Browse files
api: add vmID to EnvoyExtensionPolicy Wasm extensions
Envoy Gateway derives the Envoy Wasm `VmConfig.vm_id` from a name that is unique per EnvoyExtensionPolicy Wasm entry, so two policies that configure the exact same Wasm module still start two separate Wasm VMs. That is a safe default, but it makes the memory cost of a module grow linearly with the number of policies that attach it, which is the common shape when policies are managed per service or per route. Add an optional `vmID` field to the Wasm API that is passed through to `VmConfig.vm_id`. Wasm extensions that set the same `vmID` and are backed by the same Wasm code share a single Envoy Wasm VM. Leaving `vmID` unset keeps the current per-extension VM ID, so existing policies are unaffected. Fixes #9565 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: MohammadMahdi Ahmadi <mm.ahmadi0101@gmail.com>
1 parent 513b511 commit 95ad8d4

24 files changed

Lines changed: 1150 additions & 9 deletions

api/v1alpha1/wasm_types.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,20 @@ type Wasm struct {
3838
// Note: RootID must match the root_id parameter used to register the Context in the Wasm code.
3939
RootID *string `json:"rootID,omitempty"`
4040

41+
// VMID is the ID of the Wasm VM that runs this extension. Extensions with the
42+
// same VMID and the same Wasm code share a single VM, which saves the memory a
43+
// separate VM per extension would use.
44+
// If not specified, EG generates a VM ID that is unique to this extension, so
45+
// extensions never share a VM.
46+
//
47+
// Note: extensions sharing a VM also share its global state, and the VM is started
48+
// with the configuration of the first extension that initializes it.
49+
//
50+
// +optional
51+
// +kubebuilder:validation:MinLength=1
52+
// +kubebuilder:validation:MaxLength=253
53+
VMID *string `json:"vmID,omitempty"`
54+
4155
// Code is the Wasm code for the extension.
4256
Code WasmCodeSource `json:"code"`
4357

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2427,6 +2427,19 @@ spec:
24272427
24282428
Note: RootID must match the root_id parameter used to register the Context in the Wasm code.
24292429
type: string
2430+
vmID:
2431+
description: |-
2432+
VMID is the ID of the Wasm VM that runs this extension. Extensions with the
2433+
same VMID and the same Wasm code share a single VM, which saves the memory a
2434+
separate VM per extension would use.
2435+
If not specified, EG generates a VM ID that is unique to this extension, so
2436+
extensions never share a VM.
2437+
2438+
Note: extensions sharing a VM also share its global state, and the VM is started
2439+
with the configuration of the first extension that initializes it.
2440+
maxLength: 253
2441+
minLength: 1
2442+
type: string
24302443
required:
24312444
- code
24322445
type: object

charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2426,6 +2426,19 @@ spec:
24262426
24272427
Note: RootID must match the root_id parameter used to register the Context in the Wasm code.
24282428
type: string
2429+
vmID:
2430+
description: |-
2431+
VMID is the ID of the Wasm VM that runs this extension. Extensions with the
2432+
same VMID and the same Wasm code share a single VM, which saves the memory a
2433+
separate VM per extension would use.
2434+
If not specified, EG generates a VM ID that is unique to this extension, so
2435+
extensions never share a VM.
2436+
2437+
Note: extensions sharing a VM also share its global state, and the VM is started
2438+
with the configuration of the first extension that initializes it.
2439+
maxLength: 253
2440+
minLength: 1
2441+
type: string
24292442
required:
24302443
- code
24312444
type: object

internal/gatewayapi/envoyextensionpolicy.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,6 +1763,7 @@ func (t *Translator) buildWasm(
17631763
wasmIR := &ir.Wasm{
17641764
Name: name,
17651765
RootID: config.RootID,
1766+
VMID: config.VMID,
17661767
WasmName: wasmName,
17671768
Config: config.Config,
17681769
FailOpen: failOpen,
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
gateways:
2+
- apiVersion: gateway.networking.k8s.io/v1
3+
kind: Gateway
4+
metadata:
5+
namespace: envoy-gateway
6+
name: gateway-1
7+
spec:
8+
gatewayClassName: envoy-gateway-class
9+
listeners:
10+
- name: http
11+
protocol: HTTP
12+
port: 80
13+
allowedRoutes:
14+
namespaces:
15+
from: All
16+
httpRoutes:
17+
- apiVersion: gateway.networking.k8s.io/v1
18+
kind: HTTPRoute
19+
metadata:
20+
namespace: default
21+
name: httproute-1
22+
spec:
23+
hostnames:
24+
- www.example.com
25+
parentRefs:
26+
- namespace: envoy-gateway
27+
name: gateway-1
28+
sectionName: http
29+
rules:
30+
- matches:
31+
- path:
32+
value: "/foo"
33+
backendRefs:
34+
- name: service-1
35+
port: 8080
36+
- apiVersion: gateway.networking.k8s.io/v1
37+
kind: HTTPRoute
38+
metadata:
39+
namespace: default
40+
name: httproute-2
41+
spec:
42+
hostnames:
43+
- www.example.com
44+
parentRefs:
45+
- namespace: envoy-gateway
46+
name: gateway-1
47+
sectionName: http
48+
rules:
49+
- matches:
50+
- path:
51+
value: "/bar"
52+
backendRefs:
53+
- name: service-1
54+
port: 8080
55+
envoyextensionpolicies:
56+
# The two policies below configure the same Wasm extension for different routes
57+
# and opt into sharing a single Envoy Wasm VM by setting the same vmID.
58+
- apiVersion: gateway.envoyproxy.io/v1alpha1
59+
kind: EnvoyExtensionPolicy
60+
metadata:
61+
namespace: default
62+
name: policy-for-http-route-1
63+
spec:
64+
targetRef:
65+
group: gateway.networking.k8s.io
66+
kind: HTTPRoute
67+
name: httproute-1
68+
wasm:
69+
- name: auth-filter
70+
vmID: shared-auth-filter
71+
code:
72+
type: HTTP
73+
http:
74+
url: https://www.example.com/auth-filter.wasm
75+
sha256: f5173e637a258751276b55f1f9ca6ec3b2f21ea8e6cc34216bba899cac96e9da
76+
- apiVersion: gateway.envoyproxy.io/v1alpha1
77+
kind: EnvoyExtensionPolicy
78+
metadata:
79+
namespace: default
80+
name: policy-for-http-route-2
81+
spec:
82+
targetRef:
83+
group: gateway.networking.k8s.io
84+
kind: HTTPRoute
85+
name: httproute-2
86+
wasm:
87+
- name: auth-filter
88+
vmID: shared-auth-filter
89+
code:
90+
type: HTTP
91+
http:
92+
url: https://www.example.com/auth-filter.wasm
93+
sha256: f5173e637a258751276b55f1f9ca6ec3b2f21ea8e6cc34216bba899cac96e9da

0 commit comments

Comments
 (0)