OpenKruise Agents v0.6.0: Making Agent Sandboxes Safer, Easier to Operate, and More Resource-Efficient
Keywords: L4/L7 Traffic Control · Credential Injection · CheckpointRestore · PoolAutoscaler · Auto Pause/Resume
The v0.3.0 release answered one question: once a Sandbox is handed to an Agent, how do you upgrade it, resize it, and account for it. Its roadmap closed with two promises — TrafficPolicy / SecurityProfile for network governance, and a security identity integration that keeps platform credentials out of Agent code.
OpenKruise Agents v0.6.0 delivers both, and adds the operational machinery around them: 283 merged pull requests since v0.3.0. The four capabilities this post covers in depth are:
- Layer 4 and Layer 7 network access control plus token management —
TrafficPolicyfor destination reachability,SecurityProfilefor per-request inspection, MCP tool-level ACLs, credential injection from Kubernetes Secrets; SandboxUpdateOpswithCheckpointRestoreand paused-instance upgrades — upgrade a hibernated fleet without waking it by hand, and upgrade without losing the root filesystem;PoolAutoscaler— declarative warm pool capacity, with watermarks and cron schedules;- Automatic pause and resume — probe-driven idle detection, scheduled wake, and wake-on-traffic, so an idle Sandbox stops consuming CPU without any manual intervention.
Read together, these are three kinds of customer value: security hardening (an Agent that runs untrusted code can no longer reach whatever it wants, and never holds your API keys), operational capability (batch upgrades, autoscaling, and lifecycle automation become declarative instead of scripted), and cost optimization (idle Sandboxes hibernate, warm pools shrink at night, and paused fleets still receive upgrades).
This post is organized in three parts: the architecture changes that made all of this possible, a deep dive into the four features, and the value and roadmap summary.
Part One: What Changed in the Architecture
If v0.3.0 was a workload layer, v0.6.0 is a workload layer with its own data plane. The full component model is documented in Architecture; the short version is that traffic inspection, policy distribution, and identity all became first-class components rather than external addons.

