容器技术原理

何为容器?

容器,是一个视图隔离、资源可限制、独立文件系统的进程集合

  • 镜像?
    运行容器所需要的所有文件集合

底层技术

  • 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               限制任务的数量
│  └─ ...

你可能感兴趣的:(容器技术原理)