网易云基于 Kubernetes 的深度定制化实践

社区编辑2018-05-18 15:38

2017 年 3 月底,Kubernetes 隆重发布了 1.6 版本,在节点规模、安全性、调度和存储上都有了重大进展。目前来看,不论从社区关注度还是实践案例角度,Kubernetes 都已经超越 Mesos 和 Docker Swarm,成为最受欢迎的容器编排技术。
 
网易云从 2015 下半年开始向 Kubernetes 社区贡献代码,是国内最早的 Kubernetes 实践者和贡献者,并已经成为 CNCF(云原生计算基金会)官方授权的 CloudNative Meetup 主办方。本文将简单介绍下网易云基于 Kubernetes 的深度定制化实践。
 

1 网易云容器服务的架构

 
网易云容器服务基于网易云 IaaS。为了简化用户操作,Kubernetes 并不直接暴露给用户,而是通过上层的业务层为用户提供容器服务。增加独立的 Netease-Controller, 对接网易 IaaS 及公共平台,资源管理和复杂的业务需求。
 

 

2 kubernetes 公有云实践

 
Kubernetes 的社区版本主要面向私有云市场,没有租户的概念,只有 namespace 的逻辑隔离,Node/pv 等资源都是集群全局共享的,服务发现和负载均衡也都是全局的,Node 须在集群内预备足够,不用担心资源调度出现失败,也无需关心 Docker 隔离安全性问题。而对于公有云来说,云中有着海量用户,用户的技术背景多样,需要很高的安全隔离性。网易云在基于 Kubernetes 实现公有云的过程中,做了很多工作:
 
首先,在多租户的安全隔离方面,有专门的 IaaS 团队提供主机、硬盘和网络的隔离;
 
对于每个租户来说,都可以自定义创建 namespace;
 
原生的 Kubernetes 认证很简单,而且 Node 是全局共享的,每个 Node 上都可访问 Kubernetes 的所有资源,所以为了实现公有云,网易云做了租户级别的安全隔离,包括认证、授权和 API 分类统计和流控报警;
 
在网易云中计算、存储、网络资源均按需实时分配、回收,保证资源的利用率尽可能高;因为资源是实时分配的,所以创建起来一般比较慢,所以网易云对创建流程做了一些全局的优化,比如加快 Node 注册的进程,根据镜像选择主机等;
 
原生的 Kubernetes 中没有网络 IP 的概念,网易云增加了 Network 资源类型表示网络 IP。
 

3 网易云容器 pod 网络

 
容器的网络主要有以下几种方案:
 
○ 入门级:Docker 基础网络模型 host(共享),bridge (NAT)。
○ 进阶级:自建网桥 (IP-per-Pod),可跨主机通讯,如 Flannel, Weave。
○ 专业级: 多租户,ACL,高性能可扩展 ,如 Calico,GCE 高级网络模式。
 
网易云容器网络实现
 
网易云容器服务的网络实现与 GCE 类似,基于底层 IaaS 网络,通过 Kubernetes 与网易云网络对接,网易云容器与主机在网络上完全对等,租户内全互通。
 
Kubernetes 中没有定义 IP 的管理,可能一个容器或节点重启一下,IP就变了。网易云通过 IP 的管理实现了 IP 的保持功能,同时 Pod 支持私有网、公网双重网络。
 
此外,网易云还实现了 Pod 的私有网、公网 IP 映射关系管理,在 Kubelet 上实现 Netease CNI 插件管理网卡挂卸载、路由配置。
 

4 网易云有状态容器

 
提到容器的状态,人们常用 Cattle 和 Pet 来做比喻。Cattle 是指无状态的容器,随时可以被替换,Pet 则是有标记的,它的数据、状态和配置可能都需要持久化。社区从 1.3 版本就开始用 PetSet 实现有状态的容器,最新的 1.6 版本中,是叫 StatefulSet。
 
网易云在社区版本的有状态容器诞生之前(1.0版本),就自研了 StatefulPod 的实现方式:
 
和 StatefulSet 不同的是,它可以支持容器系统卷、数据卷的保持(PV、PVC)。StatefulSet 只能支持外挂的数据卷,但是网易云的 StatefulPod 能够保证只要不删除用户,用户系统盘的数据也能够保持下来;
 
StatefulPod 还能保证容器私有网、公网 IP 保持(Network);
 
在原生的 Docker 中,一个 Node 启动的所有容器目录都是统一的,网易云扩展 Docker 支持容器 rootfs 目录自定义;
 
网易云的有状态容器还支持故障的迁移,比如硬盘和 IP 等资源都能在 Node 间漂移。

5 网易云 Kubernetes 性能优化

 
一般在实现公有云时,会尽量保证同一个机房内,只有一个 Kubernetes 集群,但随着用户的增多,集群的规模也越来越大,会出现很多性能问题。网易云随着社区的发展一路走来,也遇到了社区在设计之初可能没有预料到的一些问题,比如:
 
