Docker容器的原理与实践 (下)

欢迎访问网易云社区,了解更多网易技术产品运营经验。

Docker原理分析

Docker架构

镜像原理

镜像是一个只读的容器模板,含有启动docker容器所需的文件系统结构及内容
Docker以镜像和在镜像基础上构建的容器为基础,以容器开发、测试、发布的单元将应用相关的所有组件和环境进行封装,避免了应用在不同平台间迁移所带来的依赖问题,确保了应用在生产环境的各阶段达到高度一致的实际效果。

主要特点

  • 分层    
    镜像采用分层构建,每个镜像由一系列的镜像层组成, 当需要修改容器内的某个文件时,只对处于最上方的读写层进行变动,不覆盖下面已有文件系统的内容。 当提交这个修改过的容器文件系统为一个新的镜像时,保存的内容仅为最上层读写文件系统中被更新过的文件。        
+ bootfs  主要包含bootloader和kernel, bootloader主要是引导加载kernel, 当容器启动成功后,kernel被加载到内存中后而引导文件系统则会被卸载unmount+ rootfs  是容器在启动时内部进程可见的文件系统,通常包含一个操作系统运行所需的文件系统
    + 传统linux在内核启动时首先会挂载一个只读的rootfs,检测器完整性之后再切换为读写模式
    + docker在挂载rootfs时也将其设为只读模式,挂载完毕后利用联合挂载技术在已有的只读rootfs上再挂载一个读写层。
    + 只有运行中文件系统发生变化,才会把变化的内容写到读写层,并隐藏只读层中的老版本文件
    + rootfs包含的就是典型Linux系统中的 /dev,/proc,/bin, /etc等标准目录和文件。
  • 写时复制
    • 可以在多个容器之间共享镜像,每个容器启动时不需要单独复制一份镜像文件
    • 将所有镜像层以只读方式挂载到一个挂载点,在上面覆盖一个可读写的容器层。
    • 写时复制配合分层机制减少了镜像对磁盘空间的占用和容器启动时间
  • 内容寻址
    • 根据内容来索引镜像和镜像层
    • 是对镜像层的内容计算检验和,生成一个内容哈希值作为镜像层的唯一标识
    • 对于来自不同构建的镜像层,只要拥有相同的内容哈希,也能被不同镜像共享
  • 联合挂载
    可以在一个挂载点挂载多个文件系统,将挂载点的原目录与被挂在内容进行整合,最终可见的文件系统将包含整合后各层的文件和目录
    • 读写层处于容器文件系统的最顶层,其下可能联合挂载多个只读层。

存储管理

为了适应不同平台不同场景的存储需求,Docker提供了各种基于不同文件系统实现的存储驱动来管理实际的镜像文件

元数据管理

镜像在设计上将元数据和文件存储完全隔离。Docker管理元数据采用的也正是从上至下repository、image、layer是3个层次。 所以repository与image两个元数据并无物理上的镜像文件与之对应,layer则存在物理上的镜像文件与之对应。

  • 仓库元数据
    文件中存储了所有版本镜像的名字和tag以及对应的镜像ID(image/aufs)
  • 镜像元数据
    文件中存储了镜像架构、操作系统、默认配置、该镜像的容器ID和配置,构建镜像的历史信息以及rootfs组成(image/aufs/imagedb/content/sha256)
  • 分层元数据
    • 镜像层
      描述不可改变的镜像层(image/aufs/layerdb/sha256)
    • 容器层
      描述可读写的容器层(image/aufs/layerdb/mounts/),读写层的ID也对应容器的ID

存储驱动

为支持写时复制特性,根据不同操作系统底层的支持提供不同的存储驱动

  • aufs(advanced multi layered unification file system)
    是一种支持联合挂载的文件系统,支持不同目录挂载到同一个目录,挂载对用户来说是透明的。
    • 从最顶层的读写层开始向下寻找,本层没有则根据层与层之间的关系到下一层找
    • 如果文件不存在则在读写层新建一个,否则向上面一样从顶层开始查找,找到后复制到读写层进行修改
    • 如果文件仅仅在读写层则直接删除;否则需要删除读写层的备份,再在读写层中创建whiteout文件来标志这个文件不存在,而不会真正删除底层文件(会有.wh.开头的隐藏文件)
    • 如果这个文件在读写层存在对应的whiteout文件则先将whiteout文件删除再新建
    • 文件操作
  • btrfs
  • zfs
  • devicemapper
  • overlay
    overlayFS是一种新型联合文件系统,允许一个文件系统与另外一个文件系统重叠,在上层文件系统中记录更改,而下层的文件系统保持不变。
  • vfs

    存储目录

