DOCKER系列二----docker的核心技术

1.容器主要特性


隔离性:可以在一个隔离环境运行,所以它的所有依赖都需要在这个隔离环境里面存在
可配额:依赖于Cgroups,来控制这个容器所能消耗的资源
便携性:因为之前有了隔离性,所以你现在的容器镜像就可以在任何地方重放了,
安全性:1.因为隔离性好 2.Linux本身有一些安全保障的技术来保证它的安全。

2.Linux内核代码中的Namespace实现

3.Linux对Namespace操作方法

一个进程在初创的时候,它就是有天然的namespace,Linux操作系统里面Pid为1的进程systemd,就是这个这个操作系统的第一个进程.systemd本身这个进程有自己的Namespace,那就是默认的namespace,也就是我们常说的主机Namespace,那么当其他的进程被init system拉起来以后,在Linux里面这个进程关系都是树状的,所有的进程其实都是通过其他进程fork出来的。当systemd去fork其他进程的时候,会把自己的namespace复制到其他进程上面去。所以默认情况下,新的子进程会跟主机共用同一个Namespace。所以默认情况下我们感受不到Namespace,因为它们共用同一个Pid的Namespace,共用网络Namespace,共用User NameSpace。
clone可以在复制进程的时候,通过flags这个参数设置新建的Namespace类型。

4.隔离性--Linux Namespace



每个用户进程其实都可以拥有自己的Namespace,主机这边有自己的主机Namespace,每个进程可以有自己的进程的Namespace,且彼此隔离。每一个进程其实都是一个自己封闭的运行空间。




进程都是主机的Namespace fork出来的,主机里面的这些进程其实也是主机fork出来的进程,所以所有的容器内部里面的进程,在主机上你都可以通过ps看到。但是在外面和容器里面的namespace看到的pid号是不一样的。它们中间是有一个映射关系。我们在容器的pid namespace里面看到的是它自己的pid号,容器启动的时候,会有一个ENTRYPOINT进程,这个进程就是我们在Pid namespace里面看到的1的进程号,所有其他的进程都是那个Pid fork 出来的。
network namespace:如果每一个进程拥有了独立的network namespace,那么这个进程它的网络身份就跟主机是不一样的。
IPC namespace:信号量和共享内存共享。不在同一个ipc namespace之间的进程是不能做IPC的。如果你希望它们之间通过IPC去通信。那么必须放在同一个ipc namespace里面。
mnt namespace:每个进程都有自己的文件系统。
uts namespace:每个进程都有自己的主机域名加上一个独立的IP
user namespace:每个进程都有自己的用户管理系统,它的这个用户也是隔离的。

5.关于namespace的常用操作


6.Cgroups


CPU、内存、磁盘等这些资源在Cgroup里面由不同的子系统管理起来。

6.1Cgroups代码实现

6.2可额度/可度量



6.2.1 CPU子系统


CPU子系统用来控制一个进程能占多少CPU。它通过了两种手段来控制,一种手段是通过cpu_shares这种相对时间,另外一种手段是通过这种绝对时间
cpu.shares:假设机器上有3个CPU,我定义了两个CGroup,那么我把第一个进程放在第一个CGroup,把第二个进程放在第二个CGroup。那这个时候进程和CGroup就产生关系了。接下来我把第一个CGroup里面的cpu_shares设成512,把第二个CGroup里面的cpu_shares设成1024,这就意味着操作系统去调用这些进程的时候,它对时间片分配就会按照1:2去分配。
绝对值是按照两个配置文件去配置的,一个是cfs_period_us,还有一个是cfs_quota_us。period是分母,quota是分子。

7.Liunx调度器

Linux里面提供了多个调度器,最高优先级的是RT,就是realtime的调度器,这个调度器基本上是轮训的,就是说如果你有多个进程是用RT调度器去调度,那么它就会轮流地去调度。次优的是CFS调度器,一般普通的用户进程都是用CFS调度器的,这是一个完全公平的调度器,它引入了一个叫做虚拟运行时间(vruntime)的概念。

7.1CFS调度器


进程的权重越大,获取的vruntime越多

7.2vruntime红黑树


vruntime最小的进程放在树的左边,vruntime最大的进程放在右边。每次做调度的时候,会从最左边取这个最小值,谁的vruntime到了,它就去运行谁。

7.3CFS进程调度


CFS本身会维护一个时钟周期,在时钟周期开始时,会调用_schedule()来调度进程运行。_schedule()函数调用pick_next_task()选一个vruntime值最小的那一个。既然调度了进程,那么就要做上下文切换,通过context_switch()切换到新的地址空间。在时钟周期结束了之后,调度器会更新这个进程的vruntime。此时红黑树会通过插入、反转、重新排序,会把一个更紧迫的进程丢在最左边。那么每次进程调度的时候,它永远从最左边去vruntime最小的这个进程进行调度。
其实vruntime跟这个cpu_shares产生了关联关系,cpu_shares越大的这种进程,它能占用的cpu时间就越多。

