《深入剖析kubernetes》中容器基础技术的入门理解(一)

《深入剖析kubernetes》中容器基础技术的入门理解(一)

新手的阅读笔记。希望记录学习的过程,也希望在写博客的同时整理一下思路。有什么问题还请多多指教。

容器:进程

容器技术诞生的依靠于以下的三个事实:

  • paas技术的普及。可以看看博主——艾尔夏尔-Layton的文章Paas、Saas、Iaas详解 ,里面提到服务商已经准备好了语言环境,库等。用户只需要把项目部署到服务商的基础设施中就可以使用)
  • docker公司发布的docker项目有里程碑式的意义
  • 容器镜像解决了应用打包这个根本难题

由于docker的隔离技术,使得容器可以不互相干扰。docker把项目翻译成二进制文件存储到硬盘中,这个二进制文件就是所谓的程序或者**“可执行镜像”**,有了可执行镜像后用户无需关注宿主机是否安装了项目运行的和环境。这些技术的加持下,docker容器可以自如的在各个机器搬来搬去,这也是书中所说的 “paas最理想的状态”。

回到程序,刚刚所说的程序或者二进制文件运行起来,他就从磁盘的二进制文件变成了一个进程的概念。
对于一个进程来说,他的静态表现就是程序,而动态表现可以理解为运行中产生的数据以及状态的总和。而主角docker就是用来约束和修改进程的动态表现,为其创造出一个“边界”

其中边界的实现,对于docker等大多数linux容器来说linux namespace技术是用来改变进程视图的主要方法。namespace的知识可以看namespace概述,里面说到:

  • namespace的本质就是把原来所有进程全局共享的资源拆分成了很多个一组一组进程共享的资源
  • 当一个namespace里面的所有进程都退出时,namespace也会被销毁,所以抛开进程谈namespace没有意义
  • 属性值相同的一组进程就属于同一个namespace,跟这组进程之间有没有亲戚关系无关
    而cgroup在上文的namespace概述的第一页也有详细的解答:namespace是为了隔离资源,改变进程的视图。而cgroup是为了对进程进行统一的资源限制与监控。
    书中后文会有关于namespace,cgroup以及rootfs的更加深入的理解。

书中举了一个例子:
当用clone()方法创建一个新的进程,且指定clone_newpid参数就会看见一个全新的进程空间,这个空间内运行的第一个程序的pid号是1.
如果进入一个docker,使用ps -ef命令也可也看到隔离之后会有一个pid为1的进程。
例如我的zookeeper的docker中就有

zookeeper的进程列表

但这只是linux namespace制造出来的障眼法,实际在宿主机的视图上面,是可以看到这个进程的真实pid的。测试了一下:

宿主机视图下namespace
确实是存在的。

可以看出容器确实就是特殊的进程

容器与虚拟机

虚拟机在操作系统之上有一个叫hypervisor的软件作为虚拟机最主要的部分。他通过把硬件虚拟化模拟出来一个操作系统所需要的各种硬件然后在这些虚拟的硬件上创建出了一个新的操作系统——客户操作系统

就是因为虚拟机创造了一个操作系统,运行在这个“操作系统”中的进程天生就拥有对于资源的隔离性,无论是进程的属性还是文件系统的文件目录以及这个虚拟机的虚拟设备。

而docker工作原理与虚拟机不一样,docker并没有创建新的系统而仍然在宿主机中运行,只不过宿主机在管理进程的时候给这个进程添加了”边界“。

docker比虚拟机更加受欢迎的原因也找到了:虚拟化技术中虚拟机是真实存在的,也就是说每开一个虚拟机都无法避免地需要创建整个操作系统这是重量级的,而docker依附于宿主机的操作系统,无需额外投入资源。所以我理解为什么人们把docker称为“轻量级”虚拟化技术,因为他用了更少的开销干出了相似的效果。

docker对比虚拟机技术的优势书中给的两个关键词是**“敏捷”,“高性能”**。这也正是paas所需要的。
但docker也有缺点,书中列举出了几个:

  • docker不能像虚拟机一样使用与宿主机不同的操作系统内核。
    可以在docker和宿主机使用 uname -r 查看内核版本
    docker中的内核版本
    宿主机的内核版本
  • namespace隔离不够彻底,许多资源是不能被namespace隔离的,书中给的例子是时间。宿主机中通过settimeofday这个系统调用修改时间,那么整个宿主机时间都会被修改。
  • 公用一个内核,系统安全性降低。

隔离与限制(namespace and cgroup)

namespace

namespace技术实际上修改了应用进程看待整个计算机的”视图”,即他的视线收到了操作系统的限制。但在宿主机视角来说这些被限制的进程跟其他进程并没有太大的区别。

