資源隔離之 Linux namespace__Linux

來源:互聯網
上載者:User
Linux namespace 簡稱 ns,在 2002 年 2.4.19 核心中被引入,發展到今天已經有 15 個年頭了。

2010 年後國內雲端運算爆發,緊接著 2013 年 Docker 崛起,ns 才作為不可或缺的一部分被重視起來。

ns 本身其實比較簡單,它是 Linux 核心的一種機制,給進程隔離和虛擬化核心資源用的。

不同的進程是共用核心資源的。好比說大家住在同一個小區,雖然到家後關起門來誰都不影響誰。但公用場所就沒辦法了,如果有人破壞環境,那麼勢必會影響到其他人。

核心資源在這裡就像是公用場所。ns 就是把公用場所隔離開來,你扔煙頭到地上隻影響你自己,其他人都看不到。這裡的隔離不是說把公用場所分成幾塊兒,每個人分一小塊兒,而是每個人都有一個和原來一樣大的公用場所,就像是每個人都有一個四維空間一樣,是不是有點玄乎啊。不要緊,下面會結合幾個小例子來說明一下 :D。

目前有七種 ns 類型:

Linux 初始化的時候為 init 進程(進程號為1)為每個 ns 類型建立一個執行個體。後面其他所有進程都可以建立新的 ns 或者加入已有的 ns。

這些 ns 執行個體在 /proc/[pid]/ns 下面,比如說 1 號進程的 ns:
Mount ns 隔離的是掛載點掛載的是檔案系統。子進程建立時(clone 時使用 CLONE_NEWNS),父進程 ns 下的所有掛載點都拷貝到子進程中,Mount ns 隔離之後,Mount Point 的建立或刪除都不會在 ns 之間傳播(除非 mount 時使用了shared subtree) ,媽媽在也不用擔心我的掛載了呢。

使用 Docker 啟動一個 Container,可以查看它的掛載,有很多和 Container 所在的 Host 的不一樣,因為它內部做了新的掛載,比如說 aufs 掛載到了根目錄 / 下面:
還有 PID ns,分屬不同 ns 的進程下可以有相同的 PID,比如說 Host 中 PID 為 1 的進程是 init,而 Container 內 PID 為 1 的進程是 bash(Docker 啟動指定的命令)。
其他幾個 ns 類型,可以參考 namespaces(7) - Linux manual page 。

我之前很好奇怎麼查看在 Linux 一共有多少 ns 執行個體,所以就寫了個簡單 Python 指令碼 https://gist.github.com/wanzixyz/53333b15d9290dd971527d61c4ee9f0c :
#!/usr/bin/env python#coding=utf-8import osimport re#format: pid, [namespaces], cmdlinedef _get_namespace(pid):    path = '/proc/{0}/ns/'.format(pid)    namespaces = []    for ns in os.listdir(path):        namespaces.append(os.readlink(path + ns))    cmdline = open('/proc/{0}/cmdline'.format(pid)).read()    if not cmdline:        cmdline = open('/proc/{0}/comm'.format(pid)).read()    return (pid, namespaces, cmdline)SBIN_INIT = _get_namespace(1)OUTPUT = [SBIN_INIT]for pid in [elt for elt in os.listdir('/proc/') if re.match('\d+', elt)]:    output = _get_namespace(pid)    if output[1] != SBIN_INIT[1]:        OUTPUT.append(output)for val in OUTPUT:    print '{0:>10}    {1}    {2}'.format(        val[0],        ' '.join(val[1]),        ' '.join(val[2].split('\x00'))[:-1]    )

運行後結果如下:
1 是 init 進程,21 是 kdevtmosfs,15320 和 29739 都是 Docker 啟動的 Container。

之後我又很好奇,如何才能進入到 Container(其實不算是進入,只是加入 Container 的 ns,看到和 Container 一樣的視圖),於是就又寫了一個指令碼 https://gist.github.com/wanzixyz/8dd24aa8882bb983873274a221934cbc :
#!/usr/bin/env python#coding=utf-8import argparseimport ctypesimport osCLONE_NEWNS =        0x00020000# /* New mount namespace group */CLONE_NEWCGROUP =    0x02000000# /* New cgroup namespace */CLONE_NEWUTS =       0x04000000# /* New utsname namespace */CLONE_NEWIPC =       0x08000000# /* New ipc namespace */CLONE_NEWUSER =      0x10000000# /* New user namespace */CLONE_NEWPID =       0x20000000# /* New pid namespace */CLONE_NEWNET =       0x40000000# /* New network namespace */parser = argparse.ArgumentParser()parser.add_argument('--pid', type = str, help = 'process id')args = parser.parse_args()if not args.pid:    print 'plz input pid..'    exit(1)#setnslibc = ctypes.CDLL('libc.so.6')namespace = [    ('ipc', CLONE_NEWIPC),    ('uts', CLONE_NEWUTS),    ('net', CLONE_NEWNET),    ('pid', CLONE_NEWPID),    ('mnt', CLONE_NEWNS),]for ns_type, ns_flag in namespace:    fd = os.open('/proc/{0}/ns/{1}'.format(args.pid, ns_type), os.O_RDONLY)    ret = libc.setns(fd, ns_flag)    os.close(fd)    if ret 
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.