Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
9 views

Understanding Linux Namespaces

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views

Understanding Linux Namespaces

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 15

Understanding Linux Namespaces

The Bored Dev


·

Feb 21

In this article we will explain what Linux namespaces are and how do we take

advantage of them in our software systems nowadays.

Let’s start!

What Is a Namespace?

A Linux namespace is a feature that Linux kernel provides to allow us to isolate

resources for a set of processes. In some way, they are a sort of implementation of the

bulkhead pattern we frequently see in microservices architectures.

What are the main advantages in the use of namespaces? The main advantages are

two:

•Isolation of resources

One troublesome process won’t be taking down the whole host, it’ll only affect

those processes belonging to a particular namespace.

•Security

The other advantage is that a security flaw in the process or processes running

under a given namespace, won’t give access to the attacked to the whole system.

Whatever he/she could do, will always be contained within the boundaries of that

namespace! This is why it’s also very important to avoid running our processes

using privileged users whenever possible.


Namespaces and Containers

Nowadays, containers make extensive use of Linux namespaces to be able to group

processes and provide resource isolation for them. Some of the most popular and

user-friendly container engines at the moment are Docker or Podman.

Namespaces (and therefore containers) are something unique to the Linux

kernel. You might be wondering, how is possible that we can run Docker or Podman in

our Mac (OSX) or Windows machines then?

Well, the answer is simple: Both Docker and Podman run a virtual machine in your

local machine (OSx or Windows) to be able to make use of namespaces and any other

kernel features required to run containers.

For example, we are running Podman in our local machine, in order to make it work we

had to initialise and start a podman machine first by running the following:
$ podman machine init

$ podman machine start

This initialises and starts a virtual machine in your local machine, which runs a linux

operating system. How can we get the details about this machine to make sure that it’s

actually a virtual machine? We can get this information by running this command:

$ podman machine inspect

This will inspect the default machine we have currently running in podman. The output

will be something similar to this:


[
{
"ConfigPath": {
"Path":
"/Users/theboreddev/.config/containers/podman/machine/qemu/podman-machine-
default.json"
},
"ConnectionInfo": {
"PodmanSocket": {
"Path":
"/Users/theboreddev/.local/share/containers/podman/machine/podman-machine-
default/podman.sock"
}
},
"Created": "2023-02-12T07:50:02.100074Z",
"Image": {
"IgnitionFilePath": {
"Path":
"/Users/theboreddev/.config/containers/podman/machine/qemu/podman-machine-
default.ign"
},
"ImageStream": "testing",
"ImagePath": {
"Path":
"/Users/theboreddev/.local/share/containers/podman/machine/qemu/podman-
machine-default_fedora-coreos-37.20230205.2.0-qemu.aarch64.qcow2"
}
},
"LastUp": "2023-02-12T07:50:02.100074Z",
"Name": "podman-machine-default",
"Resources": {
"CPUs": 1,
"DiskSize": 100,
"Memory": 2048
},
"SSHConfig": {
"IdentityPath": "/Users/theboreddev/.ssh/podman-machine-
default",
"Port": 56324,
"RemoteUsername": "xxxx"
},
"State": "running"
}
]
You can see above how Podman uses QEMU to run a virtual machine, using an image

which runs Fedora Core OS as the operating system. If you want to run a different

Linux version, our article “Run Ubuntu on Max Using QEMU” might be useful.

The way it works in Docker is very similar to what Podman does, although Docker uses

VirtualBox instead. This is the default virtual machine that comes with Docker Desktop,

but there are other alternatives like colima for example.

Now that we know what a Linux namespace is, you could be thinking: How can I create

a new namespace?

Let’s see how!

How to Use Namespaces

In order to create a namespace in Linux, we have to use the unshare command to

run a process in a new namespace.


If we consult unshare command's help section, the first we can see is something like

this:

$ unshare --help

Usage:

unshare [options] [<program> [<argument>...]]

Run a program with some namespaces unshared from the parent.

Options:

-m, --mount[=<file>] unshare mounts namespace

-u, --uts[=<file>] unshare UTS namespace (hostname


etc)

-i, --ipc[=<file>] unshare System V IPC namespace

-n, --net[=<file>] unshare network namespace


-p, --pid[=<file>] unshare pid namespace

-U, --user[=<file>] unshare user namespace

-C, --cgroup[=<file>] unshare cgroup namespace

-T, --time[=<file>] unshare time namespaceshel

You can see how most of the first few options allow us to specify different types of

namespaces, these are the different types of namespaces we have in Linux systems.

We will see cgroups in more detail in a future article, as it takes a very important role

in the containers world.

Types of Namespaces

Each type of namespace is different and it provides isolation for different resources in

our system.

If we check the namespaces in the Linux manual pages, we can see a list of namespace

types:

Namespace Flag Page Isolates

Cgroup CLONE_NEWCGROUP cgroup_namespaces(7) Cgroup root


directory

IPC CLONE_NEWIPC ipc_namespaces(7) System V IPC,

POSIX message

queues

Network CLONE_NEWNET network_namespaces(7) Network

devices,

stacks, ports,

etc.

Mount CLONE_NEWNS mount_namespaces(7) Mount points

PID CLONE_NEWPID pid_namespaces(7) Process IDs

Time CLONE_NEWTIME time_namespaces(7) Boot and

monotonic
CLONE_NEWUSER user_namespaces(7) User and group

IDs

UTS CLONE_NEWUTS uts_namespaces(7) Hostname and

