Docker原理之namespace烫止、cgroup

Docker是一個使用了Linux NamespaceCgroups的虛擬化工具
Linux Namespace是Kernel的一個功能,可以隔離一系列系統(tǒng)資源(PIDUID话侧、Network),幫助進程隔離出自己的單獨的空間闯参。
Cgroups限制一組進程及將來子進程的資源的大小瞻鹏,保證不會相互爭搶悲立,這些資源包括CPU、內(nèi)存新博、存儲薪夕、網(wǎng)絡等,并進行監(jiān)控和統(tǒng)計信息赫悄。

Namespace

  • Namespace類型及系統(tǒng)調(diào)用參數(shù):

?Namespace類型?????????????系統(tǒng)調(diào)用參數(shù)
Mount Namespace?????????CLONE_NEWNS
?UTS Namespace??????????CLONE_NEWUTS
?IPC Namespace????????????CLONE_NEWIPC
?PID Namespace????????????CLONE_NEWPID
Network Namespace??????CLONE_NEWNET
?User Namespace??????????CLONE_NEWUSER

Namespace的API主要有三個系統(tǒng)調(diào)用:
clone()創(chuàng)建新進程
unshare()將進程移除某個Namespace
setns()將進程加入到某個Namespace

  • UTS Namespace
    UTS Namespace主要來隔離nodenamedomainname兩個系統(tǒng)標識寥殖。在UTS Namespace里面,每個Namespace有自己的hostname涩蜘。
    Go實現(xiàn)代碼:
package main

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

