项目说明

初始化目录

在开始做一个项目之前,先初始化一个go项目,并使用go module进行管理。

mkdir mydocker
cd mydocker
go mod init mydocker

Linux Namespace

Namespace是Kernel的一个功能,它可以隔离一系列的系统资源,比如PID、User ID、Network等。详细可以查看02-容器基础:隔离与限制

Namespace的API主要使用如下3个系统调用。

  • clone 创建新进程。根据系统调用参数来判断哪些类型的Namespace被创建,而且它们的子进程也会被包含到这些Namespace中。

  • unshare 将进程移出某个Namespace。

  • setns 将进程加入到Namespace中。

目前Linux一共实现了以下几种不同类型的NameSpace。

  • UTS Namespace:主要用来隔离nodename和daminname这两个系统标识。

  • IPC Namespace:主要用来隔离System V IPC和POSIX message queues。

  • PID NameSpace:主要用来隔离进程ID。

  • Mount NameSpace:主要用来隔离各个进程看到的挂载点视图。

  • User NameSpace:主要用来隔离用户和用户组ID。

  • Network NameSpace:用来隔离网络设备,IP地址端口等网络栈的NameSpace.

代码实现

// main
package main

import (
        ik "mydocker/inidk"
)

func main(){
        ik.NameSpaceInit()
}

// inidk/namespace.go 
package inidk

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

func NameSpaceInit(){
        cmd := exec.Command("/bin/bash", "-c", "mount --make-rprivate / && mount -t proc proc /proc && exec /bin/sh")
        cmd.SysProcAttr = &syscall.SysProcAttr{
                Cloneflags: syscall.CLONE_NEWUTS|syscall.CLONE_NEWIPC|syscall.CLONE_NEWPID|syscall.CLONE_NEWNS|syscall.CLONE_NEWUSER|syscall.CLONE_NEWNET,
                Pdeathsig: syscall.SIGKILL,
        }

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


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

查看共享挂载信息

[root@mydocker conf.d]# cat /proc/self/mountinfo |grep proc
19 40 0:3 / /proc rw,nosuid,nodev,noexec,relatime shared:5 - proc proc rw
44 19 0:37 / /proc/sys/fs/binfmt_misc rw,relatime shared:26 - autofs systemd-1 rw,fd=33,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=14204

Cgroup

最后更新于