/var/lib/docker  
               /aufs                                aufs驱动工作的目录
                    /diff                           mount-id容器层,文件系统所有层的存储目录(下载的镜像内容就保存在这里)和容器层文件的差异变化会在这里出现。
                         /mount-id-init             最后一个只读层,用于挂载并重新生成dev/etc所列文件,这些文件与容器内的环境息息相关,但不适合被打包作为镜像的文件内容,
                                                    又不应该直接修改在宿主机文件上,所以设计了mountID-init层单独处理这些文件。这一层只在容器启动时添加。
                    /layers                         mount-id存储上述所有aufs层之间的关系等元数据,记录该层所依赖的所有其它层
                    /mnt                            aufs文件系统的挂载点,graphdriver会将diff中属于容器镜像的所有层目录以只读方式挂到mnt 
               /container                           容器配置文件目录
               /image 
                     /aufs                          存储镜像与镜像层元数据信息,真正的镜像层内容保存在aufs/diff
                          /imagedb/content          存储所有镜像的元数据
                          /layerdb                  存储所有镜像层和容器层的元数据
                                  /mounts           存储容器层元数据
                                         /init-id   init层id,这个layer存放的位置
                                         /mount-id  mount层id,这个layer存放的位置
                                         /parent    父layer的chain-id
                                  /share256         存储镜像层元数据
                                         /cache-id  该层数据存放的位置,在对应驱动目录下
                                         /diff      标识每一个layer
                                         /parent    标识父layer的chain-id
                                         /size      存放layer的数据大小
                                         /tar-split.json.gz 存放layer层的json信息
                          /repositories.json        记录镜像仓库中所有镜像的repository和tag名
               /volumes                             volumes的工作目录,存放所有volume数据和元数据

读写层、volumes、init-layer、只读层这几部分结构共同组成了一个容器所需的文件系统。
diff-id:通过docker pull下载镜像时,镜像的json文件中每一个layer都有一个唯一的diff-idchain-id:chain-id是根据parent的chain-id和自身的diff-id生成的,假如没有parent,则chain-id等于diff-id,假如有parent,则chain-id等于sha256sum( “parent-chain-id diff-id”)
cache-id:随机生成的64个16进制数。cache-id标识了这个layer的数据具体存放位置

数据卷

volume是存在于一个或多个容器中的特定文件或文件夹,这个目录以独立联合文件系统的形式存在于宿主机中

  • 特点
    • 容器创建时就会初始化,在容器运行时就可以使用其中的文件
    • 能在不同的容器中共享和重用
    • 对volume中的数据操作不会影响到镜像本身
    • 生命周期独立,即使删除容器volume依然存在

Namespace

同一个namespace下的进程可以感知彼此的变化,而对外界进程一无所知

  • UTS 隔离主机名与域名
  • IPC 隔离信号量、消息队列和共享内存
  • PID 隔离进程编号
    • 不同的PID namespaces会形成一个层级体系
    • 每个pid namespace的第一个进程 pid 1会像传统linux的init进程号一样拥有特权
  • Net 隔离网络设备、网络栈、端口
  • Mount 隔离挂载点(文件系统)
  • User 隔离用户和用户组

例子

mkdir newroot
cd newroot
cp -r /bin/ binchroot newrootexit

Cgroup

根据需求把一系列的系统任务和子任务整合到按资源划分等级的不同组内,从而为系统资源管理提供一个统计的框架

主要作用

  • 资源限制
  • 优先级分配
  • 资源统计
  • 任务控制

