Skip to main content

Commit Sandbox Image

Overview​

Commit is a namespaced CRD in OpenKruise Agents that saves the writable filesystem of a running Sandbox container as a new container image and pushes it to an image registry.

It is useful when you want to:

  • Save a configured development environment as a reusable image.
  • Turn changes made inside a running Sandbox into a versioned image.
  • Share a Sandbox workspace state with other users or future Sandbox templates.

What Commit preserves​

  • Filesystem changes inside the target container's writable layer: installed packages, source code, configuration files, generated artifacts, log files, and similar on-disk content.
  • Any data that already resides in the container's root filesystem.

What Commit does not preserve​

  • In-memory state of running processes.
  • GPU memory, GPU device state, or accelerator context.
  • Active network connections, open file descriptors, or process tables.
  • External mounts such as PVCs, hostPath volumes, or sidecar-injected volumes not part of the container's writable layer.

Unlike Snapshot Management, which captures Sandbox runtime state for pause/resume or fork workflows, Commit produces a normal container image that can be pulled by any compatible container runtime.

Feature Gate​

Commit is controlled by the Commit feature gate. In the current community implementation, it is an Alpha feature and is disabled by default.

Enable it on the sandbox controller:

--feature-gates=Commit=true

Prerequisites​

Before creating a Commit, make sure that:

  • OpenKruise Agents controller is installed and running.
  • The Commit CRD (commits.agents.kruise.io) is registered in the cluster.
  • The target Sandbox Pod is running and scheduled, and the target container is managed by containerd. Its container ID in Pod status must use the containerd:// prefix; Docker-only or CRI-O-only nodes are not supported.
  • The target node exposes the containerd socket at /run/containerd/containerd.sock. The commit Job mounts /run/containerd/ from the target node and connects to this socket with nerdctl.
  • The sandbox controller is configured with AGENT_JOB_IMAGE, and that image contains the commit-job binary and nerdctl.
  • The target registry is reachable from the target node.
  • For registry TLS verification, the commit Job uses nerdctl's default hosts directory /etc/containerd/certs.d, which is mounted from the target node. For a registry using a private CA, custom endpoint, or mirror configuration, prepare the corresponding hosts.toml and CA files under /etc/containerd/certs.d/<registry-host>/ on every node that may run the target Sandbox Pod.
  • If the registry requires authentication, a Docker config Secret exists in the same namespace as the Commit, and the registry user has push permission to the destination repository.

Commit Job Image​

The commit-job binary source is under cmd/commit-job, with the execution logic in pkg/controller/commit/job. It is packaged as a standalone image by dockerfiles/commit-job.Dockerfile; the image contains both /commit-job and the nerdctl binary.

You can build a local image with:

docker build -f dockerfiles/commit-job.Dockerfile \
--build-arg NERDCTL_BRANCH=v2.0.0 \
-t openkruise/commit-job:<version> .

Set the resulting image as AGENT_JOB_IMAGE on the sandbox controller.

Commit CRD​

The Commit resource (agents.kruise.io/v1alpha1, short name cmt) has the following key fields:

FieldTypeDescription
spec.podNamestringRequired. Name of the target Sandbox Pod. Immutable after creation.
spec.containerNamestringRequired. Name of the container whose filesystem should be committed. Immutable after creation.
spec.imagestringRequired. Destination image reference to push, for example registry.example.com/team/my-env:v1. Immutable after creation.
spec.squashLayerint32Optional. Reserved for future layer squash optimization. 0 means no squashing. Immutable after creation.
spec.timeoutSecondsint32Optional. Maximum running time of the commit Job. 0 means no timeout. Immutable after creation.
spec.ttldurationOptional. How long to retain the Commit object after it reaches Succeeded or Failed, such as 24h or 168h. Unset means no auto-deletion.
spec.registryAuth.secrets[]stringOptional. Names of kubernetes.io/dockerconfigjson Secrets in the same namespace. The first valid Secret is mounted into the commit Job for nerdctl push.
status.phasestringPending, Running, Succeeded, or Failed.
status.commitIDstringCommit identifier. Currently set to the Commit object name after the commit starts.
status.conditions[]ConditionDetailed condition information from the commit Job. Common condition types include CommitContainer and PushCommittedImage; PullBaseImage is reserved for future use.
status.startTimeTimeTime when the commit Job starts.
status.completionTimeTimeTime when the commit reaches a terminal phase.

Creating a Commit​

Create a Commit object that points to the running Sandbox Pod and the target container. If the target registry requires authentication, also reference a Docker config Secret via spec.registryAuth.secrets.

First create the registry auth Secret in the same namespace as the Commit. The registry user configured in this Secret must have push permission to the destination image repository:

kubectl create secret docker-registry push-secret \
-n sandbox-system \
--docker-server=registry.example.com \
--docker-username=<username> \
--docker-password=<password>

Then create the Commit:

apiVersion: agents.kruise.io/v1alpha1
kind: Commit
metadata:
name: commit-demo-01
namespace: sandbox-system
spec:
podName: code-interpreter-28rvn
containerName: workspace
image: registry.example.com/team/code-interpreter:demo-01
registryAuth:
secrets:
- push-secret
timeoutSeconds: 600
ttl: 168h

Apply it:

kubectl apply -f commit.yaml

The controller creates a Kubernetes Job on the same node as the target Pod. The Job performs:

nerdctl commit <container-id> <image>
nerdctl push <image>

If registryAuth is not set or no valid Secret is found, the commit Job attempts an anonymous push. The registryAuth.credentials field is reserved for future use and currently has no effect.

Monitoring Progress​

Use the short name cmt to list Commit objects:

kubectl get cmt -n sandbox-system

Example output:

NAME               PHASE       TTL    AGE
commit-demo-01 Running 168h 12s
commit-demo-auth Succeeded 168h 2m

Watch one Commit in detail:

kubectl get cmt commit-demo-01 -n sandbox-system -o yaml

Check the phase directly:

kubectl get cmt commit-demo-01 -n sandbox-system -o jsonpath='{.status.phase}'

Once status.phase becomes Succeeded, the target image has been committed and pushed successfully.

Failure Handling​

A Commit moves to Failed when the controller or commit Job cannot complete the workflow. Common causes include:

SymptomCondition typePossible causeWhat to check
Commit fails quickly-Target Pod does not exist or is being deletedVerify spec.podName and namespace.
Job generation fails-Target container is not found in Pod status, Pod is not scheduled, or AGENT_JOB_IMAGE is emptyCheck spec.containerName, Pod status, and controller environment variables.
Image commit failsCommitContainernerdctl commit failed on the target nodeCheck job Pod logs and containerd access on the target node.
Image push failsPushCommittedImageRegistry authentication, authorization, DNS, network, or TLS configuration problemCheck registry Secret, node network, and /etc/containerd/certs.d.
Job times out-spec.timeoutSeconds is too small for the image size or network speedIncrease timeoutSeconds or leave it as 0.

You can inspect the generated Job and its Pod logs for more details:

kubectl get job -n sandbox-system -l agents.kruise.io/commit-name=commit-demo-01
kubectl get pod -n sandbox-system -l agents.kruise.io/commit-name=commit-demo-01
kubectl logs -n sandbox-system -l agents.kruise.io/commit-name=commit-demo-01

Cleaning Up​

Delete the Commit object manually:

kubectl delete cmt commit-demo-01 -n sandbox-system

Or set spec.ttl so the controller automatically removes the Commit object after it reaches a terminal phase:

spec:
ttl: 24h

Deleting the Commit object does not delete the pushed image from the registry.