LINUXOR.SK ... open source notes ...

2016 - Linux Namespaces - Introduction

category: howtoz · date: 2016-11-01 · updated: 2017-01-14

The Slovak original of this document: 2016 - Linux Namespaces - Úvod (slovensky).

An introduction to Linux namespaces

1 The basic concepts of Linux namespaces

Namespaces in Linux exist to separate running programs from one another. That separation lets a program see the system, and the system's resources, differently from the rest. Namespaces can be put to many uses, but chiefly found in the implementation of container technology. The first namespaces (MNT) went into the kernel as long ago as 2002; the newest addition, in 2016, is the one for control groups (CGROUP). Seven namespaces are implemented in the Linux kernel today.

asciiart
+-----------+------------------+---------+-------+-----------------------+-------------------------------------+
| Namespace | Clone Flag       | Kernel  | Year  | Required capabilities | Isolates                            |
|           |                  |         |       |                       |                                     |
+-----------+------------------+---------+-------+-----------------------+-------------------------------------+
| MNT       | CLONE_NEWNS      | 2.4.19  | 2002  | CAP_SYS_ADMIN         | Mount points                        |
| UTS       | CLONE_NEWUTS     | 2.6.19  | 2006  | CAP_SYS_ADMIN         | Hostname and NIS domain name        |
| PID       | CLONE_NEWPID     | 2.6.24  | 2008  | CAP_SYS_ADMIN         | Process IDs                         |
| NET       | CLONE_NEWNET     | 2.6.29  | 2009  | CAP_SYS_ADMIN         | Network devices, stacks, ports, ... |
| IPC       | CLONE_NEWIPC     | 2.6.30  | 2009  | CAP_SYS_ADMIN         | System V IPC, POSIX message queues  |
| USER      | CLONE_NEWUSER    | 3.8     | 2013  | Not required          | User and group IDs                  |
| CGROUP    | CLONE_NEWCGROUP  | 4.6     | 2016  | CAP_SYS_ADMIN         | Cgroup root directory               |
+-----------+------------------+---------+-------+-----------------------+-------------------------------------+

The namespaces that have been considered but not yet implemented are: \- Security namespace \- Security keys namespace \- Device namespace \- Time namespace

REF: 2006 - Multiple Instances of the Global Linux Namespaces

1.1 What each namespace is and what it is for

Isolates the mount points a process, or a group of processes, can see, so programs in different MNT namespaces can have different views of the filesystem hierarchy. It is much like the isolation "chroot()" gives, except that an MNT namespace should be the safer and more flexible choice for the purpose.

Isolates two system identifiers: the node name (host name) and the domain name, both returned by the "uname()" system call.

Isolates process identifiers. Programs in different PID namespaces can hold the same PID.

Isolates the network resources. Each network namespace has its own devices, addresses, routing tables, port numbers and its own "/proc/net" directory.

Isolates IPC resources: System V IPC objects and POSIX message queues. Each IPC namespace has its own set of System V IPC identifiers and its own set of POSIX message queues.

Isolates user (UID) and group (GID) identifiers, so they can differ inside the namespace and outside it: one set of UIDs and GIDs applies within, another without.

Isolates the control groups a program belongs to. Each CGROUP namespace has its own cgroup root directory.

1.2 The namespace API

The namespace API is three system calls:

Creates a new process in a new namespace. It is the more general form of the "fork()" system call, with the "flags" argument deciding what it does.

Creates a new namespace without creating a new process, moving the existing program into it. Its purpose is to let a program control what it shares without having to fork.

Changes the namespace a program belongs to. In other words, this system call lets a program be dissociated from one instance of a given type of namespace — an MNT namespace, say — and re-associated with another instance of the same type: a "move" from MNT namespace X to MNT namespace Y.

2 Working with Linux namespaces - the default namespaces

Check which namespaces the Linux INIT process (init or systemd) belongs to. These are the default namespaces. Every process uses them; see the SSHD example below, which have no namespaces of their own.

asciiart
# ls -lh /proc/1/ns/
----------------------------------------------------------------------------------------------------------------
lrwxrwxrwx. 1 root root 0 Nov  8 09:54 ipc -> ipc:[4026531839]
lrwxrwxrwx. 1 root root 0 Nov  8 09:54 mnt -> mnt:[4026531840]
lrwxrwxrwx. 1 root root 0 Nov  8 09:54 net -> net:[4026531956]
lrwxrwxrwx. 1 root root 0 Nov  8 09:54 pid -> pid:[4026531836]
lrwxrwxrwx. 1 root root 0 Nov  8 09:54 user -> user:[4026531837]
lrwxrwxrwx. 1 root root 0 Nov  8 09:54 uts -> uts:[4026531838]

Check which namespaces the Linux SSHD process ($SSHD_PID) belongs to. Find the PID of sshd and list the namespaces it belongs to.

asciiart
# SSHD_PID=`ps xa | grep -m 1 /usr/sbin/sshd | awk '{print $1}'`; ls -lh /proc/$SSHD_PID/ns/
----------------------------------------------------------------------------------------------------------------
lrwxrwxrwx. 1 root root 0 Nov  8 10:04 ipc -> ipc:[4026531839]
lrwxrwxrwx. 1 root root 0 Nov  8 10:04 mnt -> mnt:[4026531840]
lrwxrwxrwx. 1 root root 0 Nov  8 10:04 net -> net:[4026531956]
lrwxrwxrwx. 1 root root 0 Nov  8 10:04 pid -> pid:[4026531836]
lrwxrwxrwx. 1 root root 0 Nov  8 10:04 user -> user:[4026531837]
lrwxrwxrwx. 1 root root 0 Nov  8 10:04 uts -> uts:[4026531838]