主要特点

  • cgroup的api是以一个为文件系统的方式实现,用户态的程序可以通过文件操作实现cgroup的组织管理
  • 组织管理操作单元可以细粒度到线程级别,可以创建和销毁cgroup从而实现资源再分配和管理
  • 所有资源管理的功能都以子系统的方式实现,接口统一
  • 子任务创建之初与父任务处于同一个cgroups控制组

相关术语

task

表示系统的一个进程或线程

cgroup

按某种资源控制标准划分而成的任务组,包含一个或多个子系统

  • 实现形式表现为一个文件系统mount -t cgroup
  • docker实现
    • 会在单独挂载了每一个子系统的控制组目录下创建一个名为docker的控制组
    • 在docker控制组里面再为每个容器创建一个容器id为名称的容器控制组
    • 容器里的所有进程号都会写到该控制组tasks中,并在控制组文件cpu.cfs_quota_us中写入预设的限制参数值
  • 工作原理
    • 本质上来说,cgroups是内核附加在程序上的一系列钩子,通过程序运行时对资源的调度触发相应的钩子以达到资源追踪和限制的目的
    • 进程所需内存超过它所属cgroup最大限制以后,如果设置了oom control,进程会收到oom信号并结束,否则进程会挂起,进入睡眠状态,直到cgroup中的其他进程释放了足够的内存资源为止

subsystem

资源调度器,cpu子系统可以控制cpu分配时间(/sys/fs/cgroup/cpu/docker/)

  • blkio 可以为块设备设定输入、输出限制,比如物理驱动设备(磁盘、固态硬盘、USB)
  • cpu 使用调度程序控制任务对CPU的使用
  • cpuacct 自动生成cgroup中任务对cpu资源使用情况的报告
  • cpuset 为cgroup中的任务分配独立的cpu和内存
  • devices 可以开启或关闭cgroup中任务对设备的访问
  • freezer 可以挂起或恢复cgroup中的任务
  • memory 可以设定cgroup中任务对内存使用量的限定
  • perf_event 使用后使cgroup中的任务可以进行统一的性能测试
  • net_cls 通过使用等级识别符标记网络数据包,从而允许linux流量控制程序(traffic controller)识别从具体cgroup中生成的数据包

hierachy

层级是由一系列cgroup以一个树状结构排列而成,每个层级通过绑定对应的子系统进行资源控制

依赖其他的内核能力

  • seccomp(secure computing mode)
    安全计算模式,这个模式可以设置容器在对系统进行调用时进行一些筛选,也就是所谓的白名单。 是一种简洁的sandboxing机制。能使一个进程进入到一种“安全”运行模式,该模式下的进程只能调用4种系统调用(system calls),即read(), write(), exit()和sigreturn(),否则进程便会被终止。
  • SELinux
    安全增强式Linux(SELinux, Security-Enhanced Linux)是一种强制访问控制(mandatory access control)的实现
  • Netlink
    用来让不同的容器之间进行通信,可用于进程间通信,Linux内核与用户空间的进程间、用户进程间的通讯
  • Netfilter
    Linux内核中的一个软件框架,用于管理网络数据包。
    不仅具有网络地址转换(NAT)的功能,也具备数据包内容修改、以及数据包过滤等防火墙功能。
  • AppArmor
    类似于selinux,主要的作用是设置某个可执行程序的访问控制权限,可以限制程序 读/写某个目录/文件,打开/读/写网络端口等等
  • capability
    Linux把原来和超级用户相关的高级权限划分成为不同的单元,称为Capability,可以单独启用或者关闭, 它打破了UNIX/LINUX操作系统中超级用户/普通用户的概念,由普通用户也可以做只有超级用户可以完成的工作

网络原理

一些概念

  • net namespace
    隔离网络栈,有自己的接口、路由、防火墙规则
  • bridge
    相当于交换机,为连接在其上的设备转发数据帧
  • veth
    相当于交换机上的端口,是一对虚拟网卡,用于不同网络空间进行通信的方式,从一张veth网卡发出的数据包可以直接到达它的peer veth
  • gateway
    就是一个网络连接到另一个网络的“关口”,与本地网络连接的机器会把向外的流量传递到此地址中从而使那个地址成为本地子网以外的IP地址的"网关".
  • iptables
    linux内核的包过滤系统。在3、4层提供规则链对包进行标记、伪装、转发等

