docker原理講解1-linux namespace
阿新 • • 發佈:2020-08-16
docker現在可以說是Paas界的幾大主流工具之一,它的大名可以說是無人不知無人不曉。為了更好的使用docker,我決定開個坑一步步的瞭解docker的內部原理,並利用golang開發一個簡易的docker程式。下面就讓我們開始進入正題。
docker是一個基於linux namespace和Cgroups開發的虛擬容器工具。這裡有兩個關鍵詞,linux namespace和Cgruops我們今天先來對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() }