容器技术基础概念-入门


一、进程 方向

容器是一种沙盒技术,集装箱

应用的边界手段: 容器技术的核心功能,就是通过约束和修改进程的动态表现,从而为其创造出一个“边界”

对于 Docker 等大多数 Linux 容器来说,Cgroups 技术是用来制造约束的主要手段,而 Namespace 技术则是用来修改进程视图的主要方法。

1.namespace

pid、network、Mount、UTS、IPC

障眼法  /bin/sh 的进程号在 宿主机中不为1. 在docker容器中为1.

$ docker run -it busybox /bin/sh
/ #

linux创建新进程的系统调用clone

int pid = clone(main_function, stack_size, SIGCHLD, NULL); 

障眼法 :clone() 系统调用创建一个新进程时,就可以在参数中指定 CLONE_NEWPID 参数

int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL); 

这,就是 Linux 容器最基本的实现原理了。

所以说,容器,其实是一种特殊的进程而已。

Docker 项目帮助用户启动的,还是原来的应用进程,只不过在创建这些进程时,Docker 为它们加上了各种各样的 Namespace 参数。

查看docker容器的namespace:

1. docker ps拿到containerID

2. 有三种常用方式查看docker在宿主机的PID:

  1) 直接查看文件cat /sys/fs/cgroup/memory/docker//cgroup.procs

  2)docker container top

  3) docker inspect -f '{{.State.Pid}}'

3. 拿到进程ID后,执行ll /proc//ns/ 可查看docker启用的具体Namespace参数

docker启用的六个Namespace: https://www.cnblogs.com/rdchenxi/p/10455831.html

二、隔离与限制

1.虚拟化和docker容器化的区别

虚拟化 占用资源高,通过hypervisor管理虚拟机

容器化 占用资源少,通过docker engine管理容器,每个容器仅仅是一个进程。同一台宿主机上的容器共享同一个内核。

             容器化隔离不彻底。内核无法隔离。

             还有一些资源无法namespace化,如时间

mount namespace的隔离,需要先重新挂载,后创建容器进程,才能生效。

mount namespace举例:  重新挂载/目录,使用chroot,即重新挂载根文件系统(rootfs,也叫容器镜像)

$ mkdir -p $HOME/test
$ mkdir -p $HOME/test/{bin,lib64,lib}
$ cd $T

$ cp -v /bin/{bash,ls} $HOME/test/bin


$ T=$HOME/test
$ list="$(ldd /bin/ls | egrep -o '/lib.*\.[0-9]')"  # 拷贝动态库
$ for i in $list; do cp -v "$i" "${T}${i}"; done


$ chroot $HOME/test /bin/bash   # 改变根目录,进程的根目录为test

 

2.限制

cgroups(control groups)

接口是 文件系统,路径为 /sys/fs/cgroup, 可以使用mount -t cgroups查看

# mount -t cgroup
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/net_cls type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)

可以限制的资源: cpu、memory、cpuset

举例cpu资源的限制方法:

root@ubuntu:/sys/fs/cgroup/cpu$ mkdir container
root@ubuntu:/sys/fs/cgroup/cpu$ ls container/
cgroup.clone_children cpu.cfs_period_us cpu.rt_period_us  cpu.shares notify_on_release
cgroup.procs      cpu.cfs_quota_us  cpu.rt_runtime_us cpu.stat  tasks

$ echo 20000 > /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us   CPU占用时间限制

$ echo 226 > /sys/fs/cgroup/cpu/container/tasks      写入pid号

cgroups限制不完善。无法限制/proc文件系统。在容器中使用top查看资源,发现是宿主机的。/proc文件系统不知道cgroups限制的存在。 

三、容器镜像

挂载在容器根目录上、用来为容器进程提供隔离后执行环境的文件系统,就是所谓的“容器镜像”。它还有一个更为专业的名字,叫作:rootfs(根文件系统)。

docker项目最核心的原理:

1.启用linux namespace配置

2.设置指定的cgroups参数

3.切换进程的根目录(change root)  切换会优先使用pivot_root

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

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

由于 rootfs 里打包的不只是应用,而是整个操作系统的文件和目录,也就意味着,应用以及它运行所需要的所有依赖,都被封装在了一起。

所以需要联合挂载: centos使用的是devicemappper的storage driver。   目录为/var/lib/docker/devicemapper/mnt下

查看镜像的rootfs

$ docker image inspect ubuntu:latest
...
     "RootFS": {
      "Type": "layers",
      "Layers": [
        "sha256:f49017d4d5ce9c0f544c...",
        "sha256:8f2b771487e9d6354080...",
        "sha256:ccd4d61916aaa2159429...",
        "sha256:c01d74f99de40e097c73...",
        "sha256:268a067217b5fe78e000..."
      ]
    }

如何被联合挂载的:

devicemapper介绍:

操作系统为centos。使用devicemapper作为docker的联合文件系统。

是一种映射块设备的技术框架

Devicemapper 提供了一种将物理块设备映射到虚拟块设备的机制,目前 Linux 下比较流行的 LVM (Logical Volume Manager 是 Linux 下对磁盘分区进行管理的一种机制)和软件磁盘阵列(将多个较小的磁盘整合成为一个较大的磁盘设备用于扩大磁盘存储和提供数据可用性)都是基于 Devicemapper 机制实现的。

关键技术
Devicemapper 将主要的工作部分分为用户空间和内核空间。
架构类似于 C/S (客户端/服务区)架构的工作模式,客户端负责具体的规则定义和配置下发,服务端根据客户端配置的规则来执行具体的处理任务。
  • 映射设备(mapped device):即对外提供的逻辑设备,它是由 Devicemapper 模拟的一个虚拟设备,并不是真正存在于宿主机上的物理设备。
  • 目标设备(target device):目标设备是映射设备对应的物理设备或者物理设备的某一个逻辑分段,是真正存在于物理机上的设备。
  • 映射表(map table):映射表记录了映射设备到目标设备的映射关系,它记录了映射设备在目标设备的起始地址、范围和目标设备的类型等变量。