49

Large-Scale Cluster Mangement & Kubernetes Under The Hood

Embed Size (px)

Citation preview

Page 1: Large-Scale Cluster Mangement & Kubernetes Under The Hood
Page 2: Large-Scale Cluster Mangement & Kubernetes Under The Hood

容器集群编排与Kubernetes原理剖析LARGE-SCALE CONTAINER CLUSTER MANAGEMENT & DEEP DIVE INTO KUBERNETES

Page 3: Large-Scale Cluster Mangement & Kubernetes Under The Hood

About Me• @resouer • Lei (Harry) Zhang• Phd & Researcher @ZJU• Contributor• Former: Baidu, VMware• Publish: – Docker & Kubernetes Under The Hood

Page 4: Large-Scale Cluster Mangement & Kubernetes Under The Hood

Contents

• 深入理解容器(以 runc实现为例)• Borg的大规模集群管理经验• Kubernetes的原理与实现

Page 5: Large-Scale Cluster Mangement & Kubernetes Under The Hood

深入理解容器第一部分

注:除非特殊说明,“容器”均指代 OpenContainer组织的 runc实现

Page 6: Large-Scale Cluster Mangement & Kubernetes Under The Hood

进程 101

• 静态视角–程序:代码和数据的集合• 表现为:磁盘上的可执行镜像( Executable

Image)• 动态视角–进程:程序运行起来的执行环境的总和• 表现为:指令与数据、寄存器值、堆栈、被打开文件数、 I/O设备状态等信息的动态变化

Page 7: Large-Scale Cluster Mangement & Kubernetes Under The Hood

容器 101• 静态视角

– 镜像:程序、数据以及它们所依赖的所有文件、目录和配置的集合– 表现为: rootfs

• 文件系统结构和 library• 目录: /dev /proc /bin /etc /lib /usr /tmp• 指令: sh ls cp mv etc...• 配置: rc inittab fstab etc...• 设备: /dev/hd* /dev/tty* /dev/fd0 etc...

– 为了避免每个进程都需要 build一个 rootfs:“层”和 unionfs• 动态视角

– 容器:程序运行起来的执行环境的视图和边界– 表现为:?

Page 8: Large-Scale Cluster Mangement & Kubernetes Under The Hood

容器 201 : docker run

Docker Daemon

Container•镜像 ID•网络配置•Volumes•其他 docker run参数

Command•Resources : cgroup配置•InitPath : dockerinit的位置•Process:

• Entrypoint + Args • e.g. /bin/sh –c echo hello

•Rootfs•其他容器参数,比如网络,Mounts等

生成

Libcontainer(runc)

linuxContainer•dockerinit•Config

• Cgroups • Namespaces

• 默认 NS• 用户指定的 NS

• Mounts• 其他 Command中的容器相关参数

Process•Entrypoint + Args•Env•User•Work dir

$ docker run ubuntu “echo hello”

Page 9: Large-Scale Cluster Mangement & Kubernetes Under The Hood

Docker Daemon

容器 201 : docker run

libcontainer

initProcess (父进程)•Pipes : childPipe, parentPipe•Cmd

• dockerinit• childPipe• Cloneflags

•Cgroups•Config

• Process (Entrypoint + Args)• LinuxContainer.Conifg

LinuxContainer.start(Process)

linuxContainer•dockerinit•Config

Process•Entrypoint •Args

initProcess

容器dockerinit

Cmd.start

1

2

将 dockerinit的 PID加入

Cgroups

创建容器内网络设备: lo ,veth

发送 Config给容器

准备 pipe 按照容器 config初始化内容和 rootfs

Pipes

EntrypointInit()

执行用户指令

Pipes

close pipe

execv

Page 10: Large-Scale Cluster Mangement & Kubernetes Under The Hood

所以,容器的动态表现是• 一个自带“世界观”的进程

– namespaces:视图– pivot_root 和 cgroups:边界– 三层文件系统: RW layer , init-layer , read-only layers

FROM ubuntu:latest

VOLUME /data

Copy-On-Write & /data

“echo hello”namespace cgroups或者 hyper , novm

