1. 程式人生 > 實用技巧 >docker原理講解1-linux namespace

docker原理講解1-linux namespace

docker現在可以說是Paas界的幾大主流工具之一,它的大名可以說是無人不知無人不曉。為了更好的使用docker,我決定開個坑一步步的瞭解docker的內部原理,並利用golang開發一個簡易的docker程式。下面就讓我們開始進入正題。
docker是一個基於linux namespaceCgroups開發的虛擬容器工具。這裡有兩個關鍵詞,linux namespaceCgruops我們今天先來對linux namespace進行講解。

1. 什麼是linux namespace###

linux namespace是linux kernel提供的一個功能用來隔離核心資源。通過namespace使得不同namespace之間的程序相互隔離互相感知不到對方的存在,同一個namespace中間的程序只能看到與自己相關的資源,其他namespace裡程序使用的資源無法看到。namespace可以對一下六種資源進行隔離(六種linux namespace):

  • UTS(主機名)
  • PID(程序ID)
  • IPC(程序間通訊)
  • Mount(掛載點)
  • NetWork(網路)
  • User(使用者)

在linux的/proc/[程序號]/ns下列出可以看到對應程序號下這六種資源的namespace編號,不同程序的相同資源如果有相同的namespace編號則說明這兩個程序的該資源在同一個namespace下。例如:

程序2327和23301的六種資源的程序號都相等,說明這兩個程序的六種資源都各自在相同的namespace中。

linux namespace通過三種系統呼叫實現分別是:

  • clone()
    建立新程序。根據系統呼叫引數來判斷哪些型別的Namespace被建立,它們的紫禁城也會被包含到這些namespace中
  • setns()
    將程序加入到namespace中
  • unshare()
    將程序遷移出當前namespace並加入到新的namespace中

使用golang開發一個指令碼,該指令碼在linux中啟動一個新的程序,該程序的六種資源全部在新的namespace中,與父程序的namespace隔離。

package main

import {
        "fmt"
        "log"
        "os"
        "os/exec"
        "syscall"
}

func RunCmdWithNewNamespace(){
        cmd := exec.Command("sh")
        cmd.SysProcAttr = &syscall.SysProcAttr{
                Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS | syscall.CLONE_NEWUSER | syscall.CLONE_NEWNET,
        }
        cmd.SysProcAttr.Credential = &syscall.Credetial(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)
}

func main(){
        RunCmdWithNewNamespace()
}