xiaohanliang
Docker
Docker
  • hi
  • STORAGE DRIVER
    • 1. 什么叫联合挂载
    • 2. 镜像ID是从哪来的
    • 3. 如何组装出一个镜像
    • 4. 为什么有这么多fs@aufs
    • 5. 为什么有这么多fs@overlay
    • 6. 为什么有这么多fs@dm
    • 7. 正确安装devicemapper
  • EXEC DRIVER
    • 1. 资源限制-cgroup
    • 2. 制造小型监狱
    • 3. 切换根目录是什么概念
    • 4. 标准极简容器runC
    • 5. 尝试安装runc工具
  • KUBERNETES NETWORK
    • 0. [WIP]我想串联容器网络的故事
    • 1. 容器网络是什么样的网络
    • 2. cnm认为应该怎样让容器组网
    • 3. 为什么会有一大堆cni插件
    • 4. 为什么要设计出pod
    • 5. 怎样形成一个服务
    • 6. Service就是iptables规则
    • 7. IPVS也能实现Service
    • 8. 从集群外访问服务-nodeport
    • 9. 从集群外访问服务-ingress
    • 10. 想要把域名变成IP
    • 11. DNS是怎么实现的
    • 12. 最常见的方案@flannel
    • 13. 使用tun设备封包@flannel
    • 14. 使用vxlan设备封包@flannel
    • 15. 可不可以不封包@flannel
Powered by GitBook
On this page
  • overlay 的优点
  • overlay 的缺点

Was this helpful?

  1. STORAGE DRIVER

5. 为什么有这么多fs@overlay

Previous4. 为什么有这么多fs@aufsNext6. 为什么有这么多fs@dm

Last updated 4 years ago

Was this helpful?

overlay 整体思路跟 aufs 非常接近, 也是搞的 以文件为最小单元+CoW 的那一套, 镜像作为只读层, 用的时候再贴上一层读写层形成容器. 如上图所示, 在 overlay 中, 我们把镜像层叫做 lowerdir , 把读写层叫做 upperdir , 它俩合并出来的我们叫它 merged, merged 也是容器直接访问的点.

overlay 的优点

那么还是那个经典的问题, 我们已经有 aufs 了, 为什么还需要 overlay? 思考一个问题, 在 aufs 中如果我们访问一个文件, 我们应该怎样找到它? aufs 没有任何办法指明这个文件到底存在哪儿, 它可能来自镜像中的任何一层, 所以为了找到这个文件, 我们需要遍历镜像中的每一层, 用一种 O(n) 的效率遍历文件.

  • 但是 overlay 只有两层, 只要这个文件不在读写层(upper), 它就一定在只读层里(lower), 因此效率高.

  • overlay 支持页缓存共享, 因此如果有好几个容器一起访问同一个文件, 他们一起用这个页缓存就好了

overlay 的缺点

... 你不觉得上面的说法很奇怪吗? 是, 你overlay会合并诸多镜像层我知道, 但如果合并镜像层真的有这么好, 那为什么 aufs 不去合并呢? 为什么这么多年了, aufs 还没把这个特性抄过来呢? 这只能说明, 这种做法同样带来了一大堆问题, 严重到已经不值得抄了.

想一个问题, 我们有镜像层, 也有读写层, 最后我们还有一个merge好了的 merged 层, 那这是不是代表说, 同一个文件, 被存储了两次? 一次存在镜像层里, 另一次存在 merged 层里?

# Merged层中, 文件 tty 的inode号
$ ls -i /var/lib/docker/overlay/b8d96b/merged/bin/tty
268731 tty

# 镜像层中(源文件层), 文件 tty 的inode号
$ ls -i /var/lib/docker/overlay/f193c2/root/bin/tty
268731 tty

你是不是都明白了? merged路径下的所有文件, 都只是源文件的一个硬链接而已, 两者指向磁盘的同一个位置, 同样一个文件并没有被存储两次, 但这个inode, 也是同样是它问题的根源

# Merged层中, 文件夹的inode号
$ ls -i /var/lib/docker/overlay/b8d/merged
277006 bin  726181 dev   726504 home  
726511 mnt  726180 proc  726301 run   
726503 srv  726501 tmp   ...

# 镜像层(源文件层)中, 文件夹的inode号
$ ls -i /var/lib/docker/overlay/f193c2/root
660604 bin  660606 dev   788158 home  
788160 mnt  788162 proc  788164 run   
788167 srv  788169 tmp   ...

除此之外, 另一个毛病也还是没有解决, 那就是overlay也是以文件为最小粒度的, 我们每次修改一下镜像层的文件, 都要先将它复制到读写层里, 哪怕是改动再小, 文件再大, 这些该做的事都得做, 我们后面会介绍一种方法不用复制整个文件的.

虽然文件使用的是同一个inode号, 但文件夹却单独搞了一个inode号, 光是这一个容器, 我们已经消耗了如此之多的inode号, 如果在大型服务器上起一大堆容器, 是真的蛮伤的.

点击这里看看overlay的上下两层结构
点击这里看看overlay的页缓存
点击这里看看inode如果消耗光了会怎么样
点击这里看看什么叫CoW