一、什么是容器

简单地说,一个容器包含了完整的运行时环境:除了应用程序本身之外,这个应用所需的全部依赖、类库、其他二进制文件、配置文件等,都统一被打入了一个称为容器镜像的包中

docker容器本质上是宿主机的进程. 可以把docker容器内部跑的进程看作是宿主机的线程。Docker通过namespace实现了资源隔离、通过cgroups实现了资源限制

linux容器技术是一种轻量级的虚拟化技术。主要特点有:

  1. 轻量:只打包了需要的bins/libs(也就是命令和库文件)。与宿主机共享操作系统,直接使用宿主机的内核.
  2. 部署快: 容器的镜像相对虚拟机的镜像小。部署速度非常快,秒级部署
  3. 移植性好: Build once,Run anywhere(一次构建,随处部署运行)。build,ship,run
  4. 资源利用率更高: 相对于虚拟机,不需要安装操作系统,所以几乎没有额外的CPU,内存消耗

下面的图片比较了 Docker 和传统虚拟化方式的不同之处,可见容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统方式则是在硬件层面实现。

image.png

image.png

一、容器的目的、本质是什么

从容器(container)的名字上,我们就能够非常直观地看出容器的优点,“提供的原材料(镜像)一样,得到的结果(运行实例)一样”、“打包隔离”、“轻松运输” 等。

如果把容器类比成集装箱的话,那运行的服务或服务对应的多个进程就应该是集装箱里对应的货物了,可以很自然地想到,容器的目的就是为进程集合提供一个独立的运行环境。那我们具体应该怎么实现 “独立的运行环境” 呢?

  1. 文件系统隔离
  • 每个容器都具有独立的文件系统,单个容器内对文件系统进行增删改查不会影响到其他容器
  • 参考 Linux 下的 chroot 命令,可以将子目录变为根目录
  1. 资源隔离
  • 利用 namespace 隔离进程之间的相互可见及通信
  • 使用 Cgroup 限制资源使用率,设置其能够使用的 CPU 以及内存量的大小

所以容器的本质就是一个视图隔离、资源可限制、独立文件系统的进程集合,它将系统的其他资源隔离开来,具有自己独立的资源视图。“视图隔离”,指的是能够看到部分进程、有独立的主机名,“资源可限制”,指的是可以限制内存大小、CPU 使用个数等。

二、镜像是什么

我们之前提到过,容器有一个独立的文件系统,它包含了容器运行时所需要的全部文件。我们将容器运行时所需要的所有文件集合称为容器镜像

那我们怎么去生成容器的镜像呢?一般来讲,我们会通过 Dockerfile来构建镜像,通过 Dockerfile 的语法糖我们可以很方便的构建一个镜像,这个语法糖我们会在之后学到。

有了自己的镜像之后,我们会想,能不能把镜像都放在一个地方统一管理,就像 GitHub 一样,可以把自己的镜像分享给别人,也可以直接使用别人的镜像,于是我们把镜像放置、统一管理的地方,称之为镜像仓库。我们可以像操作 GitHub 那样(push、pull)对镜像进行操作。

三、如何得到容器

  1. 构建一个镜像,可以直接从镜像仓库拉取,也可以自己手动生成,目的是为容器提供生成它所需要的一切
  2. 运行镜像得到想要的容器

四、数据卷

进行到这里,我们先对容器和镜像小小的总结一下:

  1. 一个镜像相当于一个模版,一个容器就像是这个模版生成的具体的运行实例
  2. 运行一个容器,就是选择某一个镜像来提供独立的文件系统并指定相应的运行程序

很明显地,容器的生命周期就和我们指定的运行程序的生命周期一致,我们也叫这个运行程序为 initial 进程,initial 进程也可以产生其他子进程。当 initial 进程退出时 ,所有的子进程也会随之退出。这样看起来,管理容器就约等于管理运行程序了。

但是这样的话,initial 进程退出,所有子进程也退出,运行程序运行产生的一些数据我们怎么能拿到并且持久化到指定目录上呢?数据卷的概念就应运而生了。

容器可以将数据持久化到指定的目录上,这个目录就叫做数据卷。数据卷最明显的特点就是,它的生命周期是独立于容器的生命周期的。

数据卷的管理方式

  1. 将目录直接挂载在容器内部,这种方式最简单,但是却提高了运维成本
  2. 运行引擎管理

    二、容器所涉及内核技术

    1.NameSpace

Linux内核实现namespace的一个主要目的就是实现轻量级虚拟化(容器)服务。在同一个namespace下的进程可以感知彼此的变化,而对外界的进程一无所知。实现的资源隔离。

linux内核提拱了6种namespace隔离的系统调用:

namespace 系统调用参数 隔离内容
UTS CLONE_NEWUTS 主机名或域名
IPC CLONE_NEWIPC 信号量、消息队列和共享内存
PID CLONE_NEWPID 进程编号
net CLONE_NEWNET 网络设备接口,IP路由表、防火墙规则等
mount CLONE_NEWNS 挂载点(文件系统)
user CLONE_NEWUSER 用户和用户组