两个例子

通过虚拟网卡实现2个namespace通信

1、创建虚拟网络环境
ip netns add net0
ip netns add net12、在虚拟的net0环境中执行
ip netns exec net0 ifconfig -aip netns exec net0 ping localhost
ip netns exec net0 ip link set lo up
ip netns exec net0 ping localhost3、创建一对虚拟网卡
ip link add type veth4、把veth0移动到net0环境里面,把veth1移动到net1环境里面
ip link set veth0 netns net0
ip link set veth1 netns net14、配置虚拟网卡
ip netns exec net0 ip link set veth0 up
ip netns exec net0 ip address add 10.0.1.1/24 dev veth0
ip netns exec net1 ip link set veth1 up
ip netns exec net1 ip address add 10.0.1.2/24 dev veth15、测试
ip netns exec net0 ping -c 3 10.0.1.2ip netns exec net0 ping -c 3 10.0.1.1ip netns exec net1 ping -c 3 10.0.1.1

通过网桥实现多个namespace通信及外网访问原理

1、创建虚拟网络环境并连接网线
ip netns add net0
ip netns add net1
ip netns add bridge

ip link add type veth
ip link set dev veth0 name net0-bridge netns net0
ip link set dev veth1 name bridge-net0 netns bridge

ip link add type veth
ip link set dev veth0 name net1-bridge netns net1
ip link set dev veth1 name bridge-net1 netns bridge2、在bridge中创建虚拟网桥
ip netns exec bridge brctl addbr br
ip netns exec bridge ip link set dev br up
ip netns exec bridge ip link set dev bridge-net0 up
ip netns exec bridge ip link set dev bridge-net1 up
ip netns exec bridge brctl addif br bridge-net0
ip netns exec bridge brctl addif br bridge-net1
ip netns exec bridge brctl show3、配置虚拟环境网卡
ip netns exec net0 ip link set dev net0-bridge up
ip netns exec net0 ip address add 10.0.1.1/24 dev net0-bridge

ip netns exec net1 ip link set dev net1-bridge up
ip netns exec net1 ip address add 10.0.1.2/24 dev net1-bridge4、测试
ip netns exec net0 ping -c 3 10.0.1.2ip netns exec net1 ping -c 3 10.0.1.1ip netns exec bridge ping -c 3 10.0.1.25、需要给当前网络环境配置一个网卡ip不然没有网络路由网络不可达
ip netns exec bridge ip address add 10.0.1.3/24 dev br6、想要ping宿主机网络怎么办?
ip netns exec bridge ping 192.168.99.100ip link add A type veth peer name B
ip link set B netns bridge
ip netns exec bridge ip link set dev B up

ip link set A up6、给AB网卡配置ip
ip netns exec bridge ip address add 172.22.0.11/24 dev B
ip address add 172.22.0.10/24 dev A7、设置bridge默认网关
ip netns exec bridge route add default gw 172.22.0.10ip netns exec bridge ping 192.168.99.1008、设置net0默认网关
ip netns exec net0 ping 192.168.99.100ip netns exec net0 route add default gw 10.0.1.3ip netns exec net0 ping 192.168.99.100 不通9、地址伪装
ip netns exec bridge iptables -t nat -A POSTROUTING -o B -j MASQUERADE
ip netns exec net0 ping 192.168.99.10010、让虚拟网卡访问外网
ip netns exec net0 ping 8.8.8.8iptables -t filter -I FORWARD -o A -j ACCEPT
iptables -t filter -I FORWARD -i A -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -s 172.22.0.0/24 -j MASQUERADE11、vbox访问mac地址
ip netns exec bridge ping 192.168.99.1iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
ip netns exec bridge ping 192.168.99.1

影响网络连通的几个要素

  • 内核是否开启IP转发支持
    cat /proc/sys/net/ipv4/ip_forward
    sysctl -w net.ipv4.ip_forward=1
  • 防火墙转发规则是否打开
  • 是否开启IP地址伪装
  • 是否正确设置网关

