传统虚拟机和Docker架构图
- 对比图中Docker和应用同级别并且在靠边的位置
- 用户在容器里的应用进程,跟宿主机上的其他进程一样,都由宿主机操作系统统一管理
- 只不过这些被隔离的进程拥有额外设置过的Namespace参数
- Docker在这里扮演的更多是旁路是的辅助和管理工作
KVM虚拟机和容器的性能
- 一个运行CentOS的KVM虚拟机在不做优化的情况下,虚拟机自己就要占用100-200MB内存
- 用户应用会被宿主机操作系统拦截和处理,损耗性能
- 容器化的应用依然是宿主机的一个进程,不存在虚拟化带来的性能损耗
- 使用Namespace作为隔离手段的容器并不需要单独的Guest OS,容器额外资源占用几乎不存在
- "敏捷"和"高性能"是容器对比虚拟机的最大优势
容器的隔离不彻底
- 宿主机上的多个容器之间使用的还是同一个宿主机的操作系统内核
- 很多资源和对象不能被Namespace化,比如时间
Cgroups资源限制
- blkio 为块设备设定I/O限制,一般用于磁盘等设置
- cpuset 为进程分配单独的CPU核和对应的内存节点
- memory 为进程设定内存使用的限制
容器是单进程模型
- 容器的本质就是一个进程,用户的应用进程实际上就是容器里的PID=1的进程
- 也是其他后续的所有进程的父进程
- 在一个容器中,只能实现找到一个公共的PID=1的程序来充当两个不同应用的父进程
- 这就是为什么很多人会使用systemd或者supervisord这样的软件来替代应用本身作为容器的启动进程
容器编排与容器生命周期
- 容器本身的设计是希望容器和应用能够同生命周期
- 否则一旦出现容器是正常运行的,但是应用早就挂了的情况
- 在容器编排处理起来就很麻烦了
Cgroups不完善的地方/proc文件系统
- Linux下的/proc目录存储是记录当前内核运行状态的一系列特殊文件
- 用户能通过这些文件,查看系统以及当前正在运行的进程的信息,
- 比如CPU使用,内存占用等,这些信息是top命令的主要信息来源
- 如果你在容器中执行top指令,就会发现它显示的是宿主机的CPU和内存数据,并不是当前容器的数据
- 因为/proc文件系统并不知道用户通过Cgroups给这个容器做了什么资源限制
- 即/proc文件系统并不了解Cgroup限制的存在
- 生产环境中必须修正这个问题,否则应用程序在容器里读取到的CPU核数,可用内存等信息都是宿主机上的数据
- 会给应用的运行带来非常大的风险和困惑,这是容器化相较于虚拟机不尽人意的地方