Linux enables us to run multiple processes simultaneously. However, sometimes we may want to isolate some processes from others. For instance, we could opt to run a web server in a separate environment from our desktop applications. Also, we may want to create a sandbox for experimenting with new software without affecting our system. One way to achieve this is by using namespaces.
Namespaces are a feature of the Linux kernel that enables us to create isolated environments for running processes. Each namespace has its own resources, such as process IDs, network interfaces, mount points, user IDs, and hostnames. Processes in different namespaces can’t see or affect each other’s resources unless they share a common namespace.
Notably, each type of namespace isolates a different aspect of the system. Mainly, seven types of namespaces are used in Linux:
- PID namespace
- network namespace
- IPC namespace
- mount namespace
- UTS namespace
- user namespace
- cgroup namespace
Further, namespaces have identifiers, i.e., inode numbers that uniquely identify each namespace on the system. Now, let’s discuss various tools and commands to determine the namespaces of a process in Linux.
3. Using the ps Command
The ps command is a common tool for displaying information about processes. One of the ps options is to show the namespace identifiers for each process.
3.1. Root Namespaces
To use this option, we specify which type of namespace we want to see:
$ ps -o pid,pidns,args PID PIDNS COMMAND 1 4026531836 /sbin/init splash 2 4026531836 [kthreadd] 3 4026531836 [rcu_gp] 4 4026531836 [rcu_par_gp] 6 4026531836 [kworker/0:0H-kblockd] 9 4026531836 [mm_percpu_wq] 10 4026531836 [ksoftirqd/0] 11 4026531836 [rcu_sched]
The -o option specifies the output format by choosing which columns to show for each process. The pidns value is one of the possible column names. It shows the PID namespace identifier for each process. Also, we can see that all current processes share the same PID namespace identifier (4026531836). Thus, this means that they belong to the same PID namespace.
Similarly, we can use the same option for other types of namespaces:
- netns – network namespace
- ipcns – IPC namespace
- mntns – mount namespace
- utsns – UTS namespace
- userns – user namespace
However, these namespaces are usually the root or default namespaces on the system.
3.2. New Namespaces
In addition to them, we can create a new PID namespace by using the unshare command:
$ sudo unshare --fork --pid --mount-proc bash
We can display the namespaces of a particular PID with the appropriate option:
# ps -o pid,pidns,netns,mntns,ipcns,utsns,userns,args -p 1 PID PIDNS NETNS MNTNS IPCNS UTSNS USERNS COMMAND 1 4026532718 4026531840 4026532699 4026531839 4026531838 4026531837 bash
Apparently, PID 1 belongs to six different namespaces:
We can also see their inode numbers and the command line arguments of the process.
Of course, if the PID doesn’t belong to any namespace, then the ps command won’t show any output in the respective columns:
# ps -o pid,pidns,netns,mntns,ipcns,utsns,userns,args -p 9999 PID PIDNS NETNS MNTNS IPCNS UTSNS USERNS COMMAND
We can see that there’s no output, so process 9999 doesn’t belong to any namespace.
4. The /proc/<PID>/ns Directory
Generally, the /proc/<PID>/ns directory contains symbolic links to the namespace files for each type of namespace that the process belongs to.
For instance, let’s use ls to check the namespaces of the process with PID 5151:
$ ls -l /proc/5151/ns total 0 lrwxrwxrwx 1 abdulhameed abdulhameed 0 Jul 26 06:48 cgroup -> 'cgroup:' lrwxrwxrwx 1 abdulhameed abdulhameed 0 Jul 26 06:55 ipc -> 'ipc:' lrwxrwxrwx 1 abdulhameed abdulhameed 0 Jul 26 06:55 mnt -> 'mnt:' lrwxrwxrwx 1 abdulhameed abdulhameed 0 Jul 26 06:55 net -> 'net:' lrwxrwxrwx 1 abdulhameed abdulhameed 0 Jul 26 06:55 pid -> 'pid:' lrwxrwxrwx 1 abdulhameed abdulhameed 0 Jul 26 07:36 pid_for_children -> 'pid:' lrwxrwxrwx 1 abdulhameed abdulhameed 0 Jul 26 07:32 time -> 'time:' lrwxrwxrwx 1 abdulhameed abdulhameed 0 Jul 26 07:36 time_for_children -> 'time:' lrwxrwxrwx 1 abdulhameed abdulhameed 0 Jul 26 06:55 user -> 'user:' lrwxrwxrwx 1 abdulhameed abdulhameed 0 Jul 26 06:55 uts -> 'uts:'
From the output above, we can see that each symbolic link has the format <type> -> ‘<type>:[<inode>]’. Firstly, <type> is the type of namespace, such as cgroup, ipc, mnt, net, pid, or user. Then, the <inode> is the inode number that uniquely identifies each namespace on the system.
Additionally, we can use these inode numbers to enter the namespaces of the process using the nsenter command:
$ sudo nsenter --net=/proc/5151/ns/net
Basically, we run a shell in the network namespace of the process with PID 5151. In this shell, we can use network commands and tools to inspect and modify the network configuration and communication of that namespace.
5. ip-netns Command
Firstly, we need to have a network namespace file in the /var/run/netns directory. This file can be created by using the ip-netns add command:
$ sudo ip netns add router
Thus, we create a network namespace file named router in the /var/run/netns directory.
Next, we can create a new named network namespace using the ip-netns attach command:
$ sudo ip netns attach router 350
If router is available in /var/run/netns, this command attaches the network namespace of process 350 to router as if it were created with ip-netns.
Of course, we can use ip-netns to find the namespace of a process:
$ sudo ip netns identify 5151
In this case, 5151 is the process ID to look up the namespaces of.
6. Using Python listns.v3.py
Alternatively, we can find the namespaces of a process with a Python script called listns.v3.py.
To use this script, we need to have Python installed on our system. Let’s verify using the python3 –version command:
$ python3 --version
If Python is installed, we’d see the version number. If not, the output shows an error message or a command to install Python using the system package manager.
After ensuring we have the interpreter available, we use wget to download the listns.v3.py from its GitHub repository:
$ wget https://raw.githubusercontent.com/Intika-Linux-Namespace/Namespace-Lister/master/listns.v3.py
Now, we can run the script with root access:
$ sudo python3 listns.v3.py PID Namespace Thread/Command 38 mnt: 312 uts: 312 mnt: 583 uts: 583 mnt: 585 mnt: 590 uts: 590 mnt: 684 net: 684 mnt: 693 mnt: 698 mnt: 705 mnt: 745 mnt: 749 uts: 749 mnt: 812 mnt: 880 mnt: 902 mnt:
Evidently, listns.v3.py lists all the namespaces on the system, along with their type and inode number.
$ sudo python3 listns.v3.py | grep 11861 11861 net: 11861 pid: 11861 pid:
Here, we see the namespaces associated with PID 11861.
7. Docker and Containerization
Docker is a popular and widely-used tool for creating and managing containers on Linux. In essence, containers provide isolated environments for running applications and services that don’t affect each other or the host system. Moreover, containers are based on namespaces and other features of the Linux kernel. Indeed, namespaces are of benefit to containers due to their similar characteristics:
At the core of Docker’s functionality lies the concept of namespaces. By using these namespaces, Docker ensures that each container operates independently, safeguarding against interference with other processes on the host machine.
When exploring namespaces to find the isolation boundaries of a process in Linux, the principles and mechanisms that Docker employs in containerization become greatly relevant. Understanding Docker’s implementation shows us how namespaces enable secure and isolated environments for running applications. This makes it a powerful tool for developers and system administrators alike.
Docker uses namespaces to limit resource usage and system calls of containers. At the same time, it provides a high-level and low-level interface for creating and managing containers and interacting with namespaces.
An example use case for this is to run multiple web servers on the same host, each in its own container with a different network namespace. This way, each web server can listen on port 80 without conflicting with each other. Also, they can be accessed by different IP addresses or hostnames.
In this article, we’ve learned what namespaces are, and why they are important for process isolation. Also, we explored various methods to find the namespaces of a process in Linux. Finally, we briefly discussed how namespaces are used in Docker and containerization technology.