read-only layer

/bin /dev /etc /home /lib /lib64 /media /mnt /opt /proc /root /run /sbin /sys /tmp /usr /var /data

/etc/hosts /etc/hostname /etc/resolv.confinit-layer

read-write layer

/var/lib/docker/

volumes/<volume_id>/_data

container/<container_id>/hosts container/<container_id>/resolv.confcontainer/<container_id>/hostname

aufs/mnt

Page 11: Large-Scale Cluster Mangement & Kubernetes Under The Hood

从 BORG 谈容器集群编排第二部分

Borg : http://research.google.com/pubs/pub43438.html

Page 12: Large-Scale Cluster Mangement & Kubernetes Under The Hood

从单机到集群• 多任务单机操作系统• 进程隔离

– 每个进程有自己的虚拟地址空间– 进程间使用 IPC通信

• 单机资源共享– 资源对象

• CPU• 物理内存• 文件• 外部设备

– 并发:进程上下文切换• 兼顾公平与高效的调度

• 多容器集群数据中心• 进程 +环境隔离

– 环境隔离与资源边界: namespaces和 cgroups

– 容器间通信:网络方案• 集群资源共享

– 资源对象:机器(或资源包)– 在机器内部才考虑单机资源共享

• CPU,物理内存,文件,外部设备,并发,公平调度• 兼顾公平、高效、利用率、能耗、访问延时的调度• 机器规模是关键

Page 13: Large-Scale Cluster Mangement & Kubernetes Under The Hood

容器集群管理中的问题1. 任务分类与优先级?2. 提升利用率?3. 允许抢占的调度?4. 如何评估调度算法?5. 调度策略优化?6. 是否混部的权衡?

Lei Zhang
结合WSC加个框架,这是框架的一部分
Page 14: Large-Scale Cluster Mangement & Kubernetes Under The Hood

问题一:容器的分类• LRS ( Long Running Service)–“死循环”,比如一个Web服务–需要立刻响应用户的请求,时延敏感–高优先级或生产环境级( prod)

• batch jobs– Map-Reduce,或者其它类似的计算任务• 它们的执行往往需要持续一段时间,但是最终都会停止

–对服务器瞬时的性能波动不敏感– 低优先级( non-prod )

Page 15: Large-Scale Cluster Mangement & Kubernetes Under The Hood

容器分类举例• 监控级、生产级、批任务级、尽力级(也叫测试级)– 监控级和生产级: prod任务

• prod任务可以抢占非 prod任务的资源• prod任务不能互相抢占–避免触发连锁反应( A抢占 B , B抢占 C , C再抢占 D)

Page 16: Large-Scale Cluster Mangement & Kubernetes Under The Hood

问题二:提升利用率by LeanCloud 陈伟, Docker Meetup

Page 17: Large-Scale Cluster Mangement & Kubernetes Under The Hood

资源边界• cgroups 只是资源边界– 只有在资源申请试图超出限额时才发挥作用–所以一台机器理应运行更多的容器

• 但是,我们必须有合理的判断依据来决定“这台机器尚能运行多少个新容器”– 硬指标: 4G机器, 1G的任务,还剩 3G– 超卖: 4G的机器, 1G的任务,还剩 4G*2-

1G=7G–有没有更好的做法?

Page 18: Large-Scale Cluster Mangement & Kubernetes Under The Hood

宿主机: 10G可用: 6G

动态资源边界4G

容器 A

资源回收事件

宿主机: 10G可用: 9G

回收资源: 3G

1G

容器 A

• 宿主机默认按照动态边界计算自己的可用资源• 如果容器资源使用超出 1G:迅速恢复资源边界到初始值(比如 4G)• prod级别的容器永远只使用现有容器的原始边界计算可用资源,而非动态边界• 效果:将近一半的集群减少了 30%的机器

Page 19: Large-Scale Cluster Mangement & Kubernetes Under The Hood

资源回收事件• 容器启动成功并运行 300s 后– 减少该容器资源边界

• 机器某种资源的可用值不足(比如流量激增)–可压缩资源,比如 CPU 周期和磁盘 I/O带宽

