Docker探索namespace詳解
Docker通過(guò)namespace實(shí)現(xiàn)了資源隔離,通過(guò)cgroups實(shí)現(xiàn)了資源限制,通過(guò)寫(xiě)時(shí)復(fù)制(copy-on-write)實(shí)現(xiàn)了高效的文件操作。
1.namespace資源隔離
namepsace的6項(xiàng)隔離:
| namespace |
系統(tǒng)調(diào)用參數(shù) |
隔離內(nèi)容 |
| UTS |
CLONE_NEWUTS |
主機(jī)名與域名 |
| IPC |
CLONE_NEWIPC |
信號(hào)量,消息隊(duì)列和共享內(nèi)存 |
| PID |
CLONE_NEWPID |
進(jìn)程編號(hào) |
| Network |
CLONE_NEWNET |
網(wǎng)絡(luò)設(shè)備,網(wǎng)絡(luò)棧,端口等 |
| Mount |
CLONE_NEWNS |
掛載點(diǎn)(文件系統(tǒng)) |
| User |
CLONE_NEWUSER |
用戶(hù)和用戶(hù)組 |
Linux內(nèi)核實(shí)現(xiàn)namespace的主要目的之一是實(shí)現(xiàn)輕量級(jí)虛擬化(容器)服務(wù)。在同一個(gè)namespace下的進(jìn)程可以感知彼此的變化,而對(duì)外界進(jìn)程一無(wú)所知。這樣就可以讓容器中的進(jìn)程產(chǎn)生錯(cuò)覺(jué),仿佛自己置身于一個(gè)獨(dú)立的系統(tǒng)環(huán)境中,以達(dá)到獨(dú)立和隔離的目的。
進(jìn)行namespace API操作的4種方式
namespace的API包括clone(),setns()以及unshare(),還有/proc下的部分文件。為了確定隔離的到底是哪6項(xiàng)namespace,在使用這些API時(shí),通常需要指定以下6個(gè)參數(shù)的一個(gè)或多個(gè),通過(guò)位或操作來(lái)實(shí)現(xiàn)。
CLONE_NEWUTS,CLONE_NEWIPC,CLONE_NEWPID,CLONE_NEWNET,CLONE_NEWNS,CLONE_NEWUSER.
通過(guò)clone()在創(chuàng)建新進(jìn)程的同時(shí)創(chuàng)建namespace
使用clone()來(lái)創(chuàng)建一個(gè)獨(dú)立namespace的進(jìn)程是最常見(jiàn)的做法,也是Docker使用namespace的最基本的方法,它的調(diào)用方式如下。
NAME
clone, __clone2 - create a child process
SYNOPSIS
/* Prototype for the glibc wrapper function */
#include <sched.h>
int clone(int (*fn)(void *), void *child_stack,
int flags, void *arg, ...
/* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );
clone()實(shí)際上是fork系統(tǒng)調(diào)用的一種更通用的實(shí)現(xiàn)方式,它可以通過(guò)flags來(lái)控制使用多少功能。一共有20多種CLONE_*的flag(標(biāo)志位)參數(shù)用來(lái)控制clone進(jìn)程的方方面面(如是否與父進(jìn)程共享虛擬內(nèi)存等).
查看/proc/[pid]/ns文件
從3.8版本內(nèi)核開(kāi)始,用戶(hù)可以在該文件下看到指向不同namespace號(hào)的文件:
ls -l /proc/2597/ns total 0 lrwxrwxrwx 1 zhangxa zhangxa 0 Mar 2 06:42 cgroup -> cgroup:[4026531835] lrwxrwxrwx 1 zhangxa zhangxa 0 Mar 2 06:42 ipc -> ipc:[4026531839] lrwxrwxrwx 1 zhangxa zhangxa 0 Mar 2 06:42 mnt -> mnt:[4026531840] lrwxrwxrwx 1 zhangxa zhangxa 0 Mar 2 06:42 net -> net:[4026531957] lrwxrwxrwx 1 zhangxa zhangxa 0 Mar 2 06:42 pid -> pid:[4026531836] lrwxrwxrwx 1 zhangxa zhangxa 0 Mar 2 06:42 user -> user:[4026531837] lrwxrwxrwx 1 zhangxa zhangxa 0 Mar 2 06:42 uts -> uts:[4026531838]
如果2個(gè)進(jìn)程namespace號(hào)相同,說(shuō)明它們?cè)谕粋€(gè)namespace下。
/proc/[pid]/ns里設(shè)置這些符號(hào)鏈接的另一個(gè)作用是,一旦上述鏈接文件被打開(kāi),那么就算該namespace下的所有進(jìn)程都已經(jīng)結(jié)束,這個(gè)namespace也會(huì)一直存在,后續(xù)進(jìn)程也可以再加進(jìn)來(lái)。在Docker中,通過(guò)文件描述符定位和加入一個(gè)存在的namespace是最基本的方式。
另外,把/proc/[pid]/ns目錄文件使用--bind方式掛載起來(lái)可以直到同樣的作用:
# mount --bind /proc/2454/ns/uts uts
通過(guò)setns()加入一個(gè)已經(jīng)存在的namespace
上面提到,在進(jìn)程都結(jié)束的情況下,也可以通過(guò)掛載的形式把namespace保留下來(lái),保留namespace的目的是為以后有進(jìn)程加入做準(zhǔn)備。在Docker中,使用docker exec命令在已經(jīng)運(yùn)行著的容器中執(zhí)行一個(gè)新命令,就需要用到該方法。通過(guò)setns()系統(tǒng)調(diào)用,進(jìn)程從原先的namespace加入某個(gè)已經(jīng)存在的namespace,使用方法如下。通常為了不影響進(jìn)程的調(diào)用者,也為了使新加入的pid namespace生效,會(huì)在setns()函數(shù)執(zhí)行后使用clone創(chuàng)建子進(jìn)程繼續(xù)執(zhí)行命令,讓原先的進(jìn)程結(jié)束。
NAME
setns - reassociate thread with a namespace
SYNOPSIS
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <sched.h>
int setns(int fd, int nstype);
fd = open(argv[1],O_RDONLY); setns(fd,0); execvp(argv[2],&argv[2]);
假設(shè)編譯后的程序?yàn)?setns-test"
# ./setns-test ~/uts /bin/bash
至此,就可以在新加入的namespace中執(zhí)行shell命令了。
通過(guò)unshare()在原先進(jìn)程上進(jìn)行namespace隔離
它與clone()很像,不同的是,unshare()運(yùn)行在原先的進(jìn)程上,不需要啟動(dòng)一個(gè)新進(jìn)程。
NAME
unshare - disassociate parts of the process execution context
SYNOPSIS
#include <sched.h>
int unshare(int flags);
調(diào)用unshare()的主要作用就是不啟動(dòng)一個(gè)新進(jìn)程就可以起到隔離的效果,相當(dāng)跳出原先的namespace進(jìn)行操作。這樣,就可以在原進(jìn)程進(jìn)行一些需要隔離的操作。Linux自帶的unshare命令,就是通過(guò)unshare()系統(tǒng)調(diào)用實(shí)現(xiàn)的。Docker目前并沒(méi)有使用這個(gè)系統(tǒng)調(diào)用。
總結(jié)
以上就是本文關(guān)于Docker探索namespace詳解的全部?jī)?nèi)容,希望對(duì)大家有所幫助,感興趣的朋友可以繼續(xù)參閱本站:淺談Docker安全機(jī)制內(nèi)核安全與容器之間的網(wǎng)絡(luò)安全、詳解Docker使用Linux iptables 和 Interfaces管理容器網(wǎng)絡(luò)等,有什么問(wèn)題可以隨時(shí)留言,小編會(huì)及時(shí)回復(fù)大家的。感謝朋友們對(duì)本站的支持!
相關(guān)文章
docker容器無(wú)法訪問(wèn)宿主機(jī)端口的解決
這篇文章主要介紹了docker容器無(wú)法訪問(wèn)宿主機(jī)端口的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11
通過(guò)Dockerfile構(gòu)建Docker鏡像的方法步驟
這篇文章主要介紹了通過(guò)Dockerfile構(gòu)建Docker鏡像的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02
Docker容器在系統(tǒng)啟動(dòng)時(shí)自動(dòng)運(yùn)行配置方法
docker容器化可以使得環(huán)境相對(duì)獨(dú)立,減少污染,這篇文章主要給大家介紹了關(guān)于Docker容器在系統(tǒng)啟動(dòng)時(shí)自動(dòng)運(yùn)行配置的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09
教你使用Portainer管理多臺(tái)Docker容器環(huán)境的方法
這篇文章主要介紹了Portainer管理多臺(tái)Docker容器環(huán)境,本文給大家介紹的非常詳細(xì),包括環(huán)境準(zhǔn)備及管理docker的詳細(xì)過(guò)程,需要的朋友可以參考下2021-11-11
詳解Docker 配置國(guó)內(nèi)免費(fèi)registry mirror
本篇文章主要介紹了 Docker 配置國(guó)內(nèi)免費(fèi)registry mirror,具有一定的參考價(jià)值,有興趣的小伙伴們可以參考一下2017-07-07
Centos8安裝docker報(bào)錯(cuò)(錯(cuò)誤提示:All?mirrors?were?tried)的問(wèn)題
最近總是遇到“All?mirrors?were?tried”的報(bào)錯(cuò)信息,沒(méi)辦法,就rm?-rf?/etc/yum.repos.d/*?全部!刪了,下面小編通過(guò)本文給大家介紹下Centos8安裝docker報(bào)錯(cuò)(錯(cuò)誤提示:All?mirrors?were?tried)的問(wèn)題及解決過(guò)程,感興趣的朋友一起看看吧2022-03-03
docker實(shí)踐之容器的導(dǎo)入與導(dǎo)出
Docker技術(shù)為IT界帶來(lái)了巨大的改變,它使得云服務(wù)可以用來(lái)共享應(yīng)用和工作流程自動(dòng)化,使得應(yīng)用可以用組件快速組合,消除了開(kāi)發(fā)、品質(zhì)保證、產(chǎn)品環(huán)境間的摩擦。這篇文章我們將詳細(xì)的介紹docker容器的導(dǎo)入與導(dǎo)出,感興趣的朋友們下面來(lái)一起看看吧。2016-10-10