CNM网络模型

  • 沙盒,一个沙盒包含了一个容器网络栈信息。沙盒可以对容器的接口、路由和DNS设置等进行管理。一个沙盒可以有多个端点和多个网络。
  • 端点,一个端点可以加入一个沙盒和一个网络。端点的实现可以使veth pair、open vSwitch内部端口。
  • 网络,一个网络是一组可以互相联通的端点。网络的实现可以是linux bridge、VLAN等。    

内置驱动

 

  • bridge
    默认设置,libnetwork将创建出来的容器连接到docker网桥。其与外界使用NAT.

    操作例子

      docker network create br3
      docker run -itd --name busybox-bridge --net=br3 busybox
    
      docker run -itd --name busybox-bridge-none busybox
      docker network connect br3 busybox-bridge-none
      查看容器网络和宿主机网桥及其上端口
  • host
    libnetwork不为docker容器创建网络协议栈及独立的network namespace。
    • 容器使用宿主机的网卡、IP、端口、路由、iptable规则
    • host驱动很好的解决了容器与外界通信的地址转换问题,但也降低了容器与容器建、容器与宿主机之间的网络隔离性,引起网络资源竞争的冲突。

      例子

      docker run -itd --name busybox-host --net=host busybox
  • container
    • 指定新创建的容器和已存在的容器共享一个网络空间
    • 两个容器的进程可以通过lo网卡设备通信

      例子

      docker run -itd --name busybox busyboxdocker run -itd --name busybox-container --net=container:busybox-bridge busybox
  • none
    容器拥有自己的network namespace,但不进行任何网络配置。

    例子

docker run -itd --name busybox-none --net=none busybox
  • overlay
    • 使用标准的VXLAN
    • 使用过程中需要一个额外的配置存储服务如consul、etcd、Zookeeper
    • 需要在daemon启动的时候额外添加参数来指定配置存储服务地址
  • remote
    实现插件化,调用用户自行实现的网络驱动插件

DNAT来实现外部访问容器

docker run -itd -p 9901:991 --name busybox-dnat busybox

容器云平台

云平台厂家

如果你从头看到尾那真是太棒了,如果你也对docker技术感兴趣欢迎popo([email protected])联系交流。

相关阅读:Docker容器的原理与实践(上)

本文来自网易实践者社区,经作者陈志良授权发布。

相关文章:
【推荐】 MongoDB的正确使用姿势
【推荐】 为什么我打的jar包没有注解?
【推荐】 Web框架下安全漏洞的测试反思

原文地址:https://www.cnblogs.com/zyfd/p/10000365.html

时间: 2024-11-03 21:35:25

Docker容器的原理与实践 (下)的相关文章

docker容器网络通信原理分析

概述 自从docker容器出现以来,容器的网络通信就一直是大家关注的焦点,也是生产环境的迫切需求.而容器的网络通信又可以分为两大方面:单主机容器上的相互通信和跨主机的容器相互通信.而本文将分别针对这两方面,对容器的通信原理进行简单的分析,帮助大家更好地使用docker. docker单主机容器通信 基于对net namespace的控制,docker可以为在容器创建隔离的网络环境,在隔离的网络环境下,容器具有完全独立的网络栈,与宿主机隔离,也可以使容器共享主机或者其他容器的网络命名空间,基本可以

虚拟化技术—docker容器—PIPEWORK解读与实践

本文通过3个样例 -- 将Docker容器配置到本地网络环境中.单主机Docker容器的VLAN划分.多主机Docker容器的VLAN划分,演示了如何使用pipework帮助我们进行复杂的网络设置,以及pipework是如何工作的. 1.pipework的使用以及源码分析 Docker自身的网络功能比较简单,不能满足很多复杂的应用场景.因此,有很多开源项目用来改善Docker的网络功能,如pipework.weave.flannel等.这里,就先介绍一下pipework的使用和工作原理. pip

Docker容器技术的核心原理