3 Introducing the "namespaces-info.sh" script

While reading about namespaces I wrote a small tool for the BASH shell called "namespaces-info.sh". It prints the basic facts about the namespaces on a system. The script itself is on GitHub -> github - bash-namespaces-info

The syntax of "bash-namespaces-info.sh" is:

asciiart
-d      List the system/default (parent) namespaces
-a      List every namespace of every process (PIDs)
-n      List the non-system/non-default namespaces of every process (PIDs)
-p PID  List the namespaces of one process (PID)
-v      Print the version of the script

Running "namespaces-info.sh" with "-d".

asciiart
# /root/namespaces-info.sh -d
--------------- + --------------------------
Linux Namespace | System default namespaces
--------------- + --------------------------
IPC  namespace  | ipc:[4026531839]
MNT  namespace  | mnt:[4026531840]
NET  namespace  | net:[4026531956]
PID  namespace  | pid:[4026531836]
USER namespace  | user:[4026531837]
UTS  namespace  | uts:[4026531838]
--------------- + --------------------------

Running "namespaces-info.sh" with "-a".

asciiart
# /root/namespaces-info.sh -a
---------- + ---------- + -------------------- + -------- + ----------------------------------------
PID        | PPID       | NAMESPACE            | DEFAULT  | COMMAND
---------- + ---------- + -------------------- + -------- + ----------------------------------------
1          |      0     | ipc:[4026531839]     | YES      | /usr/lib/systemd/systemd --switched-root
1          |      0     | mnt:[4026531840]     | YES      | /usr/lib/systemd/systemd --switched-root
1          |      0     | net:[4026531956]     | YES      | /usr/lib/systemd/systemd --switched-root
1          |      0     | pid:[4026531836]     | YES      | /usr/lib/systemd/systemd --switched-root
1          |      0     | user:[4026531837]    | YES      | /usr/lib/systemd/systemd --switched-root
1          |      0     | uts:[4026531838]     | YES      | /usr/lib/systemd/systemd --switched-root
---------- + ---------- + -------------------- + -------- + ----------------------------------------
2          |      0     | ipc:[4026531839]     | YES      | [kthreadd]
2          |      0     | mnt:[4026531840]     | YES      | [kthreadd]
2          |      0     | net:[4026531956]     | YES      | [kthreadd]
2          |      0     | pid:[4026531836]     | YES      | [kthreadd]
2          |      0     | user:[4026531837]    | YES      | [kthreadd]
2          |      0     | uts:[4026531838]     | YES      | [kthreadd]
---------- + ---------- + -------------------- + -------- + ----------------------------------------

Running "namespaces-info.sh" with "-n".

asciiart
# /root/namespaces-info.sh -n
---------- + ---------- + -------------------- + -------- + ----------------------------------------
PID        | PPID       | NAMESPACE            | DEFAULT  | COMMAND
---------- + ---------- + -------------------- + -------- + ----------------------------------------
18         |      2     | mnt:[4026531856]     | NO       | [kdevtmpfs]
---------- + ---------- + -------------------- + -------- + ----------------------------------------
582        |      1     | mnt:[4026532423]     | NO       | /usr/lib/systemd/systemd-udevd
---------- + ---------- + -------------------- + -------- + ----------------------------------------
718        |      1     | mnt:[4026532450]     | NO       | /usr/bin/vmtoolsd
---------- + ---------- + -------------------- + -------- + ----------------------------------------
750        |      1     | mnt:[4026532451]     | NO       | /usr/sbin/NetworkManager --no-daemon
---------- + ---------- + -------------------- + -------- + ----------------------------------------
9870       |    750     | mnt:[4026532451]     | NO       | /sbin/dhclient -d -q -sf /usr/libexec/nm
---------- + ---------- + -------------------- + -------- + ----------------------------------------
72966      |   9926     | mnt:[4026532578]     | NO       | bash
72966      |   9926     | net:[4026532452]     | NO       | bash
---------- + ---------- + -------------------- + -------- + ----------------------------------------
72975      |   9945     | mnt:[4026532579]     | NO       | bash
72975      |   9945     | net:[4026532510]     | NO       | bash
---------- + ---------- + -------------------- + -------- + ----------------------------------------

Running "namespaces-info.sh" with "-p".

asciiart
# /root/lh-ns.sh -p 72975
---------- + ---------- + -------------------- + -------- + ----------------------------------------
PID        | PPID       | NAMESPACE            | DEFAULT  | COMMAND
---------- + ---------- + -------------------- + -------- + ----------------------------------------
72975      |   9945     | ipc:[4026531839]     | YES      | bash
72975      |   9945     | mnt:[4026532579]     | NO       | bash
72975      |   9945     | net:[4026532510]     | NO       | bash
72975      |   9945     | pid:[4026531836]     | YES      | bash
72975      |   9945     | user:[4026531837]    | YES      | bash
72975      |   9945     | uts:[4026531838]     | YES      | bash
---------- + ---------- + -------------------- + -------- + ----------------------------------------
← howtoz(EN | SK)