亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 6148 | 回復(fù): 4
打印 上一主題 下一主題

操作系統(tǒng)虛擬化底層基礎(chǔ)之命名空間(namespace) [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2011-03-16 19:28 |只看該作者 |倒序瀏覽
操作系統(tǒng)虛擬化底層基礎(chǔ)之命名空間(namespace).pdf (427.95 KB, 下載次數(shù): 294)

操作系統(tǒng)虛擬化底層基礎(chǔ)之命名空間(namespace)

黎潤(yijunzhu@qq.com)


背景
隨著公司業(yè)務(wù)的迅猛發(fā)展,大量的機(jī)器在線上業(yè)務(wù)號召下投入了服務(wù)于廣大網(wǎng)民的神圣職責(zé)。不過基于一個不完全統(tǒng)計,我們公司的線上機(jī)器平均利用率20%左右,這就意味著70%左右的機(jī)器都是可回收或者復(fù)用的。

出于節(jié)約機(jī)器,統(tǒng)一管理以及在線遷移的初衷,我們進(jìn)行了虛擬化計算的研究。經(jīng)過選型測試以及具體應(yīng)用場景的研究,我們選擇了操作系統(tǒng)虛擬化技術(shù),即LXC。(為什么選擇LXC,OpenVZ如何? Xen效果如何等等這些問題請參考其他文檔,本文主要討論LXC的底層實現(xiàn)技術(shù))。LXC本身不是一個具體的技術(shù),它是一個集合技術(shù)的代稱,我們可以總體上來看,LXC主要有namespace和cgroup兩大模塊構(gòu)建而成,本系列主要就是說說這兩個技術(shù),本文則專注于namespace。

在我們講述具體的技術(shù)之前,先來看看容器模塊的整個狀態(tài)系統(tǒng),目前主要是IBM,google等公司的團(tuán)隊在負(fù)責(zé)維護(hù)更新。



目前container已經(jīng)被上有內(nèi)核所接納,所以不存在自己維護(hù)分支版本的問題。但是這些團(tuán)隊之間合作不是我們想象的和諧,不同利益集團(tuán)之間是有內(nèi)核的政治訴求,都想把自家的內(nèi)容扶位正房,導(dǎo)致我們再看操作系統(tǒng)虛擬化的時候會有不同項目博弈的事跡。


總覽
每一個進(jìn)程其所包含的命名空間都被抽象層一個nsproxy指針,共享同一個命名空間的進(jìn)程指向同一個指針,指針的結(jié)構(gòu)通過引用計數(shù)(count)來確定使用者數(shù)目。當(dāng)一個進(jìn)程其所處的用戶空間發(fā)生變化的時候就發(fā)生分裂。通過復(fù)制一份老的命名空間數(shù)據(jù)結(jié)構(gòu),然后做一些簡單的修改,接著賦值給相應(yīng)的進(jìn)程。


看了上面的數(shù)據(jù)結(jié)構(gòu),我們就會基本明白,命名空間本身只是一個框架,需要其他實行虛擬化的子系統(tǒng)實現(xiàn)自己的命名空間。這些子系統(tǒng)的對象就不再是全局維護(hù)的一份結(jié)構(gòu)了,而是和進(jìn)程的用戶空間數(shù)目一致,每一個命名空間都會有對象的一個具體實例。目前Linux系統(tǒng)實現(xiàn)的命名空間子系統(tǒng)主要有UTS、IPC、MNT、PID以及NET網(wǎng)絡(luò)子模塊。我們在下文會針對這些子模塊進(jìn)行進(jìn)一步的分析。
UTS命名空間子模塊
UTS相對而言是一個簡單的扁平化命名空間子模塊,其不同的命名空間之間沒有層次關(guān)系。我們先來看一下UTS的數(shù)據(jù)結(jié)構(gòu)。

New_utename結(jié)構(gòu)里面就是我們通過uname –a能夠看到的信息?匆幌聶C(jī)器上的輸出:

我通過紅色斜線把uname –a的輸出分隔開,分別對應(yīng)上面的new_utsname的結(jié)構(gòu)體。另外內(nèi)核還把這些信息也通過proc文件系統(tǒng)導(dǎo)出,我們可以通過/proc/sys/kernel目錄里面的如下等變量(Ostype/ hostname/osrelease/ version)查看,當(dāng)然這些變量的值也是可以更改的。
初始的時候,系統(tǒng)默認(rèn)構(gòu)造了一個UTS結(jié)構(gòu),他的值分別如下所述。

        當(dāng)一個新的命名空間創(chuàng)建的時候,copy_utsname會被調(diào)用來創(chuàng)建一個UTS的命名空間,主要工作在clone_uts_ns函數(shù)里面完成。

上面講述了UTS的代碼表示,我們再來只管看一下UTS Namespace和Kref配合使用的場景。

  上述順序描述了ustname在容器里面的局部化以及和引用計數(shù)配合完成的對象生命周期管理。
IPC命名空間子模塊
IPC作為一個常見的進(jìn)程間通信工具,命名空間對他也進(jìn)行了部分支持。另外IPC也是一個較為簡單的扁平化進(jìn)程間通信工具,命名空間之間不存在層級。

上面羅列的主要是IPC 命名空間里面包含的元素,各個命名空間之間的關(guān)系是并列的。





我們直觀的給一個圖描述資源隔離使用概念圖。

屬于不同命名空間的進(jìn)程之間是不能訪問對方的全局資源的,這兒展示的主要是IPC的SHM,MSG以及SEM,在較新的代碼里MQueue也可以被隔離。
MNT命名空間子模塊
        虛擬機(jī)的一個核心功能就是完成應(yīng)用的隔離,即業(yè)務(wù)之間相互不可見。這一塊主要通過文件系統(tǒng)的視圖來完成,進(jìn)程創(chuàng)建的時候,每一個進(jìn)程都有自己的文件掛節(jié)點信息?匆幌陆(jīng)典的struct task_struct.
在一個系統(tǒng)啟動的時候,0號進(jìn)程就設(shè)置好了自己所在的根目錄以及當(dāng)前目錄。在創(chuàng)建子進(jìn)程的時候,通過CLONE_FS來指明父子之間的共享信息,如果設(shè)置了兩者共享同一個結(jié)構(gòu)(指針加上引用計數(shù)),沒有設(shè)置標(biāo)記的話,子進(jìn)程創(chuàng)建一個新的拷貝,兩者之間互不影響。如果設(shè)置了CLONE_FS,接下來通過chroot(2), chdir(2), or umask(2)的調(diào)用結(jié)果兩者之間會相互影響,反之兩者是獨立的。
        下面這張圖清晰明了的刻畫了進(jìn)程內(nèi)部的文件系統(tǒng)信息以及文件描述符的位置,同時還可以看到一個文件的主要組成部分。

通過文字以及代碼描述還是比較枯燥而且不方便直觀,下面我們通過圖形的方式來看一下進(jìn)程的文件系統(tǒng)映射情況。

最初我們在系統(tǒng)(system)目錄里面創(chuàng)建了一個container目錄,然后在這個目錄里面為每一個虛擬機(jī)創(chuàng)建了獨立的目錄,例如1和2(本例)。在目錄1和2里面分別創(chuàng)建相應(yīng)虛擬機(jī)的根目錄文件系統(tǒng)。這樣虛擬機(jī)啟動的時候,我們chroot到1或者2里面,看到的文件系統(tǒng)試圖就如下所示。

在這種使用方式下,虛擬機(jī)1和虛擬機(jī)2之間的文件系統(tǒng)是互不可見的,而且虛擬機(jī)也看不到除了根目錄之外的其他文件目錄。為了和系統(tǒng)或者其他虛擬機(jī)部分共享文件,我們可以映射特定目錄到虛擬機(jī)的根文件系統(tǒng),達(dá)到部分隔離以及共享的效果,下圖。

PID命名空間子模塊
        PID是虛擬化命名空間里面較復(fù)雜的模塊,因為前面的命名空間基本都是扁平的,沒有層次結(jié)構(gòu)。但是PID命名空間是有層次的,在高層次命名空間能夠看到所有的低層次命名空間信息,反之則不行。
        先直觀來看看層次化的命名空間結(jié)構(gòu)以及進(jìn)程的數(shù)字變化。需要指出的是,對于命名空間里面的進(jìn)程,我們看到好像有多個,其實是一一對應(yīng)的,即進(jìn)程只有一個,但是在不同的命名空間里面有不同的數(shù)據(jù)表示,獲取一個進(jìn)程信息需要進(jìn)程號加上空間信息才能唯一確定一個進(jìn)程。

看完了PID命名空間的組織后,我們來看看他的代碼實現(xiàn)。
struct pid_namespace {
        struct kref kref;
        struct pidmap pidmap[PIDMAP_ENTRIES];
        int last_pid;
        struct task_struct *child_reaper;
        struct kmem_cache *pid_cachep;
        unsigned int level;
        struct pid_namespace *parent;
    ……
};
上圖里面重要的一些字段通過紅色標(biāo)注了出來,child_reaper指向的進(jìn)程作用相當(dāng)于全局命名空間的init進(jìn)程,其中一個目的是對孤兒進(jìn)程進(jìn)行回收。Level則表明自己所處的命名空間在系統(tǒng)命名空間里面的深度,這是一個重要的標(biāo)記,因為層次高的命名空間可以看到低級別的所有信息。系統(tǒng)的命名空間從0開始技術(shù),然后累加。命名空間的層次結(jié)構(gòu)通過parent來關(guān)聯(lián)。
了解完P(guān)ID命名空間的信息后,我們再來看看PID為了支持命名空間所需要做的修改。以前的PID命名空間是全局唯一的,現(xiàn)在則必須是命名空間局部化,有一個可見的命名空間就必須有一個PID變量。
        來看看PID的內(nèi)核表示,系統(tǒng)對于每一個PID都有一個PID結(jié)構(gòu)體來表示,但是在每一個命名空間里面的upid表示具體的數(shù)值。         上面的PID就是我們在系統(tǒng)中內(nèi)核的表示,一個PID可能對應(yīng)多個task_struct,所以在上面的表示里面通過一個task數(shù)組來表示。接著numbers數(shù)字分別表示在不同命名空間里面可以看到的pid數(shù)值,因為numbers在最后一個位置,所有本質(zhì)上來說相當(dāng)于一個指針,增加命名空間的時候,再增加一個numbers即可。

        上述的upid則是具體的命名空間內(nèi)數(shù)值表示,nr表示數(shù)字,ns則指向關(guān)聯(lián)的命名空間。當(dāng)然系統(tǒng)的所有upid通過pid_chain掛在同一個全局鏈表里。


這張表格和上圖一起結(jié)合起來我們理解PID的管理結(jié)構(gòu)。一個task_struct通過pid_link的hlist_node掛接到struct pid的鏈表上面去。同時task_struct又是用過pid_link找到pid,通過pid遍歷tasks鏈表又能夠得到所有的任務(wù),當(dāng)然也可以讀取numbers數(shù)字獲取每一個命名空間里面的數(shù)字信息。
為了在pid和upid之間轉(zhuǎn)換,系統(tǒng)提供了很多內(nèi)部轉(zhuǎn)換接口,我們首先來了解一些基本指導(dǎo)性原則。
..._nr()
通過nr結(jié)尾的函數(shù)就是獲取以前所謂的全局PID,這個全局PID和我們在以前系統(tǒng)里面所見的PID是一致的。例如pid_nr(pid)就返回給定pid的全局PID數(shù)值。這些數(shù)值往往只有在本機(jī)有效,例如一些通過PID獲取進(jìn)程結(jié)構(gòu)的代碼。但是在這種情況下,保存pid結(jié)構(gòu)往往比全局PID更有意義,因為全局PID不能隨意遷移。

..._vnr()
Vnr結(jié)尾的函數(shù)主要和局部pid打交道,例如一個進(jìn)程可見的局部ID。來看一個例子,task_pid_vnr(tsk)就返回它能夠看到任務(wù)PID。需要注意的是,這個數(shù)字僅僅在本命名空間內(nèi)有效。

..._nr_ns()
以nr_ns結(jié)尾的函數(shù)能夠獲取到特定命名空間課間的PID數(shù)值,如果你想得到一些任務(wù)的PID數(shù)值,你就可以通過task_pid_nr_ns(tsk, current->nsproxy->pid_ns)調(diào)用得到數(shù)字,接著通過find_task_by_pid_ns(pid, current->nsproxy->pid_ns)反過來找到任務(wù)結(jié)構(gòu)。當(dāng)一個用戶請求過來的時候,基本上都是調(diào)用這組函數(shù),因為這種情況下一個任務(wù)可能需要得到另外一個命名空間的信息。

NET命名空間子模塊
NET的命名空間隔離做的工作相對而言是最多的,但是整體思路還是一致的,即把全局的資源局部化,在每一個命名空間里面保留自己的控制信息。例如在目前的內(nèi)核里面路由表,arp表,netfilter表,設(shè)備等等都已經(jīng)空間化了,其所做的后續(xù)操作都要首先關(guān)聯(lián)到特定的命名空間,然后再取出里面的數(shù)據(jù)進(jìn)行后面的分析。

首先來看看net命名空間的結(jié)構(gòu)體
struct net {
        atomic_t                count;/* To decided when the network namespace should be freed. */
#ifdef NETNS_REFCNT_DEBUG
        atomic_t                use_count;        /* To track references we destroy on demand*/
#endif
        struct list_head        list;                /* list of network namespaces */
        struct work_struct        work;        /* work struct for freeing */
        struct proc_dir_entry         *proc_net;
        struct proc_dir_entry         *proc_net_stat;
#ifdef CONFIG_SYSCTL
        struct ctl_table_set        sysctls;
#endif
        struct net_device       *loopback_dev;          /* The loopback */
        struct list_head         dev_base_head;
        struct hlist_head         *dev_name_head;
        struct hlist_head        *dev_index_head;
        /* core fib_rules */
        struct list_head        rules_ops;
        spinlock_t                rules_mod_lock;
        struct sock                 *rtnl;                        /* rtnetlink socket */

        struct netns_core        core;
        struct netns_mib        mib;
        struct netns_packet        packet;
        struct netns_unix        unx;
        struct netns_ipv4        ipv4;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        struct netns_ipv6        ipv6;
#endif
#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
        struct netns_dccp        dccp;
#endif
#ifdef CONFIG_NETFILTER
        struct netns_xt                xt;
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
        struct netns_ct                ct;
#endif
#endif
#ifdef CONFIG_XFRM
        struct netns_xfrm        xfrm;
#endif
        struct net_generic        *gen;
};
上面這個結(jié)構(gòu)實在較大,您在需要深入了解的時候慢慢了解每個子模塊吧。在一個命名空間創(chuàng)建的時候,會做一些初始化。所有系統(tǒng)定義了一個回調(diào)函數(shù),讓感興趣的模塊注冊。結(jié)構(gòu)如下:
注冊接口如下
        一個新的用戶空間被創(chuàng)建的時候,注冊模塊的init結(jié)構(gòu)被創(chuàng)建。同理,一個空間銷毀的時候,exit函數(shù)也會被調(diào)用。
那么現(xiàn)在有了很多命名空間,而且命名空間之間是隔離的,那么他們之間怎么通信呢。這兒需要注意的是引入了一個新的概念,就做網(wǎng)絡(luò)設(shè)備對。一個設(shè)備對即A設(shè)備接收到的時間自動發(fā)送到B設(shè)備,反之亦然。
我們先來從直觀上看一下網(wǎng)絡(luò)概念圖。

接下來的問題就是如何通信?其實可以通過二層或者三層來實現(xiàn)網(wǎng)絡(luò)轉(zhuǎn)發(fā),本質(zhì)上就是通過橋接還是路由。我們下面以橋接為例來說明數(shù)據(jù)報文是如何轉(zhuǎn)發(fā)的。
對于容器1來說,veth1需要配置一個IP地址,但是veth0和eth0配置在同一個橋接設(shè)備上。Veth0和veth1是網(wǎng)絡(luò)設(shè)備對。
        是一個實際網(wǎng)絡(luò)環(huán)境里面的虛擬化配置,veth0和eth0是通過橋接來完成轉(zhuǎn)發(fā),但是veth0和veth1之間是通過設(shè)備對來完成數(shù)據(jù)轉(zhuǎn)發(fā),其他概念都沒有太多變化,除了增加一個獨立的命名空間,這兒我們來看看網(wǎng)絡(luò)設(shè)備對是如何工作的。
創(chuàng)建過程不再討論,就是每次創(chuàng)建一對,A和B的對端分別指向彼此。
創(chuàng)建完了后,彼此關(guān)聯(lián)。
我們還是來看看數(shù)據(jù)通道,他們的數(shù)據(jù)是如何透傳的。
        過eth_type_trans替換設(shè)備指針,接著就通過netif_rx送上起,設(shè)備已經(jīng)屬于一個特定的命名空間了,接著就在特定的命名空間里面完成這個報文的應(yīng)用層處理。但是不管怎么樣,通過這個小函數(shù)我們就能夠輕松的把一個報文從一個命名空間發(fā)送到另外一個命名空間里面。

總結(jié)
終于把內(nèi)核的命名空間大致模塊都看了一遍,其實我們只要在心理面把握住重要的一點就可以了。所有虛擬化的資源,在獲取資源的時候,必須首先通過nsproxy獲取到合適的命名空間,然后再進(jìn)行接下來的操作。另外命名空間雖然用戶空間程序不是很多,但是在內(nèi)核里面很早就引入了,而且一堆人活躍的維護(hù)著。

論壇徽章:
0
2 [報告]
發(fā)表于 2011-03-16 23:21 |只看該作者
LXC 主頁: http://lxc.sourceforge.net/

不知道和OPENVZ比有啥區(qū)別? 和XEN就不用比了,本來就是不同的東西。。。

論壇徽章:
0
3 [報告]
發(fā)表于 2011-03-21 10:52 |只看該作者
回復(fù) 2# accessory


    根據(jù)openvz一個技術(shù)負(fù)責(zé)人的觀點是:
1.LXC充分利用了openvz的成果
2.openvz還會維護(hù)一段時間(最新一個開發(fā)分支基于2.6.32)
3.LXC已經(jīng)被合并入內(nèi)核主線版本,而openvz則在苦苦支撐
4.現(xiàn)在IBM以及google等大公司都在LXC方面做了很多努力
5.目前LXC功能還沒有openvz多和穩(wěn)定,但是長期來看,LXC可能成為主流

論壇徽章:
0
4 [報告]
發(fā)表于 2011-03-22 01:47 |只看該作者
了解。多謝。。。

第三點是關(guān)鍵。。。

論壇徽章:
0
5 [報告]
發(fā)表于 2011-03-22 13:22 |只看該作者
所有虛擬化的資源,在獲取資源的時候,必須首先通過nsproxy獲取到合適的命名空間,然后再進(jìn)行接下來的操作。
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP