何為容器?
容器,是一個(gè)視圖隔離、資源可限制、獨(dú)立文件系統(tǒng)的進(jìn)程集合
- 鏡像?
運(yùn)行容器所需要的所有文件集合
底層技術(shù)
- namespaces-資源視圖隔離
- cgroup-控制資源使用率
- chroot-獨(dú)立的文件系統(tǒng)
chroot
簡(jiǎn)介
chroot (英文全稱:change root wiki) 命令用于改變根目錄,可以把根目錄換成指定的目的目錄,可以使其文件系統(tǒng)獨(dú)立
基本實(shí)驗(yàn)
mkdir chroottest
# 拷貝命令
cp -r /bin/ chroottest/bin
# 拷貝依賴庫(kù)
cp -r /lib/ chroottest/lib64
cp -r /lib64/ chroottest/lib64
cd chroottest/
# 將當(dāng)前目錄設(shè)為根目錄(chroot 需要root) 此時(shí)pwd輸出/
chroot .
# 推出
exit
注:chroot實(shí)驗(yàn)的要求必須有bash環(huán)境,為了方便拷貝了/lib64和/lib,當(dāng)然也可以通過(guò)ldd /bin/bash拷貝指定依賴
C函數(shù)
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void spawn_bash(void)
{
char *newargv[] = { "/bin/bash", NULL };
execv("/bin/bash", newargv);
perror("exec");
exit(EXIT_FAILURE);
}
int main() {
int ret;
char chroot_path[] = "/root/chroottest/";
char *pwd;
/*chroot 需要root權(quán)限*/
ret = chroot(chroot_path);
if (ret != 0) {
perror("chroot:");
exit(-1);
}
pwd = getcwd(NULL, 80);
printf("pwd is [%s]\n",pwd);
free(pwd);
spawn_bash();
}
其他
為了在Linux中具有可用的chroot環(huán)境,wiki上提供了操作方法,考慮wiki訪問(wèn)不友好,將方法寫(xiě)到本博客中,方法如下:
# Mount Kernel Virtual File Systems
TARGETDIR="/mnt/chroot"
$ mount -t proc proc $TARGETDIR/proc
$ mount -t sysfs sysfs $TARGETDIR/sys
$ mount -t devtmpfs devtmpfs $TARGETDIR/dev
$ mount -t tmpfs tmpfs $TARGETDIR/dev/shm
$ mount -t devpts devpts $TARGETDIR/dev/pts
# Copy /etc/hosts
/bin/cp -f /etc/hosts $TARGETDIR/etc/
# Copy /etc/resolv.conf
/bin/cp -f /etc/resolv.conf $TARGETDIR/etc/resolv.conf
# Link /etc/mtab
chroot $TARGETDIR rm /etc/mtab 2> /dev/null
chroot $TARGETDIR ln -s /proc/mounts /etc/mtab
namespaces(命名空間)
簡(jiǎn)介
Linux namespaceswiki包含了大多數(shù)現(xiàn)代容器實(shí)現(xiàn)背后的一些基本技術(shù)。在較高的級(jí)別上,它們?cè)试S隔離獨(dú)立進(jìn)程之間的全局系統(tǒng)資源。例如,文件系統(tǒng)、主機(jī)名、用戶、網(wǎng)絡(luò)和進(jìn)程
基本實(shí)驗(yàn)
# 查看當(dāng)前主機(jī)名
$ hostname
# 在新UTS名稱空間中執(zhí)行shell
$ unshare -u /bin/sh
# 設(shè)置 hostname
$ hostname abcd
$ hostname
# 推出
$ exit
# 查看當(dāng)前主機(jī)名 沒(méi)有更改
$ hostname
C函數(shù)
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
int spawn_bash(void)
{
char *newargv[] = { "/bin/bash", NULL };
execv("/bin/bash", newargv);
perror("exec");
exit(EXIT_FAILURE);
}
int child(void *args)
{
printf("pid as seen in the child: %lu\n", (unsigned long)getpid());
spawn_bash();
}
int main()
{
//需要 root 權(quán)限
int namespaces = CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS|CLONE_NEWNET;
pid_t p = clone(child, malloc(4096) + 4096, SIGCHLD|namespaces, NULL);
if (p == -1) {
perror("clone");
exit(1);
}
printf("child pid: %lu\n", p);
waitpid(p, NULL, 0);
return 0;
}
cgroups
簡(jiǎn)介
cgroups,wiki,其名稱源自控制組群(英語(yǔ):control groups)的簡(jiǎn)寫(xiě),是Linux內(nèi)核的一個(gè)功能,用來(lái)限制、控制與分離一個(gè)進(jìn)程組的資源(如CPU、內(nèi)存、磁盤(pán)輸入輸出等)
基本實(shí)驗(yàn)
# 安裝cgroup ubuntu
$ apt-get install cgroup-bin
$ cd /sys/fs/cgroup
# 設(shè)置可分配最大內(nèi)存為 300 MB
$ cd /memory
$ mkdir test
$ cd test
$ echo 314572800 > memory.limit_in_bytes
創(chuàng)建一個(gè)分配內(nèi)存的程序
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define CHUNK_SIZE 1024 * 1024 * 100
void main(){
char *p;
int i;
for(i = 0; i < 10; i ++)
{
p = malloc(sizeof(char) * CHUNK_SIZE);
if(p == NULL){
printf("fail to malloc!");
return ;
}
memset(p, 0, CHUNK_SIZE);
printf("malloc memory %d MB\n", (i + 1) * 100);
}
}
執(zhí)行結(jié)果如下,當(dāng)進(jìn)程占用的內(nèi)存超過(guò)限制時(shí),將被 kill
$ cgexec -g memory:test./a.out
malloc memory 100 MB
malloc memory 200 MB
Killed
目錄說(shuō)明
├─/sys/fs/cgroup
│ ├─blkio 對(duì)塊設(shè)備的IO進(jìn)行限制
│ ├─ cpu 限制 CPU 時(shí)間片的分配,與 cpuacct 掛載在同一目錄
│ ├─ cpuacct 生成 cgroup 中的任務(wù)占用 CPU 資源的報(bào)告,與 cpu 掛載在同一目錄
│ ├─cpuset 給 cgroup 中的任務(wù)分配獨(dú)立的 CPU(多處理器系統(tǒng)) 和內(nèi)存節(jié)點(diǎn)
│ ├─devices 允許或禁止 cgroup 中的任務(wù)訪問(wèn)設(shè)備
│ ├─freezer 暫停/恢復(fù) cgroup 中的任務(wù)
│ ├─hugetlb 限制使用的內(nèi)存頁(yè)數(shù)量
│ ├─memory 對(duì) cgroup 中的任務(wù)的可用內(nèi)存進(jìn)行限制,并自動(dòng)生成資源占用報(bào)告
│ ├─pids 限制任務(wù)的數(shù)量
│ └─ ...