资源经验分享如何搞懂容器的核心技术点?

如何搞懂容器的核心技术点?

2019-08-22 | |  345 |   0

原标题:人工智能可助识别分析野生黑猩猩

原文来自:CSDN      原创:阿文


很多接触过类似KVM、Vmware 等虚拟化产品的开发者一定知道,传统的虚拟机其实是模拟真实计算机硬件,然后需要独立安装一个单独的操作系统。这个操作系统可以是 Linux 或者是 windows,而 Docker 容器则不需要你去安装动则几十个 G 的操作系统——它提供的镜像启动后能够做到很小,例如 busybox 镜像只有几 M 大小:


# docker imagesREPOSITORY          TAG                 IMAGE ID            CREATED             SIZEubuntu              latest              3556258649b2        3 weeks ago         64.2MBbusybox             latest              db8ee88ad75f        4 weeks ago         1.22MB
而当我们执行:
docker exec -it docker 进程 /bin/bash


进入到 docker 容器中,得到一个和宿主机一样的 shell 终端,和我们连接虚拟机得到的终端几乎没什么不同,我们还可以在终端中执行例如:


apt-get update


亦或是安装各种命令。

等等,这似乎这就是一台虚拟机嘛。可是事实上真的是这样吗?


作为一名云计算行业的从业人员,我见过很多小白用户把容器当初虚拟机来使用,因为在他们看来启动一个容器比启动一个虚拟机要快很多,而且不需要手动去安装操作系统,在容器的终端中执行各种命令也和虚拟机没什么区别?这些初学者,他们会使用 Dockerfile 构建 Docker 镜像,也能够熟练的使用 Docker 的各种命令来管理容器。可是当遇到一些问题时,他们便束手无策,因为他们把容器镜像当成一个小型的操作系统来使用,什么东西都往容器放,导致容器的体积不断变大,导致一个容器镜像就高达到了几个 G,而对此他们便束手无策了,归其原因,还是因为他们并不了解 Docker。
今天我就跟大家聊一聊 Docker 到底是个什么东西。

容器其实是一种特殊进程

容器其实本质上就是一个进程,只不过容器的进程是比较特殊的。
容器技术的核心功能,就是通过约束和修改进程的动态表现,创造出一个“边界”,通过“障眼法”让人觉得它是一个独立的系统。大多数容器都是使用 Cgroups 技术来约束进程,通过 Namespace 技术来修改进程的视图。
Namespace
什么是 Namespace ?
我们通过一个案例来讲解,这里我们使用 Docker 运行一个 busybox 的容器:
# docker run -it busybox /bin/sh/ # psPID   USER     TIME  COMMAND    1 root      0:00 /bin/sh    6 root      0:00 ps/ #
我们可以看到在容器中,只有 2 个进程在云信,一个 PID 为 1 的进程,它就是我们的 sh 程序。
我们再重新打开一个窗口执行执行 ps aux | grep docker:
# ps aux | grep dockerroot      3490  0.0  5.7 843208 58032 ?        Ssl  Aug14   0:22 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sockroot     14669  0.0  6.3 709900 63612 pts/0    Sl+  14:36   0:00 docker run -it busybox /bin/sh


可以看到进程 14669 正在执行`docker run -it busybox /bin/sh`,事实上这个 14669 才是这个 Docker 容器的真正 PID。


那它是如何做到在我们 exec 进入容器之后把进程 ID 改成 1 的呢?事实上进程 ID=1 正是操作系统的第一号进程,它是所有进程的父进程。我们可以通过ps aux | grep systemd 查看会发现 systemd 为 1 号进行:
ps aux | grep systemdroot         1  0.0  0.7 225308  7828 ?        Ss   Jun20   3:12 /lib/systemd/systemd --system --deserialize 39
现在 Docker 把这个/bin/sh 的程序运行在容器中,就需要给这个 ID=14669 的进程做一些手脚,把它自己变成 1 号进程来骗过其他进程。这种机制就是对隔离应用的进程空间做了手脚,使得这些进程只能看到重新计算过的进程 ID,可是实际上它还是宿主机的 14669 号进程。
这种技术被称为 Namespace。
Namespace 其实是在创建新进程时候加了一个可选参数,它利用 Linux 的系统调用 clone() 为新创建的进程指定一个 CLONE_NEWPID 的参数,那么新创建的进程就会看到一个全新的进程空间,在这个进程空间里面它的 PID 就是 1。
Namespace 除了可以模拟 PID 之外,还提供了 Mout、UTS、IPC、Network 和 User 等,在不同的进程上下文做隔离操作。
而这些就是 Linux 容器的基本实现原理。
Cgroups
有了 Namespace ,使得容器就像一个沙盒一样看起来在一个独立的系统内运行,与宿主机互不干扰,可是,事实上只是 Namespace 隔离起来并不彻底。因为容器只是运行在宿主机上的一种特殊进程,所有的容器还是要共享宿主机的操作系统内核。并且有一些资源和对象是不能被隔离的,比如时间,如果你修改了容器的时间,那么操作系统的实际也会被修改。这显然不是我们希望看到的。另外使用 Namespace 并不能限制一个容器使用资源的边界,例如我们要限制一个容器使用的 CPU 资源或内存等,这些是 Namespace 无法做到的,它需要 Cgroup 来实现。那么什么是 Cgroup?
Cgroups 是Linux内核提供的一种可以限制单个进程或者多个进程所使用资源的机制,全称是 control groups,可以对 CPU、内存等资源实现精细化的控制。典型的子系统介绍如下:


  • cpu 子系统,主要限制进程的 CPU 使用率。

  • cpuacct 子系统,可以统计 Cgroups 中的进程的 CPU 使用报告。

  • cpuset 子系统,可以为 Cgroups 中的进程分配单独的 CPU 节点或者内存节点。

  • memory 子系统,可以限制进程的 memory 使用量。

  • blkio 子系统,可以限制进程的块设备 IO。

  • devices 子系统,可以控制进程能够访问某些设备。

  • net_cls 子系统,可以标记 Cgroups 中进程的网络数据包,然后可以使用 tc 模块(traffic control)对数据包进行控制。

  • freezer 子系统,可以挂起或者恢复 Cgroups 中的进程。

  • ns 子系统,可以使不同 Cgroups 下面的进程使用不同的 Namespace。


免责声明:本文来自互联网新闻客户端自媒体,不代表本网的观点和立场。

合作及投稿邮箱:E-mail:editor@tusaishared.com

上一篇:推荐 | 一文看懂迁移学习:从基础概念到技术研究!

下一篇:撬动百亿台设备,让物联网“造”起来!

用户评价
全部评价

热门资源

  • Python 爬虫(二)...

    所谓爬虫就是模拟客户端发送网络请求,获取网络响...

  • TensorFlow从1到2...

    原文第四篇中,我们介绍了官方的入门案例MNIST,功...

  • TensorFlow从1到2...

    “回归”这个词,既是Regression算法的名称,也代表...

  • 机器学习中的熵、...

    熵 (entropy) 这一词最初来源于热力学。1948年,克...

  • TensorFlow2.0(10...

    前面的博客中我们说过,在加载数据和预处理数据时...