容器与Linux Namespace

1,078 阅读2分钟

 Linux Namespace可以隔离一系列的系统资源,如一下6种不同类型的Namespace:


1.Network Namespace

用来隔离网络设备,IP地址端口等网络栈的Namespace,让每个容器拥有自己独立的(虚拟的)网络设备,而且容器内的应用可以绑定到自己的端口,每个Namespace内的端口都不会冲突.在宿主机上搭建网桥后,能很方面地实现容器之间的通信.

可以使用命令ifconfig,在宿主机查看网络设备,运行最下方例子后,再次运行ifconfig会发现网络设备不同.


2.UTS Namespace

用来隔离nodename和domainname两个系统标识.在UTS Namespace里面,每个Namespace允许有自己的hostname.

可以使用命令pstree -pl查看系统中进程之间的关系

通过命令redlink   /proc/19912/ns/uts               

        redlink /proc/19912/ns/uts

验证一下父进程和子进程是否不再同一个UTS Namespace里面


在不同的UTS Namespace通过命令hostname -b xxxxhostname 绑定一个hostname,并在宿主机(另一个UTS Namespace)上运行hostname,可以看到宿主机的hostname不受绑定影响.


3.IPC Namespace

用来隔离System V和POSIX message queues.

通过命令ipcmk -Q创建一个message queue.查看命令ipcs -q来验证


4.PID Namespace

用来隔离进程ID.同样一个进程在不同的PID Namespace里可以拥有不同的PID.

通过命令pstree -pl查看进程树,ps -ef查看进程来验证


5.Mount Namespace

用来隔离各个进程看到的挂载点视图.在不同Namespace的进程中,看到的文件系统层次是不一样的.在Mout Namespace中调用mount()和umount()仅仅只会影响当前Namespace内的文件系统,而对全局的文件系统是没有影响的.

通过查看文件内容来验证:

ls /proc

mount -t proc poc /proc

ls /proc


6.User Namespace

用来隔离用户的用户组ID.也就是说,一个进程的User ID和Group ID在User Namespace内外是不同的.通常是让一个用户在自己的User Namespace拥有自己的root权限,但对外没有root权限.


go代码例子:

package main

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

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

    cmd.SysProcAttr = &syscall.SysProcAttr{
        Clonefalgs: syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWPID|
           syscall.CLONE_NEWNS | syscall.CLONE_NEWUSER | syscall.CLONE_NEWNET,
    }

    cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(1),Gid: uint32(1)}
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr  if err := cmd.Run(); err != nil{
      log.Fatal(err)
  }    os.Exit(-1)
}


参考自<自己动手写Docker>