Linux namespace in Go - Part 1, UTS and PID
This article starts some Golang experiments on Linux namespace and provides context for Container technology. Linux namespace is an important foundation of container technology, it provides lightweight isolation between processes with Linux kernel support, therefore, different services can share the same machine with better resource utilization, great security.
The series of Linux namespace in Go:
- Linux namespace in Go - Part 1, UTS and PID
- Linux namespace in Go - Part 2, UID and Mount
- Linux namespace in Go - Part 3, Cgroups resource limit
There’s a definition from Linux manual introducing Linux namespace:
A namespace wraps a global system resource in an abstraction that makes it appear to the processes within the namespace that they have their own isolated instance of the global resource. Changes to the global resource are visible to other processes that are members of the namespace, but are invisible to other processes.
So, Linux namespace is the key that we can control the resources the processes can access.
What kind of isolation could we control is decided by the namespace types.
Hostname and NIS domain name
Controls the system resources (like CPU, Memory…) the process can use.
POSIX message queues
Network devices, stacks, ports, etc.
Boot and monotonic clocks
User and group IDs
Note that Linux namespace is only available in Linux distributions, I use Ubuntu 20.04 and Golang 1.14.2 here to run the experiments. If you’re using other OS, you might find the Linux namespace libraries missing, go and find a Linux machine and Ubuntu is recommended.
Note: The experiments code can be found in https://github.com/songrgg/namespace-demo
UTS will isolate the hostname for the forked process from its caller.
// folder v1
This script needs
sudo permission, run
sudo go run main.go and it will create a new bash process with a new UTS namespace, you could modify hostname within this namespace and it won’t change the outside’s hostname.
[sojiang@ namespace-demo]$ hostname
PID namespace would create a new namespace for the process where the process ID is the same as the parent process, but note that you can only operate the processes under your namespace and can’t operate the processes in the parent namespace, in the opposite, the parent namespace has permission to operate the processes under the child namespaces.
Create a PID namespace simply by adding a
Run the process again,
[sojiang@ namespace-demo]$ sudo go run exercise02/main.go
ps -ef output, we could see
zsh which runs in the parent namespace and
go run exercise02/main.go is running in the process’s namespace. We call the parent namespace
P and the child namespace
C, if we run
sleep 100 in
ps -ef to get the process id and run
kill -9 <process-id> in
C, it will output “process not exist”. In the opposite, we could kill the process in
C, that’s because the process visibility is in a single direction, only parent namespace could see all the processes in both
Like the following picture, pid 1 is in the parent namespace of pid Namespace x, so pid 1 could see all the processes, pid 3 could only see pid 3, pid 5 and pid 5.
Here I did experiments on Linux UTS and PID namespaces, we know the isolation mechanism of them. I still have several questions,
- How to run the program as other user instead of root?
- I can still see the process list by
ps -efin the child namespace, however, most of the processes are in the parent namespace, there’s no need for me to see them, how to hide them or have my own process list?
The answer is in the Linux namespace in Go - Part 2, UID and Mount.