总结:容器使用的命名空间有哪些?
应用程序运行环境隔离的空间,就是一个NameSpace(容器),每一个NameSpace(容器)都将拥有UTS、IPC、Mount、Net、User、PID 隔离的namespace

2.CGroups

  • 控制组(CGroups)是Linux内核的一个特性,主要用来对共享资源进行隔离、限制、审计等。
  • 只有能控制分配到容器的资源,才能避免多个容器同时运行时对宿主机系 统的资源竞争。
  • 控制组可以提供对容器的内存、CPU、磁盘IO等资源进行限制和计费管理
  • 控制组
  • 作用:用于实现容器的资源隔离,可对进程做资源隔离
  • cgroups实现对9大子系统做资源配额和度量
    • 把资源定义为子系统,可以通过子系统对资源进行限制
      • CPU 可以让进程使用CPU的比例
      • memory 限制内存使用,例如50Mi,150Mi
      • blkio 限制块设备输入输出的 IO 例如:磁盘,光盘。以及usb
      • cpuacct 生成Cgroup使用CPU的资源报告
      • cpuset 用于多CPU执行Cgroup时,对进程进行CPU分组
      • devices 允许或拒绝设备的访问
      • freezer 暂停或恢复Cgroup运行
      • net_cls 标记每个网络包
      • ns 名称空间子系统

安装docker后,用户可以在/sys/fs/cgroup/memory/docker目录下看到对Docker组应用的各种限制限,包括:

  1. # cd /sys/fs/cgroup
  2. blkio cpuacct cpuset freezer memory net_cls,net_prio perf_event systemd cpu cpu,cpuacct devices hugetlb net_cls net_prio pids
  3. # cd /sys/fs/cgroup/memory/docker
  4. # ls

用户可以通过修改这些文件值来控制组限制docker应用资源。

3.应用案例

3.1限制进程对CPU的使用

  • 部署Cgroup

    1. [root@bogon ~]# yum -y install libcgroup*
    2. [root@bogon ~]# systemctl status cgconfig
    3. cgconfig.service - Control Group configuration service
    4. Loaded: loaded (/usr/lib/systemd/system/cgconfig.service;
    5. disabled; vendor preset: disabled)
    6. Active: inactive (dead)
    7. [root@bogon ~]# systemctl enable cgconfig
    8. Created symlink from
    9. /etc/systemd/system/sysinit.target.wants/cgconfig.service to
    10. /usr/lib/systemd/system/cgconfig.service.
    11. [root@bogon ~]# systemctl start cgconfig
    12. [root@bogon ~]# systemctl status cgconfig
    13. cgconfig.service - Control Group configuration service
    14. Loaded: loaded (/usr/lib/systemd/system/cgconfig.service; enabled;
    15. vendor preset: disabled)
    16. Active: active (exited) since 2019-04-25 16:30:03 CST; 7s ago
    17. Process: 17061 ExecStart=/usr/sbin/cgconfigparser -l
    18. /etc/cgconfig.conf -L /etc/cgconfig.d -s 1664 (code=exited,
    19. status=0/SUCCESS)
    20. Main PID: 17061 (code=exited, status=0/SUCCESS)
    21. 4 25 16:30:03 bogon systemd[1]: Starting Control Group
    22. configuration ser.....
    23. 4 25 16:30:03 bogon systemd[1]: Started Control Group configuration
    24. service.
    25. Hint: Some lines were ellipsized, use -l to show in full.
  • Cgroup限制对CPU使用的步骤

    • 第一步:创建Cgroup组

      #使用cpu子系统创建2个cgroup
      [root@bogon ~]# vim /etc/cgconfig.conf
      group lesscpu {
      cpu {
        cpu.shares=200;
      }
      }
      group morecpu {
      cpu {
        cpu.shares=800;
      }
      }
      [root@bogon ~]# systemctl restart cgconfig
      
    • 第二步:把进程添加到Cgroup

      [root@bogon ~]# cgexec -g cpu:lesscpu md5sum /dev/zero
      #终端1
      [root@bogon ~]# cgexec -g cpu:morecpu sha1sum /dev/zero
      #终端2
      [root@bogon ~]# top
      #终端3
      

      image.png

3.2限制内存使用

错误内存限制