NIS domain

name
clocks

User CLONE_NEWUSER user_namespaces(7) User and group

IDs

UTS CLONE_NEWUTS uts_namespaces(7) Hostname and

NIS domain

name

We won’t get into too much detail, but you can clearly see how every namespace will

isolate a different resource in our system. Therefore, we can see briefly what the

different types of namespaces in a Linux system are:


•User namespace

Contains an independent set of user IDs and group IDs that can be assigned to

processes.

•PID namespace

Contains its own set of process IDs (PIDs). Every time we create a new namespace,

the process will get assigned PID 1. Every child process created in the new

namespace will be assigned subsequent IDs.

•Mount namespace

They allow the management of mount points in our system. Doing unmount in our

new namespace won’t have any effect on the main host, as every new mount will

be private to the current namespace.

•Network namespace

Virtualises the network stack for the new namespace. This means that the new

namespace will have its own virtual interface/s, private IPs, IP route table, sockets,

etc.

•IPC (Inter-Process Communication) namespace

Allows defining shared memory segments between processes within a namespace

for inter-process communications, not interfering with other namespaces.

•UTS (Unix Time-Sharing) namespace


Allows our system to have different host names and domain names for each

namespace.

•Time namespace

This namespace was released quite recently in Linux (2020), it allows having

different system times within our system by specifying different time namespaces.

•CGroup (Control Groups) namespace

Introduced in 2016 as part of Linux release 4.6, limits the resource usage in our

system (cpu, memory, disk, etc) for a particular group of processes (under this

namespace). As we will see in future articles, this is a very important feature of

Linux Kernel in the containerised world we now live in!


Now that we have gone through all the existing types of namespaces in Linux, we’re

going to show a simple example to understand the power that namespaces bring to

us.

Let’s run the following command:

$ unshare --user --pid --map-root-user --mount-proc --fork


bash

What exactly are we doing here? What are we telling the Kernel to do? Let’s go step by

step to try to understand what we are doing.

If we check each of these options in the manual here, we can see each of these options

tell the Kernel to do the following:

•— user: Create a new user namespace.

•— pid: Create a new pid namespace. (Will fail if — fork is not specified)

•— map-root-user: Wait to start the process until the current user (running

unshare command) gets mapped to the superuser in the new namespace. This

allows having root privileges within the namespace, but not outside of that scope.

•— mount-proc: Mount /proc filesystem in the new namespace and create a new

mount, this is to be able to have different processes with same process IDs in both

namespaces.

•— fork: Run command as a child process of the unshare command, instead of

running it directly. It's required when creating a new PID namespace.

Let’s see what this implies. First of all, if we list the processes in the new namespace,

we only see the new processes running in the new namespace and not the processes

running in the host’s default namespace:


$ ps -ef

PID USER TIME COMMAND

1 root 0:00 /bin/bash

2 root 0:00 ps -ef

This is because we’ve used both --pid and –fork options.

You will also notice that our processes are running as root within the new

namespace, this is what the –map—root-user does. The current user is root within

this namespace only, this use won't be able to do any harm to any of the external

namespaces! This is great, right?

Lastly, we can see how the IDs of the processes are 1 and 2, this is because we create a

new /proc mount for our namespace using --mount-proc.

Is that clear? We hope so!

It’s also worth mentioning that the unshare command we just ran is equivalent to the

following command using a docker/podman client:

docker exec -it myImage /bin/bash

This will be very familiar to those used to work with containers, as this is normally used

to gain access through a terminal inside the container. Now that we’ve mentioned

containers, let’s see what the namespaces role is inside of Linux containers.
Namespaces Role in Containers

Namespaces have been available in the Linux kernel since 2002, however, the use of

them was restricted to those with a very advanced knowledge of Linux systems. Linux

namespaces and containers were made “popular” by Docker, when it made possible a

wide adoption of containers across the sector for anyone with a minimum (or zero)

understanding of Linux Kernel internals.

The use of namespaces is not transparent to the users, and that’s probably why most

users don’t understand containers in they way they actually are.

There’s a considerable number of people in the sector that see containers as some sort

of virtual machine that does not contain the kernel, but shares it with the host instead.

This is a wrong understanding of what a container is, we’ll see why very soon.

Containers create an illusion that could make you think that you’re actually running a

virtual machine on your host, but this is far from the truth. When you run a virtual

machine on your host , you are actually booting a new OS distribution on your
machine, with the difference being that this OS will make calls to a middleware

provided by the virtualisation engine you use (Virtual Box, QEMU, etc).

This middleware translates every kernel call inside your virtual machine to a system call

that your host can understand. This is what mades possible, for example, to run

different operating systems like Windows on a unix system!

On the other hand, a Linux container makes use of Linux namespaces to provide this

illusion of running a different operating system. When we create an image based a any

known Linux distribution, we are actually mounting its filesystem, giving us the

impression of being on a new operating system. But actually we’re just inside of a new

namespace!
Conclusion

In this article we have seen what Linux namespaces are and the very important role

they play in distributed systems nowadays. We’ve also tried to clarify one of the biggest

misconceptions around Linux containers with regards to Linux namespaces and virtual

machines.

We really hope that every concept is now clearer to you. If you are still confused and

this is unclear, don’t worry, this can happen. Just re-read these concepts and eventually

you will get the point of Linux namespaces.

That’s all from us today! We really hope you’ve enjoyed reading this article as much as

we enjoyed writing it!

Thanks for reading us!

You might also like