○ Kube-scheduler 对所有 Pod 顺序串行调度;
○ Kube-controller 的 deltaQueue 是无优先级的 FIFO 队列;
○ Serviceaccounts 控制器里没有 Secret 本地缓存;
○ 所有 Node 重复配置集群所有 Service 的 iptables 规则;
○ Kubelet 的 SyncLoop 每次检查都重复 GET imagePullSecrets;
○ 大量 Node 的心跳汇报严重影响了 Node 的监听;
○ Kube-apiserver 没有查询索引。
 

master 端的调度器

 
针对这些问题,网易云做了很多性能优化,首先是 master 端的调度器:
 
公有云的场景和私有云不一样,容器分布在不同的租户中,每个租户的资源都是独立的,本身就可以通过租户来沟通并调度;
 
通常在调度的时候需要一个个去遍历 Node,实际上很多无闲置资源的 Node 可以不参与调度的检查,网易云会在遍历前过滤掉无闲置资源的 Node;
 
优化 predicate 调度算法过滤顺序,提高调度效率;
 
网易云中,调度都是基于事件的,比如调度失败如果是因为 Node 资源不足,就会发一个事件去申请资源,资源回来后会又返回一个事件驱动 Pod 重调度,没有任何时间等待。
 


 

 

 

mater 端控制器的优化

 
Kubernetes 中有很多控制器,比如 Node 控制器、Namespace 控制器,其中 Replication Controller 是一个核心的控制器,能确保任何时候 Kubernetes 集群中有指定数量的 Pod 副本在运行。网易云创建了事件优先级机制,根据事件类型进入优先级队列 workqueue。
 

Node 端的优化

 
网易云的用户很多,用户之间都是完全隔离的,网易云 kube-proxy 按租户对 Node 分组:
 
○ 租户之间容器网络完全隔离,不配多余转发规则;
○ 只监听本租户的 Service,再生成 iptable 规则。
 
Kubelet 降低 master 请求负载:
 
○ imagePullSecret 推迟都要拉镜像才 GET 或增加 Secret local cache;
○ 只监听本租户相关资源变化(依赖 apiserver 新加的 tenant 索引);
○ 精简 kubelet watch 低 master 连接数,包括 Node。
 

单集群扩展的优化

 
根据官方的数据,Kubernetes 1.0 最多支持 100 个 Node,3000 个 Pod;在 1.3 版本中这个数字上升到 2000 个 Node,6 万个 Pod,今年最新发布的 1.6 版本已经支持 5K 个 Node,15W 个 Pod。
 

 
通过上图可以知道 APIserver 是整个集群的通信网关,只是一个 proxy 代理,而且 goroutine 对 web 服务完美支持,最终性能瓶颈体现在对 etcd 的访问上。
 
为了解决这个问题,首先想到的是分库,按 Node/RS/Pod/Event 分库存入多个 etcd 集群。因为 Etcd 本身容量和性能均不能水平扩展,而且没有性能诊断工具:
 
○ Etcd2 调优,比如针对 snapshot 的优化,采用 SSD 硬盘等;
○ 升级 Etcd3,在之前的版本中,每次更改都会发送一个请求,一个请求又对应一个回复,在Etcd3 中是批量请求的方式,可能一次请求就把1000 个变化推送过来了,所以效率提高很多;
○ 更换 Kubernetes 后端的存储,换其他性能更优的 KV 存储。
 
Node 心跳汇报模式修改:
 
○ Node 心跳间隔延长;
○ Node 心跳不持久化;
○ 心跳从 Node 分离出来,Node 心跳只需 list 不必watch;
○ NodeController 被动改主动探测。
 

其它优化

 
镜像、容器的 GC 完善:目前的 GC 只考虑了磁盘的空间使用量,没考虑 inode 的问题,很多用户的小文件很多,所以网易云新增了磁盘 inode 使用率检查。
 
容器监控统计:Cadvisor 新增网络流量、TCP 连接、磁盘相关统计。
 
NodeController 安全模式,自定义 Protected,Normal,Advanced 3 种模式:
 
○ Protected: 底层 IaaS 主动临时运维时,为了避免大规模迁移波动, Node 离线只报警不迁移;
○ Normal:有状态的不迁移,无状态的及时离线删除重建。(仅仅底层云盘、网络故障);
○ Advanced:有状态无状态都自动迁移恢复。
 
还需要注意的一些问题:
 
○ Pod 的 graceful delete 要容器能正常传递 SIGTERM 信号;
○ StatefulSet 在 kubelet 挂掉时可能出现两个同时运行的 Pod。
 

 
娄超,网易云容器编排技术负责人。曾经参与淘宝分布式文件系统 TFS 和阿里云缓存服务研发,2015 年加入网易参与网易云容器服务研发,经历网易云基础服务(蜂巢)v1.0,v2.0 的容器编排相关的设计和研发工作,并推动网易云内部 Kubernetes 版本不断升级。