第1页
Container内核原理介绍
邱模炯 @ UCloud
第2页
虚拟化技术:VM与Container
Hardware
Host Kernel
Hypervisor(VMM)
Guest
Kernel
Binaries/
Libraries
App
System Virtualization
Guest
Kernel
Binaries/
Libraries
App
Guest
Kernel
Binaries/
Libraries
App
Hardware
Host Kernel
Binaries/
Libraries
App
Binaries/
Libraries
App
Binaries/
Libraries
App
Container Virtualization
轻量:高比例部署,秒级启动
第3页
虚拟化技术:VM与Container
Hardware
Host Kernel
Hypervisor(VMM)
Guest
Kernel
Binaries/
Libraries
App
System Virtualization
Guest
Kernel
Binaries/
Libraries
App
Guest
Kernel
Binaries/
Libraries
App
Hardware
Host Kernel
Binaries/
Libraries
App
Binaries/
Libraries
App
Binaries/
Libraries
App
Container Virtualization
namespace & cgroup
内容:
namespace
cgroup
aufs
两者对比
namespace+cgroup相当于hypervisor,都提供了虚拟化环境以及资源隔离功能
aufs是个联合文件系统,同一个机器上的container往往是同质或者同一个基础镜像的。aufs使得一个container的镜像非常小,相对于基础镜像的增量部分。这是docker非常依赖的
第4页
namespace:进程组虚拟化的手段
进程运行环境有哪些?
VFS mount, 即文件系统rootfs
uid, gid
network,即独立的网络设备和tcpip
pid, 父pid
devices, hostinfo, IPC, /proc, /sys等
进程虚拟化/隔离
已有ns
pid:进程ID
mnt:文件系统挂载点
net:网络栈
uts:主机名
ipc:进程间通信
user:用户ID, 组ID,capabilities
子进程自动继承父的ns
进程运行环境有哪些
namespace提供了一组进程的虚拟运行环境以及隔离手段
已有的ns对应我们刚才所讲的运行环境
子进程自动继承父进程的ns
第5页
nsproxy相当于运行环境
struct task_struct{
struct nsproxy *nsproxy
...
}
struct task_struct{
struct nsproxy *nsproxy
...
}
struct task_struct{
struct nsproxy *nsproxy
...
}
struct nsproxy:
uts_namespace
ipc_namespace
pid_namespace
mnt_namespace
net
struct nsproxy:
uts_namespace
ipc_namespace
pid_namespace
mnt_namespace
net
UTS0
UTS1
PID0
PID1
NET0
MNT0
IPC0
NET1
多个ns包含在一个nsproxy,相当于提供了一个运行环境
第6页
mnt ns提供私有的rootfs
每个mnt ns有自己的rootfs,相对于host的根目录
struct mnt_namespace{
struct mount * root;
...
}
第7页
pid ns映射后的pid空间
struct pid_namespace{
struct pidmap pidmap[PIDMAP_ENTRIES];
...
}
内核维护一个PID之间的映射表
PID级别可以多级
每个PID NS都有init进程1,进程回收、僵尸进程规则等
第8页
第9页
net ns提供独立的网络栈
每一个ns
私有的网络设备
lo, veth等虚设备
物理网卡
独立的协议栈
ipv4, ipv6(含IP地址和路由表)
tcp, sctp, dccp
iptables规则
ipvs等
第10页
其他ns
uts, ipc
user ns
C1的1001 id和C2的1001不是同一
主要处理uid, gid, capabilities的虚拟化
3.8版本提交;需要文件系统配合,目前不完善
还有什么namespace没有实现?
time, device, security keys, security
第11页
namespace能做到什么?
虚拟机,但资源无保证
独立的mnt (chroot)
独立的pid空间
独立的网络协议栈
uts
uid, gid
ipc
Hardware
Host Kernel
Binaries/
Libraries
App
Binaries/
Libraries
App
Binaries/
Libraries
App
namespace
第12页
cgroup: 资源隔离和统计
哪些控制组
memory
usage_in_bytes
limit_in_bytes
stat
kmem...
kmem.tcp...
memsw...
cpu
blkio
cpuset, freezer, net_cls, net_prio, devices, perf, cpuacct, hugetlb
mount –t cgroup none /cgroup
ulimit的群体版
Google 2006年
目前Maintainer: Zefan Li(华为), Tejun Heo
和ulimit类比
创建控制组,放入进程:
limit & isolate
account
一套cgroup基础设施,不同用途的cgroup插件,代码散落在内核各个地方
开销很小,通常情况下不到1%
第13页
cgroup: 内存子系统接口
memory.limit_in_bytes
memory.soft_limit_in_bytes
memory.usage_in_bytes
memory.failcnt
memory.max_usage_in_bytes
memory.stat
memory.kmem.limit_in_bytes
memory.kmem.usage_in_bytes
memory.kmem.failcnt
memory.kmem.max_usage_in_bytes
memory.kmem.tcp.xxx
总体内存
kmem内存
kmem.tcp内存
第14页
cgroup: 内存子系统原理
mem_cgroup包含该group允许使用内存上限,当前使用量,LRU等信息
每个进程task_struct知道自己属于哪个group
每个页面page有对应的page_cgroup信息,从page_cgroup可知道该页面属于哪个group
在page fault或分配page cache页面时,系统会设置page_cgroup属于哪个mem_cgroup
memory.usage_in_bytes
memory.max_usage_in_bytes
memory.limit_in_bytes
memory.soft_limit_in_bytes
memory.failcnt
memory.stat
memory.force_empty
memory.use_hierarchy
memory.swappiness
memory.move_charge_at_immigrate
memory.oom_control
memory.numa_stat (only if CONFIG_NUMA is set)
memory.kmem.limit_in_bytes (only if CONFIG_MEMCG_KMEM is set)
memory.kmem.usage_in_bytes (only if CONFIG_MEMCG_KMEM is set)
memory.kmem.failcnt (only if CONFIG_MEMCG_KMEM is set)
memory.kmem.max_usage_in_bytes (only if CONFIG_MEMCG_KMEM is set)
memory.kmem.tcp.limit_in_bytes (only if CONFIG_MEMCG_KMEM is set)
memory.kmem.tcp.usage_in_bytes (only if CONFIG_MEMCG_KMEM is set)
memory.kmem.tcp.failcnt (only if CONFIG_MEMCG_KMEM is set)
memory.kmem.tcp.max_usage_in_bytes (only if CONFIG_MEMCG_KMEM is set)
memory.kmem.slabinfo (only if CONFIG_SLABINFO is set)
memory.memsw.usage_in_bytes (only if CONFIG_MEMCG_SWAP is set)
memory.memsw.max_usage_in_bytes (only if CONFIG_MEMCG_SWAP is set)
memory.memsw.limit_in_bytes (only if CONFIG_MEMCG_SWAP is set)
memory.memsw.failcnt
第15页
cgroup: CPU子系统接口
cpu.shares group间CPU调度权重
cpu.stat
cpu.cfs_period_us
cpu.cfs_quota_us
cpu.rt_runtime_us
cpu.rt_period_us
cpu.share默认1024
第16页
cgroup: CPU子系统原理
Complete Faire Scheduling调度的基础是red-black tree,二叉排序树。
启用cgroup前,所有可运行进程都被排序
p1
p2
p3
p4
p6
p5
group1
group2
root
p1
p2
p3
p4
p5
p6
启用cgroup后,变为两级调度!
第一级:container间
第二级:container内
这是近似做法。实际上调度的设计更加通用,是一种层次化允许嵌套的模式。每个调度实体可以是进程,也可以是一个组。如果是组,则继续CFS,直到找出进程
第17页
cgroup: 其它子系统
blkio
cpuset, freezer, net_cls, net_prio, devices, perf, cpuacct, hugetlb
第18页
namespace + cgroup能做到?
虚拟机且资源有保证
但,如何使得container精简?
Hardware
Host Kernel
Binaries/
Libraries
App
Binaries/
Libraries
App
Binaries/
Libraries
App
namespace & cgroup
如果一个container的rootfs大小是100M,1000个container要100G?而且传输起来费事
第19页
aufs overview
Another Union File System 同类:Overlayfs
/base
boot
bin
lib
lib64
usr
sbin
/c1
data
mount -t aufs -o br=/base=ro:/c1=rw none /union
/union
boot
bin
lib
lib64
usr
sbin
data
原理和目标均相同,不同的是代码实现。均未进upstream
aufs约20K行有效代码
用途:livecd, 嵌入式设备的factory reset
节省空间,节省pagecache,体积小
第20页
aufs: 原理
aufs
AUFS是个中转器
从图上可以看出:
1)aufs支持联合多种格式的文件系统
2)共用page cache,省内存
第21页
aufs: 有待完善
一个写操作导致整个文件的拷贝
branch文件重名时的处理
如何确保可预测可推理的行为
“下层”文件被绕开修改
“上层”编辑文件,新branch恰有同名文件
/rw
(none)
/ro
fileA
/new
fileA
/union
fileA
/union打开fileA,这时/new加入,那么后面的read返回谁的fileA?
文件系统有大量的细节
各种网络文件系统、内存文件系统
软链、硬链
xattr属性
aufs on NFS server
umount再remount
第22页
Container VS VM: 内核是运行环境的一部分
内核版本与libc有一定耦合
内核特性
系统调用,/proc, /sys
磁盘设备名
系统配置文件
硬件
用户态环境
内核
程序
VM
Container
Container要处理更为复杂的运行环境兼容性。几个例子:
1)一个container在RHEL host运行良好,若部署在Debian可能会有问题。(docker base image能解决之)
2)内核版本对部分用户态库和工具有要求,如libc, perf系统工具等
3)磁盘设备名甚至影响到程序(vda -> sda)
4)系统配置文件不能修改
5)内核版本有要求,如果要userns,需3.8+
除了内核裁剪和容器内调用库的权限限制,另外很多c++程序还需要带着系统库打包,docker跟host共享内核,那意味着还是host决定了程序运行环境而不是docker虚拟出的container。coreos的超精简Linux host自然满足不了很多软件的要求。多个container如果有不同版本的库需求也会是有问题的,就像不同系统软件可能对Linux内核都有不同版本的要求
第23页
Container VS VM:应用场景
性能和大小
运行开销、部署速度、启动速度
迁移
隔离和安全
适用场景?
适用场景(大公司内部,PaaS云,IaaS云,测试部署)
参考观点:
1)docker帮助加速应用部署和扩容,方便devops
2)container无法迁移
3)公有云卖资源不合适,而公司内部使用合适。想想安全性,软件bug fix的困难;没有彻底的隔离
第24页
Thank You