畅谈 docker 技术

畅谈 docker 技术,第1张

背景

2018 年可以说是 docker 容器技术 最火热的一年,各大厂商,互联网公司都开始构建自己的容器化平台,CI/CD 工具
那么为什么 docker 会这么火,以及 docker 技术内涵是什么?,这篇文章,我将以一个学习者的身份详细解析 docker 容器化技术

为什么选择 docker

在容器化时代到来之前,AWS 以及 OpenStack 可谓盛极一时,与此同时还有以 Cloud Foundry 为代表的开源 PaaS 项目。

PaaS 开源项目火热的主要原因主要是它提供了一种应用托管 的能力。各个国内外技术厂商都在进行上云体验。
具体的 *** 作就是:Cloud Foundry 为每种主流编程语言都定义了一种打包格式,类似 cf push app 的 *** 作就是将 app 的可执行文件和启动命令
打包进一个压缩包中,上传到 Cloud Foundry 的存储中。然后 Cloud Foundry 会通过调度器选择一个可以运行这个应用的虚拟机,然后通过这个机器上的 agent 将应用压缩包下载下来启动。

对于一个虚拟机来说,需要在其上启动很多个来自不同用户的应用,Cloud Foundry 会调用 *** 作系统 CgroupsNamespace 机制为每个应用单独创建一个
称作沙盒的隔离环境,然后在沙盒环境中启动这些应用,这样就形成了一个个隔离的环境运行多个应用。

以上就是 PaaS 项目的核心的功能,也就是容器化技术。

也正是和 docker 项目相同的技术核心,通过 CgroupsNamespace来构建一个资源和边界,实现沙盒环境。

那么为什么 docker 技术为何在短短几个月就风靡全世界了?

  • 实则正是 docker image

对于 Paas 项目而言,将项目运行的文件打包是一件极其麻烦的事情,对于每种语言,每种框架,每个版本都需要维护一个打好的包。

docker image 可以基于你所需要的系统文件,构建一个可以基于云端环境运行的压缩包。

容器化技术的发展

在以上的文章中,介绍了 docker 技术为何火热的原因。
对于一个大型的业务应用来说,从前端,后端,到数据库系统,文件系统等,往往是需要多个容器的,那么就存在着,如何能够优雅的在云端环境有序地运行。
于是,docker 公司便开发出了一个容器编排化的工具, docker Swarm 项目

与此同时,Mesos 社区也开发出了一个类似的工具Marathon, 它虽然不能像 Swarm 那样提供原生的 Docker API, 但是其却拥有一个独特的核心竞争力:

  • 超大规模集群的管理经验

也就在这个时候,google 公司根据公司多年的发展经验和借助成熟的内部项目Borg系统,宣布了 Kubernetes 项目的诞生。
而也是仅仅在两年之前,各个国内外的互联网厂商开始将自己的项目接入 k8s,宣布了 k8s 时代的到来。

本文仅仅讨论 docker 容器化技术,对于容器化编排不做过多的介绍。

容器到底是怎么一回事?

在上述的文章中,已经简单介绍了几个概念:

  • 虚拟器
  • 容器
  • 容器化技术
  • 镜像

我们可以总结一下:容器其实就是一种沙盒技术,使用 CgroupsNamespace 技术,将你的应用通过限制和隔离的技术在指定的环境中,良好的运行起来

先说结论,容器其实就是一种特殊的进程而已

隔离技术 - Namespace

那么隔离技术是如何实现的?

首先创建一个容器:

docker run -it --name=ubuntu-test ubuntu:18.04 /bin/sh
# ps
  PID TTY          TIME CMD
    1 pts/0    00:00:00 sh
    7 pts/0    00:00:00 ps
#

我们可以看到这个容器中,一共有两个进程,通过 ps 可以看到 sh ,就是这个容器内部的第 1 号进程(PID=1)。

这是为什么呢?

本来,当我们在宿主机上运行了一个 /bin/sh 程序的时候,我们的 *** 作系统都会给其分配一个进程编号,例如 PID=100。但是通过 docker run 命令时,docker
就会在当前的进程时,调整其 namespace 相关参数,将其变为在这个 docker 中的 1 号进程。

这种技术就是Linux 里面的 Namespace 机制。

我们知道,在 Linux 系统中创建进程的系统调用是 clone():

int pid = clone(main_function, stack_size, SIGCHID, NUll);