目录 1 前言 2 docker容器技术 2.1 隔离:Namespace 2.2 限制:Cgroup 2.3 rootfs 2.4 镜像分层 3 docker容器与虚拟机的对比 1 前言 上图是百度的虚拟机和Docker容器的对比图,看着好像都差不多.那么虚拟机技术都这么成熟了,为什么Docker会火起来呢,Docker对比虚拟机等传统技术有什么优势?Docker又是通过什么方式来实现容器的一致性呢?这篇文章我们就通过探究Docker的核心原理,来侧面回答这个疑问. 2 docker容器技术

Docker——容器与容器云——互动出版网

这篇是计算机类的优质预售推荐>>>><Docker--容器与容器云> Docker和Kubernetes这一本就够了!从内核知识到容器原理,容器云技术深度揭秘!全面理解Docker源码实现与高级使用技巧.深入解读Kubernetes源码分析和最佳实践! 编辑推荐 从源码层面深度解析Docker核心原理 Kubernetes源码完全解读+最佳实践 广泛涵盖Docker高级实践技巧 全面梳理主流容器云技术架构方法 内容简介 本书从实践者的角度,在讲解Docker高级实践技巧

动手搭建docker并在docker容器中建spark集群

本人亲自测试搭建,由于是初学一路搭建下来走了不少弯路.如有不对或更简洁的步骤请提出环境: win10上安装的虚拟机,虚拟机装的centos7,并liunx界面化(之前搭建一次在网和端口都可以telnet前提下,就是访问不了docker容器中的服务地址,此次是为了防止宿机不能访问下用虚拟机界面浏览器),centos7的命令和centos6有区别,而且centos7中是没有iptables命令,如要使用自己安装.本人搭建的 虚拟机ip:192.168.20.129spark master节点IP:

有容云:梁胜-如何让Docker容器在企业中投产(下)

编者注: 本文是对上海容器大会有容云专场梁胜博士直播视频的文字回播,力求高度还原当天演讲内容未加个人观点,如在细节部分略有出入欢迎留言指正.(文章较长,分为上.下两个部分) 前情提要: 在上篇中梁博士讲了容器技术短时间内爆发的根本原因,容器在企业中投产的必要性.必然性以及容器投产四种场景中的前两种:新一代的私有云.混合云环境:企业应用商店和一键部署:本篇将介绍最后两种场景:多环境.多资源池的DevOps流水线,构建轻量级PaaS服务,以及微服务.容器云等方面的内容,阅读前文清点击:梁胜 | 如何

[CoreOS 转载] CoreOS实践指南(七):Docker容器管理服务

转载:http://www.csdn.net/article/2015-02-11/2823925 摘要:当Docker还名不见经传的时候,CoreOS创始人Alex就预见了这个项目的价值,并将其做为CoreOS支持的第一套应用程序隔离方案.本文将主要介绍在具体的场景下,如何在CoreOS中恰当地管理Docker容器. 注:本文首发于CSDN,转载请标明出处. [编者按]在“漫步云端:CoreOS实践指南”系列的前几篇文章中,ThoughtWorks的软件工程师林帆主要介绍了CoreOS及其相关

再次实践 MySQL chart - 每天5分钟玩转 Docker 容器技术(166)

学习了 chart 结构和模板的知识后,现在重新实践一次 MySQL chart,相信会有更多收获. chart 安装前的准备 作为准备工作,安装之前需要先清楚 chart 的使用方法.这些信息通常记录在 values.yaml 和 README.md 中.除了下载源文件查看,执行 helm inspect values 可能是更方便的方法. 输出的实际上是 values.yaml 的内容.阅读注释就可以知道 MySQL chart 支持哪些参数,安装之前需要做哪些准备.其中有一部分是关于存储的

Docker容器环境下ASP.NET Core Web API

Docker容器环境下ASP.NET Core Web API应用程序的调试 本文主要介绍通过Visual Studio 2015 Tools for Docker – Preview插件,在Docker容器环境下,对ASP.NET Core Web API应用程序进行调试.在自己做实验的过程中也碰到了一些问题,经过一些测试和搜索资料,基本解决了这些问题,本文也会对这些问题进行介绍,以免有相同需求的朋友多走弯路. 插件的下载与安装 至撰写本文为止,Visual Studio 2015 Tools