Overview of linux namespace

What is the namespace of linux

About the linux namespace, Official documents Here's what it says:

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.
One use of namespaces is to implement containers.

The following is a simple translation:
namespace is an abstraction of system resources: it can make the process look like it has independent resources
You can use namespace technology to implement containers

Summary: namespace can isolate the resources used by the process and can be used as a container

What namespace s are there?

Or reference: https://man7.org/linux/man-pages/man7/namespaces.7.html , list two tables:

nameView locationSupported versionsexplain
cgroup/proc/[pid]/ns/cgroupsince Linux 4.6Control the resources used by the process,
(e.g. limit maximum memory usage)
IPC/proc/[pid]/ns/ipcsince Linux 3.0Isolate interprocess communication
Mount/proc/[pid]/ns/mntsince Linux 3.8Make each process seem to have its own file system,
A bit like chroot()
Network/proc/[pid]/ns/netsince Linux 3.0Processes can have independent cyberspace
PID/proc/[pid]/ns/cgroupsince Linux 3.8Isolation pid
USER/proc/[pid]/ns/cgroupsince Linux 3.8Isolate users
UTS(UNIX Time-Sharing)/proc/[pid]/ns/cgroupsince Linux 3.0Isolate nodename, hostname

In addition to those listed above, Official documents It also gives: pid_for_children, time, etc. students who are interested can learn by themselves

Give an example to illustrate the role of namespace

There are many namespaces listed above. In fact, there are some system calls or commands about the namespace. Give a few examples to intuitively feel it and learn what the use of the namespace is?

This is mainly demonstrated by the command: unshare. The man document of unshare makes it very clear:

unshare - run program with some namespaces unshared from parent

In fact, you can guess from the name, UN share, which probably means not sharing, that is, monopolizing and isolating

Here are some examples:

Isolation PID

$ unshare --fork --pid --mount-proc /bin/bash
$ ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 20:22 pts/0    00:00:00 /bin/bash
root        19     1  0 20:22 pts/0    00:00:00 ps -ef
$

It is found that the PID of bash process in the current namespace is 1, and there is no other process information, indicating that the PID of the current namespace and the operating system has been isolated
This has the advantage that if you want to do any experiment, you can easily view the process through PID namespace without being disturbed by other processes

Quarantine hostname

$ hostname # Check the host name first
myvm
$ unshare --fork --uts /bin/bash # Isolate uts namespace
$ hostname # Check the hostname and find that it inherits the hostname of the system
myvm
$ hostname -b test # Modify the hostname in the current namespace
$ hostname
test # Check again and find that the hostname in the current namespace has been modified
# $ exit # At this time, use exit to exit the current namespace or open another shell to check the hostname of the system and find that it is still the original myvm
# exit
$ hostname
myvm

An example of UTS namespace written in C language (from man clone)

#define _GNU_SOURCE
#include <sys/wait.h>
#include <sys/utsname.h>
#include <sched.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \
                                            } while (0)

/* Start function for cloned child */
static int childFunc(void *arg)
{
    struct utsname uts;

    /* Change hostname in UTS namespace of child */
    if (sethostname(arg, strlen(arg)) == -1)
            errExit("sethostname");

    /* Retrieve and display hostname */
    if (uname(&uts) == -1)
            errExit("uname");
    printf("uts.nodename in child:  %s\n", uts.nodename);

    /* Keep the namespace open for a while, by sleeping.
           This allows some experimentation--for example, another
           process might join the namespace. */

    sleep(200);

    return 0;           /* Child terminates now */
}

#define STACK_SIZE (1024 * 1024)    /* Stack size for cloned child */

int main(int argc, char *argv[])
{
    char *stack;                    /* Start of stack buffer */
    char *stackTop;                 /* End of stack buffer */
    pid_t pid;
    struct utsname uts;

    if (argc < 2) {
            fprintf(stderr, "Usage: %s <child-hostname>\n", argv[0]);
            exit(EXIT_SUCCESS);
    }

    /* Allocate stack for child */

    stack = malloc(STACK_SIZE);
    if (stack == NULL)
            errExit("malloc");
    stackTop = stack + STACK_SIZE;  /* Assume stack grows downward */

    /* Create child that has its own UTS namespace;
           child commences execution in childFunc() */
    // Note the third parameter
    pid = clone(childFunc, stackTop, CLONE_NEWUTS | SIGCHLD, argv[1]);
    if (pid == -1)
            errExit("clone");
    printf("clone() returned %ld\n", (long) pid);

    /* Parent falls through to here */
    sleep(1);           /* Give child time to change its hostname */

    /* Display hostname in parent's UTS namespace. This will be
           different from hostname in child's UTS namespace. */

    if (uname(&uts) == -1)
            errExit("uname");
    printf("uts.nodename in parent: %s\n", uts.nodename);

    if (waitpid(pid, NULL, 0) == -1)    /* Wait for child */
            errExit("waitpid");
    printf("child has terminated\n");

    exit(EXIT_SUCCESS);
}

Run verification:

$ gcc main.c
$ ./a.out xx
clone() returned 22122
uts.nodename in child:  xx # Indicates that the hostname has been quarantined
uts.nodename in parent: myvm
^C
$ 

Examples of UTS namespace written in go language

main.go:

package main

import (
	"log"
	"os"
	"os/exec"
	"syscall"
)

func main() {
	cmd := exec.Command("sh")

	cmd.SysProcAttr = &syscall.SysProcAttr{
		Cloneflags: syscall.CLONE_NEWUTS, // In fact, it is the flags parameter of the clone() system call
	}

	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	if err := cmd.Run(); err != nil {
		log.Fatal(err)
	}
}

Run verification:

$ go run main.go # After running this sentence, UTS namespace has taken effect
$ hostname
myvm
$ hostname -b xx
$ hostname
xx
$ exit
exit
$ hostname
myvm
$ 

summary

namespace is one of the core technologies to implement container. The bottom layer needs to call clone system functions

reference resources

(end)

Keywords: Linux Operation & Maintenance server

Added by daveh33 on Sun, 30 Jan 2022 23:05:55 +0200