• 热回收,调节 LRS容器的容器边界– 如若达不到目的,触发重调度事件,移除部分容器

– 不可压缩资源,比如内存和磁盘空间• 只能按优先级从低到高杀死容器,直到恢复合理的可用值

Page 20: Large-Scale Cluster Mangement & Kubernetes Under The Hood

安全余量• 安全边界 = 实际资源使用量 + 可配置的安全余量• 方法:以集群为单位,通过实验获得该集群的合理余量

– 给定不同的安全余量值– 观察不同余量下资源 margin 和 OOM 次数在一段时间内的的变化– 选取平衡点的余量值 资源margin

Page 21: Large-Scale Cluster Mangement & Kubernetes Under The Hood

问题三:允许抢占的调度• 第一,可行性检查

– Node是否满足容器资源需求• 可用资源 = 机器容量 – 所有容器的边界 + 可以抢占的容器的资源

– 是否满足自定义约束(比如指定的磁盘类型)– 得到候选机器列表

• 第二,打分– 尽量避免发生资源抢占;如果避免不了,则让被抢占的容器数量最少、优先级最低– 挑选容器依赖更完备的机器(比如 package 完备,已经 pull 过所需的镜像)– 使容器尽量分布在不同的高可用域当中– 尽量混合部署不同优先级的容器

• 流量峰值突然出现后便于回收资源

Lei Zhang
这一部分话有点长,精简一下!
Page 22: Large-Scale Cluster Mangement & Kubernetes Under The Hood

问题四:如何评估调度算法• 压缩实验– 不断减少集群中机器的数量(“压缩”),然后重调度某个指定的容器到该集群,直到它再也不能正常调度运行在这个集群上

• 结果: 最小工作集群• 调度算法越优秀,对于同一个容器来说它最后得到的最小集群单元中的机器数就越少

Page 23: Large-Scale Cluster Mangement & Kubernetes Under The Hood

问题五:调度策略优化• 缓存机器的打分结果

– 只有当机器本身信息或者容器发生了变化(比如容器数目或者容器边界)时,才更新缓存的机器分数– 忽略那些不太明显的变化,减少缓存的更新次数

• 划分容器组(等价类)– 为一组需求和约束都一样的、亲密关系的容器执行调度过程,而不是单个容器

• 随机选择一组机器来做可行性检查,而不是整个集群– 随机挑选一个机器来检查可行性,判断是否通过,再挑选下一个,直到通过筛选的机器达到预设的数目,返回之作为候选机器列表– 参见 Sparrow调度器

• 效果:极端情况可能耗时几天的任务 -> 几百秒

Page 24: Large-Scale Cluster Mangement & Kubernetes Under The Hood

问题六:是否混部的权衡• LRS 和 batch job分开部署:–需要额外增加 20%-30%的机器

• 不同用户的容器分开部署:–需要额外增加 20%-150%的机器

• 共享带来的 CPU 性能损失: 3%– CPI ( cycles per instruction)–每增加一个容器,其他任务的 CPI 增加 0.3%

• 权衡:减少的机器数量 VS CPU 性能损失

Page 25: Large-Scale Cluster Mangement & Kubernetes Under The Hood

KUBERNETES 原理与实现第三部分

Page 26: Large-Scale Cluster Mangement & Kubernetes Under The Hood

Kubernetes

1. k8s 是 Borg的开源实现吗?他俩什么关系?2. K8s的架构?3. 怎么部署 Kubernetes?4. Pod的作用?5. Pod的调度策略?6. 如何创建一个 Pod?7. Pod如何被访问到?8. k8s提供跨主机网络不?9. k8s 跟 XXX到底啥区别?

Page 27: Large-Scale Cluster Mangement & Kubernetes Under The Hood

Kubernetes 核心结构

Page 28: Large-Scale Cluster Mangement & Kubernetes Under The Hood

部署 1 : k8s in dockerMaster Worker

docker daemon docker daemon

docker-bootstrap daemon--iptables=false

docker-bootstrap daemon--iptables=false

flanneld etcd flanneld

kubelet kube-proxy kubelet kube-