关于namespace的实现方式,我查阅了一下资料:namespace通常有许多种不同的类型,比如用于隔离pid的pid namepace,用于隔离hostname的uts namespace等。大部分的类型中进程都可以通过使用一个数据结构来确定是否在同一个 namespace 中。这个数据结构被称为 “namespace ID” 或 “nsproxy”。每个进程都有一个指向 nsproxy 结构的指针,该结构中包含了一组不同类型的 namespace ID。这些 namespace ID 可以用来确定进程是否在同一个 namespace 中。

关于namespace还有许多细节可以看我上面引用的 namespace概述 中的文章。里面有更详细的解读。

经过namespace之后会发现仍然有问题,那就是虽然视图问题是解决了。容器只能看到操作系统希望他看到的部分。但是对于系统资源来说每个容器还是一个平等的竞争关系。试想多个租户购置了同等价钱的paas服务,假设他们的容器都被分配到一个物理机上,结果一个docker天天搁着跑大任务占用大部分资源。这显然是不合理的,跟沙盒的理念是相悖的。

这就要引出cgroup。

cgroup

linux cgroup的主要作用就是限制一个进程组能够使用的资源上限,包括CPU,内存,硬盘,网络带宽等等
此外cgroup还能对进程进行优先级设置,审计等等。

cgroup是通过文件系统暴露接口的。意思是用户可以通过读写cgroup文件系统中的特定文件来操作cgroup,例如,用户可以通过修改文件中的值来更改cgroup的参数,或者通过读取文件中的值来查看cgroup的状态。
在linux中使用mount -t cgroup命令可以查看。

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

这些挂载点下的文件就是用于配置和管理cgroup的,通过修改这些文件就可以实现对cgroup的修改。

书中展示的一个实验:

reins@reins-PowerEdge-R740-2:/home/go/src/fabric_in_edge-cloud_fabric-master$ cd /sys/fs/cgroup/cpu
reins@reins-PowerEdge-R740-2:/sys/fs/cgroup/cpu$ sudo mkdir container
[sudo] password for reins: 
reins@reins-PowerEdge-R740-2:/sys/fs/cgroup/cpu$ ls container
cgroup.clone_children  cpuacct.usage         cpuacct.usage_percpu_sys   cpuacct.usage_user  cpu.shares      cpu.uclamp.min
cgroup.procs           cpuacct.usage_all     cpuacct.usage_percpu_user  cpu.cfs_period_us   cpu.stat        notify_on_release
cpuacct.stat           cpuacct.usage_percpu  cpuacct.usage_sys          cpu.cfs_quota_us    cpu.uclamp.max  tasks

首先是如果进入cgroup中创建一个文件夹,那么操作系统会自动在文件夹中创建好对应的资源。这些资源可以看作是cgroup的配置参数,你去修改这些文件的参数就会影响到cgroup的限制效果。而container文件夹相当于是定义了一个控制组,即加入控制组的进程会共同被限制。

啥事没配置下后台运行一下一个死循环脚本

while : ; do : ; done &

cpu占用率
单线程下占用满了。

此时如果去修改cgroup

#先看看cpu的quota和period
reins@reins-PowerEdge-R740-2:/sys/fs/cgroup/cpu/container$ cat cpu.cfs_quota_us 
-1
reins@reins-PowerEdge-R740-2:/sys/fs/cgroup/cpu/container$ cat cpu.cfs_period_us 
100000

这里意思是:
quota -1:无限制
period 100000: 100000ns(100ms)为cpu时长的计算周期

我们要做的修改是:

  1. 修改quota的值,单位是ns,意思是周期为100000ns(100ms)的时长中允许这个组的进程占用cpu多少ns。假如希望占用率是20%那么应该改为20000
  2. 把这个进程的pid加入到这个组中

具体如下:

reins@reins-PowerEdge-R740-2:/sys/fs/cgroup/cpu/container$ sudo sh -c 'echo 20000 > /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us'
[sudo] password for reins: 
reins@reins-PowerEdge-R740-2:/sys/fs/cgroup/cpu/container$ cat cpu.cfs_quota_us 
20000
reins@reins-PowerEdge-R740-2:/sys/fs/cgroup/cpu/container$ while : ; do : ; done &
[1] 14226
#这一步就是把进程加入到这个cgroup的限制组中
reins@reins-PowerEdge-R740-2:/sys/fs/cgroup/cpu/container$ sudo sh -c 'echo 14226 > /sys/fs/cgroup/cpu/container/tasks'

修改cgroup后cpu占用率
加上机器中还在运行的其他进程,就是用了20%资源。

除了cpu之外,cgroup的每一个子系统都有他独有的资源限制能力。如为块设备设定io限制,为进程设定内存使用限制等。
在docker的使用中,可以直接在docker run中加入参数

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

总结

  • 容器只是特殊的进程
  • 一个运行的docker容器其实就是一个启用了多个linux namespace(包括network namespace, pid namespace等等)的应用进程,而这个进程能够收到cgroup的配置限制。
  • 容器是一个单进程模型
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值