• 深入剖析Kubernetes学习笔记:深入理解镜像(07)


    一、容器里的进程看到的文件系统又是什么样子呢?

    1、你会看到好多宿主机的文件

    [root@k8s-master ~]# vim ns.c
    [root@k8s-master ~]# gcc -o nl nl.c
    [root@k8s-master ~]# ll
    total 20
    drwxr-xr-x 5 root root 4096 Jan 30 10:00 2019-1-30
    -rwxr-xr-x 1 root root 8824 Jan 30 10:01 ns
    -rw-r--r-- 1 root root 728 Jan 30 10:01 ns.c
    [root@k8s-master ~]# ./ns
    Parent - start a container!
    Container - inside the container!
    [root@k8s-master ~]# ls
    2019-1-30 ns ns.c
    [root@k8s-master ~]# ls /tmp/
    kubectl-edit-fplln.yaml systemd-private-afc4026216a1411886ba9484a063bd2f-vmtoolsd.service-6f4pjo
    systemd-private-0ea8ac9f463c47a2a1fd701cd31b7f11-chronyd.service-g7wBf0 systemd-private-b950aff5d80e486799e4380086de4b44-chronyd.service-pMgZnM
    systemd-private-5de01992e9814dbebf18d4b5bedc759b-chronyd.service-0EbBnM tmp.3eJpxKKBQM
    systemd-private-5de01992e9814dbebf18d4b5bedc759b-vgauthd.service-G9Hekh tmp.3X3XJVLq4z
    .........
    systemd-private-afc4026216a1411886ba9484a063bd2f-vgauthd.service-hgIgbE tmp.ZTAC6cOJKw

    Mount Namespace 修改的,是容器进程对文件系统"挂载点"的认知,但是这也就意味,只有在"挂载"这个操作
    之后,进程的视图才会被改变,而在此之前,新常见的容器会直接继承宿主机的各个挂载点

    2、tmp 变成了一个空目录

    修改nc文件

    [root@k8s-master ~]# cat ns.c
    #define _GNU_SOURCE
    #include <sys/mount.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <stdio.h>
    #include <sched.h>
    #include <signal.h>
    #include <unistd.h>
    #define STACK_SIZE (1024 * 1024)
    static char container_stack[STACK_SIZE];
    char* const container_args[] = {
    "/bin/bash",
    NULL
    };
    
    int container_main(void* arg)
    {
    printf("Container - inside the container!
    ");
    // 如果你的机器的根目录的挂载类型是 shared,那必须先重新挂载根目录
    // mount("", "/", NULL, MS_PRIVATE, "");
    mount("none", "/tmp", "tmpfs", 0, "");
    execv(container_args[0], container_args);
    printf("Something's wrong!
    ");
    return 1;
    }
    
    
    int main()
    {
    printf("Parent - start a container!
    ");
    int container_pid = clone(container_main, container_stack+STACK_SIZE, CLONE_NEWNS | SIGCHLD , NULL);
    waitpid(container_pid, NULL, 0);
    printf("Parent - container stopped!
    ");
    return 0;
    }

    再次执行

    [root@k8s-master ~]# gcc -o ns ns.c
    [root@k8s-master ~]# ./ns
    Parent - start a container!
    Container - inside the container!
    [root@k8s-master ~]# ls /tmp/
    [root@k8s-master ~]# ls
    2019-1-30 ns ns.c

     可以看到,这次/tmp变成了一个空目录,这意味着重新挂载生效了,我们用mount -l检查一下

    [root@k8s-master ~]# mount -l | grep tmpfs
    devtmpfs on /dev type devtmpfs (rw,nosuid,size=1006112k,nr_inodes=251528,mode=755)
    tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
    tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
    tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
    tmpfs on /run/user/0 type tmpfs (rw,nosuid,nodev,relatime,size=203192k,mode=700)
    none on /tmp type tmpfs (rw,relatime)
    [root@k8s-master ~]# ls /tmp/
    [root@k8s-master ~]# exit
    exit
    Parent - container stopped!
    [root@k8s-master ~]# mount -l | grep tmpfs
    devtmpfs on /dev type devtmpfs (rw,nosuid,size=1006112k,nr_inodes=251528,mode=755)
    tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
    tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
    tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
    tmpfs on /run/user/0 type tmpfs (rw,nosuid,nodev,relatime,size=203192k,mode=700)
    none on /tmp type tmpfs (rw,relatime)

    这就是 Mount Namespace 跟其他 Namespace 的使用略有不同的地方:它对容器进程视图的改变
    一定是伴随着挂载操作(mount)才能生效。

    二、Mount Namespace 和 rootfs为容器进程构建出一个完善的文件系统隔离环境

    1、chroot 的命令改变简称的根目录到你指定的位置

    mkdir -p luoahong/test
    mkdir -p luoahong/test/{bin,lib64,lib}
    T=luoahong/test
    cd $T
    
    cp -v /bin/{bash,ls} luoahong/test/bin
    
    T=/root/luoahong/test
    list="$(ldd /bin/ls | egrep -o '/lib.*.[0-9]')"
    for i in $list; do cp -v "$i" "${T}${i}"; done
    
    $ chroot /root/luoahong/test /bin/bash
    chroot

    实际上,Mount Namespace 正是基于对 chroot 的不断改良才被发明出来的,它也是Linux 操作系统里的第一个 Namespace

    2、Mount Namespace最核心的原理是?

    它最核心的原理实际上就是为待创建的用户进程

    1、启用Linux Namespace配置;
    2、设置置顶的Cgroups参数
    3、切换进程的跟目录

    roots只是一个操作系统所含的文件,配置和目录,并不包含操作系统内核,在linux操作系统中,
    这两部分是分开存放的,操作系统只有在开机启动时才会加载指定版本的内核镜像

    3、容器的灵魂在哪呢?

    正是由于rootfs的存在,容器才有了一个被反复宣传至今的只要特性:一致性

    由于rootfs里打包的不只是应用,而是整个操作系统的文件目录,也就意味着,应用以及它运行所需要的

    所有依赖,被封装在了一起

    对一个应用来说,操作系统本身才是它所需的最完整的"依赖库"

    这种深入到操作系统级别的运行环境一致性,打通了应用在本地开发和远端执行环境之间难以逾越的鸿沟。

    Docker 在镜像的设计中,引入了层(layer)的概念。也就是说,用户制作镜像的每一步操作,都会生成一个层,也就是一个增量rootfs

    4、什么是联合文件系统?

    $ mkdir C
    $ mount -t aufs -o dirs=./A:./B none ./C
    
    [root@k8s-master tree]# tree
    .
    ├── A
    │   ├── a
    │   └── x
    └── B
    ├── b
    └── X
    
    $ tree ./C
    ./C
    ├── a
    ├── b
    └── x

    5、经典留言

    继Namespace构建了四周的围墙(进程隔离),Cgroups构建了受控的天空优先使用阳光雨露(资源限制),Mount namespace与rootfs构建了脚下的大地,这片土地是你熟悉和喜欢的,不管你走到哪里,都可以带着它,就好像你从未离开过家乡,没有丝毫的陌生感(容器的一致性)~

  • 相关阅读:
    Python进阶: Decorator 装饰器你太美
    计算机网络自顶向下方法第3章-传输层 (Transport Layer).2
    Python进阶:值传递,引用传递?不存在的,是赋值传递
    Python进阶:对象复制与比较,分深浅,见真假
    Python基础:模块化来搭项目
    这说明一个问题
    我稍微思考了一下
    由LruCache和DiskLruCache提供三级缓存支持的ImageLoader
    回忆一个加塞方法
    三年六班的李子明同学,你妈拿了两本计算机基础在二号树上等你
  • 原文地址:https://www.cnblogs.com/luoahong/p/10407620.html
Copyright © 2020-2023  润新知