proxy

master

2

1

• 优点:快速,无依赖, self-deploy,操作系统无关,适合开发环境或小型集群• 缺点:不方便与现有系统集成,需要登录到每台机器上执行脚本• 见: <k8s>/getting-started-guides/docker-multinode.md

mastermaster

Page 29: Large-Scale Cluster Mangement & Kubernetes Under The Hood

部署 2 : ubuntu cluster1. 编译出 kubernetes , etcd, flanneld 二进制文件2. 规划集群:

3. 部署:

• 优点:一键部署,适合一定规模的集群,符合 k8s e2e test规范,便于同现有运维系统集成• 缺点:只支持 Ubuntu,暂不支持 systemd• 见: <k8s>/docs/getting-started-guides/ubuntu.md

IP Address Role

10.10.103.223 node

10.10.103.162 node

10.10.103.250 both master and node

export [email protected] [email protected] [email protected] role="ai i i“export NUM_MINIONS=${NUM_MINIONS:-3}export SERVICE_CLUSTER_IP_RANGE=192.168.3.0/24export FLANNEL_NET=172.16.0.0/16 KUBERNETES_PROVIDER=ubuntu ./kube-up.sh

Page 30: Large-Scale Cluster Mangement & Kubernetes Under The Hood

Why Pod

• Pod– IP 、 port等网络资源的分配的基本单位– 共享存储卷 volume– 共享 namespace

• pid, network, ipc, uts

• 两个典型场景:– Kubernetes 的 Master组件

• ./apiserver --address=0.0.0.0• ./scheduler --master=127.0.0.1:8080• ./controller-manager --master=127.0.0.1:8080

– 一个应用容器和它的日志转发器• Web app• log aggregator

apiserver

scheduler controller-manager

Lei Zhang
试一下其他namespace的共享!
Page 31: Large-Scale Cluster Mangement & Kubernetes Under The Hood

But wait …• Pod并不是一组容器的简单集合或者集群• Pod 是 Kubernetes 世界观里的“容器”

– Lessons learned from Borg– 成规模场景下的任务组织形式

• Pod :进程组• 容器 :进程

– 超亲密关系– 地位对等– 共同决定 Pod状态

containers: - name: container A - name: container BrestartPolicy: - string: {}volumes: - name: string source: emptyDir | HostDir emptyDir: {} hostDir: path: string

Page 32: Large-Scale Cluster Mangement & Kubernetes Under The Hood

如何创建 Pod?

V0.16.2

Page 33: Large-Scale Cluster Mangement & Kubernetes Under The Hood

Scheduler默认策略• 完全插件化• Predicates:筛选出合格的 Node

– 容器申请的主机端口是否可用– 可用 CPU和内存是否满足 Pod 里的需求

• 不支持抢占机制,不关注利用率– host volume目录是否冲突– 是否匹配用户指定的 Label– 是不是指定的 hostname

• Priorities:对通过上述筛选的 Node打分– 选择资源空闲更多的机器– 选择调度完成后 CPU和内存利用率更平衡的机器– 属于同一个任务的副本 Pod 尽量分布在不同机器上

V0.16.2

Lei Zhang
尝试一下可插拔的调度:https://github.com/kubernetes/kubernetes/blob/master/examples/scheduler-policy-config.json
Page 34: Large-Scale Cluster Mangement & Kubernetes Under The Hood

Scheduler如何采集信息?• 向 API Server请求信息( 10s),有 client 缓存机制• 两种数据更新方法

– Reflector:监测( watch)对象变化– Poller:抓取不支持 etcd watch操作的 api对象数据描述 采集方法 数据对象 client 缓存类型

所有未调度的 pod Reflector podQueue queue所有已调度运行的pod

Reflector podLister cache

所有可用的minion Poller MinionLister cache所有 service对象 Reflector ServiceLister cache

V0.16.2

Lei Zhang
尝试一下可插拔的调度:https://github.com/kubernetes/kubernetes/blob/master/examples/scheduler-policy-config.json
Page 35: Large-Scale Cluster Mangement & Kubernetes Under The Hood

SyncPods

pods

