docker容器学习(1)

微信扫一扫,分享到朋友圈

docker容器学习(1)

初学docker和k8s的时候,看了不少书和专栏,对于docker,目前有了一些实践,所以现在再回来看的时候,清晰了不少,后续会对看的内容做一些笔记,方便后续理解。今天推荐的就是极客时间专栏《深入剖析Kubernetes》,难度有点大,但慢慢学,对于系统掌握还是有好处的。

docker容器是沙盒,有了它应用之间有了边界,互相隔离;其次容器可以方便的搬移。

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

$ docker run -it busybox /bin/sh

表示什么含义呢?-it 参数告诉了 Docker 项目在启动容器后,需要给分配一个文本输入 / 输出环境(TTY),跟容器的标准输入相关联,这样就可以和这个 Docker 容器进行交互了,而 /bin/sh 就是我们要在 Docker 容器里运行的程序。/bin/sh是这个容器中唯一的进程(PID=1)。

如何让容器中的进程和宿主机中的进程隔离的呢?通过Linux Namespace机制 实现的,Linux 操作系统还提供了 Mount、UTS、IPC、Network和User这些 Namespace,用来对各种不同的进程上下文进行“障眼法”操作。

比如,Mount Namespace用于让被隔离进程只看到当前Namespace里的挂载点信息;Network Namespace用于让被隔离进程看到当前Namespace里的网络设备和配置。

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

在使用Docker的时候,并没有一个真正的“Docker容器”运行在宿主机里面。Docker引擎帮助用户启动的还是原来的应用进程,只不过在创建这些进程时,Docker为它们加上了各种各样的Namespace参数(属于linux技术)。

Namespace技术实际上修改了应用进程看待整个计算机“视图”,即它的“视线”被操作系统做了限制,只能“看到”某些指定的内容。但对于宿主机来说,这些被“隔离”了的进程跟其他进程并没有太大区别。

用户运行在容器里的应用进程,跟宿主机上的其他进程一样,都由宿主机操作系统统一管理,只不过这些被隔离的进程拥有额外设置过的Namespace参数。而Docker引擎在这里扮演的角色,更多的是旁路式的辅助和管理工作。

容器化后的用户应用,依然还是一个宿主机上的普通进程,所以它快(虚拟机需要额外的Hypervisor管理);容器使用 Namespace作为隔离手段的容器并不需要单独的Guest OS,这就使得容器额外的资源占用几乎可以忽略不计,几乎没有性能消耗。

“敏捷”和“高性能”是容器相较于虚拟机最大的优势,也是它能够在PaaS 这种更细粒度的资源管理平台上大行其道的重要原因。

Linux Namespace最大的问题是隔离得不彻底,这是它比虚拟机软件弱的地方。

1:既然容器只是运行在宿主机上的一种特殊的进程,那么多个容器之间使用的就还是同一个宿主机的操作系统内核。

这一段话理解了很久,容器中运行的进程对宿主机内核有要求;对于一个ubuntu镜像来说,里面的进程使用ubuntu里的文件,使用宿主机(CentOS)上的内核;而windows中的docker其实是一个linux虚拟机,因为linux镜像无法使用windows的内核,容器用的就是wndows docker这个虚拟机的内核,docker软件负责启动这个虚拟机;在进入容器运行的进程是entrypoint进程的子进程,docker基本上是旁路控制的作用。

容器中除了pid=1的进程,其他进程是不受docker控制的,对于使用exec进去之后的 后台 进程,是不受控制的(没有回收和生命周期管理),它们都是pid=1进程的子进程(因为不是init进程,孤儿进程管理很麻烦),所以对于一个容器来说,里面一般建议就运行一个进程(docker容器单进程的概念,是可控的)。

容器是一个“单进程”模型。由于一个容器的本质就是一个进程,用户的应用进程实际上就是容器里 PID=1 的进程,也是其他后续创建的所有进程的父进程。这就意味着,在一个容器中,你没办法同时运行两个不同的应用,除非你能事先找到一个公共的 PID=1 的程序来充当两个不同应用的父进程,这也是为什么很多人都会用systemd或者supervisord这样的软件来代替应用本身作为容器的启动进程。

2:在Linux内核中,有很多资源和对象是不能被Namespace化的,最典型的例子就是时间,比如在容器中修改了时间,宿主机中的时间也会被修改,所以在部署容器的时候必须知道什么能做,什么不能做。

除了namespace,实现容器另外一种技术是Cgroups,它是Linux内核中用来为进程设置资源限制的一个重要功能。为什么要限制呢?不能让容器耗尽宿主机所有的资源(比如CPU、内存)。

Linux Cgroups的全称是Linux Control Group。它最主要的作用,就是限制一个进程组能够使用的资源上限,包括CPU、内存、磁盘、网络带宽等等。在Linux 中,Cgroups 给用户暴露出来的操作接口是文件系统,即它以文件和目录的方式组织在操作系统的/sys/fs/cgroup路径下。

$ mount -t cgroup
cgroup on /sys/fs/cgroup/cpu,net_prio type cgroup
cgroup on /sys/fs/cgroup/devices type cgroup

可以在/sys/fs/cgroup/cpu创建一个子目录,然后设置限制,最后将要被限制cpu使用的进程pid写入/sys/fs/cgroup/cpu/container/tasks文件,这就是Cgroup技术。

Linux Cgroups 的设计还是比较易用的,简单粗暴地理解呢,它就是一个子系统目录加上一组资源限制文件的组合。而对于 Docker 等 Linux 容器项目来说,它们只需要在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录),然后在启动容器进程之后,把这个进程的 PID 填写到对应控制组的 tasks 文件中就可以了。

$ docker run -it --cpu-period=100000 --cpu-quota=20000 ubuntu /bin/bash

docker run的时候通过参数(—cpu-quota)限制容器对于cpu的使用。

Cgroups 对资源的限制能力也有很多不完善的地方,被提及最多的自然是/proc文件系统的问题,在容器中运行top命令的时候,实际上读取到的是宿主机的信息(比如cpu核数)。

配置hive的元数据到Mysql中

上一篇

我坐在马桶上热泪盈眶,这就是“顺产”的感觉吧

下一篇

你也可能喜欢

docker容器学习(1)

长按储存图像,分享给朋友