func main(){
    cmd := exec.Command("bash")
    cmd.SysProcAttr = &syscall.SysProcAttr{
        Cloneflags:syscall.CLONE_NEWUTS,
    }
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

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

exec.Command("bash")用來制定被fork出來的新進程內(nèi)的初始命令嚼贡,默認用bash來執(zhí)行。

驗證UTS隔離:

[jin1ming@ML ~]$ echo $$
5576
[ML myDockerLite]# echo $$
5780
$ readlink /proc/5780/ns/uts 
uts:[4026532587]
$ readlink /proc/5576/ns/uts 
uts:[4026531838]
[ML myDockerLite]# hostname dockelite
[ML myDockerLite]# hostname
dockelite
[jin1ming@ML ~]$ hostname
ML
  • IPC Namespace
    IPC Namespace用來隔離System V IPCPOSIX message queue同诫。
    略微修改一下代碼:
package main

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

func main(){
    cmd := exec.Command("bash")
    cmd.SysProcAttr = &syscall.SysProcAttr{
        Cloneflags:syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC,
    }
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

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

驗證 IPC 隔離:

[jin1ming@ML ~]$ ipcs

--------- 消息隊列 -----------
鍵        msqid      擁有者  權限     已用字節(jié)數(shù) 消息      

------------ 共享內(nèi)存段 --------------
鍵        shmid      擁有者  權限     字節(jié)     連接數(shù)  狀態(tài)      
0x512c001f 131072     jin1ming   600        33024      1                       
0x00000000 1441793    jin1ming   600        16777216   2          目標       
0x00000000 327682     jin1ming   600        524288     2          目標       
0x00000000 1769475    jin1ming   600        22528      2          目標       
0x00000000 1474564    jin1ming   700        16472      2          目標       
0x00000000 1638405    jin1ming   700        130544     2          目標       

--------- 信號量數(shù)組 -----------
鍵        semid      擁有者  權限     nsems     
0x512c001e 32768      jin1ming   600        1         
[ML myDockerLite]# ipcs

--------- 消息隊列 -----------
鍵        msqid      擁有者  權限     已用字節(jié)數(shù) 消息      

------------ 共享內(nèi)存段 --------------
鍵        shmid      擁有者  權限     字節(jié)     連接數(shù)  狀態(tài)      

--------- 信號量數(shù)組 -----------
鍵        semid      擁有者  權限     nsems     
  • PID Namespace
    PID Namespace用來隔離進程ID粤策,同一個進程在不同的PID Namespace有不同的PID
    略微修改代碼:
package main

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

func main(){
    cmd := exec.Command("bash")
    cmd.SysProcAttr = &syscall.SysProcAttr{
        Cloneflags:syscall.CLONE_NEWUTS | 
            syscall.CLONE_NEWIPC | 
            syscall.CLONE_NEWPID,
    }
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

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

驗證PID隔離:

[ML linux_shell]# cat testgo.sh 
#!/bin/bash

echo PID:$$
read input
echo $input

1.未進行隔離時:

[ML linux_shell]# ./testgo.sh 
PID:14141
[jin1ming@ML linux_shell]$ pgrep -f testgo
14141

2.進行隔離時:

[ML linux_shell]# ./testgo.sh 
PID:7
$ pgrep -f testgo
14586
  • Mount Namespace
    Mount Namespace 用來隔離各個進程看到的掛載點視圖误窖。在不同的Namespace中看到的文件系統(tǒng)層次是不一樣的叮盘。在Mount Namespace中調(diào)用mount()umount()僅僅只會影響到當前Namespace內(nèi)的文件系統(tǒng),而對全局的文件系統(tǒng)是沒有影響的霹俺。
    略微修改代碼:
package main

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

func main(){
    cmd := exec.Command("bash")
    cmd.SysProcAttr = &syscall.SysProcAttr{
        Cloneflags:syscall.CLONE_NEWUTS |
            syscall.CLONE_NEWIPC |
            syscall.CLONE_NEWPID |
            syscall.CLONE_NEWNS,
    }
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

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

驗證Mount Namespace 隔離:

[ML myDockerLite]# mount -t proc proc /proc
[ML myDockerLite]# ls /proc
1          crypto       ioports        loadavg       schedstat      timer_list
7          devices      irq            locks         scsi           tty
acpi       diskstats    kallsyms       meminfo       self           uptime
asound     dma          kcore          misc          slabinfo       version
buddyinfo  driver       keys           modules       softirqs       vmallocinfo
bus        execdomains  key-users      mounts        stat           vmstat
cgroups    fb           kmsg           mtrr          swaps          zoneinfo
cmdline    filesystems  kpagecgroup    net           sys
config.gz  fs           kpagecount     pagetypeinfo  sysrq-trigger
consoles   interrupts   kpageflags     partitions    sysvipc
cpuinfo    iomem        latency_stats  sched_debug   thread-self
[ML myDockerLite]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 10:56 pts/2    00:00:00 bash
root         8     1  0 10:58 pts/2    00:00:00 ps -ef
[jin1ming@ML ~]$ ls /proc
1      1176   1382   16675  247   479   613   80    962          kmsg
10     1177   1386   16765  25    48    615   81    963          kpagecgroup
1000   1184   139    16770  2552  484   62    810   9659         kpagecount
10075  1185   1395   16776  26    488   63    815   982          kpageflags
1021   1188   14     1724   269   489   637   8175  987          latency_stats
1027   1189   140    1781   27    49    639   82    989          loadavg
1029   1195   14001  18     275   493   64    824   993          locks
10459  1197   14004  1800   28    496   65    826   994          meminfo
#........此處省略一部分
[jin1ming@ML ~]$ ps -ef
Error, do this: mount -t proc proc /proc
  • User Namespace
    User Namespace 主要是隔離用戶的用戶組ID柔吼。一個進程的User IDGroup ID在User Namespace內(nèi)外可以是不同的。
    對代碼略作修改:
package main

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

func main(){
    cmd := exec.Command("bash")
    cmd.SysProcAttr = &syscall.SysProcAttr{
        Cloneflags:syscall.CLONE_NEWUTS |
            syscall.CLONE_NEWIPC |
            syscall.CLONE_NEWPID |
            syscall.CLONE_NEWNS |
            syscall.CLONE_NEWUSER,
    }

    cmd.SysProcAttr.Credential = &syscall.Credential{
        Uid:0,
        Gid:0,
    }
//此處代表root

    cmd.SysProcAttr.UidMappings = []syscall.SysProcIDMap{{ContainerID: 0, HostID: 1001, Size: 1}}
    cmd.SysProcAttr.GidMappings = []syscall.SysProcIDMap{{ContainerID: 0, HostID: 1001, Size: 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)
}

驗證User Namespace隔離:

[ML home]# id
uid=0(root) gid=0(root) 組=0(root),65534(nobody)
[ML home]# cd jin1ming/
bash: cd: jin1ming/: 權限不夠

如果具有真正的root權限將可以訪問

  • Network Namespace
    Network Namespace 是用來隔離網(wǎng)絡設備丙唧、IP地址端口等網(wǎng)絡棧的Namespace愈魏。Network Namespace可以讓每個容器擁有自己獨立的網(wǎng)絡設備(虛擬的),而且容器內(nèi)的應用可以綁定到自己的端口想际,每個Namespace內(nèi)的端口都不會沖突培漏。
    略微修改代碼:
package main

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

func main(){
    cmd := exec.Command("bash")
    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.Credential{
        Uid:0,
        Gid:0,
    }

    cmd.SysProcAttr.UidMappings = []syscall.SysProcIDMap{{ContainerID: 0, HostID: 1001, Size: 1}}
    cmd.SysProcAttr.GidMappings = []syscall.SysProcIDMap{{ContainerID: 0, HostID: 1001, Size: 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)
}

驗證Network隔離:

[jin1ming@ML ~]$ ifstat 
#kernel
Interface        RX Pkts/Rate    TX Pkts/Rate    RX Data/Rate    TX Data/Rate  
                 RX Errs/Drop    TX Errs/Drop    RX Over/Rate    TX Coll/Rate  
lo                    48 0            48 0          4072 0          4072 0      
                       0 0             0 0             0 0             0 0      
enp1s0                 0 0             0 0             0 0             0 0      
                       0 0             0 0             0 0             0 0      
wlp2s0             11052 0          9055 0        11277K 0         2388K 0      
                       0 0             0 0             0 0             0 0     
[ML myDockerLite]# ifstat 
#kernel
Interface        RX Pkts/Rate    TX Pkts/Rate    RX Data/Rate    TX Data/Rate  
                 RX Errs/Drop    TX Errs/Drop    RX Over/Rate    TX Coll/Rate  

Linux Cgroups

Cgroups中的3個組件

  • cgroup 是對進程分組管理的一種機制,一個cgroup包含一組進程胡本,并可以在這個cgroup上增加Linux subsystem的各種參數(shù)配置牌柄,將一組進程和一組subsystem的系統(tǒng)參數(shù)關聯(lián)起來。
  • subsystem是一組資源控制的模塊侧甫,一般包含如下幾項:
    blkio設置對塊設備(比如硬盤)輸入輸出的訪問控制珊佣。
    cpu設置cgroup中進程的CPU被調(diào)度的策略。
    cpuacct可以統(tǒng)計cgroup中進程的cpu占用披粟。
    cpuset在多核機器上設置cgroup中的進程可以使用的CPU內(nèi)存(此處內(nèi)存僅使用于NUMA架構)
    devices 控制cgroup中進程對設備的訪問
    freezer 用于掛起(suspends)恢復(resumes) cgroup中的進程
    memory 用于控制cgroup中進程的內(nèi)存占用
    net_cls用于將cgroup中進程產(chǎn)生的網(wǎng)絡包分類(classify)咒锻,以便Linux的tc(traffic controller)可以根據(jù)分類(classid)區(qū)分出來自某個cgroup的包并做限流監(jiān)控
    net_prio 設置cgroup中進程產(chǎn)生的網(wǎng)絡流量的優(yōu)先級
    ns 這個subsystem比較特殊僻爽,它的作用是cgroup中進程在新的namespacefork新進程(NEWNS)時虫碉,創(chuàng)建出一個新的cgroup,這個cgroup包含新的namespace中進程胸梆。
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末敦捧,一起剝皮案震驚了整個濱河市须板,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌兢卵,老刑警劉巖习瑰,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異秽荤,居然都是意外死亡甜奄,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門窃款,熙熙樓的掌柜王于貴愁眉苦臉地迎上來课兄,“玉大人,你說我怎么就攤上這事晨继⊙滩” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵紊扬,是天一觀的道長蜒茄。 經(jīng)常有香客問我,道長餐屎,這世上最難降的妖魔是什么檀葛? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮腹缩,結果婚禮上屿聋,老公的妹妹穿的比我還像新娘。我一直安慰自己庆聘,他們只是感情好胜臊,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布勺卢。 她就那樣靜靜地躺著伙判,像睡著了一般。 火紅的嫁衣襯著肌膚如雪黑忱。 梳的紋絲不亂的頭發(fā)上宴抚,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天,我揣著相機與錄音甫煞,去河邊找鬼菇曲。 笑死,一個胖子當著我的面吹牛抚吠,可吹牛的內(nèi)容都是我干的常潮。 我是一名探鬼主播,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼楷力,長吁一口氣:“原來是場噩夢啊……” “哼喊式!你這毒婦竟也來了孵户?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤岔留,失蹤者是張志新(化名)和其女友劉穎夏哭,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體献联,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡竖配,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了里逆。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片进胯。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖原押,靈堂內(nèi)的尸體忽然破棺而出龄减,到底是詐尸還是另有隱情,我是刑警寧澤班眯,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布希停,位于F島的核電站,受9級特大地震影響署隘,放射性物質(zhì)發(fā)生泄漏宠能。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一磁餐、第九天 我趴在偏房一處隱蔽的房頂上張望违崇。 院中可真熱鬧,春花似錦诊霹、人聲如沸羞延。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伴箩。三九已至,卻和暖如春鄙漏,著一層夾襖步出監(jiān)牢的瞬間嗤谚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工怔蚌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留巩步,地道東北人。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓桦踊,卻偏偏與公主長得像椅野,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 寫這個系列文章主要是對之前做項目用到的docker相關技術做一些總結竟闪,包括docker基礎技術Linux命名空間声离,...
    __七把刀__閱讀 5,804評論 0 16
  • Docker容器技術已經(jīng)發(fā)展了好些年,在很多項目都有應用瘫怜,線上運行也很穩(wěn)定术徊。整理了部分Docker的學習筆記以及新...
    __七把刀__閱讀 11,450評論 0 58
  • 轉載自 http://blog.opskumu.com/docker.html 一、Docker 簡介 Docke...
    極客圈閱讀 10,501評論 0 120
  • 之前認為不會有什么原因能讓自己停止看書和寫作鲸湃,現(xiàn)在好不容易將家人搬到一起赠涮,離工作很近,居然停止了一些學習方面的好習...
    做個思行者閱讀 338評論 2 0
  • 憶古 點滴陰翠滿中庭暗挑, 庭中隱約離人影笋除。 落落紫帳淚痕濕, 淡淡案臺火獨紅炸裆。
    張白鷴閱讀 256評論 0 14