pod nodeName

pod nodeName

新版 kubelet

scheduler APIServer

POST /binding

pod node list

RunKubeletPods with pod.host == nodeName

watch (三种源)

startKubelet

Pods

statusManager

Pod.statusPod

SyncPods

ContainerManager,Cadvisor

managePodLoop

managePodLoop

managePodLoopWorker

updatePod

Pods合法性检查

Pod

Pod

V1.0

SyncPod : Pod vs 现有 Pod

1.创建 Pod数据目录2.创建 API实体3.mount Volume4.更新 status

DockerManager1.遍历 Pod中的Containers2.pull镜像3.生成 Docker参数4.启动容器

Lei Zhang
pod_works.UpdatePod新建worker之后,就只剩下创建了。虽然SyncPod里明显有update Pod
Page 36: Large-Scale Cluster Mangement & Kubernetes Under The Hood

期望状态RC: replica: 2 selector: ‘label’ : ‘test’ // pod definition …

如何控制 Pod?• Controller Manager– Replication Controller (RC)– 检测循环( 10s):

期望状态RC: replica: 2 selector: ‘label’ : ‘test’ // pod definition …

Diff

•期望的 replica值•查询到的 Pod数量APIserver

etcd1. label 匹配2. 选择状态不为

podFailed 的 Pods

create/delete Pod

fetch with Reflector cache

Page 37: Large-Scale Cluster Mangement & Kubernetes Under The Hood

如何访问 Pod?• Service:– Portal,提供访问 Pod的固定入口( portal_ip : port)– 多个副本 Pod的动态 Load Balancer– 适合强依赖于 IP的业务 NAME SELECTOR IP PORT

…service-nginx name=nginx 11.1.1.88 800111.1.1.88:8001

Label: name=nginx

Pod A-1

Label: name=nginx

Pod A-2

Label: name=nginx

Pod A-3

Endpoint

Page 38: Large-Scale Cluster Mangement & Kubernetes Under The Hood

Node

Service

Node

// 请求发起自容器: PREROUTINGtarget prot opt source destination …REDIRECT tcp -- 0.0.0.0/0 11.1.1.88 tcp dpt:8001 redir ports 43318// 请求发起在 HOST : OUTPUTtarget prot opt source destination …DNAT tcp -- 0.0.0.0/0 11.1.1.88 tcp dpt:8001 to:10.10.103.58:43318

11.1.1.88:8001

kube-proxy

Proxier43318

LoadBalancer

Pod地址 : 端口

根据 etcd 中 Service的增删创建并维护规则

Request

etcd

1. Service变化2. Endpoint变化

Pod地址 : 端口bi-directionally io.Copy

Round-RobinSession Affinity

Page 39: Large-Scale Cluster Mangement & Kubernetes Under The Hood

Service• portalIP 仅在集群范围内的机器上有效

– publicIP(使用机器的 public IP 做 portalIP)– 外部 LoadBalancer

• 大规模 &高并发场景下的担忧– 可能的瓶颈:

• userspace 的 Proxier ( 已经 Fixed,需要 iptables 1.4.0)• iptables 更新耗时

– 可选替换: cloudfoundry/gorouter , flynn/flynn/router , HAproxy• 监视: <master:port>/api/v1beta3/watch/pods,更新 Server Pool• 缺点:

– 不能有效提供 portal_ip– 需要域名依赖或者端口管理 Host A

pod_1

Host B

pod_1pod_2

pod_1.mydomain.com

LB

Page 40: Large-Scale Cluster Mangement & Kubernetes Under The Hood

如何创建 Service?

V0.16.2

Page 41: Large-Scale Cluster Mangement & Kubernetes Under The Hood

如何控制 Service?• Controller Manager– Service Controller:使用真实状态更新 Service– 检测循环:• 遍历所有 Service

– 根据 label,查询出 Pod 列表(真实状态)– 该 Service 持有的 Endpoint 列表(期望状态)– Diff– 有差异:删除多余的 Endpoint或者检查实际状态列表的资源版本号

等于 0,真实 Pod并没有出现在 Endpoint 列表中,创建该Endpoint