1.1 From Four Components to Six
| Component | Role in v0.6.0 |
|---|---|
sandbox-manager | Stateless backend that serves the E2B-compatible northbound API and owns sandbox lifecycle, quota, and route & traffic-token orchestration |
sandbox-controller | Reconciles Sandbox, SandboxSet, SandboxClaim and warm pools, and hosts the admission webhooks. In v0.6.0 it also drives the automatic pause/resume controller |
sandbox-gateway | The data plane, built as Envoy Go filters. The ingress gateway proxies user traffic to sandboxes with host/path routing, access tokens, and wake-on-traffic. The egress gateway proxies outbound sandbox traffic with policy-enforced L7 egress |
traffic-control-plane | New. istiod distributes xDS configuration to the gateways and the in-pod proxies; the Egress Policy Enforcer (EPE) applies L7 policy, MCP ACL, and token injection on egress traffic |
agent-runtime | Sidecar providing E2B envd-compatible command, file, and port (49983) operations |
traffic-proxy | New. A sidecar that acts as the in-pod L4 enforcement point for egress traffic policies |
Two consequences are worth internalizing. First, egress is no longer the Pod's own business — it is captured in-pod, routed through an egress gateway, and decided by a policy engine that sees the request, not just the socket. Second, the ingress gateway can wake a sandbox, which is what makes wake-on-traffic possible without an external poller.
1.2 The Enforcement Path
Every gateway-routed outbound request from a Sandbox running the traffic-proxy runtime walks the same path:
Sandbox application container
-> TrafficProxy in-pod capture
-> egress gateway chosen by egress routing
-> Envoy external processing
-> Egress Policy Enforcer decision
-> external service, or a blocked response
The split of responsibility is deliberate: EPE compiles TrafficPolicy / GlobalTrafficPolicy and pushes them to the data plane, so an L4 rejection is dropped before the gateway. EPE only inspects L7 for gateway-routed HTTP requests — direct passthrough traffic never reaches it, and L7 cannot override an L4 rejection.
1.4 The CRD Surface Doubled
v0.3.0 shipped six CRDs. v0.6.0 ships twelve:
| CRD | Scope | Role |
|---|---|---|
Sandbox | Namespaced | A single sandbox instance with full lifecycle operations |
SandboxSet | Namespaced | Manages a batch of homogeneous Sandboxes; maintains the warm pool |
SandboxTemplate | Namespaced | Immutable template version snapshot for version tracing |
SandboxClaim | Namespaced | Claims an idle Sandbox and performs post-processing (image swap, mounts, in-place resize) |
Checkpoint | Namespaced | Runtime snapshot (memory and/or rootfs) used to fork new instances |
Commit | Namespaced | Alpha, behind the Commit feature gate. Saves the writable layer as a new image and pushes it to a registry |
SandboxUpdateOps | Namespaced | One-shot batch upgrade of claimed Sandboxes |
PoolAutoscaler | Namespaced | New. Declarative warm pool capacity and cron scaling |
TrafficPolicy | Namespaced | New. L3/L4 egress and ingress destination control |
GlobalTrafficPolicy | Cluster | New. Cluster-scoped L4 baseline |
SecurityProfile | Namespaced | New. L7 request inspection, MCP ACL, credential injection, audit |
GlobalSecurityProfile | Cluster | New. Cluster-scoped L7 baseline |
1.5 E2B Compatibility Moved Forward, With Documented Edges
The northbound API stays E2B-compatible, and the compatibility matrix is now explicit about where it is partial:
pauseis fully compatible and synchronous — the request blocks until the Sandbox reachesPaused;createis partially compatible — network access control is supported, MCP integration on the create path is still pending;networkis partially compatible —allowOut,denyOut, andrulesare supported;egressProxyandmaskRequestHostare rejected outright rather than silently ignored;- Not yet supported: pre-signed upload/download URLs, logs, metrics, lifecycle events, and Volumes.
Part Two: The Four Features in Depth
2.1 Network Access Control and Token Management
This is the largest single area of the release, and it answers three distinct questions: what may a Sandbox reach, who is allowed to reach the Sandbox, and — the one most platforms get wrong — who holds the upstream API key.
Layer 4: Is the Destination Reachable at All
TrafficPolicy selects calling Pods and holds an ordered egress rule list. Every rule must declare to, and may declare action (allow or reject) and a ports list. A peer accepts fqdn, cidr, service, or workload, and multiple peers are ORed.
apiVersion: agents.kruise.io/v1alpha1
kind: TrafficPolicy
metadata:
name: sandbox-egress
namespace: default
spec:
selector:
matchLabels:
app: traffic-sample
egress:
rules:
- action: allow
to:
- service:
name: kube-dns
namespace: kube-system
- action: allow
to:
- fqdn: api.example.com
- action: reject
ports:
- protocol: TCP
port: 443
to:
- cidr: 10.0.0.0/8
Three semantics matter more than the syntax:
- Once a policy selects a Pod, outbound traffic matching no allow rule is rejected. The policy is an allowlist the moment it attaches;
- A rule missing its peer field is skipped by the compiler — it does not establish a default deny. A typo in
toweakens your policy silently; - Always allow the cluster DNS Service, or hostname resolution fails and every FQDN rule looks broken.
GlobalTrafficPolicy is the cluster-scoped equivalent, for baselines your platform team owns centrally.
Layer 7: What May This Specific Request Do
SecurityProfile matches HTTP requests and applies actions. Each rule has a unique name, at least one match clause, and actions. Clauses in match are ORed; every populated field inside one clause is ANDed; domains is required.
The action set is small and its terminal behavior is the part to memorize:
| Action | Terminal | Behavior |
|---|---|---|
block | Yes | Returns statusCode (default 403) with an optional body, never forwards upstream, discards pending mutations |
bypass | Yes | Forwards the request and skips every remaining action and rule, preserving mutations already applied |
mcpToolPolicy | No | Allows or denies MCP JSON-RPC tools/call requests by tool name |
headerManipulation | No | Sets or removes plaintext headers. Values are stored verbatim — never use it for credentials |
tokenTransformation | No | Rewrites a request credential from a Secret or credential provider. Governed by failStrategy, default Block |
audit | No | Sends an asynchronous webhook event; never changes the decision |
Evaluation order is a merge, not a namespace-local list: lower spec.priority first (default 1000), then earlier creation time, name, and namespace. Global and namespaced profiles share this order, and an exact tie places the global profile first. Matching is not first-rule-wins — a later rule can still match after a broad earlier rule; only a terminal action stops the chain. Within one rule, actions run in the fixed order bypass, block, mcpToolPolicy, headerManipulation, tokenTransformation, regardless of YAML key order.
A representative baseline that blocks management paths anywhere:
apiVersion: agents.kruise.io/v1alpha1
kind: SecurityProfile
metadata:
name: deny-management-paths
namespace: default
spec:
selector:
matchLabels:
app: traffic-sample
rules:
- name: deny-management-paths
match:
- domains:
- "*"
paths:
- type: Prefix
value: /admin
- type: Prefix
value: /console
- type: Prefix
value: /dashboard
actions:
block:
statusCode: 403
body: '{"error":"management paths are blocked"}'
The highest-value profile for Agent workloads, though, is the SSRF guard. Prompt-injected code reliably tries to reach internal services and cloud metadata endpoints:
apiVersion: agents.kruise.io/v1alpha1
kind: GlobalSecurityProfile
metadata:
name: cluster-baseline
spec:
selector:
matchLabels:
app: traffic-sample
priority: 50
rules:
- name: deny-metadata-endpoint
match:
- domains:
- metadata.internal
- "*.internal.company.com"
- "*.corp.net"
actions:
block:
statusCode: 403
body: '{"error":"access to internal services is forbidden"}'
Note priority: 50 — a cluster baseline should sort ahead of tenant profiles on purpose, and a GlobalSecurityProfile must not set metadata.namespace.
MCP Tool-Level ACL
When an Agent talks to an MCP server, domain-level control is too coarse: the dangerous operation is a specific tool. mcpToolPolicy governs only JSON-RPC tools/call and matches the exact params.name; tools/list and initialize pass through.
apiVersion: agents.kruise.io/v1alpha1
kind: SecurityProfile
metadata:
name: mcp-tool-whitelist
namespace: default
spec:
selector:
matchLabels:
app: traffic-sample
rules:
- name: protect-mcp-tools
match:
- domains:
- mcp.example.com
schemes:
- https
paths:
- type: Prefix
value: /mcp
actions:
mcpToolPolicy:
defaultAction: deny
unsupportedVersionAction: deny
denyResponse:
statusCode: 403
body: MCP tool is not permitted
rules:
- method: tools/call
toolNames:
- read_file
- search_docs
action: allow
Rules are evaluated in document order and the first match wins; an empty toolNames list matches every tool for that method. Use defaultAction: deny for a whitelist — with defaultAction: allow, an unreadable body or an unnameable tool call is allowed by design. The enforcer buffers the full body, so payloads over 8 MiB, JSON-RPC batches, and unsupported encodings fall back to defaultAction. Supported MCP protocol versions are 2025-06-18, 2025-11-25, and 2026-07-28.
Credential Injection: Your API Key Never Enters the Sandbox
This is the piece that changes the security conversation with your compliance team. The credential lives in a Kubernetes Secret; the egress proxy resolves it per request and rewrites the outbound request just before it leaves the cluster. The workload and the Agent code only ever see their own placeholder header.
apiVersion: v1
kind: Secret
metadata:
name: example-api-credentials
namespace: agent-demo
type: Opaque
stringData:
apiKey: REPLACE_WITH_YOUR_API_KEY
apiVersion: agents.kruise.io/v1alpha1
kind: SecurityProfile
metadata:
name: example-api-credentials
namespace: agent-demo
spec:
selector:
matchLabels:
app: agent
rules:
- name: inject-example-api-key
match:
- domains:
- api.example.com
schemes:
- https
paths:
- type: Prefix
value: /v1/
actions:
tokenTransformation:
type: ApiKey
failStrategy: Block
credentialRef:
secret:
name: example-api-credentials
apiKey:
targetHeaders:
names:
- authorization
value:
template: "Bearer {{ .Token }}"
Because resolution happens at the proxy, the credential is not in the Pod spec, the environment, or Sandbox metadata — and rotating the Secret takes effect without restarting the Sandbox. credentialRef.secret.namespace is optional: a SecurityProfile falls back to its own namespace, a GlobalSecurityProfile to each selected Pod's namespace. Exactly one of secret or credentialProvider may be set, targetHeaders.cel supports dynamic header names, and failStrategy defaults to Block so a missing credential fails closed rather than leaking an unauthenticated call.
E2B-Native Network Controls
Teams that do not want to write CRDs can express network intent through the E2B SDK, provided the Sandbox runs traffic-proxy:
from e2b_code_interpreter import Sandbox
sandbox = Sandbox.create(
template="code-interpreter",
network={
"allow_out": ["api.example.com", "10.0.0.0/8"],
"deny_out": ["0.0.0.0/0"],
},
)
The asymmetry to remember: allowOut accepts IPs, CIDRs, and concrete FQDNs (wildcards rejected), while denyOut accepts IPs and CIDRs only. Hostname filtering is therefore expressed as an allowlist plus a 0.0.0.0/0 deny, and allow beats deny. rules carries per-domain header transforms and does not grant reachability. Updates go through PUT /sandboxes/{sandboxID}/network or sandbox.update_network(...): an omitted rules key keeps the existing chain, an empty object clears it, a non-empty one replaces it.
These controls compose into a hierarchy: cluster-scoped GlobalTrafficPolicy and GlobalSecurityProfile set the global baseline, namespace-scoped TrafficPolicy and SecurityProfile carry per-tenant rules, and per-Sandbox inline network controls apply to a single Sandbox — multi-layered, fine-grained network access control from the global dimension down to the tenant and the individual Sandbox.
Guardrails You Should Not Skip
The four manuals behind this section are Traffic Access Control, E2B Network Controls, Credential Injection, and Traffic Access Token Rotation. They are explicit about the limits, and so is this post:
- Enforcement covers gateway-routed traffic only. HTTPS inspection additionally requires TLS termination, a signing CA, and workload trust;
- A container running as root or with
NET_ADMIN/SYS_ADMINcan bypass the in-pod ACLs. Pair these policies with Kubernetes NetworkPolicies, a host firewall, or cloud security groups — this is defense in depth, not a single wall; - TrafficProxy reserves ports 15001, 15006, 15012, 15020, 15021, 15090 and runs as UID/GID 1337;
- A forged
Hostheader can evade L4 matching, which is exactly why L7 profiles exist; - Per-Sandbox inline rules (
agents.kruise.io/security-rules) are evaluated after selector-matched profiles; a compile failure keeps the previous rules or enforces none, surfaced by theepe_profile_staleandepe_profile_unenforcedmetrics withscope="pod"; - EPE is a network hop on every gateway-routed request. Size its Deployment independently of the gateways.
2.2 SandboxUpdateOps: CheckpointRestore and Upgrading Paused Sandboxes
v0.3.0 introduced SandboxUpdateOps with a single mode: Recreate, meaning the Pod is destroyed and rebuilt, so memory, IP, and the rootfs writable layer are all lost, and preUpgrade / postUpgrade hooks are your only way to carry state across. v0.6.0 adds two things users asked for immediately: a mode that preserves the rootfs, and the ability to include paused Sandboxes in a batch upgrade. Both require v0.6.0; the base flow works from v0.3.0. Details are in Sandbox Update.