通过指定 CLONE_NEWPID 参数,而每个 Namespace里的应用进程,都会认为自己是当前容器里的第一号进程。

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

在 Linux *** 作系统中,还提供了 MountUTSIPCNetworkUser 这些 Namespace,用来对各种不同的进程上下文进行"障眼法" *** 作。

限制技术 - Cgroups

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

#
# mount -t cgroup
cpuset on /sys/fs/cgroup/cpuset type cgroup (ro,nosuid,nodev,noexec,relatime,cpuset)
cpu on /sys/fs/cgroup/cpu type cgroup (ro,nosuid,nodev,noexec,relatime,cpu)
cpuacct on /sys/fs/cgroup/cpuacct type cgroup (ro,nosuid,nodev,noexec,relatime,cpuacct)
blkio on /sys/fs/cgroup/blkio type cgroup (ro,nosuid,nodev,noexec,relatime,blkio)
memory on /sys/fs/cgroup/memory type cgroup (ro,nosuid,nodev,noexec,relatime,memory)
devices on /sys/fs/cgroup/devices type cgroup (ro,nosuid,nodev,noexec,relatime,devices)
freezer on /sys/fs/cgroup/freezer type cgroup (ro,nosuid,nodev,noexec,relatime,freezer)
net_cls on /sys/fs/cgroup/net_cls type cgroup (ro,nosuid,nodev,noexec,relatime,net_cls)
perf_event on /sys/fs/cgroup/perf_event type cgroup (ro,nosuid,nodev,noexec,relatime,perf_event)
net_prio on /sys/fs/cgroup/net_prio type cgroup (ro,nosuid,nodev,noexec,relatime,net_prio)
hugetlb on /sys/fs/cgroup/hugetlb type cgroup (ro,nosuid,nodev,noexec,relatime,hugetlb)
pids on /sys/fs/cgroup/pids type cgroup (ro,nosuid,nodev,noexec,relatime,pids)
rdma on /sys/fs/cgroup/rdma type cgroup (ro,nosuid,nodev,noexec,relatime,rdma)
cgroup on /sys/fs/cgroup/systemd type cgroup (ro,nosuid,nodev,noexec,relatime,name=systemd)
#

其中,例如 cpusetcpumemory 这样的子目录,也叫子系统。这些都是可以被 Cgroups 进行限制的资源种类。

现在我们看一下子系统中关于 CPU 的相关配置文件

# ls /sys/fs/cgroup/cpu
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

这些输出配置中,可以看到 cpu.cfs_period_uscpu.cfs_quota_us,这两个参数需要组合使用,可以用来限制进程在长度cfs_period的一段时间内,
只能被分配到总量为 cfs_quota 的 CPU 时间。

另开一个终端,输入:

while : ; do : ; done &

23223

键入:

top
%Cpu0 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

可以看到 CPU 的使用率已经 100% 了, quota 还没有任何限制(-1)

$ cat /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us 
-1
$ cat /sys/fs/cgroup/cpu/container/cpu.cfs_period_us 
100000

在现在的默认配置中,在 100 ms 中的 cpu 时间中,使用 100ms 的 CPU 时间,也就是 100 %。
现在调整为 20%:

$ echo 20000 > /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us

然后将限制的进程 PID 写入 container 组里的 tasks 文件:


$ echo 23223 > /sys/fs/cgroup/cpu/container/tasks 

然后使用 top 指令查看:

%Cpu0 : 20.3 us, 0.0 sy, 0.0 ni, 79.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

现在可以看到已经为 20% 左右了
其他关于 blkiocpusetmemory 可以自行尝试

docker 运行时的限制参数
$ docker run -it --cpu-period=100000 --cpu-quota=20000 ubuntu:18.04 /bin/bash

这个配置就会将对应的值写入到 docker-container 的配置文件中,这个 Docker 容器,只能使用到 20% 的 CPU 带宽。

虚拟机和容器对比

虚拟机的工作原理,通过硬件虚拟化功能,模拟出了运行一个 *** 作系统需要的各种硬件,例如 CPU、内存、I/O 设备等等。
docker 项目帮助用户启动的,还是原来的应用进程,但是 Docker 会为它们加上了各种各样的 Namespace 参数。

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/731305.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-27
下一篇 2022-04-27

发表评论

登录后才能评论

评论列表(0条)

保存