Namespaces partition names and resource views that would otherwise be global. Each task has one namespace instance of each supported type, and tasks in the same instance observe the same instance-specific resources. Namespaces do not, by themselves, constrain CPU, memory, or I/O consumption; cgroups provide those resource controls.
Linux exposes eight namespace types. Time namespaces were added in Linux 5.6;
the other types predate that release. The namespace flags in
include/uapi/linux/sched.h
are the version-specific source of truth.
| Type | Creation flag | Isolated resource |
|---|---|---|
| Cgroup | CLONE_NEWCGROUP | Cgroup-root view |
| IPC | CLONE_NEWIPC | System V IPC objects and POSIX message queues |
| Network | CLONE_NEWNET | Network devices, protocol stacks, routing tables, firewall state, and port space |
| Mount | CLONE_NEWNS | Mount table and mount-propagation relationships |
| PID | CLONE_NEWPID | Process-ID number space and PID 1 semantics |
| Time | CLONE_NEWTIME | Offsets for monotonic and boot-time clocks |
| User | CLONE_NEWUSER | User and group ID mappings, credentials, and scoped capabilities |
| UTS | CLONE_NEWUTS | Hostname and NIS domain name |
The initial system starts with one instance of each type. Namespace identity is
not a portable, globally meaningful 32-bit ID. Instead, /proc/PID/ns exposes
namespace handles as symbolic links such as net:[4026531840]; the number
identifies that kernel object’s inode in the namespace filesystem.
ls -l /proc/self/ns
lsns
readlink /proc/self/ns/netCreating and Joining Namespaces #
clone(2) and clone3(2) create a child in new namespaces when passed one or
more CLONE_NEW* flags. unshare(2) makes the calling task use newly created
namespaces, subject to each namespace type’s rules. PID and time namespace
unsharing instead affects subsequently created children; the caller remains in
its current PID or time namespace. setns(2) joins a namespace referred to by
an open file descriptor. The unshare(1) and nsenter(1) tools are convenient
front ends for experiments and administration.
# New user, mount, and PID namespaces; the child becomes PID 1 in its PID namespace.
unshare --user --map-root-user --mount --pid --fork --mount-proc sh
# Join the mount namespace of an existing process.
sudo nsenter --target "$PID" --mount shNamespace operations are not interchangeable:
- A new PID namespace affects subsequently created children. A task cannot move
itself into another PID namespace;
setns()into one makes future children visible there. - A new mount namespace initially copies the caller’s mount table. Shared mount propagation can still transfer mounts across namespaces, so container setup commonly makes the relevant tree private or slave before mounting filesystems.
- Network namespaces begin with a loopback device that must be brought up. Moving a veth endpoint into the namespace is a common way to connect it.
- User-namespace creation has credential and mapping rules that differ from the
other namespace types. Do not assume that a successful
setns()grants host privileges.
The kernel checks capabilities in the relevant user namespaces and rejects unsafe transitions. Callers should use the syscall manual pages and the target kernel source for exact error conditions because they vary by namespace type and kernel release.
Handles and Lifetime #
/proc/PID/ns/<type> can be opened as a namespace file descriptor. The
namespace remains alive while tasks or namespace file descriptors refer to it.
A bind mount of such an entry also holds a reference, which lets a supervisor
retain a namespace after its last process exits:
sudo mkdir -p /run/netns/demo
sudo touch /run/netns/demo
sudo mount --bind /proc/"$PID"/ns/net /run/netns/demo
ip netns exec demo ip linkThe bind mount must be unmounted when no longer needed. Treat namespace handles
as authority-bearing objects: access to /proc/PID/ns is subject to /proc
visibility and ptrace-style access checks, and an inherited descriptor can allow
the recipient to call setns().
User Namespaces and ID Mappings #
A user namespace maps a contiguous range of IDs inside the namespace to IDs in
its parent user namespace. The creator can often obtain a namespace-local
effective UID 0 with --map-root-user, but that identity has no automatic
privilege over unmapped host IDs or global host resources.
For an unprivileged setup, a supervisor commonly writes uid_map, then writes
deny to setgroups, and then writes gid_map. The ordering prevents a process
from gaining group-based access through an unmapped group transition. Mapping
rules are intentionally restrictive; delegated ranges and the newuidmap and
newgidmap helpers handle mappings the caller cannot write directly.
Capabilities are evaluated relative to a user namespace. A process with
CAP_SYS_ADMIN in a child user namespace can perform operations governed by that
namespace, such as configuring its mount namespace, but it lacks that capability
in the initial user namespace. Kernel objects owned by an ancestor namespace,
device access, and LSM policy still form security boundaries.
Composition for Containers #
A container is a composition of isolation mechanisms rather than one namespace. One practical setup order is:
- Create a user namespace and install deliberate UID/GID mappings, because it supplies namespace-scoped capabilities for later setup.
- Create a mount namespace, change propagation deliberately, and construct the filesystem view.
- Create a PID namespace, fork the intended init process, and mount a new
/procfrom the mount namespace so process reporting matches the PID view. - Create or join network, IPC, UTS, time, and cgroup namespaces as required; configure network links from a privileged host-side manager.
- Place the workload in a host-managed cgroup before execution and retain namespace file descriptors for inspection and teardown.
PID 1 deserves explicit handling because it reaps orphaned children and has special signal behavior. A minimal container command that merely creates a PID namespace can therefore leave zombies or ignore termination signals; a runtime needs an init/reaper or equivalent supervision.
Mount namespaces control filesystem mount visibility, whereas chroot(2) only
changes pathname resolution. Combining both with careful mount propagation is
necessary to avoid exposing or receiving unintended mounts.
Cgroups and Cgroup Namespaces #
A cgroup namespace virtualizes the path to a task’s cgroup root. It changes what
the task reads from /proc/PID/cgroup and from a cgroup filesystem mounted in
that namespace, which prevents an inner workload from discovering ancestor
paths. It does not create an independent cgroup hierarchy and does not weaken
host CPU, memory, I/O, or PID limits.
For a complete namespace ABI description, consult the relevant
namespaces(7) manual page
alongside the target release’s
kernel source.
Comments
Read or comment on GitHub (sign-in required to comment)