不等于 0,更新该 Endpoint

Page 42: Large-Scale Cluster Mangement & Kubernetes Under The Hood

Pod网络:单 Pod 单 IP模型

pause

Container A Container B

--net=container:pause

/proc/{pid}/ns/net -> net:[4026532483]

• 网络容器( infra容器)– 使用 docker0网桥作为默认网关,并且被分配该网桥上的一个 IP地址作为所有容器共享的 IP地址

Page 43: Large-Scale Cluster Mangement & Kubernetes Under The Hood

Kubernetes的网络假设1. 容器之间可以跨主机通信,无需经过 NAT2. 所有主机与容器之间可以直接通信,无需经过

NAT3. 容器本身看到的自己的 IP地址与其他容器看它的 IP地址是一样的但是, Kubernetes 本身对上述假设不做任何实现e.g. Flannel SocketPlane Calico OVS macvlan ipvlan ...

Page 44: Large-Scale Cluster Mangement & Kubernetes Under The Hood

典型的网络实现• 两条基本原则

– 绝大部分 Docker 跨主网络方案均可以满足上述“网络假设”– 可以随意更改 Daemon的配置、启动参数,但是 Kubernetes目前必须使用标准 Docker API

• docker run … √• my_tool run … ×

• API 不一致,使用 Powerstrip进行转义 : https://github.com/ClusterHQ/powerstrip

kubelet

Powerstrip

docker run

my_tool run

Page 45: Large-Scale Cluster Mangement & Kubernetes Under The Hood

抛砖引玉• Flannel

– overlay网络, UDP 封装或者 VxLAN封装– 用 Docker 启动 flanneld 后配置 DOCKER_OPTS 的 --bip 即可– 简单,稳定,但没有划分多个隔离域的能力

• Weave– 通过 ambassador容器抓取链路层流量,使用 UDP 转发该报文到目的端

• SocketPlane– OVS的功能性封装,使用 GRE/VxLAN隧道– 使用 Powerstrip– Hack:修改 kubelet,在启动 infra容器时添加” SP_NETWORK=xxx”环境变量

Qperf test Flannel UDP

Flannel VxLAN Weave Socketplane Native

TCP bandwidth 28.7 MB/s 47.8 MB/s 3.75 MB/s 42.8 MB/s 62.5 MB/s

TCP latency 200 µs 127 µs 384.4 µs 110.9 µs 96.1µs

Lei Zhang
calico其实值得关注!
Page 46: Large-Scale Cluster Mangement & Kubernetes Under The Hood

Kubernetes VS 小伙伴们• 祖师: Borg

– 专注于支撑成规模的企业服务并且最大程度地提高资源利用率• Kubernetes

– 典型的容器集群管理工具(类似 Swarm),但基本单位是 Pod

– 暂时不关注资源抢占和任务混部,以及资源利用率提升– K8S大量借鉴了 Borg的优秀思想、架构、甚至代码实现,但并不能说就是 Borg的开源实现– Goal :” run your container workload at scale”

Page 47: Large-Scale Cluster Mangement & Kubernetes Under The Hood

Kubernetes VS 小伙伴们• Mesos

– 专注于 Scheduling和资源抽象,需要同上层框架协作– 良好的 framework 支持,适合作为基础依赖– 适合大数据场景,非原生针对容器集群管理设计– Goal: “I already have a Layer 1 (business or platform layer), but I need Layer 0

(infrastructure layer) to run it on cluster“

• Flynn Deis Marathon + Mesos Cloud Foundry OpenShift – 更类似 PaaS– “从代码,到可运行制品,再到运行实体”– 低用户自由度,高自动化程度

• Compose + Swarm– 最 Docker友好的容器集群管理工具– 最原生的 Docker 支持 = vendor lock in– 缺乏成规模集群管理的 vision

Page 48: Large-Scale Cluster Mangement & Kubernetes Under The Hood

Further Contact

• www.sel.zju.edu.cn• harryzhang AT zju.edu.cn• @柳烟堆雪

Page 49: Large-Scale Cluster Mangement & Kubernetes Under The Hood