# How CubeSandbox Uses Namespaces for Process Isolation

> Discover how CubeSandbox leverages Linux namespaces for robust process isolation. Learn about global mount namespaces and per-sandbox containerd namespaces for secure request contexts.

- Repository: [Tencent Cloud/CubeSandbox](https://github.com/TencentCloud/CubeSandbox)
- Tags: internals
- Published: 2026-07-05

---

**CubeSandbox achieves Linux process isolation by creating a dedicated global mount namespace for the cubelet daemon plus per-sandbox containerd namespaces that embed isolation metadata into every request context.**

CubeSandbox (the `cubelet` component) implements a two-layer namespace strategy that isolates each sandboxed workload while maintaining coordination with the host system. This approach combines kernel-level Linux namespaces with containerd's contextual namespace system to provide complete process isolation without the overhead of virtual machines.

---

## Global Mount Namespace for the Cubelet Process

When the cubelet binary starts, it immediately establishes a **private view of the host's mount hierarchy** through a helper process called `newCubeMnt`. This setup ensures the cubelet can operate safely while still receiving host mount events.

### The `newCubeMnt` Bootstrap

In [`Cubelet/cmd/cubelet/main.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/Cubelet/cmd/cubelet/main.go) (lines 61-71), the cubelet spawns a child process with dedicated namespaces:

```go
func newCubeMnt() error {
    // Create a child process that has its own PID+mount namespaces:
    cmd.SysProcAttr = &syscall.SysProcAttr{
        Cloneflags: syscall.CLONE_NEWPID | syscall.CLONE_NEWNS,
    }
    // Start the child, bind-mount the shared directory, make the root rslave
}

```

The helper process performs three critical operations:

1. **Creates a new mount namespace** using `CLONE_NEWNS` to isolate the cubelet's filesystem view from the host
2. **Creates a new PID namespace** using `CLONE_NEWPID` to prevent process ID leakage
3. **Re-shares the host's mount propagation tree** by binding the mount-namespace directory to `/run/cube-containers/shared` with `rslave` propagation

This configuration allows the cubelet to maintain a **private mount hierarchy** while still receiving host mount events (such as new network storage mounts) through the shared propagation tree.

---

## Per-Sandbox Namespaces via containerd Context

Every sandbox operation in CubeSandbox carries a **namespace identifier** embedded in the Go `context.Context`. This mechanism, borrowed from `containerd/pkg/namespaces`, ensures consistent isolation metadata throughout a sandbox's lifecycle.

### Context Injection and Retrieval

CubeSandbox uses two key functions from the containerd namespaces package:

- **`namespaces.WithNamespace(ctx, ns)`** — Injects a namespace into a context
- **`namespaces.NamespaceRequired(ctx)`** — Retrieves the namespace from a context (returns error if missing)

In [`Cubelet/storage/local.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/Cubelet/storage/local.go) (lines 666-670), the `Create` function extracts and persists the namespace:

```go
ns, err := namespaces.NamespaceRequired(ctx)
if err != nil {
    return ret.Err(errorcode.ErrorCode_InvalidParamFormat, err.Error())
}

// Store the namespace in the sandbox metadata
info := &StorageInfo{
    Namespace: ns,
    SandboxID: sandboxID,
}
if err := l.writeBackendFileInfo(ctx, sandboxID, info); err != nil {
    return err
}

```

The namespace identifier is stored in the `StorageInfo` struct's `Namespace` field and logged as part of the request's metadata for auditability.

### Runtime Integration

When launching a sandbox's container runtime, the cubelet passes the same context to `runc` or other runtime helpers. The runtime then translates this contextual namespace into actual **Linux namespace syscalls** (`unshare`) for PID, UTS, IPC, and mount isolation.

---

## Linux Namespace Types Used by CubeSandbox

CubeSandbox leverages multiple Linux namespace types to provide comprehensive isolation:

| Namespace | Implementation | Purpose |
|-----------|---------------|---------|
| **PID** | `CLONE_NEWPID` in `newCubeMnt` and runtime `unshare` | Guarantees each sandbox runs with its own process ID space; the parent cubelet cannot see inside sandbox processes |
| **Mount** | `CLONE_NEWNS` in `newCubeMnt` and per-sandbox setup | Provides private filesystem views; the cubelet's bootstrap ensures safe mount propagation |
| **UTS** | Per-sandbox `unshare` in runtime | Isolates hostname and domain name per sandbox |
| **IPC** | Per-sandbox `unshare` in runtime | Separates System V shared memory, semaphores, and message queues |
| **Network** | `Cubelet/network` package | Isolates network interfaces, routing tables, and firewall rules per sandbox |

The network namespace implementation resides in the separate `Cubelet/network` package, which handles creation and teardown independently of the other namespaces.

---

## Complete Lifecycle Example

This code demonstrates how CubeSandbox combines both namespace layers:

```go
// 1. Attach namespace to request context (used throughout lifecycle)
ns, err := namespaces.NamespaceRequired(ctx)
if err != nil {
    return ret.Err(errorcode.ErrorCode_InvalidParamFormat, err.Error())
}

// 2. Store in sandbox metadata
info := &StorageInfo{
    Namespace: ns,
    SandboxID: sandboxID,
}

// 3. Pass context to runtime; runc builds syscalls:
//    unshare(CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNS|CLONE_NEWPID)
if err := runc.Start(ctx, opts); err != nil {
    return err
}

```

The context propagation ensures that the same namespace identifier flows from the initial API request through storage allocation to container runtime execution.

---

## Key Files and Implementation Details

| Component | File Path | Purpose |
|-----------|-----------|---------|
| Mount namespace bootstrap | [`Cubelet/cmd/cubelet/main.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/Cubelet/cmd/cubelet/main.go) | Contains `newCubeMnt`, `Cloneflags` setup, and `needNewMnt` helper |
| Namespace context handling | [`Cubelet/storage/local.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/Cubelet/storage/local.go) | Shows `namespaces.NamespaceRequired` and `StorageInfo.Namespace` persistence |
| Context propagation tests | [`Cubelet/storage/local_test.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/Cubelet/storage/local_test.go) | Uses `namespaces.WithNamespace(context.Background(), namespaces.Default)` for verification |
| Runtime integration | [`Cubelet/services/cubebox/runc_container_op.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/Cubelet/services/cubebox/runc_container_op.go) | Passes namespaced context to runc helpers |
| Network isolation | `Cubelet/network/` | Implements per-sandbox network namespace creation |

According to the test file [`Cubelet/storage/local_test.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/Cubelet/storage/local_test.go), unit tests verify correct namespace propagation using `namespaces.WithNamespace(context.Background(), namespaces.Default)`, confirming that the context carries the expected identifier through the entire request chain.

---

## Summary

CubeSandbox uses namespaces for process isolation through two complementary mechanisms:

- **Global mount namespace** established at cubelet startup via `newCubeMnt` with `CLONE_NEWNS | CLONE_NEWPID`, providing a private filesystem view while maintaining host mount propagation
- **Per-sandbox containerd namespaces** embedded in Go contexts via `namespaces.WithNamespace`, persisted in `StorageInfo`, and passed to the runtime for syscall-level isolation

This dual approach ensures that each sandbox operates in an isolated Linux namespace environment while the cubelet maintains secure coordination with the host system.

---

## Frequently Asked Questions

### What is the difference between the cubelet's global namespace and per-sandbox namespaces?

The **global mount namespace** (created by `newCubeMnt` at lines 61-71 of [`main.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/main.go)) isolates the cubelet daemon itself from the host's mount hierarchy. **Per-sandbox namespaces** are logical identifiers stored in request contexts that the runtime translates into actual Linux namespaces (PID, UTS, IPC, mount) for each individual sandbox. The global namespace protects the cubelet; the per-sandbox namespaces protect each workload from others.

### How does CubeSandbox ensure mount events from the host still propagate to sandboxes?

The `newCubeMnt` helper binds the mount-namespace directory to `/run/cube-containers/shared` with **rslave propagation**. This configuration allows mount events from the host's shared tree to propagate into the cubelet's private view, ensuring that new network storage mounts remain visible while the cubelet's own mount operations remain isolated.

### What happens if a sandbox context is missing the namespace identifier?

The `namespaces.NamespaceRequired(ctx)` function returns an error if the namespace is absent from the context. In [`Cubelet/storage/local.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/Cubelet/storage/local.go) line 666, this error propagates to `ret.Err(errorcode.ErrorCode_InvalidParamFormat, err.Error())`, causing the request to fail with an invalid parameter code. This strict validation prevents unnamespaced sandboxes from being created.

### Is network namespace handled differently from other namespaces?

Yes. While PID, UTS, IPC, and mount namespaces are managed through the `runc` runtime integration in [`Cubelet/services/cubebox/runc_container_op.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/Cubelet/services/cubebox/runc_container_op.go), the **network namespace** is implemented in the separate `Cubelet/network` package. This separation allows independent lifecycle management and custom CNI integration for network policies.