Linux Namespace Learning Tutorial (1) UTS

[Editor's Note] The problem with the Docker core is to use LXC to implement VM-like functionality, thus using more cost-effective hardware resources to provide users with more computing resources. The LXC implementation of the isolation is mainly from the kernel's namespace, where pid, net, ipc, mnt, uts and other namespace will be the container process, network, message, file system and hostname isolation. This is the first part of the Linux Namespace Series tutorial, which introduces Linux containers and UTS namespaces through a simple example. DockerOne in the line code on the basis of proofreading and finishing.

When I worked at OVH , I had added security for a "upcoming" product, which required Linux namespace (Linux namespace). In the learning process I found that Linux's namespace is very powerful, but this document is very small

Most people should have heard of LXC – LinuX Containers , which is an enhanced version of Chroot. Simply put, LXC is to isolate the different applications, which is somewhat similar to chroot, chroot is to isolate the application to a virtual private root, and LXC on this step further. LXC internally relies on the Linux kernel's three isolated infrastructure:

  1. Chroot
  2. Cgroups
  3. Namespaces

I could have named this series "how to build your own LXC" to win a higher ranking in Google, but it might seem too arrogant to do so. In fact, LXC is far more isolated than it does, and it also includes template management, freezing, and more. This series will unlock the mystery of LXC for you.

In this series, we will use the simplest C program to start / bin / bash, and gradually add a variety of isolation mechanism for it.

Okay, let's get started now.

Interestingly, Linux container tools do not provide a black box-like mysterious container solution, but to provide separate isolation building (isolation building block), collectively known as Namespaces. Each new version will have a new component released. So that you can follow the specific application of your situation, select the required components.

Linux 3.12 kernel support 6 Namespace:

  1. UTS: hostname (described in this article)
  2. IPC: interprocess communication (the article will be mentioned later)
  3. PID: "chroot" process tree (the article will be mentioned later)
  4. NS: mount point, the first landing Linux (the article will be mentioned later)
  5. NET: network access, including interfaces (later articles will talk)
  6. USER: the local virtual user-id mapping to the real user-id (the article will be mentioned later)

The following is a complete skeleton of a program that is used to start the / bin / bash program from the child process (in order to keep the example simple, so the error check is removed):
main-0-template.c

Define _GNU_SOURCE

Include <sys / types.h>

Include <sys / wait.h>

Include <stdio.h>

Include <sched.h>

Include <signal.h>

Include <unistd.h>

Define STACK_SIZE (1024 * 1024)

Static char child_stack [STACK_SIZE];
Char * const child_args [] = {
"/ Bin / bash",
NULL
};

Int child_main (void * arg) {
Printf ("- world! \ N");
Execv (child_args [0], child_args);
Printf ("Ooops \ n");
Return 1;
}

Int main () {
Printf ("- Hello? \ N");
Int child_pid = clone (child_main, child_stack + STACK_SIZE, SIGCHLD, NULL);
Waitpid (child_pid, NULL, 0);
Return 0;
}

Please note that here we are using clone instead of fork system calls. This is where magic (coming) takes place.

  Jean-tiare @ jeantiare-Ubuntu: ~ / blog $ gcc -Wall main.c -o ns && ./ns 
- Hello?
- World!
Jean-tiare @ jeantiare-Ubuntu: ~ / blog $ # inside the container
Jean-tiare @ jeantiare-Ubuntu: ~ / blog $ exit
Jean-tiare @ jeantiare-Ubuntu: ~ / blog $ # outside the container

OK, handsome. However, if there is no comment, it is difficult to notice that we are in the child process / bin / bash. In fact, when I write this article, several times accidentally quit the parent process of the shell.

Now do some changes, such as directly modify the host name (the hostname with 0% env vars tricks), is not it will be Niubi? Just use Namespace? Very simple, we just want:

  1. Use the CLONE_NEWUTS flag in the clone system call
  2. Call sethostname in child process

main-1-uts.c

  // (needs root privileges (or appropriate capabilities)) 
// [...]
Int child_main (void * arg) {
Printf ("- world! \ N");
Sethostname ("In Namespace", 12);
Execv (child_args [0], child_args);
Printf ("Ooops \ n");
Return 1;
}

Int main () {
Printf ("- Hello? \ N");
Int child_pid = clone (child_main, child_stack + STACK_SIZE,
CLONE_NEWUTS | SIGCHLD, NULL);
Waitpid (child_pid, NULL, 0);
Return 0;
}

Run:

  Jean-tiare @ jeantiare-Ubuntu: ~ / blog $ gcc -Wall main.c -o ns && sudo ./ns 
- Hello?
- World!
Root @ In Namespace: ~ / blog $ # inside the container
Root @ In Namespace: ~ / blog $ exit
Jean-tiare @ jeantiare-Ubuntu: ~ / blog $ # outside the container

Thing is like this (at least in this article is the case)! Namespace really too TM easy to get started: clone , set a specific CLONE_NEW* logo, set the new env, get!

Do you want to go deeper? Interested in reading excellent lWN article series on namespaces .

Source: Introduction to Linux namespaces – Part 1: UTS (translation: Sun Ke review: Li Yingjie)

—————————————–
Linux Namespace Learning Tutorial (1) UTS
Linux Namespace Learning Tutorial (2) IPC
Linux Namespace Learning Tutorial (3) PID
Linux namespace learning tutorial (d) NS (FS)
Linux Namespace Learning Tutorial (5) NET

Heads up! This alert needs your attention, but it's not super important.