DockerÕâô»ð£¬Ï²»¶¼¼ÊõµÄÅóÓÑ¿ÉÄÜÒ²»áÏ룬Èç¹ûÒª×Ô¼ºÊµÏÖÒ»¸ö×ÊÔ´¸ôÀëµÄÈÝÆ÷£¬Ó¦¸Ã´ÓÄÄЩ·½ÃæÏÂÊÖÄØ£¿Ò²ÐíÄãµÚÒ»·´Ó¦¿ÉÄܾÍÊÇchrootÃüÁÕâÌõÃüÁî¸øÓû§×îÖ±¹ÛµÄ¸Ð¾õ¾ÍÊÇʹÓúó¸ùĿ¼/µÄ¹ÒÔØµãÇл»ÁË£¬¼´Îļþϵͳ±»¸ôÀëÁË¡£È»ºó£¬ÎªÁËÔÚ·Ö²¼Ê½µÄ»·¾³Ï½øÐÐͨÐźͶ¨Î»£¬ÈÝÆ÷±ØÈ»ÐèÒªÒ»¸ö¶ÀÁ¢µÄIP¡¢¶Ë¿Ú¡¢Â·Óɵȵȣ¬×ÔÈ»¾ÍÏëµ½ÁËÍøÂçµÄ¸ôÀ롣ͬʱ£¬ÄãµÄÈÝÆ÷»¹ÐèÒªÒ»¸ö¶ÀÁ¢µÄÖ÷»úÃûÒÔ±ãÔÚÍøÂçÖбêʶ×Ô¼º¡£Ïëµ½ÍøÂ磬˳Æä×ÔÈ»¾ÍÏ뵽ͨÐÅ£¬Ò²¾ÍÏëµ½Á˽ø³Ì¼äͨÐŵĸôÀë¡£¿ÉÄÜÄãÒ²Ïëµ½ÁËȨÏÞµÄÎÊÌ⣬¶ÔÓû§ºÍÓû§×éµÄ¸ôÀë¾ÍʵÏÖÁËÓû§È¨Ï޵ĸôÀë¡£×îºó£¬ÔËÐÐÔÚÈÝÆ÷ÖеÄÓ¦ÓÃÐèÒªÓÐ×Ô¼ºµÄPID,×ÔȻҲÐèÒªÓëËÞÖ÷»úÖеÄPID½øÐиôÀë¡£
ÓÉ´Ë£¬ÎÒÃÇ»ù±¾ÉÏÍê³ÉÁËÒ»¸öÈÝÆ÷ËùÐèÒª×öµÄÁùÏî¸ôÀ룬LinuxÄÚºËÖоÍÌṩÁËÕâÁùÖÖnamespace¸ôÀëµÄϵͳµ÷Óã¬ÈçϱíËùʾ¡£

