何为容器?
容器,是一个视图隔离、资源可限制、独立文件系统的进程集合
- 镜像?
运行容器所需要的所有文件集合
底层技术
- namespaces-资源视图隔离
- cgroup-控制资源使用率
- chroot-独立的文件系统
chroot
简介
chroot (英文全称:change root wiki) 命令用于改变根目录,可以把根目录换成指定的目的目录,可以使其文件系统独立
基本实验
mkdir chroottest
# 拷贝命令
cp -r /bin/ chroottest/bin
# 拷贝依赖库
cp -r /lib/ chroottest/lib64
cp -r /lib64/ chroottest/lib64
cd chroottest/
# 将当前目录设为根目录(chroot 需要root) 此时pwd输出/
chroot .
# 推出
exit
注:
chroot实验的要求必须有bash环境,为了方便拷贝了/lib64
和/lib
,当然也可以通过ldd /bin/bash
拷贝指定依赖
C函数
#include
#include
#include
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权限*/
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环境,wiki上提供了操作方法,考虑wiki访问不友好,将方法写到本博客中,方法如下:
# 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(命名空间)
简介
Linux namespaceswiki包含了大多数现代容器实现背后的一些基本技术。在较高的级别上,它们允许隔离独立进程之间的全局系统资源。例如,文件系统、主机名、用户、网络和进程
基本实验
# 查看当前主机名
$ hostname
# 在新UTS名称空间中执行shell
$ unshare -u /bin/sh
# 设置 hostname
$ hostname abcd
$ hostname
# 推出
$ exit
# 查看当前主机名 没有更改
$ hostname
C函数
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
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 权限
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
简介
cgroups,wiki,其名称源自控制组群(英语:control groups)的简写,是Linux内核的一个功能,用来限制、控制与分离一个进程组的资源(如CPU、内存、磁盘输入输出等)
基本实验
# 安装cgroup ubuntu
$ apt-get install cgroup-bin
$ cd /sys/fs/cgroup
# 设置可分配最大内存为 300 MB
$ cd /memory
$ mkdir test
$ cd test
$ echo 314572800 > memory.limit_in_bytes
创建一个分配内存的程序
#include
#include
#include
#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);
}
}
执行结果如下,当进程占用的内存超过限制时,将被 kill
$ cgexec -g memory:test./a.out
malloc memory 100 MB
malloc memory 200 MB
Killed
目录说明
├─/sys/fs/cgroup
│ ├─blkio 对块设备的IO进行限制
│ ├─ cpu 限制 CPU 时间片的分配,与 cpuacct 挂载在同一目录
│ ├─ cpuacct 生成 cgroup 中的任务占用 CPU 资源的报告,与 cpu 挂载在同一目录
│ ├─cpuset 给 cgroup 中的任务分配独立的 CPU(多处理器系统) 和内存节点
│ ├─devices 允许或禁止 cgroup 中的任务访问设备
│ ├─freezer 暂停/恢复 cgroup 中的任务
│ ├─hugetlb 限制使用的内存页数量
│ ├─memory 对 cgroup 中的任务的可用内存进行限制,并自动生成资源占用报告
│ ├─pids 限制任务的数量
│ └─ ...