Two Upgrade Modes
| Mode | Rootfs | Memory | IP | Business image change |
|---|---|---|---|---|
Recreate (default) | Lost | Lost | Changed | Supported |
CheckpointRestore | Preserved — checkpointed before, restored after | Lost | Changed | Not supported |
CheckpointRestore trades image flexibility for data continuity. The constraint is absolute: you cannot change the business container image under CheckpointRestore — doing so discards the restored rootfs, which is the entire point of the mode. What you can do is roll sidecar versions and any non-image field:
apiVersion: agents.kruise.io/v1alpha1
kind: SandboxUpdateOps
metadata:
name: upgrade-sidecar
namespace: default
spec:
updateStrategy:
type: CheckpointRestore
patch:
metadata:
annotations:
agents.kruise.io/upgrade-sidecar: "20260714"
That is the pattern for a fleet-wide agent-runtime or traffic-proxy bump: no user data touched, no backup scripts to write, no restore window to schedule. For an image change with state, Recreate plus hooks remains the answer — back up to OSS or NAS in preUpgrade, restore in postUpgrade.
Upgrading Hibernated Sandboxes
Before v0.6.0, SandboxUpdateOps only touched Sandboxes in Running or Upgrading phase. A paused fleet was invisible to it, which forced operators into an awkward manual cycle of wake, upgrade, re-pause — and made a hibernated pool a standing source of version drift.
stateFilter fixes this:
apiVersion: agents.kruise.io/v1alpha1
kind: SandboxUpdateOps
metadata:
name: upgrade-with-paused
namespace: default
spec:
stateFilter:
states:
- Running
- Paused
selector:
matchLabels:
agents.kruise.io/sandbox-template: my-sandbox-pool
updateStrategy:
maxUnavailable: 10%
patch:
spec:
containers:
- name: sandbox
image: my-registry/sandbox-image:v2
The controller wakes each paused Sandbox, upgrades it, then re-pauses it if spec.paused is still true. The end state of the fleet is the same shape as the start state — paused Sandboxes stay paused — so an upgrade does not silently convert a hibernated pool into a billing event.
2.3 PoolAutoscaler: Warm Pool Capacity as a Policy
Warm pools are the reason OpenKruise Agents delivers sub-second claims, and they are also the reason a platform team's bill grows on Saturday night when nobody is using it. PoolAutoscaler turns pool sizing into a declarative policy instead of a cron job that runs kubectl scale.
Be precise about what it does: PoolAutoscaler rewrites SandboxSet.spec.replicas. It does not collect business metrics, predict traffic, or create and delete Pods itself — the SandboxSet controller does that. What it gives you is watermark-driven feedback on available capacity, plus time-driven overrides.
Capacity Policy
apiVersion: agents.kruise.io/v1alpha1
kind: PoolAutoscaler
metadata:
name: sandbox-pool-scaler
namespace: default
spec:
scaleTargetRef:
kind: SandboxSet
name: sandbox-pool
minReplicas: 2
maxReplicas: 50
capacityPolicy:
targetAvailable: "50%"
tolerance: "10%"
scaleUp:
stabilizationWindowSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
targetAvailable: "50%" means the scaler keeps available Sandboxes at half of total replicas — a buffer that absorbs a claim burst while the pool refills. Watermarks are computed as ceil(avgReplicas x (target +/- tolerance)%), with tolerance defaulting to 10%. Asymmetric stabilization windows (fast up, slow down) are the right default for a warm pool: users feel a shortage immediately and never notice a gradual shrink.
Cron Policies
For known traffic shapes, cron wins — it triggers ahead of the burst rather than reacting to it:
apiVersion: agents.kruise.io/v1alpha1
kind: PoolAutoscaler
metadata:
name: sandbox-pool-scaler
namespace: default
spec:
scaleTargetRef:
kind: SandboxSet
name: sandbox-pool
minReplicas: 2
maxReplicas: 50
cronPolicies:
- name: weekday-peak
timezone: Asia/Shanghai
schedule: "30 8 * * 1-5"
targetReplicas: 30
- name: weekday-offpeak
timezone: Asia/Shanghai
schedule: "0 20 * * 1-5"
targetReplicas: 5
Cron takes priority when triggered and is not subject to the capacity stabilization windows, but it is still clamped by minReplicas / maxReplicas. Set timezone explicitly — the schedule is five-field cron, and validation allows up to 20 entries with unique names.
Tuning Traps
- Do not set
targetAvailable: "100%"— the pool then only ever grows; - Scale-down reachability has hard arithmetic. For absolute values,
target + downTolerancemust not exceedminReplicas; for percentages,p + qmust not exceed100 x minReplicas / (minReplicas + 1). Otherwise the policy can never trigger a shrink and validation is your only warning; tolerancemust be strictly less thantargetAvailable; a percentage target requiresminReplicasof at least 1; stabilization windows are 60 to 3600 seconds;- Validation failures return HTTP 422, including a
scaleTargetRef.kindthat is notSandboxSet,maxReplicasat or below 0, orminReplicasabovemaxReplicas; spec.suspend: truepauses the scaler without deleting it — the right move during an incident;- Deleting a PoolAutoscaler leaves
spec.replicasat its last value. The pool does not shrink back on its own.
2.4 Automatic Pause and Resume
A claimed Sandbox with an active user session and a claimed Sandbox where nobody has typed in four hours look identical to Kubernetes. Automatic pause and resume makes the difference observable, and acts on it.
The feature is configured on SandboxSet through two top-level spec fields — probes and autoPausePolicy — and probe-driven pause plus scheduled wake require the AutoPauseController feature gate on sandbox-controller, which is enabled by default. Probes on real nodes additionally require OpenKruise installed (for kruise-daemon) and the KruiseIntegration feature gate — otherwise real-node probe conditions stay Unknown and automatic pause never triggers; probes on virtual-kubelet nodes are unaffected. Inbound-traffic wake applies only to gateway-routed requests to claimed Sandboxes, and needs the gateway flags enable-wake-on-traffic and wake-timeout-seconds (default 60, after which the caller gets 503 sandbox wake failed). Both are gateway-level.
Probes: Exec Only, Message-Driven
apiVersion: agents.kruise.io/v1alpha1
kind: SandboxSet
metadata:
name: openclaw-sbs
namespace: default
spec:
probes:
- name: Active
periodSeconds: 30
timeoutSeconds: 5
exec:
command:
- sh
- -c
- |
if openclaw sessions list --active 900 | grep -q .; then
printf 'active'
else
printf 'inactive'
fi
Each probe needs a unique name (it becomes condition type agents.kruise.io/<name>), an optional containerName (defaults to the first container), and only exec is supported — no HTTP, no TCP. The command is not shell-wrapped, so write sh -c yourself. Exit code 0 produces status: "True" with stdout in message; a failed or timed-out probe never triggers a pause or a wake, which is the safe direction.
Idle-Driven Pause
autoPausePolicy:
probe: Active
pause:
whenProbedIdleState:
probe: Active
messageRegex: "^inactive$"
thresholdDuration: 10m
thresholdDuration is required and non-negative; 0 means pause on the first idle report. The window arithmetic is worth spelling out for capacity planning: with a 30-second period, a 15-minute inactivity window inside the probe command, and a 10-minute threshold, the Sandbox pauses roughly 25 minutes after the last real activity. The pending pause is visible in status.schedules as reason: probedIdle with a nextPauseTime, and a later active reading clears it.
Warm unclaimed Sandboxes run the probes but do not participate in pause decisions — the pool is managed by PoolAutoscaler, not by auto-pause.
Scheduled Wake
Some workloads are idle on a schedule: a notebook that only matters at 9am, an RL rollout that runs nightly. A second probe can print the next activation time, and the controller wakes the Sandbox ahead of it:
autoPausePolicy:
resume:
whenProbedScheduleTime:
probe: Cron
timeFormat: unix
leadTime: 5m
timeFormat is unix (default, positive integer seconds) or datetime (RFC 3339 with timezone). leadTime defaults to 5m, may be 0, and may not be negative; wake happens at task time minus lead time, surfaced as reason: probedSchedule with nextResumeTime. Two classic bugs: printing milliseconds from the probe (divide by 1000), and converting local business time to a timestamp inside the probe instead of emitting a timezone-aware value.
Wake on Inbound Traffic
This is the path that makes pausing safe for user-facing Sandboxes — the first request after a pause wakes the Sandbox instead of failing:
from e2b_code_interpreter import Sandbox
sandbox = Sandbox.create(
template="code-interpreter",
timeout=600,
lifecycle={
"on_timeout": "pause",
"auto_resume": True,
},
)
host = sandbox.get_host(3000)
After a wake, the timeout countdown restarts from the wake-up moment using the creation timeout, and positive values below 5 minutes are treated as 5 minutes. sandbox.commands.run(...) and sandbox.files.write(...) also trigger a wake. In CRD form the same re-arm is autoPausePolicy.resume.onIngressTraffic.pauseTimeout: 5m, which applies only to Sandboxes that have spec.pauseTime set — if it is unset or not greater than 0, the countdown is not reset. On its own onIngressTraffic pauses nothing; it only governs the resume behavior.
Three behaviors are universal and will otherwise cost you an afternoon:
- The request must be authorized. An unauthorized request gets
401and the Sandbox stays paused — wake-on-traffic is not an unauthenticated doorbell; - A successful wake can accompany a failed request. The triggering call may return
503 upstream connect error, or503 sandbox wake failedif it arrives mid-transition to paused. CheckSandbox.status.phaseand retry; - A warm Sandbox is still owned by its SandboxSet, so a request to one returns
502 healthy sandbox not found.
Part Three: Customer Value, Roadmap, and Community
3.1 What This Buys You
| Before v0.6.0 | With v0.6.0 | |
|---|---|---|
| Security hardening | Egress was the Pod's own business; a prompt-injected Sandbox could reach internal services, cloud metadata, and any MCP tool the server exposed. Upstream API keys had to be handed to the Agent runtime. Long-lived opaque tokens bounded replay exposure to "forever" | L3/L4 allowlists with TrafficPolicy, L7 request inspection with SecurityProfile, MCP tool whitelists, a cluster-wide Global* baseline layer, credentials resolved at the egress proxy from a Secret and rotatable without restart, and short-lived rotating JWT traffic access tokens |
| Operations capability | Paused Sandboxes were invisible to batch upgrades, so hibernated fleets drifted. Pool sizing was a cron job calling kubectl scale. Idle detection was somebody's shell script | SandboxUpdateOps covers Running and Paused via stateFilter and preserves the rootfs via CheckpointRestore; PoolAutoscaler makes capacity declarative with watermarks and cron; auto pause/resume turns idle detection into a probe |
| Cost optimization | A claimed Sandbox burned CPU whether or not anyone was using it, and the warm pool was sized for peak around the clock | Idle Sandboxes hibernate on probe evidence and wake on schedule or on first request; pools shrink at 20:00 and grow at 08:30; CheckpointRestore upgrades and paused-fleet upgrades avoid both data loss and unnecessary wake cycles |
3.2 What Is Next: Community Capability Building
The roadmap ahead emphasizes community capability building — building with other open-source communities instead of growing a proprietary stack:
- Open-source checkpoint with the Kata Containers community — implement an open-source checkpoint capability on top of the
PodCheckpointAPI introduced in Kubernetes 1.37, in collaboration with the Kata community, moving beyond today's platform-specific snapshot backend; - On-demand mounting for open-source storage — build on the existing on-demand volume mounting framework so open-source storage solutions such as MinIO can be mounted into a Sandbox on demand;
- Integration with open-source identity systems — such as Keycloak, so platform authentication can be unified with your existing identity provider.
3.3 Community
OpenKruise Agents is built in the open, and this release had 27 new contributors. If you are running Agent sandboxes on Kubernetes, the fastest way to shape the roadmap is to file an issue or join the community call.
- GitHub: https://github.com/openkruise/agents
- Documentation: https://openkruise.io/kruiseagents/
- Slack: Kubernetes Slack #openkruise channel
- DingTalk Group: Search for group number
23330762 - WeChat: Add
openkruiseto be invited by the bot - Bi-weekly community meeting (Chinese): Every Thursday 19:30 GMT+8
OpenKruise Agents v0.6.0 is now available on GitHub Releases and major container registries. We look forward to your feedback and Pull Requests.