±í namespaceÁùÏî¸ôÀë
ʵ¼ÊÉÏ£¬LinuxÄÚºËʵÏÖnamespaceµÄÖ÷ҪĿµÄ¾ÍÊÇΪÁËʵÏÖÇáÁ¿¼¶ÐéÄ⻯£¨ÈÝÆ÷£©·þÎñ¡£ÔÚͬһ¸önamespaceϵĽø³Ì¿ÉÒÔ¸ÐÖª±Ë´ËµÄ±ä»¯£¬¶ø¶ÔÍâ½çµÄ½ø³ÌÒ»ÎÞËùÖª¡£ÕâÑù¾Í¿ÉÒÔÈÃÈÝÆ÷ÖеĽø³Ì²úÉú´í¾õ£¬·Â·ð×Ô¼ºÖÃÉíÓÚÒ»¸ö¶ÀÁ¢µÄϵͳ»·¾³ÖУ¬ÒÔ´Ë´ïµ½¶ÀÁ¢ºÍ¸ôÀëµÄÄ¿µÄ¡£
ÐèҪ˵Ã÷µÄÊÇ£¬±¾ÎÄËùÌÖÂÛµÄnamespaceʵÏÖÕë¶ÔµÄ¾ùÊÇLinuxÄÚºË3.8¼°ÆäÒÔºóµÄ°æ±¾¡£½ÓÏÂÀ´£¬ÎÒÃǽ«Ê×ÏȽéÉÜʹÓÃnamespaceµÄAPI£¬È»ºóÕë¶ÔÕâÁùÖÖnamespace½øÐÐÖðÒ»½²½â£¬²¢Í¨¹ý³ÌÐòÈÃÄãÇ×Éí¸ÐÊÜÒ»ÏÂÕâЩ¸ôÀëЧ¹û£¨²Î¿¼×Ôhttp://lwn.net/Articles/531114/£©¡£
1. µ÷ÓÃnamespaceµÄAPI
namespaceµÄAPI°üÀ¨clone()¡¢setns()ÒÔ¼°unshare()£¬»¹ÓÐ/procϵIJ¿·ÖÎļþ¡£ÎªÁËÈ·¶¨¸ôÀëµÄµ½µ×ÊÇÄÄÖÖnamespace£¬ÔÚʹÓÃÕâЩAPIʱ£¬Í¨³£ÐèÒªÖ¸¶¨ÒÔÏÂÁù¸ö³£ÊýµÄÒ»¸ö»ò¶à¸ö£¬Í¨¹ý|£¨Î»»ò£©²Ù×÷À´ÊµÏÖ¡£Äã¿ÉÄÜÒѾÔÚÉÏÃæµÄ±í¸ñÖÐ×¢Òâµ½£¬ÕâÁù¸ö²ÎÊý·Ö±ðÊÇCLONE_NEWIPC¡¢CLONE_NEWNS¡¢CLONE_NEWNET¡¢CLONE_NEWPID¡¢CLONE_NEWUSERºÍCLONE_NEWUTS¡£
£¨1£©Í¨¹ýclone()´´½¨Ð½ø³ÌµÄͬʱ´´½¨namespace
ʹÓÃclone()À´´´½¨Ò»¸ö¶ÀÁ¢namespaceµÄ½ø³ÌÊÇ×î³£¼û×ö·¨£¬ËüµÄµ÷Ó÷½Ê½ÈçÏ¡£
int clone(int (*child_func)(void *), void *child_stack, int flags, void *arg); |
clone()ʵ¼ÊÉÏÊÇ´«Í³UNIXϵͳµ÷ÓÃfork()µÄÒ»ÖÖ¸üͨÓõÄʵÏÖ·½Ê½£¬Ëü¿ÉÒÔͨ¹ýflagsÀ´¿ØÖÆÊ¹ÓöàÉÙ¹¦ÄÜ¡£Ò»¹²ÓжþÊ®¶àÖÖCLONE_*µÄflag£¨±ê־룩²ÎÊýÓÃÀ´¿ØÖÆclone½ø³ÌµÄ·½·½ÃæÃ棨ÈçÊÇ·ñÓ븸½ø³Ì¹²ÏíÐéÄâÄÚ´æµÈµÈ£©£¬ÏÂÃæÍâÃæÖðÒ»½²½âcloneº¯Êý´«ÈëµÄ²ÎÊý¡£
²ÎÊýchild_func´«Èë×Ó½ø³ÌÔËÐеijÌÐòÖ÷º¯Êý¡£
²ÎÊýchild_stack´«Èë×Ó½ø³ÌʹÓõÄÕ»¿Õ¼ä
²ÎÊýflags±íʾʹÓÃÄÄЩCLONE_*±ê־λ
²ÎÊýargsÔò¿ÉÓÃÓÚ´«ÈëÓû§²ÎÊý
ÔÚºóÐøµÄÄÚÈÝÖн«»áÓÐʹÓÃclone()µÄʵ¼Ê³ÌÐò¿É¹©´ó¼Ò²Î¿¼¡£
£¨2£©²é¿´/proc/[pid]/nsÎļþ
´Ó3.8°æ±¾µÄÄں˿ªÊ¼£¬Óû§¾Í¿ÉÒÔÔÚ/proc/[pid]/nsÎļþÏ¿´µ½Ö¸Ïò²»Í¬namespaceºÅµÄÎļþ£¬Ð§¹ûÈçÏÂËùʾ£¬ÐÎÈç[4026531839]Õß¼´ÎªnamespaceºÅ¡£
$ ls -l /proc/$$/ns <<-- $$ ±íʾӦÓõÄPID total 0 lrwxrwxrwx. 1 mtk mtk 0 Jan 8 04:12 ipc -> ipc:[4026531839] lrwxrwxrwx. 1 mtk mtk 0 Jan 8 04:12 mnt -> mnt:[4026531840] lrwxrwxrwx. 1 mtk mtk 0 Jan 8 04:12 net -> net:[4026531956] lrwxrwxrwx. 1 mtk mtk 0 Jan 8 04:12 pid -> pid:[4026531836] lrwxrwxrwx. 1 mtk mtk 0 Jan 8 04:12 user->user:[4026531837] lrwxrwxrwx. 1 mtk mtk 0 Jan 8 04:12 uts -> uts:[4026531838] |
Èç¹ûÁ½¸ö½ø³ÌÖ¸ÏòµÄnamespace±àºÅÏàͬ£¬¾Í˵Ã÷ËûÃÇÔÚͬһ¸önamespaceÏ£¬·ñÔòÔòÔÚ²»Í¬namespaceÀïÃæ¡£/proc/[pid]/nsµÄÁíÍâÒ»¸ö×÷ÓÃÊÇ£¬Ò»µ©Îļþ±»´ò¿ª£¬Ö»Òª´ò¿ªµÄÎļþÃèÊö·û£¨fd£©´æÔÚ£¬ÄÇô¾ÍËãPIDËùÊôµÄËùÓнø³Ì¶¼ÒѾ½áÊø£¬´´½¨µÄnamespace¾Í»áÒ»Ö±´æÔÚ¡£ÄÇÈçºÎ´ò¿ªÎļþÃèÊö·ûÄØ£¿°Ñ/proc/[pid]/nsĿ¼¹ÒÔØÆðÀ´¾Í¿ÉÒÔ´ïµ½Õâ¸öЧ¹û£¬ÃüÁîÈçÏ¡£
# touch ~/uts # mount --bind /proc/27514/ns/uts ~/uts |
Èç¹ûÄã¿´µ½µÄÄÚÈÝÓë±¾ÎÄËùÃèÊöµÄ²»·û£¬ÄÇô˵Ã÷ÄãʹÓõÄÄÚºËÔÚ3.8°æ±¾ÒÔǰ¡£¸ÃĿ¼Ï´æÔÚµÄÖ»ÓÐipc¡¢netºÍuts£¬²¢ÇÒÒÔÓ²Á´½Ó´æÔÚ¡£
£¨3£©Í¨¹ýsetns()¼ÓÈëÒ»¸öÒѾ´æÔÚµÄnamespace
ÉÏÎĸÕÌáµ½£¬ÔÚ½ø³Ì¶¼½áÊøµÄÇé¿öÏ£¬Ò²¿ÉÒÔͨ¹ý¹ÒÔØµÄÐÎʽ°Ñnamespace±£ÁôÏÂÀ´£¬±£ÁônamespaceµÄÄ¿µÄ×ÔÈ»ÊÇΪÒÔºóÓнø³Ì¼ÓÈë×ö×¼±¸¡£Í¨¹ýsetns()ϵͳµ÷Óã¬ÄãµÄ½ø³Ì´ÓÔÏȵÄnamespace¼ÓÈëÎÒÃÇ×¼±¸ºÃµÄÐÂnamespace£¬Ê¹Ó÷½·¨ÈçÏ¡£
int setns(int fd, int nstype); |
²ÎÊýfd±íʾÎÒÃÇÒª¼ÓÈëµÄnamespaceµÄÎļþÃèÊö·û¡£ÉÏÎÄÒѾÌáµ½£¬ËüÊÇÒ»¸öÖ¸Ïò/proc/[pid]/nsĿ¼µÄÎļþÃèÊö·û£¬¿ÉÒÔͨ¹ýÖ±½Ó´ò¿ª¸ÃĿ¼ÏµÄÁ´½Ó»òÕß´ò¿ªÒ»¸ö¹ÒÔØÁ˸ÃĿ¼ÏÂÁ´½ÓµÄÎļþµÃµ½¡£
²ÎÊýnstypeÈõ÷ÓÃÕß¿ÉÒÔÈ¥¼ì²éfdÖ¸ÏòµÄnamespaceÀàÐÍÊÇ·ñ·ûºÏÎÒÃÇʵ¼ÊµÄÒªÇó¡£Èç¹ûÌî0±íʾ²»¼ì²é¡£
ΪÁ˰ÑÎÒÃÇ´´½¨µÄnamespaceÀûÓÃÆðÀ´£¬ÎÒÃÇÐèÒªÒýÈëexecve()ϵÁк¯Êý£¬Õâ¸öº¯Êý¿ÉÒÔÖ´ÐÐÓû§ÃüÁ×î³£ÓõľÍÊǵ÷ÓÃ/bin/bash²¢½ÓÊܲÎÊý£¬ÔËÐÐÆðÒ»¸öshell£¬Ó÷¨ÈçÏ¡£
fd = open(argv[1], O_RDONLY); /* »ñÈ¡namespaceÎļþÃèÊö·û */ setns(fd, 0); /* ¼ÓÈëеÄnamespace */ execvp(argv[2], &argv[2]); /* Ö´ÐгÌÐò */ |
¼ÙÉè±àÒëºóµÄ³ÌÐòÃû³ÆÎªsetns¡£
# ./setns ~/uts /bin/bash # ~/uts Êǰ󶨵Ä/proc/27514/ns/uts |
ÖÁ´Ë£¬Äã¾Í¿ÉÒÔÔÚеÄÃüÃû¿Õ¼äÖÐÖ´ÐÐshellÃüÁîÁË£¬ÔÚÏÂÎÄÖлá¶à´ÎʹÓÃÕâÖÖ·½Ê½À´ÑÝʾ¸ôÀëµÄЧ¹û¡£
£¨4£©Í¨¹ýunshare()ÔÚÔÏȽø³ÌÉϽøÐÐnamespace¸ôÀë
×îºóÒªÌáµÄϵͳµ÷ÓÃÊÇunshare()£¬Ëü¸úclone()ºÜÏñ£¬²»Í¬µÄÊÇ£¬unshare()ÔËÐÐÔÚÔÏȵĽø³ÌÉÏ£¬²»ÐèÒªÆô¶¯Ò»¸öнø³Ì£¬Ê¹Ó÷½·¨ÈçÏ¡£
µ÷ÓÃunshare()µÄÖ÷Òª×÷ÓþÍÊDz»Æô¶¯Ò»¸öнø³Ì¾Í¿ÉÒÔÆðµ½¸ôÀëµÄЧ¹û£¬Ï൱ÓÚÌø³öÔÏȵÄnamespace½øÐвÙ×÷¡£ÕâÑù£¬Äã¾Í¿ÉÒÔÔÚÔ½ø³Ì½øÐÐһЩÐèÒª¸ôÀëµÄ²Ù×÷¡£LinuxÖÐ×Ô´øµÄunshareÃüÁ¾ÍÊÇͨ¹ýunshare()ϵͳµ÷ÓÃʵÏֵģ¬ÓÐÐËȤµÄ¶ÁÕß¿ÉÒÔÔÚÍøÉÏËÑË÷Ò»ÏÂÕâ¸öÃüÁîµÄ×÷Óá£
£¨5£©ÑÓÉìÔĶÁ£ºfork£¨£©ÏµÍ³µ÷ÓÃ
ϵͳµ÷Óú¯Êýfork()²¢²»ÊôÓÚnamespaceµÄAPI£¬ËùÒÔÕⲿ·ÖÄÚÈÝÊôÓÚÑÓÉìÔĶÁ£¬Èç¹û¶ÁÕßÒѾ¶Ôfork()ÓÐ×ã¹»µÄÁ˽⣬ÄÇ´ó¿ÉÌø¹ý¡£
µ±³ÌÐòµ÷ÓÃfork£¨£©º¯Êýʱ£¬ÏµÍ³»á´´½¨ÐµĽø³Ì£¬ÎªÆä·ÖÅä×ÊÔ´£¬ÀýÈç´æ´¢Êý¾ÝºÍ´úÂëµÄ¿Õ¼ä¡£È»ºó°ÑÔÀ´µÄ½ø³ÌµÄËùÓÐÖµ¶¼¸´ÖƵ½ÐµĽø³ÌÖУ¬Ö»ÓÐÉÙÁ¿ÊýÖµÓëÔÀ´µÄ½ø³ÌÖµ²»Í¬£¬Ï൱ÓÚ¿Ë¡ÁËÒ»¸ö×Ô¼º¡£ÄÇô³ÌÐòµÄºóÐø´úÂëÂß¼ÒªÈçºÎÇø·Ö×Ô¼ºÊÇнø³Ì»¹ÊǸ¸½ø³ÌÄØ£¿
fork()µÄÉñÆæÖ®´¦ÔÚÓÚËü½ö½ö±»µ÷ÓÃÒ»´Î£¬È´Äܹ»·µ»ØÁ½´Î£¨¸¸½ø³ÌÓë×Ó½ø³Ì¸÷·µ»ØÒ»´Î£©£¬Í¨¹ý·µ»ØÖµµÄ²»Í¬¾Í¿ÉÒÔ½øÐÐÇø·Ö¸¸½ø³ÌÓë×Ó½ø³Ì¡£Ëü¿ÉÄÜÓÐÈýÖÖ²»Í¬µÄ·µ»ØÖµ£º
ÔÚ¸¸½ø³ÌÖУ¬fork·µ»ØÐ´´½¨×Ó½ø³ÌµÄ½ø³ÌID
ÔÚ×Ó½ø³ÌÖУ¬fork·µ»Ø0
Èç¹û³öÏÖ´íÎó£¬fork·µ»ØÒ»¸ö¸ºÖµ
ÏÂÃæ¸ø³öÒ»¶ÎʵÀý´úÂ룬ÃüÃûΪfork_example.c¡£
#include <unistd.h> #include <stdio.h> int main (){ pid_t fpid; //fpid±íʾforkº¯Êý·µ»ØµÄÖµ int count=0; fpid=fork(); if (fpid < 0)printf("error in fork!"); else if (fpid == 0) { printf("I am child. Process id is %d/n",getpid()); } else { printf("i am parent. Process id is %d/n",getpid()); } return 0; } |
±àÒë²¢Ö´ÐУ¬½á¹ûÈçÏ¡£
root@local:~# gcc -Wall fork_example.c && ./a.out I am parent. Process id is 28365 I am child. Process id is 28366 |
ʹÓÃfork()ºó£¬¸¸½ø³ÌÓÐÒåÎñ¼à¿Ø×Ó½ø³ÌµÄÔËÐÐ״̬£¬²¢ÔÚ×Ó½ø³ÌÍ˳öºó×Ô¼º²ÅÄÜÕý³£Í˳ö£¬·ñÔò×Ó½ø³Ì¾Í»á³ÉΪ¡°¹Â¶ù¡±½ø³Ì¡£
ÏÂÃæÎÒÃǽ«·Ö±ð¶ÔÁùÖÖnamespace½øÐÐÏêϸ½âÎö¡£
2. UTS£¨UNIX Time-sharing System£©namespace
UTS namespaceÌṩÁËÖ÷»úÃûºÍÓòÃûµÄ¸ôÀ룬ÕâÑùÿ¸öÈÝÆ÷¾Í¿ÉÒÔÓµÓÐÁ˶ÀÁ¢µÄÖ÷»úÃûºÍÓòÃû£¬ÔÚÍøÂçÉÏ¿ÉÒÔ±»ÊÓ×÷Ò»¸ö¶ÀÁ¢µÄ½Úµã¶ø·ÇËÞÖ÷»úÉϵÄÒ»¸ö½ø³Ì¡£
ÏÂÃæÎÒÃÇͨ¹ý´úÂëÀ´¸ÐÊÜÒ»ÏÂUTS¸ôÀëµÄЧ¹û£¬Ê×ÏÈÐèÒªÒ»¸ö³ÌÐòµÄ¹Ç¼Ü£¬ÈçÏÂËùʾ¡£´ò¿ª±à¼Æ÷´´½¨uts.cÎļþ£¬ÊäÈëÈçÏ´úÂë¡£
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#define STACK_SIZE (1024 * 1024)
static char child_stack[STACK_SIZE];
char* const child_args[] = {
"/bin/bash",
NULL
};
int child_main(void* args) {
printf("ÔÚ×Ó½ø³ÌÖÐ!\n");
execv(child_args[0], child_args);
return 1;
}
int main() {
printf("³ÌÐò¿ªÊ¼: \n");
int child_pid = clone(child_main, child_stack + STACK_SIZE, SIGCHLD, NULL);
waitpid(child_pid, NULL, 0);
printf("ÒÑÍ˳ö\n");
return 0;
} |
±àÒë²¢ÔËÐÐÉÏÊö´úÂ룬ִÐÐÈçÏÂÃüÁЧ¹ûÈçÏ¡£
root@local:~# gcc -Wall uts.c -o uts.o && ./uts.o ³ÌÐò¿ªÊ¼: ÔÚ×Ó½ø³ÌÖÐ! root@local:~# exit exit ÒÑÍ˳ö root@local:~# |
ÏÂÃæ£¬ÎÒÃǽ«Ð޸ĴúÂ룬¼ÓÈëUTS¸ôÀë¡£ÔËÐдúÂëÐèÒªrootȨÏÞ£¬ÎªÁË·ÀÖ¹ÆÕͨÓû§ÈÎÒâÐÞ¸ÄϵͳÖ÷»úÃûµ¼ÖÂset-user-IDÏà¹ØµÄÓ¦ÓÃÔËÐгö´í¡£
//[...] int child_main(void* arg) { printf("ÔÚ×Ó½ø³ÌÖÐ!\n"); sethostname("Changed Namespace", 12); execv(child_args[0], child_args); return 1; }
int main() { //[...] int child_pid = clone(child_main, child_stack+STACK_SIZE, CLONE_NEWUTS | SIGCHLD, NULL); //[...] }
|
ÔÙ´ÎÔËÐпÉÒÔ¿´µ½hostnameÒѾ±ä»¯¡£
root@local:~# gcc -Wall namespace.c -o main.o && ./main.o ³ÌÐò¿ªÊ¼: ÔÚ×Ó½ø³ÌÖÐ! root@NewNamespace:~# exit exit ÒÑÍ˳ö root@local:~# <- »Øµ½ÔÀ´µÄhostname |
Ò²ÐíÓжÁÕßÊÔ×Ų»¼ÓCLONE_NEWUTS²ÎÊýÔËÐÐÉÏÊö´úÂ룬·¢ÏÖÖ÷»úÃûÒ²±äÁË£¬ÊäÈëexitÒÔºóÖ÷»úÃûÒ²»á±ä»ØÀ´£¬ËƺõÃ»Ê²Ã´Çø±ð¡£Êµ¼ÊÉϲ»¼ÓCLONE_NEWUTS²ÎÊý½øÐиôÀë¶øÊ¹ÓÃsethostnameÒѾ°ÑËÞÖ÷»úµÄÖ÷»úÃû¸ÄµôÁË¡£Äã¿´µ½exitÍ˳öºó»¹ÔÖ»ÊÇÒòΪbashÖ»ÔڸյǼµÄʱºò¶Áȡһ´ÎUTS£¬µ±ÄãÖØÐµÇ½»òÕßʹÓÃunameÃüÁî½øÐв鿴ʱ£¬¾Í»á·¢ÏÖ²úÉúÁ˱仯¡£
DockerÖУ¬Ã¿¸ö¾µÏñ»ù±¾¶¼ÒÔ×Ô¼ºËùÌṩµÄ·þÎñÃüÃûÁË×Ô¼ºµÄhostname¶øÃ»ÓжÔËÞÖ÷»ú²úÉúÈκÎÓ°Ï죬ÓõľÍÊÇÕâ¸öÔÀí¡£
3. IPC£¨Interprocess Communication£©namespace
ÈÝÆ÷Öнø³Ì¼äͨÐŲÉÓõķ½·¨°üÀ¨³£¼ûµÄÐźÅÁ¿¡¢ÏûÏ¢¶ÓÁк͹²ÏíÄڴ档Ȼ¶øÓëÐéÄâ»ú²»Í¬µÄÊÇ£¬ÈÝÆ÷ÄÚ²¿½ø³Ì¼äͨÐŶÔËÞÖ÷»úÀ´Ëµ£¬Êµ¼ÊÉÏÊǾßÓÐÏàͬPID
namespaceÖеĽø³Ì¼äͨÐÅ£¬Òò´ËÐèÒªÒ»¸öΨһµÄ±êʶ·ûÀ´½øÐÐÇø±ð¡£ÉêÇëIPC×ÊÔ´¾ÍÉêÇëÁËÕâÑùÒ»¸öÈ«¾ÖΨһµÄ32λID£¬ËùÒÔIPC
namespaceÖÐʵ¼ÊÉϰüº¬ÁËϵͳIPC±êʶ·ûÒÔ¼°ÊµÏÖPOSIXÏûÏ¢¶ÓÁеÄÎļþϵͳ¡£ÔÚͬһ¸öIPC namespaceϵĽø³Ì±Ë´Ë¿É¼û£¬¶øÓëÆäËûµÄIPC
namespaceϵĽø³ÌÔò»¥Ï಻¿É¼û¡£
IPC namespaceÔÚ´úÂëÉϵı仯ÓëUTS namespaceÏàËÆ£¬Ö»ÊDZêʶλÓÐËù±ä»¯£¬ÐèÒª¼ÓÉÏCLONE_NEWIPC²ÎÊý¡£Ö÷Òª¸Ä¶¯ÈçÏ£¬ÆäËû²¿Î»²»±ä£¬³ÌÐòÃû³Æ¸ÄΪipc.c¡££¨²âÊÔ·½·¨²Î¿¼×Ô£ºhttp://crosbymichael.com/creating-containers-part-1.html£©
//[...] int child_pid = clone(child_main, child_stack+STACK_SIZE, CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD, NULL); //[...] |
ÎÒÃÇÊ×ÏÈÔÚshellÖÐʹÓÃipcmk -QÃüÁî´´½¨Ò»¸ömessage queue¡£
root@local:~# ipcmk -Q Message queue id: 32769 |
ͨ¹ýipcs -q¿ÉÒԲ鿴µ½ÒѾ¿ªÆôµÄmessage queue£¬ÐòºÅΪ32769¡£
root@local:~# ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages 0x4cf5e29f 32769 root 644 0 0 |
È»ºóÎÒÃÇ¿ÉÒÔ±àÒëÔËÐмÓÈëÁËIPC namespace¸ôÀëµÄipc.c£¬ÔÚн¨µÄ×Ó½ø³ÌÖе÷ÓõÄshellÖÐÖ´ÐÐipcs
-q²é¿´message queue¡£
root@local:~# gcc -Wall ipc.c -o ipc.o && ./ipc.o ³ÌÐò¿ªÊ¼: ÔÚ×Ó½ø³ÌÖÐ! root@NewNamespace:~# ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages root@NewNamespace:~# exit exit ÒÑÍ˳ö |
ÉÏÃæµÄ½á¹ûÏÔʾÖпÉÒÔ·¢ÏÖ£¬ÒѾÕÒ²»µ½ÔÏÈÉùÃ÷µÄmessage queue£¬ÊµÏÖÁËIPCµÄ¸ôÀë¡£
ĿǰʹÓÃIPC namespace»úÖÆµÄϵͳ²»¶à£¬ÆäÖбȽÏÓÐÃûµÄÓÐPostgreSQL¡£Docker±¾Éíͨ¹ýsocket»òtcp½øÐÐͨÐÅ¡£
4. PID namespace
PID namespace¸ôÀë·Ç³£ÊµÓã¬Ëü¶Ô½ø³ÌPIDÖØÐ±êºÅ£¬¼´Á½¸ö²»Í¬namespaceϵĽø³Ì¿ÉÒÔÓÐͬһ¸öPID¡£Ã¿¸öPID
namespace¶¼ÓÐ×Ô¼ºµÄ¼ÆÊý³ÌÐò¡£ÄÚºËΪËùÓеÄPID namespaceά»¤ÁËÒ»¸öÊ÷×´½á¹¹£¬×î¶¥²ãµÄÊÇϵͳ³õʼʱ´´½¨µÄ£¬ÎÒÃdzÆÖ®Îªroot
namespace¡£Ëû´´½¨µÄÐÂPID namespace¾Í³ÆÖ®Îªchild namespace£¨Ê÷µÄ×ӽڵ㣩£¬¶øÔÏȵÄPID
namespace¾ÍÊÇд´½¨µÄPID namespaceµÄparent namespace£¨Ê÷µÄ¸¸½Úµã£©¡£Í¨¹ýÕâÖÖ·½Ê½£¬²»Í¬µÄPID
namespaces»áÐγÉÒ»¸öµÈ¼¶Ìåϵ¡£ËùÊôµÄ¸¸½Úµã¿ÉÒÔ¿´µ½×Ó½ÚµãÖеĽø³Ì£¬²¢¿ÉÒÔͨ¹ýÐźŵȷ½Ê½¶Ô×Ó½ÚµãÖеĽø³Ì²úÉúÓ°Ïì¡£·´¹ýÀ´£¬×ӽڵ㲻ÄÜ¿´µ½¸¸½ÚµãPID
namespaceÖеÄÈκÎÄÚÈÝ¡£Óɴ˲úÉúÈçϽáÂÛ£¨²¿·ÖÄÚÈÝÒý×Ô£ºhttp://blog.dotcloud.com/under-the-hood-linux-kernels-on-dotcloud-part£©¡£
ÿ¸öPID namespaceÖеĵÚÒ»¸ö½ø³Ì¡°PID 1¡°£¬¶¼»áÏñ´«Í³LinuxÖеÄinit½ø³ÌÒ»ÑùÓµÓÐÌØÈ¨£¬ÆðÌØÊâ×÷Óá£
Ò»¸önamespaceÖеĽø³Ì£¬²»¿ÉÄÜͨ¹ýkill»òptraceÓ°Ï츸½Úµã»òÕßÐֵܽڵãÖеĽø³Ì£¬ÒòΪÆäËû½ÚµãµÄPIDÔÚÕâ¸önamespaceÖÐûÓÐÈκÎÒâÒå¡£
Èç¹ûÄãÔÚеÄPID namespaceÖÐÖØÐ¹ÒÔØ/procÎļþϵͳ£¬»á·¢ÏÖÆäÏÂÖ»ÏÔʾͬÊôÒ»¸öPID namespaceÖÐµÄÆäËû½ø³Ì¡£
ÔÚroot namespaceÖпÉÒÔ¿´µ½ËùÓеĽø³Ì£¬²¢Çҵݹé°üº¬ËùÓÐ×Ó½ÚµãÖеĽø³Ì¡£
µ½ÕâÀ¿ÉÄÜÄãÒѾÁªÏëµ½Ò»ÖÖÔÚÍⲿ¼à¿ØDockerÖÐÔËÐгÌÐòµÄ·½·¨ÁË£¬¾ÍÊÇ¼à¿ØDocker
DaemonËùÔÚµÄPID namespaceϵÄËùÓнø³Ì¼´Æä×Ó½ø³Ì£¬ÔÙ½øÐÐɾѡ¼´¿É¡£
ÏÂÃæÎÒÃÇͨ¹ýÔËÐдúÂëÀ´¸ÐÊÜÒ»ÏÂPID namespaceµÄ¸ôÀëЧ¹û¡£ÐÞ¸ÄÉÏÎĵĴúÂ룬¼ÓÈëPID namespaceµÄ±êʶ룬²¢°Ñ³ÌÐòÃüÃûΪpid.c¡£
//[...] int child_pid = clone(child_main, child_stack+STACK_SIZE, CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD, NULL); //[...] |
±àÒëÔËÐпÉÒÔ¿´µ½ÈçϽá¹û¡£
root@local:~# gcc -Wall pid.c -o pid.o && ./pid.o ³ÌÐò¿ªÊ¼: ÔÚ×Ó½ø³ÌÖÐ! root@NewNamespace:~# echo $$ 1 <<--×¢Òâ´Ë´¦¿´µ½shellµÄPID±ä³ÉÁË1 root@NewNamespace:~# exit exit ÒÑÍ˳ö |
´òÓ¡$$¿ÉÒÔ¿´µ½shellµÄPID£¬Í˳öºóÈç¹ûÔÙ´ÎÖ´ÐпÉÒÔ¿´µ½Ð§¹ûÈçÏ¡£
root@local:~# echo $$ 17542 |
ÒѾ»Øµ½ÁËÕý³£×´Ì¬¡£¿ÉÄÜÓеĶÁÕßÔÚ×Ó½ø³ÌµÄshellÖÐÖ´ÐÐÁËps aux/topÖ®ÀàµÄÃüÁ·¢ÏÖ»¹ÊÇ¿ÉÒÔ¿´µ½ËùÓи¸½ø³ÌµÄPID£¬ÄÇÊÇÒòΪÎÒÃÇ»¹Ã»ÓжÔÎļþϵͳ½øÐиôÀ룬ps/topÖ®ÀàµÄÃüÁîµ÷ÓõÄÊÇÕæÊµÏµÍ³ÏµÄ/procÎļþÄÚÈÝ£¬¿´µ½µÄ×ÔÈ»ÊÇËùÓеĽø³Ì¡£
´ËÍ⣬ÓëÆäËûµÄnamespace²»Í¬µÄÊÇ£¬ÎªÁËʵÏÖÒ»¸öÎȶ¨°²È«µÄÈÝÆ÷£¬PID namespace»¹ÐèÒª½øÐÐһЩ¶îÍâµÄ¹¤×÷²ÅÄÜÈ·±£ÆäÖеĽø³ÌÔËÐÐ˳Àû¡£
£¨1£©PID namespaceÖеÄinit½ø³Ì
µ±ÎÒÃÇн¨Ò»¸öPID namespaceʱ£¬Ä¬ÈÏÆô¶¯µÄ½ø³ÌPIDΪ1¡£ÎÒÃÇÖªµÀ£¬ÔÚ´«Í³µÄUNIXϵͳÖУ¬PIDΪ1µÄ½ø³ÌÊÇinit£¬µØÎ»·Ç³£ÌØÊâ¡£Ëû×÷ΪËùÓнø³ÌµÄ¸¸½ø³Ì£¬Î¬»¤Ò»ÕŽø³Ì±í£¬²»¶Ï¼ì²é½ø³ÌµÄ״̬£¬Ò»µ©ÓÐij¸ö×Ó½ø³ÌÒòΪ³ÌÐò´íÎó³ÉΪÁË¡°¹Â¶ù¡±½ø³Ì£¬init¾Í»á¸ºÔð»ØÊÕ×ÊÔ´²¢½áÊøÕâ¸ö×Ó½ø³Ì¡£ËùÒÔÔÚÄãҪʵÏÖµÄÈÝÆ÷ÖУ¬Æô¶¯µÄµÚÒ»¸ö½ø³ÌÒ²ÐèҪʵÏÖÀàËÆinitµÄ¹¦ÄÜ£¬Î¬»¤ËùÓкóÐøÆô¶¯½ø³ÌµÄÔËÐÐ״̬¡£
¿´µ½ÕâÀ¿ÉÄܶÁÕßÒѾÃ÷°×ÁËÄÚºËÉè¼ÆµÄÁ¼¿àÓÃÐÄ¡£PID namespaceά»¤ÕâÑùÒ»¸öÊ÷×´½á¹¹£¬·Ç³£ÓÐÀûÓÚϵͳµÄ×ÊÔ´¼à¿ØÓë»ØÊÕ¡£DockerÆô¶¯Ê±£¬µÚÒ»¸ö½ø³ÌÒ²ÊÇÕâÑù£¬ÊµÏÖÁ˽ø³Ì¼à¿ØºÍ×ÊÔ´»ØÊÕ£¬Ëü¾ÍÊÇdockerinit¡£
£¨2£©ÐźÅÓëinit½ø³Ì
PID namespaceÖеÄinit½ø³ÌÈç´ËÌØÊ⣬×ÔÈ»ÄÚºËҲΪËû¸³ÓèÁËÌØÈ¨¡ª¡ªÐÅºÅÆÁ±Î¡£Èç¹ûinitÖÐûÓÐд´¦Àíij¸öÐźŵĴúÂëÂß¼£¬ÄÇôÓëinitÔÚͬһ¸öPID
namespaceϵĽø³Ì£¨¼´Ê¹Óг¬¼¶È¨ÏÞ£©·¢Ë͸øËüµÄ¸ÃÐźŶ¼»á±»ÆÁ±Î¡£Õâ¸ö¹¦ÄܵÄÖ÷Òª×÷ÓÃÊÇ·ÀÖ¹init½ø³Ì±»Îóɱ¡£
ÄÇôÆä¸¸½ÚµãPID namespaceÖеĽø³Ì·¢ËÍͬÑùµÄÐźŻᱻºöÂÔÂ𣿸¸½ÚµãÖеĽø³Ì·¢Ë͵ÄÐźţ¬Èç¹û²»ÊÇSIGKILL£¨Ïú»Ù½ø³Ì£©»òSIGSTOP£¨ÔÝÍ£½ø³Ì£©Ò²»á±»ºöÂÔ¡£µ«Èç¹û·¢ËÍSIGKILL»òSIGSTOP£¬×Ó½ÚµãµÄinit»áÇ¿ÖÆÖ´ÐУ¨ÎÞ·¨Í¨¹ý´úÂë²¶×½½øÐÐÌØÊâ´¦Àí£©£¬Ò²¾ÍÊÇ˵¸¸½ÚµãÖеĽø³ÌÓÐȨÖÕÖ¹×Ó½ÚµãÖеĽø³Ì¡£
Ò»µ©init½ø³Ì±»Ïú»Ù£¬Í¬Ò»PID namespaceÖÐµÄÆäËû½ø³ÌÒ²»áËæÖ®½ÓÊÕµ½SIGKILLÐźŶø±»Ïú»Ù¡£ÀíÂÛÉÏ£¬¸ÃPID
namespace×ÔȻҲ¾Í²»¸´´æÔÚÁË¡£µ«ÊÇÈç¹û/proc/[pid]/ns/pid´¦ÓÚ±»¹ÒÔØ»òÕß´ò¿ª×´Ì¬£¬namespace¾Í»á±»±£ÁôÏÂÀ´¡£È»¶ø£¬±£ÁôÏÂÀ´µÄnamespaceÎÞ·¨Í¨¹ýsetns()»òÕßfork()´´½¨½ø³Ì£¬ËùÒÔʵ¼ÊÉϲ¢Ã»ÓÐʲô×÷Óá£
ÎÒÃdz£Ëµ£¬DockerÒ»µ©Æô¶¯¾ÍÓнø³ÌÔÚÔËÐУ¬²»´æÔÚ²»°üº¬Èκνø³ÌµÄDocker£¬Ò²¾ÍÊÇÕâ¸öµÀÀí¡£
£¨3£©¹ÒÔØprocÎļþϵͳ
ǰÎÄÖÐÒѾÌáµ½£¬Èç¹ûÄãÔÚеÄPID namespaceÖÐʹÓÃpsÃüÁî²é¿´£¬¿´µ½µÄ»¹ÊÇËùÓеĽø³Ì£¬ÒòΪÓëPIDÖ±½ÓÏà¹ØµÄ/procÎļþϵͳ£¨procfs£©Ã»ÓйÒÔØµ½ÓëÔ/proc²»Í¬µÄλÖá£ËùÒÔÈç¹ûÄãÖ»Ïë¿´µ½PID
namespace±¾ÉíÓ¦¸Ã¿´µ½µÄ½ø³Ì£¬ÐèÒªÖØÐ¹ÒÔØ/proc£¬ÃüÁîÈçÏ¡£
root@NewNamespace:~# mount -t proc proc /proc root@NewNamespace:~# ps a PID TTY STAT TIME COMMAND 1 pts/1 S 0:00 /bin/bash 12 pts/1 R+ 0:00 ps a |
¿ÉÒÔ¿´µ½Êµ¼ÊµÄPID namespace¾ÍÖ»ÓÐÁ½¸ö½ø³ÌÔÚÔËÐС£
×¢Ò⣺ÒòΪ´ËʱÎÒÃÇûÓнøÐÐmount namespaceµÄ¸ôÀ룬ËùÒÔÕâÒ»²½²Ù×÷ʵ¼ÊÉÏÒѾӰÏìÁË root
namespaceµÄÎļþϵͳ£¬µ±ÄãÍ˳öн¨µÄPID namespaceÒÔºóÔÙÖ´ÐÐps a¾Í»á·¢ÏÖ³ö´í£¬ÔÙ´ÎÖ´ÐÐmount
-t proc proc /proc¿ÉÒÔÐÞ¸´´íÎó¡£
£¨4£©unshare()ºÍsetns()
ÔÚ¿ªÆªÎÒÃǾͽ²µ½ÁËunshare()ºÍsetns()ÕâÁ½¸öAPI£¬¶øÕâÁ½¸öAPIÔÚPID namespaceÖÐʹÓÃʱ£¬Ò²ÓÐÒ»Ð©ÌØ±ðÖ®´¦ÐèҪעÒâ¡£
unshare()ÔÊÐíÓû§ÔÚÔÓнø³ÌÖн¨Á¢namespace½øÐиôÀë¡£µ«ÊÇ´´½¨ÁËPID namespaceºó£¬ÔÏÈunshare()µ÷ÓÃÕß½ø³Ì²¢²»½øÈëеÄPID
namespace£¬½ÓÏÂÀ´´´½¨µÄ×Ó½ø³Ì²Å»á½øÈëеÄnamespace£¬Õâ¸ö×Ó½ø³ÌÒ²¾ÍËæÖ®³ÉΪÐÂnamespaceÖеÄinit½ø³Ì¡£
ÀàËÆµÄ£¬µ÷ÓÃsetns()´´½¨ÐÂPID namespaceʱ£¬µ÷ÓÃÕß½ø³ÌÒ²²»½øÈëеÄPID namespace£¬¶øÊÇËæºó´´½¨µÄ×Ó½ø³Ì½øÈë¡£
Ϊʲô´´½¨ÆäËûnamespaceʱunshare()ºÍsetns()»áÖ±½Ó½øÈëеÄnamespace¶øÎ¨¶ÀPID
namespace²»ÊÇÈç´ËÄØ£¿ÒòΪµ÷ÓÃgetpid()º¯ÊýµÃµ½µÄPIDÊǸù¾Ýµ÷ÓÃÕßËùÔÚµÄPID namespace¶ø¾ö¶¨·µ»ØÄĸöPID£¬½øÈëеÄPID
namespace»áµ¼ÖÂPID²úÉú±ä»¯¡£¶ø¶ÔÓû§Ì¬µÄ³ÌÐòºÍ¿âº¯ÊýÀ´Ëµ£¬ËûÃǶ¼ÈÏΪ½ø³ÌµÄPIDÊÇÒ»¸ö³£Á¿£¬PIDµÄ±ä»¯»áÒýÆðÕâЩ½ø³Ì±¼À£¡£
»»¾ä»°Ëµ£¬Ò»µ©³ÌÐò½ø³Ì´´½¨ÒÔºó£¬ÄÇôËüµÄPID namespaceµÄ¹ØÏµ¾ÍÈ·¶¨ÏÂÀ´ÁË£¬½ø³Ì²»»á±ä¸üËûÃǶÔÓ¦µÄPID
namespace¡£
5. Mount namespaces
Mount namespaceͨ¹ý¸ôÀëÎļþϵͳ¹ÒÔØµã¶Ô¸ôÀëÎļþϵͳÌṩ֧³Ö£¬ËüÊÇÀúÊ·ÉϵÚÒ»¸öLinux
namespace£¬ËùÒÔËüµÄ±êʶλ±È½ÏÌØÊ⣬¾ÍÊÇCLONE_NEWNS¡£¸ôÀëºó£¬²»Í¬mount namespaceÖеÄÎļþ½á¹¹·¢Éú±ä»¯Ò²»¥²»Ó°Ïì¡£Äã¿ÉÒÔͨ¹ý/proc/[pid]/mounts²é¿´µ½ËùÓйÒÔØÔÚµ±Ç°namespaceÖеÄÎļþϵͳ£¬»¹¿ÉÒÔͨ¹ý/proc/[pid]/mountstats¿´µ½mount
namespaceÖÐÎļþÉ豸µÄͳ¼ÆÐÅÏ¢£¬°üÀ¨¹ÒÔØÎļþµÄÃû×Ö¡¢ÎļþϵͳÀàÐÍ¡¢¹ÒÔØÎ»Öõȵȡ£
½ø³ÌÔÚ´´½¨mount namespaceʱ£¬»á°Ñµ±Ç°µÄÎļþ½á¹¹¸´ÖƸøÐµÄnamespace¡£ÐÂnamespaceÖеÄËùÓÐmount²Ù×÷¶¼Ö»Ó°Ïì×ÔÉíµÄÎļþϵͳ£¬¶ø¶ÔÍâ½ç²»»á²úÉúÈκÎÓ°Ïì¡£ÕâÑù×ö·Ç³£ÑϸñµØÊµÏÖÁ˸ôÀ룬µ«ÊÇijЩÇé¿ö¿ÉÄܲ¢²»ÊÊÓᣱÈÈ縸½ÚµãnamespaceÖеĽø³Ì¹ÒÔØÁËÒ»ÕÅCD-ROM£¬Õâʱ×Ó½Úµãnamespace¿½±´µÄĿ¼½á¹¹¾ÍÎÞ·¨×Ô¶¯¹ÒÔØÉÏÕâÕÅCD-ROM£¬ÒòΪÕâÖÖ²Ù×÷»áÓ°Ïìµ½¸¸½ÚµãµÄÎļþϵͳ¡£
2006 ÄêÒýÈëµÄ¹ÒÔØ´«²¥£¨mount propagation£©½â¾öÁËÕâ¸öÎÊÌ⣬¹ÒÔØ´«²¥¶¨ÒåÁ˹ÒÔØ¶ÔÏó£¨mount
object£©Ö®¼äµÄ¹ØÏµ£¬ÏµÍ³ÓÃÕâЩ¹ØÏµ¾ö¶¨ÈκιÒÔØ¶ÔÏóÖеĹÒÔØÊ¼þÈçºÎ´«²¥µ½ÆäËû¹ÒÔØ¶ÔÏ󣨲ο¼×Ô£ºhttp://www.ibm.com/developerworks/library/l-mount-namespaces/£©¡£Ëùν´«²¥Ê¼þ£¬ÊÇÖ¸ÓÉÒ»¸ö¹ÒÔØ¶ÔÏóµÄ״̬±ä»¯µ¼ÖÂµÄÆäËü¹ÒÔØ¶ÔÏóµÄ¹ÒÔØÓë½â³ý¹ÒÔØ¶¯×÷µÄʼþ¡£
¹²Ïí¹ØÏµ£¨share relationship£©¡£Èç¹ûÁ½¸ö¹ÒÔØ¶ÔÏó¾ßÓй²Ïí¹ØÏµ£¬ÄÇôһ¸ö¹ÒÔØ¶ÔÏóÖеĹÒÔØÊ¼þ»á´«²¥µ½ÁíÒ»¸ö¹ÒÔØ¶ÔÏ󣬷´Ö®ÒàÈ»¡£
´ÓÊô¹ØÏµ£¨slave relationship£©¡£Èç¹ûÁ½¸ö¹ÒÔØ¶ÔÏóÐγɴÓÊô¹ØÏµ£¬ÄÇôһ¸ö¹ÒÔØ¶ÔÏóÖеĹÒÔØÊ¼þ»á´«²¥µ½ÁíÒ»¸ö¹ÒÔØ¶ÔÏ󣬵«ÊÇ·´¹ýÀ´²»ÐУ»ÔÚÕâÖÖ¹ØÏµÖУ¬´ÓÊô¶ÔÏóÊÇʼþµÄ½ÓÊÕÕß¡£
Ò»¸ö¹ÒÔØ×´Ì¬¿ÉÄÜΪÈçÏÂµÄÆäÖÐÒ»ÖÖ£º
¹²Ïí¹ÒÔØ£¨shared£©
´ÓÊô¹ÒÔØ£¨slave£©
¹²Ïí/´ÓÊô¹ÒÔØ£¨shared and slave£©
˽ÓйÒÔØ£¨private£©
²»¿É°ó¶¨¹ÒÔØ£¨unbindable£©
´«²¥Ê¼þµÄ¹ÒÔØ¶ÔÏó³ÆÎª¹²Ïí¹ÒÔØ£¨shared mount£©£»½ÓÊÕ´«²¥Ê¼þµÄ¹ÒÔØ¶ÔÏó³ÆÎª´ÓÊô¹ÒÔØ£¨slave
mount£©¡£¼È²»´«²¥Ò²²»½ÓÊÕ´«²¥Ê¼þµÄ¹ÒÔØ¶ÔÏó³ÆÎªË½ÓйÒÔØ£¨private mount£©¡£ÁíÒ»ÖÖÌØÊâµÄ¹ÒÔØ¶ÔÏó³ÆÎª²»¿É°ó¶¨µÄ¹ÒÔØ£¨unbindable
mount£©£¬ËüÃÇÓë˽ÓйÒÔØÏàËÆ£¬µ«ÊDz»ÔÊÐíÖ´Ðа󶨹ÒÔØ£¬¼´´´½¨mount namespaceʱÕâ¿éÎļþ¶ÔÏ󲻿ɱ»¸´ÖÆ¡£

ͼ1 mount¸÷Àà¹ÒÔØ×´Ì¬Ê¾Òâͼ
¹²Ïí¹ÒÔØµÄÓ¦Óó¡¾°·Ç³£Ã÷ÏÔ£¬¾ÍÊÇΪÁËÎļþÊý¾ÝµÄ¹²ÏíËù±ØÐë´æÔÚµÄÒ»ÖÖ¹ÒÔØ·½Ê½£»´ÓÊô¹ÒÔØ¸ü´óµÄÒâÒåÔÚÓÚijЩ¡°Ö»¶Á¡±³¡¾°£»Ë½ÓйÒÔØÆäʵ¾ÍÊÇ´¿´âµÄ¸ôÀ룬×÷Ϊһ¸ö¶ÀÁ¢µÄ¸öÌå¶ø´æÔÚ£»²»¿É°ó¶¨¹ÒÔØÔòÓÐÖúÓÚ·ÀֹûÓбØÒªµÄÎļþ¿½±´£¬Èçij¸öÓû§Êý¾ÝĿ¼£¬µ±¸ùĿ¼±»µÝ¹éʽµÄ¸´ÖÆÊ±£¬Óû§Ä¿Â¼ÎÞÂÛ´ÓÒþ˽»¹ÊÇʵ¼ÊÓÃ;¿¼ÂǶ¼ÐèÒªÓÐÒ»¸ö²»¿É±»¸´ÖƵÄÑ¡Ïî¡£
ĬÈÏÇé¿öÏ£¬ËùÓйÒÔØ¶¼ÊÇ˽Óеġ£ÉèÖÃΪ¹²Ïí¹ÒÔØµÄÃüÁîÈçÏ¡£
mount --make-shared <mount-object> |
´Ó¹²Ïí¹ÒÔØ¿Ë¡µÄ¹ÒÔØ¶ÔÏóÒ²Êǹ²ÏíµÄ¹ÒÔØ£»ËüÃÇÏ໥´«²¥¹ÒÔØÊ¼þ¡£
ÉèÖÃΪ´ÓÊô¹ÒÔØµÄÃüÁîÈçÏ¡£
mount --make-slave <shared-mount-object> |
´Ó´ÓÊô¹ÒÔØ¿Ë¡µÄ¹ÒÔØ¶ÔÏóÒ²ÊÇ´ÓÊôµÄ¹ÒÔØ£¬ËüÒ²´ÓÊôÓÚÔÀ´µÄ´ÓÊô¹ÒÔØµÄÖ÷¹ÒÔØ¶ÔÏó¡£
½«Ò»¸ö´ÓÊô¹ÒÔØ¶ÔÏóÉèÖÃΪ¹²Ïí/´ÓÊô¹ÒÔØ£¬¿ÉÒÔÖ´ÐÐÈçÏÂÃüÁî»òÕß½«ÆäÒÆ¶¯µ½Ò»¸ö¹²Ïí¹ÒÔØ¶ÔÏóÏ¡£
mount --make-shared <slave-mount-object> |
Èç¹ûÄãÏë°ÑÐ޸ĹýµÄ¹ÒÔØ¶ÔÏóÖØÐ±ê¼ÇΪ˽Óеģ¬¿ÉÒÔÖ´ÐÐÈçÏÂÃüÁî¡£
mount --make-private <mount-object> |
ͨ¹ýÖ´ÐÐÒÔÏÂÃüÁ¿ÉÒÔ½«¹ÒÔØ¶ÔÏó±ê¼ÇΪ²»¿É°ó¶¨µÄ¡£
mount --make-unbindable <mount-object> |
ÕâЩÉèÖö¼¿ÉÒԵݹéʽµØÓ¦Óõ½ËùÓÐ×ÓĿ¼ÖУ¬Èç¹û¶ÁÕ߸ÐÐËȤ¿ÉÒÔËÑË÷µ½Ïà¹ØµÄÃüÁî¡£
ÔÚ´úÂëÖÐʵÏÖmount namespace¸ôÀëÓëÆäËûnamespaceÀàËÆ£¬¼ÓÉÏCLONE_NEWNS±êʶλ¼´¿É¡£ÈÃÎÒÃÇÔÙ´ÎÐ޸ĴúÂ룬²¢ÇÒÁí´æÎªmount.c½øÐбàÒëÔËÐС£
//[...] int child_pid = clone(child_main, child_stack+STACK_SIZE, CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD, NULL); //[...] |
Ö´ÐеÄЧ¹û¾ÍÈçͬPID namespaceÒ»½ÚÖС°¹ÒÔØprocÎļþϵͳ¡±µÄÖ´Ðнá¹û£¬Çø±ð¾ÍÊÇÍ˳ömount
namespaceÒÔºó£¬root namespaceµÄÎļþϵͳ²»»á±»ÆÆ»µ£¬´Ë´¦¾Í²»ÔÙÑÝʾÁË¡£
6. Network namespace
ͨ¹ýÉϽڣ¬ÎÒÃÇÁ˽âÁËPID namespace£¬µ±ÎÒÃÇÐËÖ²ª²ªµØÔÚн¨µÄnamespaceÖÐÆô¶¯Ò»¸ö¡°Apache¡±½ø³Ìʱ£¬È´³öÏÖÁË¡°80¶Ë¿ÚÒѱ»Õ¼ÓᱵĴíÎó£¬ÔÀ´Ö÷»úÉÏÒѾÔËÐÐÁËÒ»¸ö¡°Apache¡±½ø³Ì¡£Ôõô°ì£¿Õâ¾ÍÐèÒªÓõ½network
namespace¼¼Êõ½øÐÐÍøÂç¸ôÀëÀ²¡£
Network namespaceÖ÷ÒªÌṩÁ˹ØÓÚÍøÂç×ÊÔ´µÄ¸ôÀ룬°üÀ¨ÍøÂçÉ豸¡¢IPv4ºÍIPv6ÐÒéÕ»¡¢IP·ÓÉ±í¡¢·À»ðǽ¡¢/proc/netĿ¼¡¢/sys/class/netĿ¼¡¢¶Ë¿Ú£¨socket£©µÈµÈ¡£Ò»¸öÎïÀíµÄÍøÂçÉ豸×î¶à´æÔÚÔÚÒ»¸önetwork
namespaceÖУ¬Äã¿ÉÒÔͨ¹ý´´½¨veth pair£¨ÐéÄâÍøÂçÉ豸¶Ô£ºÓÐÁ½¶Ë£¬ÀàËÆ¹ÜµÀ£¬Èç¹ûÊý¾Ý´ÓÒ»¶Ë´«ÈëÁíÒ»¶ËÒ²ÄܽÓÊÕµ½£¬·´Ö®ÒàÈ»£©ÔÚ²»Í¬µÄnetwork
namespace¼ä´´½¨Í¨µÀ£¬ÒԴ˴ﵽͨÐŵÄÄ¿µÄ¡£
Ò»°ãÇé¿öÏ£¬ÎïÀíÍøÂçÉ豸¶¼·ÖÅäÔÚ×î³õµÄroot namespace£¨±íʾϵͳĬÈϵÄnamespace£¬ÔÚPID
namespaceÖÐÒѾÌá¼°£©ÖС£µ«ÊÇÈç¹ûÄãÓжà¿éÎïÀíÍø¿¨£¬Ò²¿ÉÒÔ°ÑÆäÖÐÒ»¿é»ò¶à¿é·ÖÅ䏸д´½¨µÄnetwork
namespace¡£ÐèҪעÒâµÄÊÇ£¬µ±Ð´´½¨µÄnetwork namespace±»ÊÍ·Åʱ£¨ËùÓÐÄÚ²¿µÄ½ø³Ì¶¼ÖÕÖ¹²¢ÇÒnamespaceÎļþûÓб»¹ÒÔØ»ò´ò¿ª£©£¬ÔÚÕâ¸önamespaceÖеÄÎïÀíÍø¿¨»á·µ»Øµ½root
namespace¶ø·Ç´´½¨¸Ã½ø³ÌµÄ¸¸½ø³ÌËùÔÚµÄnetwork namespace¡£
µ±ÎÒÃÇ˵µ½network namespaceʱ£¬ÆäʵÎÒÃÇÖ¸µÄδ±ØÊÇÕæÕýµÄÍøÂç¸ôÀ룬¶øÊǰÑÍøÂç¶ÀÁ¢³öÀ´£¬¸øÍⲿÓû§Ò»ÖÖ͸Ã÷µÄ¸Ð¾õ£¬·Â·ð¸úÁíÍâÒ»¸öÍøÂçʵÌåÔÚ½øÐÐͨÐÅ¡£ÎªÁË´ïµ½Õâ¸öÄ¿µÄ£¬ÈÝÆ÷µÄ¾µä×ö·¨¾ÍÊÇ´´½¨Ò»¸öveth
pair£¬Ò»¶Ë·ÅÖÃÔÚеÄnamespaceÖУ¬Í¨³£ÃüÃûΪeth0£¬Ò»¶Ë·ÅÔÚÔÏȵÄnamespaceÖÐÁ¬½ÓÎïÀíÍøÂçÉ豸£¬ÔÙͨ¹ýÍøÇŰѱðµÄÉ豸Á¬½Ó½øÀ´»òÕß½øÐзÓÉת·¢£¬ÒÔ´ËÍøÂçʵÏÖͨÐŵÄÄ¿µÄ¡£
Ò²ÐíÓжÁÕß»áºÃÆæ£¬ÔÚ½¨Á¢Æðveth pair֮ǰ£¬Ð¾Énamespace¸ÃÈçºÎͨÐÅÄØ£¿´ð°¸ÊÇpipe£¨¹ÜµÀ£©¡£ÎÒÃÇÒÔDocker
DaemonÔÚÆô¶¯ÈÝÆ÷dockerinitµÄ¹ý³ÌΪÀý¡£Docker DaemonÔÚËÞÖ÷»úÉϸºÔð´´½¨Õâ¸öveth
pair£¬Í¨¹ýnetlinkµ÷Ó㬰ÑÒ»¶Ë°ó¶¨µ½docker0ÍøÇÅÉÏ£¬Ò»¶ËÁ¬½øÐ½¨µÄnetwork namespace½ø³ÌÖС£½¨Á¢µÄ¹ý³ÌÖУ¬Docker
DaemonºÍdockerinit¾Íͨ¹ýpipe½øÐÐͨÐÅ£¬µ±Docker DaemonÍê³Éveth-pairµÄ´´½¨Ö®Ç°£¬dockerinitÔڹܵÀµÄÁíÒ»¶ËÑ»·µÈ´ý£¬Ö±µ½¹ÜµÀÁíÒ»¶Ë´«À´Docker
Daemon¹ØÓÚvethÉ豸µÄÐÅÏ¢£¬²¢¹Ø±Õ¹ÜµÀ¡£dockerinit²Å½áÊøµÈ´ýµÄ¹ý³Ì£¬²¢°ÑËüµÄ¡°eth0¡±Æô¶¯ÆðÀ´¡£Õû¸öЧ¹ûÀàËÆÏÂͼËùʾ¡£

ͼ2 DockerÍøÂçʾÒâͼ
¸úÆäËûnamespaceÀàËÆ£¬¶Ônetwork namespaceµÄʹÓÃÆäʵ¾ÍÊÇÔÚ´´½¨µÄʱºòÌí¼ÓCLONE_NEWNET±êʶλ¡£Ò²¿ÉÒÔͨ¹ýÃüÁîÐй¤¾ßip´´½¨network
namespace¡£ÔÚ´úÂëÖн¨Á¢ºÍ²âÊÔnetwork namespace½ÏΪ¸´ÔÓ£¬ËùÒÔÏÂÎÄÖ÷Ҫͨ¹ýipÃüÁîÖ±¹ÛµÄ¸ÐÊÜÕû¸önetwork
namespaceÍøÂ罨Á¢ºÍÅäÖõĹý³Ì¡£
Ê×ÏÈÎÒÃÇ¿ÉÒÔ´´½¨Ò»¸öÃüÃûΪtest_nsµÄnetwork namespace¡£
µ±ipÃüÁ¾ß´´½¨Ò»¸önetwork namespaceʱ£¬»áĬÈÏ´´½¨Ò»¸ö»Ø»·É豸£¨loopback
interface£ºlo£©£¬²¢ÔÚ/var/run/netnsĿ¼Ï°ó¶¨Ò»¸ö¹ÒÔØµã£¬Õâ¾Í±£Ö¤Á˾ÍËãnetwork
namespaceÖÐûÓнø³ÌÔÚÔËÐÐÒ²²»»á±»ÊÍ·Å£¬Ò²¸øÏµÍ³¹ÜÀíÔ±¶Ôд´½¨µÄnetwork namespace½øÐÐÅäÖÃÌṩÁ˳ä×ãµÄʱ¼ä¡£
ͨ¹ýip netns execÃüÁî¿ÉÒÔÔÚд´½¨µÄnetwork namespaceÏÂÔËÐÐÍøÂç¹ÜÀíÃüÁî¡£
# ip netns exec test_ns ip link list 3: lo: <LOOPBACK> mtu 16436 qdisc noop state DOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 |
ÉÏÃæµÄÃüÁîΪÎÒÃÇչʾÁËн¨µÄnamespaceÏ¿ɼûµÄÍøÂçÁ´½Ó£¬¿ÉÒÔ¿´µ½×´Ì¬ÊÇDOWN,ÐèÒªÔÙͨ¹ýÃüÁîÈ¥Æô¶¯¡£¿ÉÒÔ¿´µ½£¬´ËʱִÐÐpingÃüÁîÊÇÎÞЧµÄ¡£
# ip netns exec test_ns ping 127.0.0.1 connect: Network is unreachable |
Æô¶¯ÃüÁîÈçÏ£¬¿ÉÒÔ¿´µ½Æô¶¯ºóÔÙ²âÊԾͿÉÒÔpingͨ¡£
# ip netns exec test_ns ip link set dev lo up # ip netns exec test_ns ping 127.0.0.1 PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data. 64 bytes from 127.0.0.1: icmp_req=1 ttl=64 time=0.050 ms ... |
ÕâÑùÖ»ÊÇÆô¶¯Á˱¾µØµÄ»Ø»·£¬ÒªÊµÏÖÓëÍⲿnamespace½øÐÐͨÐÅ»¹ÐèÒªÔÙ½¨Ò»¸öÍøÂçÉ豸¶Ô£¬ÃüÁîÈçÏ¡£
# ip link add veth0 type veth peer name veth1 # ip link set veth1 netns test_ns # ip netns exec test_ns ifconfig veth1 10.1.1.1/24 up # ifconfig veth0 10.1.1.2/24 up |
µÚÒ»ÌõÃüÁî´´½¨ÁËÒ»¸öÍøÂçÉ豸¶Ô£¬ËùÓз¢Ë͵½veth0µÄ°üveth1Ò²ÄܽÓÊÕµ½£¬·´Ö®ÒàÈ»¡£
µÚ¶þÌõÃüÁîÔòÊǰÑveth1ÕâÒ»¶Ë·ÖÅäµ½test_nsÕâ¸önetwork
namespace¡£
µÚÈý¡¢µÚËÄÌõÃüÁî·Ö±ð¸øtest_nsÄÚ²¿ºÍÍⲿµÄÍøÂçÉ豸ÅäÖÃIP£¬veth1µÄIPΪ10.1.1.1£¬veth0µÄIPΪ10.1.1.2¡£
´ËʱÁ½±ß¾Í¿ÉÒÔ»¥ÏàÁ¬Í¨ÁË£¬Ð§¹ûÈçÏ¡£
# ping 10.1.1.1 PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data. 64 bytes from 10.1.1.1: icmp_req=1 ttl=64 time=0.095 ms ... # ip netns exec test_ns ping 10.1.1.2 PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data. 64 bytes from 10.1.1.2: icmp_req=1 ttl=64 time=0.049 ms ... |
¶ÁÕßÓÐÐËȤ¿ÉÒÔͨ¹ýÏÂÃæµÄÃüÁî²é¿´£¬ÐµÄtest_nsÓÐ×Å×Ô¼º¶ÀÁ¢µÄ·ÓɺÍiptables¡£
ip netns exec test_ns route ip netns exec test_ns iptables -L |
·ÓɱíÖÐÖ»ÓÐÒ»ÌõͨÏò10.1.1.2µÄ¹æÔò£¬´ËʱÈç¹ûÒªÁ¬½ÓÍâÍø¿Ï¶¨ÊDz»¿ÉÄܵģ¬Äã¿ÉÒÔͨ¹ý½¨Á¢ÍøÇÅ»òÕßNATÓ³ÉäÀ´¾ö¶¨Õâ¸öÎÊÌâ¡£Èç¹ûÄã¶Ô´Ë·Ç³£¸ÐÐËȤ£¬¿ÉÒÔÔĶÁDockerÍøÂçÏà¹ØÎÄÕ½øÐиüÉîÈëµÄ½²½â¡£
×öÍêÕâЩʵÑ飬Ä㻹¿ÉÒÔͨ¹ýÏÂÃæµÄÃüÁîɾ³ýÕâ¸önetwork namespace¡£
ÕâÌõÃüÁî»áÒÆ³ý֮ǰµÄ¹ÒÔØ£¬µ«ÊÇÈç¹ûnamespace±¾Éí»¹Óнø³ÌÔËÐУ¬namespace»¹»á´æÔÚÏÂÈ¥£¬Ö±µ½½ø³ÌÔËÐнáÊø¡£
ͨ¹ýnetwork namespaceÎÒÃÇ¿ÉÒÔÁ˽⵽£¬Êµ¼ÊÉÏÄں˴´½¨ÁËnetwork namespaceÒÔºó£¬ÕæµÄÊǵõ½ÁËÒ»¸ö±»¸ôÀëµÄÍøÂç¡£µ«ÊÇÎÒÃÇʵ¼ÊÉÏÐèÒªµÄ²»ÊÇÕâÖÖÍêÈ«µÄ¸ôÀ룬¶øÊÇÒ»¸ö¶ÔÓû§À´ËµÍ¸Ã÷¶ÀÁ¢µÄÍøÂçʵÌ壬ÎÒÃÇÐèÒªÓëÕâ¸öʵÌåͨÐÅ¡£ËùÒÔDockerµÄÍøÂçÔÚÆð²½½×¶Î¸øÈËÒ»Öַdz£ÄÑÓõĸоõ£¬ÒòΪһÇж¼Òª×Ô¼ºÈ¥ÊµÏÖ¡¢È¥ÅäÖá£ÄãÐèÒªÒ»¸öÍøÇÅ»òÕßNATÁ¬½Ó¹ãÓòÍø£¬ÄãÐèÒªÅäÖ÷ÓɹæÔòÓëËÞÖ÷»úÖÐÆäËûÈÝÆ÷½øÐбØÒªµÄ¸ôÀ룬ÄãÉõÖÁ»¹ÐèÒªÅäÖ÷À»ðǽÒÔ±£Ö¤°²È«µÈµÈ¡£ËùÐÒÕâÒ»ÇÐÒѾÓÐÁ˽ÏΪ³ÉÊìµÄ·½°¸£¬ÎÒÃÇ»áÔÚDockerÍøÂ粿·Ö½øÐÐÏêϸµÄ½²½â¡£
7. User namespaces
User namespaceÖ÷Òª¸ôÀëÁ˰²È«Ïà¹ØµÄ±êʶ·û£¨identifiers£©ºÍÊôÐÔ£¨attributes£©£¬°üÀ¨Óû§ID¡¢Óû§×éID¡¢rootĿ¼¡¢key£¨Ö¸ÃÜÔ¿£©ÒÔ¼°ÌØÊâȨÏÞ¡£ËµµÃͨË×Ò»µã£¬Ò»¸öÆÕͨÓû§µÄ½ø³Ìͨ¹ýclone()´´½¨µÄнø³ÌÔÚÐÂuser
namespaceÖпÉÒÔÓµÓв»Í¬µÄÓû§ºÍÓû§×é¡£ÕâÒâζ×ÅÒ»¸ö½ø³ÌÔÚÈÝÆ÷ÍâÊôÓÚÒ»¸öûÓÐÌØÈ¨µÄÆÕͨÓû§£¬µ«ÊÇËû´´½¨µÄÈÝÆ÷½ø³ÌÈ´ÊôÓÚÓµÓÐËùÓÐȨÏ޵ij¬¼¶Óû§£¬Õâ¸ö¼¼ÊõΪÈÝÆ÷ÌṩÁ˼«´óµÄ×ÔÓÉ¡£
User namespaceÊÇĿǰµÄÁù¸önamespaceÖÐ×îºóÒ»¸öÖ§³ÖµÄ£¬²¢ÇÒÖ±µ½LinuxÄÚºË3.8°æ±¾µÄʱºò»¹Î´ÍêȫʵÏÖ£¨»¹Óв¿·ÖÎļþϵͳ²»Ö§³Ö£©¡£ÒòΪuser
namespaceʵ¼ÊÉϲ¢²»ËãÍêÈ«³ÉÊ죬ºÜ¶à·¢Ðа浣ÐݲȫÎÊÌ⣬ÔÚ±àÒëÄں˵Äʱºò²¢Î´¿ªÆôUSER_NS¡£Êµ¼ÊÉÏĿǰDockerÒ²»¹²»Ö§³Öuser
namespace£¬µ«ÊÇÔ¤ÁôÁËÏàÓ¦½Ó¿Ú£¬ÏàÐÅÔÚ²»¾Ãºó¾Í»áÖ§³ÖÕâÒ»ÌØÐÔ¡£ËùÒÔÔÚ½øÐнÓÏÂÀ´µÄ´úÂëʵÑéʱ£¬ÇëÈ·±£ÄãϵͳµÄLinuxÄں˰汾¸ßÓÚ3.8²¢ÇÒÄں˱àÒëʱ¿ªÆôÁËUSER_NS£¨Èç¹ûÄã²»»áÑ¡Ôñ£¬¿ÉÒÔʹÓÃUbuntu14.04£©¡£
LinuxÖУ¬ÌØÈ¨Óû§µÄuser ID¾ÍÊÇ0£¬ÑÝʾµÄ×îÖÕÎÒÃǽ«¿´µ½user ID·Ç0µÄ½ø³ÌÆô¶¯user
namespaceºóuser ID¿ÉÒÔ±äΪ0¡£Ê¹ÓÃuser namespaceµÄ·½·¨¸ú±ðµÄnamespaceÏàͬ£¬¼´µ÷ÓÃclone()»òunshare()ʱ¼ÓÈëCLONE_NEWUSER±êʶλ¡£ÀÏÑù×Ó£¬Ð޸ĴúÂë²¢Áí´æÎªuserns.c£¬ÎªÁË¿´µ½Óû§È¨ÏÞ(Capabilities)£¬¿ÉÄÜÄ㻹ÐèÒª°²×°Ò»ÏÂlibcap-dev°ü¡£
Ê×ÏȰüº¬ÒÔÏÂÍ·ÎļþÒÔµ÷ÓÃCapabilities°ü¡£
#include <sys/capability.h> |
Æä´ÎÔÚ×Ó½ø³Ìº¯ÊýÖмÓÈëgeteuid()ºÍgetegid()µÃµ½namespaceÄÚ²¿µÄuser ID£¬Æä´Îͨ¹ýcap_get_proc()µÃµ½µ±Ç°½ø³ÌµÄÓû§ÓµÓеÄȨÏÞ£¬²¢Í¨¹ýcap_to_text£¨£©Êä³ö¡£
int child_main(void* args) { printf("ÔÚ×Ó½ø³ÌÖÐ!\n"); cap_t caps; printf("eUID = %ld; eGID = %ld; ", (long) geteuid(), (long) getegid()); caps = cap_get_proc(); printf("capabilities: %s\n", cap_to_text(caps, NULL)); execv(child_args[0], child_args); return 1; } |
ÔÚÖ÷º¯ÊýµÄclone()µ÷ÓÃÖмÓÈëÎÒÃÇÊìϤµÄ±êʶ·û¡£
//[...] int child_pid = clone(child_main, child_stack+STACK_SIZE, CLONE_NEWUSER | SIGCHLD, NULL); //[...] |
ÖÁ´Ë£¬µÚÒ»²¿·ÖµÄ´úÂëÐ޸ľͽáÊøÁË¡£ÔÚ±àÒë֮ǰÎÒÃÇÏȲ鿴һϵ±Ç°Óû§µÄuidºÍguid£¬Çë×¢Òâ´ËʱÎÒÃÇÊÇÆÕͨÓû§¡£
È»ºóÎÒÃÇ¿ªÊ¼±àÒëÔËÐУ¬²¢½øÐÐн¨µÄuser namespace£¬Äã»á·¢ÏÖshellÌáʾ·ûǰµÄÓû§ÃûÒѾ±äΪnobody¡£
sun@ubuntu$ gcc userns.c -Wall -lcap -o userns.o && ./userns.o ³ÌÐò¿ªÊ¼: ÔÚ×Ó½ø³ÌÖÐ! eUID = 65534; eGID = 65534; capabilities: = cap_chown,cap_dac_override,[...]37+ep
<<--´Ë´¦Ê¡ÂÔ²¿·ÖÊä³ö£¬ÒÑÓµÓÐÈ«²¿È¨ÏÞ nobody@ubuntu$ |
ͨ¹ýÑéÖ¤ÎÒÃÇ¿ÉÒԵõ½ÒÔÏÂÐÅÏ¢¡£
user namespace±»´´½¨ºó£¬µÚÒ»¸ö½ø³Ì±»¸³ÓèÁ˸ÃnamespaceÖеÄÈ«²¿È¨ÏÞ£¬ÕâÑùÕâ¸öinit½ø³Ì¾Í¿ÉÒÔÍê³ÉËùÓбØÒªµÄ³õʼ»¯¹¤×÷£¬¶ø²»»áÒòȨÏÞ²»×ã¶ø³öÏÖ´íÎó¡£
ÎÒÃÇ¿´µ½namespaceÄÚ²¿¿´µ½µÄUIDºÍGIDÒѾÓëÍⲿ²»Í¬ÁË£¬Ä¬ÈÏÏÔʾΪ65534£¬±íʾÉÐδÓëÍⲿnamespaceÓû§Ó³Éä¡£ÎÒÃÇÐèÒª¶Ôuser
namespaceÄÚ²¿µÄÕâ¸ö³õʼuserºÍÆäÍⲿnamespaceij¸öÓû§½¨Á¢Ó³É䣬ÕâÑù¿ÉÒÔ±£Ö¤µ±Éæ¼°µ½Ò»Ð©¶ÔÍⲿnamespaceµÄ²Ù×÷ʱ£¬ÏµÍ³¿ÉÒÔ¼ìÑéÆäȨÏÞ£¨±ÈÈç·¢ËÍÒ»¸öÐźŻò²Ù×÷ij¸öÎļþ£©¡£Í¬ÑùÓû§×éÒ²Òª½¨Á¢Ó³Éä¡£
»¹ÓÐÒ»µãËäÈ»²»ÄÜ´ÓÊä³öÖп´³öÀ´£¬µ«ÊÇÖµµÃ×¢Òâ¡£Óû§ÔÚÐÂnamespaceÖÐÓÐÈ«²¿È¨ÏÞ£¬µ«ÊÇËûÔÚ´´½¨ËûµÄ¸¸namespaceÖв»º¬ÈκÎȨÏÞ¡£¾ÍËãµ÷Óúʹ´½¨ËûµÄ½ø³ÌÓÐÈ«²¿È¨ÏÞÒ²ÊÇÈç´Ë¡£ËùÒÔÄÄÅÂÊÇrootÓû§µ÷ÓÃÁËclone()ÔÚuser
namespaceÖд´½¨³öµÄÐÂÓû§ÔÚÍⲿҲûÓÐÈκÎȨÏÞ¡£
×îºó£¬user namespaceµÄ´´½¨ÆäʵÊÇÒ»¸ö²ã²ãǶÌ×µÄÊ÷×´½á¹¹¡£×îÉϲãµÄ¸ù½Úµã¾ÍÊÇroot
namespace£¬Ð´´½¨µÄÿ¸öuser namespace¶¼ÓÐÒ»¸ö¸¸½Úµãuser namespaceÒÔ¼°Áã¸ö»ò¶à¸ö×Ó½Úµãuser
namespace£¬ÕâÒ»µãÓëPID namespace·Ç³£ÏàËÆ¡£
½ÓÏÂÀ´ÎÒÃǾÍÒª½øÐÐÓû§°ó¶¨²Ù×÷£¬Í¨¹ýÔÚ/proc/[pid]/uid_mapºÍ/proc/[pid]/gid_mapÁ½¸öÎļþÖÐдÈë¶ÔÓ¦µÄ°ó¶¨ÐÅÏ¢¿ÉÒÔʵÏÖÕâÒ»µã£¬¸ñʽÈçÏ¡£
ID-inside-ns ID-outside-ns length |
дÕâÁ½¸öÎļþÐèҪעÒâÒÔϼ¸µã¡£
ÕâÁ½¸öÎļþÖ»ÔÊÐíÓÉÓµÓиÃuser namespaceÖÐCAP_SETUIDȨÏ޵Ľø³ÌдÈëÒ»´Î£¬²»ÔÊÐíÐ޸ġ£
дÈëµÄ½ø³Ì±ØÐëÊǸÃuser namespaceµÄ¸¸namespace»òÕß×Ónamespace¡£
µÚÒ»¸ö×Ö¶ÎID-inside-ns±íʾн¨µÄuser namespaceÖжÔÓ¦µÄuser/group
ID£¬µÚ¶þ¸ö×Ö¶ÎID-outside-ns±íʾnamespaceÍⲿӳÉäµÄuser/group ID¡£×îºóÒ»¸ö×ֶαíʾӳÉ䷶Χ£¬Í¨³£Ìî1£¬±íʾֻӳÉäÒ»¸ö£¬Èç¹ûÌî´óÓÚ1µÄÖµ£¬Ôò°´Ë³Ðò½¨Á¢Ò»Ò»Ó³Éä¡£
Ã÷°×ÁËÉÏÊöÔÀí£¬ÎÒÃÇÔÙ´ÎÐ޸ĴúÂ룬Ìí¼ÓÉèÖÃuidºÍguidµÄº¯Êý¡£
//[...] void set_uid_map(pid_t pid, int inside_id, int outside_id, int length) { char path[256]; sprintf(path, "/proc/%d/uid_map", getpid()); FILE* uid_map = fopen(path, "w"); fprintf(uid_map, "%d %d %d", inside_id, outside_id, length); fclose(uid_map); } void set_gid_map(pid_t pid, int inside_id, int outside_id, int length) { char path[256]; sprintf(path, "/proc/%d/gid_map", getpid()); FILE* gid_map = fopen(path, "w"); fprintf(gid_map, "%d %d %d", inside_id, outside_id, length); fclose(gid_map); } int child_main(void* args) { cap_t caps; printf("ÔÚ×Ó½ø³ÌÖÐ!\n"); set_uid_map(getpid(), 0, 1000, 1); set_gid_map(getpid(), 0, 1000, 1); printf("eUID = %ld; eGID = %ld; ", (long) geteuid(), (long) getegid()); caps = cap_get_proc(); printf("capabilities: %s\n", cap_to_text(caps, NULL)); execv(child_args[0], child_args); return 1; } //[...] |
±àÒëºó¼´¿É¿´µ½userÒѾ±ä³ÉÁËroot¡£
$ gcc userns.c -Wall -lcap -o usernc.o && ./usernc.o ³ÌÐò¿ªÊ¼: ÔÚ×Ó½ø³ÌÖÐ! eUID = 0; eGID = 0; capabilities: = [...],37+ep root@ubuntu:~# |
ÖÁ´Ë£¬Äã¾ÍÒѾÍê³ÉÁ˰󶨵Ť×÷£¬¿ÉÒÔ¿´µ½ÑÝʾȫ³Ì¶¼ÊÇÔÚÆÕͨÓû§ÏÂÖ´Ðеġ£×îÖÕʵÏÖÁËÔÚuser
namespaceÖгÉΪÁËroot¶ø¶ÔÓ¦µ½ÍâÃæµÄÊÇÒ»¸öuidΪ1000µÄÆÕͨÓû§¡£
Èç¹ûÄãÒª°Ñuser namespaceÓëÆäËûnamespace»ìºÏʹÓã¬ÄÇôÒÀ¾ÉÐèÒªrootȨÏÞ¡£½â¾ö·½°¸¿ÉÒÔÊÇÏÈÒÔÆÕͨÓû§Éí·Ý´´½¨user
namespace£¬È»ºóÔÚн¨µÄnamespaceÖÐ×÷ΪrootÔÙclone()½ø³Ì¼ÓÈëÆäËûÀàÐ͵Änamespace¸ôÀë¡£
½²ÍêÁËuser namespace£¬ÎÒÃÇÔÙÀ´Ì¸Ì¸Docker¡£ËäÈ»DockerĿǰÉÐδʹÓÃuser namespace£¬µ«ÊÇËûÓõ½ÁËÎÒÃÇÔÚuser
namespaceÖÐÌá¼°µÄCapabilities»úÖÆ¡£´ÓÄÚºË2.2°æ±¾¿ªÊ¼£¬Linux°ÑÔÀ´ºÍ³¬¼¶Óû§Ïà¹ØµÄ¸ß¼¶È¨ÏÞ»®·Ö³ÉΪ²»Í¬µÄµ¥Ôª£¬³ÆÎªCapability¡£ÕâÑù¹ÜÀíÔ±¾Í¿ÉÒÔ¶ÀÁ¢¶ÔÌØ¶¨µÄCapability½øÐÐʹÄÜ»ò½ûÖ¹¡£DockerËäȻûÓÐʹÓÃuser
namespace£¬µ«ÊÇËû¿ÉÒÔ½ûÓÃÈÝÆ÷Öв»ÐèÒªµÄCapability£¬Ò»´ÎÔÚÒ»¶¨³Ì¶ÈÉϼÓÇ¿ÈÝÆ÷°²È«ÐÔ¡£
µ±È»£¬Ëµµ½°²È«£¬namespaceµÄÁùÏî¸ôÀë¿´ËÆÈ«Ãæ£¬Êµ¼ÊÉÏÒÀ¾ÉûÓÐÍêÈ«¸ôÀëLinuxµÄ×ÊÔ´£¬±ÈÈçSELinux¡¢
CgroupsÒÔ¼°/sys¡¢/proc/sys¡¢/dev/sd*µÈĿ¼ÏµÄ×ÊÔ´¡£¹ØÓÚ°²È«µÄ¸ü¶àÌÖÂۺͽ²½â£¬ÎÒÃÇ»áÔÚºóÎÄÖнÓ×Å̽ÌÖ¡£
8. ×ܽá
±¾ÎÄ´ÓnamespaceʹÓõÄAPI¿ªÊ¼£¬½áºÏDockerÖð²½¶ÔÁù¸önamespace½øÐн²½â¡£ÏàÐŰѽ²½â¹ý³ÌÖÐËùÓеĴúÂëÕûºÏÆðÀ´£¬ÄãÒ²ÄÜʵÏÖÒ»¸öÊôÓÚ×Ô¼ºµÄ¡°shell¡±ÈÝÆ÷ÁË¡£ËäÈ»namespace¼¼ÊõʹÓÃÆðÀ´·Ç³£¼òµ¥£¬µ«ÊÇÒªÕæÕý°ÑÈÝÆ÷×öµ½°²È«Ò×ÓÃÈ´²¢·ÇÒ×Ê¡£PID
namespaceÖУ¬ÎÒÃÇҪʵÏÖÒ»¸öÍêÉÆµÄinit½ø³ÌÀ´Î¬»¤ºÃËùÓнø³Ì£»network namespaceÖУ¬ÎÒÃÇ»¹Óи´ÔӵķÓɱíºÍiptables¹æÔòûÓÐÅäÖã»user
namespaceÖл¹ÓкܶàȨÏÞÉϵÄÎÊÌâÐèÒª¿¼Âǵȵȡ£ÆäÖÐÓÐЩ·½ÃæDockerÒѾ×öµÄºÜºÃ£¬ÓÐЩ·½ÃæÒ²²Å¸Õ¸Õ¿ªÊ¼¡£Ï£Íûͨ¹ý±¾ÎÄ£¬ÄÜΪ´ó¼Ò¸üºÃµÄÀí½âDocker±³ºóÔËÐеÄÔÀíÌṩ°ïÖú¡£
|