7.3.1 CPU子系统实战


首先创建一个cpudemo的cgroup: cd /sys/fs/cgroup/cpu/ mkdir cpudemo
运行一个程序,记录其中的进程号
cd cpudemo 并执行 echo 进程号 > cgroup.procs 把进程号加入到这个cgroup里面。那这个进程就被这个cgroup控制了。

8 cpuacct子系统

9 Memory子系统

10 Cgroup driver


Cgroup本身可以有不同的driver,比如说docker,它用的是cgroupfs作为驱动,整个操作系统它是用的systemd的Cgroup driver

11 文件系统


Docker的文件系统是利用了Union FS。什么是Union FS呢,它其实是通过某些技术,把不通的目录mount到同一个虚拟目录里面去,那不同目录在这个新的虚拟目录里面又可以有独立的权限,比如说可以设定readonly,readwritre。通过这种方式就会把多个子目录,多个不同来源的这种目录模拟成一个完整的操作系统或者说文件系统。

11.1 容器镜像


Docker它开创性地提出了一种容器镜像的概念。它利用源代码的形式(dockerFile),允许开发人员去定义一个面向应用的容器镜像构建的源代码。
假设说对于同一个用户或者在同一台机器上面,如果我们需要构建多个镜像,而这多个镜像它的基础镜像又是一样的,那么两个镜像可以共用这些基础镜像,相当于只保存了一份基础镜像。

11.2 Docker的文件系统


一般一个Linux会分为两个主要组成部分,一个是bootfs,一个是rootfs。bootfs分为2个子模块,一个叫bootloader,一个叫kernel。bootloader的主要作用是引导操作系统的启动,它主要其实就是把kernel加载出来就完成任务了。当kernel被加载到内存以后,整个bootfs会被umount掉。接下来的事情就是加载rootfs,rootfs就是我们日常常见的像/dev,/proc,/bin,/etc这些文件。

11.3 Docker的启动


Docker初始化也是将rootfs以readOnly方式去加载,但是它检查完了之后并不是把rootfs直接变成可写,而是在这个readonly的文件层基础之上,再添加新的层。所以它首先去加在Base Image,比如说Ubuntu,然后加在完成以后,Ubuntu这一层就变成readonly了,然后在这个基础之上再加一个jre层,然后再加比如说我们后面的这些指令层,那么它这样一层一层的堆叠,那么下面的层级永远都是只读,当这些所有层级加在完毕以后,它会把最上面的一层变成readwrite,那么所有你针对这个容器内部的文件修改,事实上都是在最上面这一层的修改。它并不会动到下面readonly的这些层的

11.4写操作


一个镜像是可以被多个容器使用的,而且一个镜像里面的不同层也是被多个镜像共享的,所以有了写时复制技术。它确保了下面的基础镜像层永远是不会被修改的。那么无论你通过这个基础镜像启动了多少个容器,那它底层的基础镜像层都是一致的,也就是只有一份拷贝,不需要为不同的容器进程、容器实例在复制一份出来。

11.5 容器存储驱动


11.6 OverlayFS


UNIONFS是把多个目录组织到一个虚拟目录里面去,使得这个虚拟目录包含来自不同源的内容,并且这个虚拟目录,它最终在Docker里面就作为rootfs供这个容器进程使用的。

11.6.1 OverlayFS的演示

11.7 OCI容器标准

12 Docker引擎架构


Docker daemon是Docker本身的一个后台的服务端,它事实上本身就是一个Rest API。
containerd是真正的控制运行时进程的这样一个后台程序,其本身也是一个可以独立运行的组件。containerd真正地会去启动一个containerd的shim进程,再通过runc(底层运行时的一个接口)去启动容器进程。
早起的时候没有containerd和shim,直接是由daemon来拉起进程的,那这样会有一个什么样的问题呢?docker daemon是所有容器进程的父进程。当你去升级Docker或者重启Docker的时候,父进程就不存在了,那个时候所有的子进程都会被重启,这样我们就无法轻易去升级Docker的。containerd作为一个更轻量级的容器管理进程,当去启动一个应用进程的时候,不是直接去启动的,而是通过shim进程,shim进程相当于用来维护这个容器进程生命周期的。这个shim的进程在运行起来以后,它会把这个shim进程交给操作系统的systemd,这样containerd下面是不挂任何子进程的,containerd就可以随便的去升级和重启

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容