操作系统级虚拟化概述
2019獨角獸企業(yè)重金招聘Python工程師標準>>>
操作系統(tǒng)級虛擬化
KVM、XEN等虛擬化技術(shù)允許各個虛擬機擁有自己獨立的操作系統(tǒng)。與KVM、XEN等虛擬化技術(shù)不同,所謂操作系統(tǒng)級虛擬化,也被稱作容器化,是操作系統(tǒng)自身的一個特性,它允許多個相互隔離的用戶空間實例的存在。這些用戶空間實例也被稱作為容器。普通的進程可以看到計算機的所有資源而容器中的進程只能看到分配給該容器的資源。通俗來講,操作系統(tǒng)級虛擬化將操作系統(tǒng)所管理的計算機資源,包括進程、文件、設備、網(wǎng)絡等分組,然后交給不同的容器使用。容器中運行的進程只能看到分配給該容器的資源。從而達到隔離與虛擬化的目的。
實現(xiàn)操作系統(tǒng)虛擬化需要用到Namespace及cgroups技術(shù)。
命名空間(Namespace)
在編程語言中,引入命名空間的概念是為了重用變量名或者服務例程名。在不同的命名空間中使用同一個變量名而不會產(chǎn)生沖突。Linux系統(tǒng)引入命名空間也有類似的作用。例如,在沒有操作系統(tǒng)級虛擬化的Linux系統(tǒng)中,用戶態(tài)進程從1開始編號(PID)。引入操作系統(tǒng)虛擬化之后,不同容器有著不同的PID命名空間,每個容器中的進程都可以從1開始編號而不產(chǎn)生沖突。
目前,Linux中的命名空間有6種類型,分別對應操作系統(tǒng)管理的6種資源:
- 掛載點(mount point) CLONE_NEWNS
- 進程(pid) CLONE_NEWPID
- 網(wǎng)絡(net) CLONE_NEWNET
- 進程間通信(ipc) CLONE_NEWIPC
- 主機名(uts) CLONE_NEWUTS
- 用戶(uid) CLONW_NEWUSER
將來還會引入時間、設備等對應的namespace.
Linux 2.4.19版本引入了第一個命名空間——掛載點,因為那時還沒有其他類型的命名空間,所以clone系統(tǒng)調(diào)用中引入的flag就叫做CLONE_NEWNS
與命名空間相關(guān)的三個系統(tǒng)調(diào)用(system calls)
下面3個系統(tǒng)調(diào)用用來操作命名空間:
- clone() —— 用來創(chuàng)建新的進程及新的命名空間,新的進程會被放到新的命名空間中
- unshare() —— 創(chuàng)建新的命名空間但并不創(chuàng)建新的子進程,之后創(chuàng)建的子進程會被放到新創(chuàng)建的命名空間中去
- setns() —— 將進程加入到已經(jīng)存在的命名空間中
注意:這3個系統(tǒng)調(diào)用都不會改變調(diào)用進程(calling process)的pid命名空間,而是會影響其子進程的pid命名空間
命名空間本身并沒用名字(囧),不同的命名空間用不同的inode號來標識,這也符合Linux用文件一統(tǒng)天下的慣例。可以在proc文件系統(tǒng)中查看一個進程所屬的命名空間,例如,查看PID為4123的進程所屬的命名空間:
kelvin@desktop:~$ ls -l /proc/4123/ns/ 總用量 0 lrwxrwxrwx 1 kelvin kelvin 0 12月 26 16:28 cgroup -> cgroup:[4026531835] lrwxrwxrwx 1 kelvin kelvin 0 12月 26 16:28 ipc -> ipc:[4026531839] lrwxrwxrwx 1 kelvin kelvin 0 12月 26 16:28 mnt -> mnt:[4026531840] lrwxrwxrwx 1 kelvin kelvin 0 12月 26 16:28 net -> net:[4026531963] lrwxrwxrwx 1 kelvin kelvin 0 12月 26 16:28 pid -> pid:[4026531836] lrwxrwxrwx 1 kelvin kelvin 0 12月 26 16:28 user -> user:[4026531837] lrwxrwxrwx 1 kelvin kelvin 0 12月 26 16:28 uts -> uts:[4026531838]下面的代碼演示了如何利用上述3個系統(tǒng)調(diào)用來操作進程的命名空間:
#define _GNU_SOURCE #include <sys/types.h> #include <sys/wait.h> #include <sched.h> #include <signal.h> #include <unistd.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>#define STACK_SIZE (10 * 1024 * 1024)char child_stack[STACK_SIZE];int child_main(void* args) {pid_t child_pid = getpid();printf("I'm child process and my pid is %d \n", child_pid);// 子進程會被放到clone系統(tǒng)調(diào)用新創(chuàng)建的pid命名空間中, 所以其pid應該為1sleep(300);// 命名空間中的所有進程退出后該命名空間的inode將會被刪除, 為后續(xù)操作保留它return 0; }int main() {/* Clone */pid_t child_pid = clone(child_main, child_stack + STACK_SIZE, \CLONE_NEWPID | SIGCHLD, NULL);if(child_pid < 0) {perror("clone failed");}/* Unshare */int ret = unshare(CLONE_NEWPID); // 父進程調(diào)用unshare, 創(chuàng)建了一個新的命名空間,//但不會創(chuàng)建子進程. 之后再創(chuàng)建的子進程將會被加入到新的命名空間中if (ret < 0) {perror("unshare failed");}int fpid = fork();if (fpid < 0) {perror("fork error");} else if (fpid == 0) {printf("I am child process. My pid is %d \n", getpid());// Fork后的子進程會被加入到unshare創(chuàng)建的命名空間中, 所以pid應該為1exit(0);} else {}waitpid(fpid, NULL, 0);/* Setns */char path[80] = "";sprintf(path, "/proc/%d/ns/pid", child_pid);int fd = open(path, O_RDONLY);if (fd == -1)perror("open error");if (setns(fd, 0) == -1)// setns并不會改變當前進程的命名空間, 而是會設置之后創(chuàng)建的子進程的命名空間perror("setns error");close(fd);int npid = fork();if (npid < 0) {perror("fork error");} else if (npid == 0) {printf("I am child process. My pid is %d \n", getpid());// 新的子進程會被加入到第一個子進程的pid命名空間中, 所以其pid應該為2exit(0);} else {}return 0; }運行結(jié)果:
$ sudo ./ns I'm child process and my pid is 1 I am child process. My pid is 1 I am child process. My pid is 2?
控制組(Cgroups)
如果說命名空間是從命名和編號的角度進行隔離,而控制組則是將進程進行分組,并真正的將各組進程的計算資源進行限制、隔離。控制組是一種內(nèi)核機制,它可以對進程進行分組、跟蹤限制其使用的計算資源。對于每一類計算資源,控制組通過所謂的子系統(tǒng)(subsystem)來進行控制,現(xiàn)階段已有的子系統(tǒng)包括:
-
cpusets: 用來分配一組CPU給指定的cgroup,該cgroup中的進程只等被調(diào)度到該組CPU上去執(zhí)行
-
blkio : 限制cgroup的塊IO
-
cpuacct : 用來統(tǒng)計cgroup中的CPU使用
-
devices : 用來黑白名單的方式控制cgroup可以創(chuàng)建和使用的設備節(jié)點
-
freezer : 用來掛起指定的cgroup,或者喚醒掛起的cgroup
-
hugetlb : 用來限制cgroup中hugetlb的使用
-
memory : 用來跟蹤限制內(nèi)存及交換分區(qū)的使用
-
net_cls : 用來根據(jù)發(fā)送端的cgroup來標記數(shù)據(jù)包,流量控制器(traffic controller)會根據(jù)這些標記來分配優(yōu)先級
-
net_prio : 用來設置cgroup的網(wǎng)絡通信優(yōu)先級
-
cpu :用來設置cgroup中CPU的調(diào)度參數(shù)
-
perf_event : 用來監(jiān)控cgroup的CPU性能
與命名空間不同,控制組并沒有增加系統(tǒng)調(diào)用,而是實現(xiàn)了一個文件系統(tǒng),通過文件及目錄操作來管理控制組。下面通過一個例子來看一看cgroup是如何利用cpuset子系統(tǒng)來把進程綁定到指定的CPU上去執(zhí)行的。
1. 創(chuàng)建一個一直執(zhí)行的shell腳本
#!/bin/bashx=0while [ True ];do: done;2. 在后臺執(zhí)行這個腳本
# bash run.sh & [1] 205533. 查看該腳本在哪個CPU上運行
# ps -eLo ruser,lwp,psr,args | grep 20553 | grep -v grep root 20553 3 bash run.sh可以看到PID為20553的進程運行在編號為3的CPU上,下面利用cgroups將其綁定到編號為2的CPU上去執(zhí)行
4. 掛載cgroups類型的文件系統(tǒng)到一個新創(chuàng)建的目錄cgroups中
# mkdir cgroups # mount -t cgroup -o cpuset cgroups ./cgroups/ # ls cgroups/ cgroup.clone_children cpuset.memory_pressure_enabled cgroup.procs cpuset.memory_spread_page cgroup.sane_behavior cpuset.memory_spread_slab cpuset.cpu_exclusive cpuset.mems cpuset.cpus cpuset.sched_load_balance cpuset.effective_cpus cpuset.sched_relax_domain_level cpuset.effective_mems docker cpuset.mem_exclusive tasks cpuset.mem_hardwall notify_on_release cpuset.memory_migrate release_agent cpuset.memory_pressure5. 創(chuàng)建一個新的組group0
# mkdir group0 # ls group0/ cgroup.clone_children cpuset.mem_exclusive cpuset.mems cgroup.procs cpuset.mem_hardwall cpuset.sched_load_balance cpuset.cpu_exclusive cpuset.memory_migrate cpuset.sched_relax_domain_level cpuset.cpus cpuset.memory_pressure notify_on_release cpuset.effective_cpus cpuset.memory_spread_page tasks cpuset.effective_mems cpuset.memory_spread_slab6. 將上面的進程20553加入到新建的控制組中:
# echo 20553 >> group0/tasks # cat group0/tasks 205537. 限制該組的進程只能運行在編號為2的CPU上
# echo 2 > group0/cpuset.cpus # cat group0/cpuset.cpus 28. 查看PID為20553的進程所運行的CPU編號
# ps -eLo ruser,lwp,psr,args | grep 20553 | grep -v grep root 20553 2 bash run.sh上面的例子簡單的展示了如何使用控制組。控制組通過文件和目錄來操作,文件系統(tǒng)又是樹形結(jié)構(gòu),因此如果不對cgroups的使用做一些限制的話,配置會變得異常復雜和混亂。因此,在新版的cgroups中做了一些限制。
小結(jié)
本文簡要介紹了操作系統(tǒng)虛擬化的概念,以及實現(xiàn)操作系統(tǒng)虛擬化的技術(shù)——命名空間及控制組。并通過兩個簡單的例子演示了命名空間及控制組的使用方法。
閱讀原文
轉(zhuǎn)載于:https://my.oschina.net/kelvinxupt/blog/1602990
總結(jié)
以上是生活随笔為你收集整理的操作系统级虚拟化概述的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jquery 轮播插件 bxslider
- 下一篇: K:大数加法