[root@bogon ~]# vim /etc/cgconfig.conf
group lessmem {
   memory {
       memory.limit_in_bytes=268435465;
}
}
[root@bogon ~]# systemctl restart cgconfig
[root@bogon ~]# mkdir /mnt/mem_test
[root@bogon ~]# df -h
文件系统         容量 已用 可用 已用% 挂载点
/dev/mapper/centos-root  17G  1.5G  16G   9% /
devtmpfs         2.0G   0  2.0G   0% /dev
tmpfs           2.0G   0  2.0G   0% /dev/shm
tmpfs           2.0G  8.7M  2.0G   1% /run
tmpfs           2.0G   0  2.0G   0% /sys/fs/cgroup
/dev/vda1        1014M 163M 852M  17% /boot
tmpfs          336M   0 336M   0% /run/user/0
[root@bogon ~]#
[root@bogon ~]# mount -t tmpfs /dev/shm /mnt/mem_test
[root@bogon ~]# df -h
文件系统         容量 已用 可用 已用% 挂载点
/dev/mapper/centos-root  17G  1.5G  16G   9% /
devtmpfs         2.0G   0  2.0G   0% /dev
tmpfs           2.0G   0  2.0G   0% /dev/shm
tmpfs           2.0G  8.7M  2.0G   1% /run
tmpfs           2.0G   0  2.0G   0% /sys/fs/cgroup
/dev/vda1        1014M 163M 852M  17% /boot
tmpfs          336M   0 336M   0% /run/user/0
/dev/shm         952M   0 952M   0% /mnt/mem_test
[root@bogon ~]#
[root@bogon ~]# cgexec -g memory:lessmem dd if=/dev/zero of=/mnt/mem_test/file1 bs=1M
count=200
记录了200+0 的读入
记录了200+0 的写出
209715200字节(210 MB)已复制,0.100733 秒,2.1 GB/秒
[root@bogon ~]# ls /mnt/mem_test/
file1
[root@bogon ~]# rm -rf /mnt/mem_test/file1
[root@bogon ~]# cgexec -g memory:lessmem dd if=/dev/zero of=/mnt/mem_test/file1 bs=1M
count=500
记录了500+0 的读入
记录了500+0 的写出
524288000字节(524 MB)已复制,0.353956 秒,1.5 GB/秒

正确的内存限制

[root@bogon ~]# vim /etc/cgconfig.conf
group lessmem {
   memory {
       memory.limit_in_bytes=268435465;
       memory.memsw.limit_in_bytes=268435465;
}
}
[root@bogon ~]# systemctl restart cgconfig
[root@bogon ~]# mount -t tmpfs /dev/shm /mnt/mem_test
[root@bogon ~]# df -h
文件系统         容量 已用 可用 已用% 挂载点
/dev/mapper/centos-root  17G  1.5G  16G   9% /
devtmpfs         2.0G   0  2.0G   0% /dev
tmpfs           2.0G   0  2.0G   0% /dev/shm
tmpfs           2.0G  8.7M  2.0G   1% /run
tmpfs           2.0G   0  2.0G   0% /sys/fs/cgroup
/dev/vda1        1014M 163M 852M  17% /boot
tmpfs          336M   0 336M   0% /run/user/0
/dev/shm         952M   0 952M   0% /mnt/mem_test
[root@bogon ~]# cgexec -g memory:lessmem dd if=/dev/zero of=/mnt/mem_test/file1 bs=1M
count=200
记录了200+0 的读入
记录了200+0 的写出
209715200字节(210 MB)已复制,0.105744 秒,2.0 GB/秒
[root@bogon ~]# rm -rf /mnt/mem_test/file1
[root@bogon ~]# cgexec -g memory:lessmem dd if=/dev/zero of=/mnt/mem_test/file1 bs=1M
count=500
已杀死

4.扩展

  • 主机虚拟化实现资源隔离的方式
    • 使用Hypervisor中的VMM实现资源隔离
  • PAM

    • 用户认证
    • 资源限制
      • ulimit
      • 仅对用户做资源限制

        三、容器管理工具介绍

  • LXC

    • 2008是第一套完整的容器管理解决方案不需要任何补丁直接运行在linux内核之上管理容器创建容器慢,不方便移置
  • Docker(容器管理系统)
    • 2013dotcloud是在LXC基础上发展起来的拥有一套容器管理生态系统生态系统包含:容器镜像、注册表、RESTFul API及命令行操作界面属于容器管理系统
  • Docker版本介绍
    • 2017之前版本
      • 1.7 ,1.8,1.9,1.10,1.11,1.12,1.13
    • 2017年3月1日后
      • 把docker做商业开源
        • docker-ce社区版
        • docker-ee企业版
      • 17-03-ce17-06-ce18-03-ce18-06-ce18-09-ceMoby:

内容小结:

  • 容器属于typeIII虚拟化,属于Paas
  • 容器是一种轻量级,进程级的虚拟机
  • 相比于虚拟机的优势
    • 不需要安装OS,和宿主机共享
    • 镜像存储空间小
    • 启动速度快(容器为秒级,虚拟机一般需要10秒左右)
    • 移植性更好,更轻便
    • 性能更好
  • docker是一个实现容器的软件,底层使用LXC
  • docker主要使用namespace命名空间技术实现资源隔离,使用cgroup实现资源限制