2017年3月25日,网易云技术布道系列第三期 • 对话架构师上海站的活动中,网易云基础设施技术总监张晓龙带来了题为“网易云容器服务研发实践分享”的干货演讲。网易从2012年春开始云计算研发,陆续上线私有云IaaS、PaaS服务,并实现网易95%以上的互联网业务迁移上云。本次活动中,张晓龙分享了网易云基础服务团队在研发容器服务过程中的实战经验。
张晓龙,网易云基础设施技术总监,网易专业技术委员会委员。浙江大学本科、博士毕业。目前主导网易私有云以及网易公有云基础设施服务的技术研发,在云计算基础设施、分布式系统方面有多年的架构设计与研发经验。
张晓龙首先介绍了网易云的研发历程和整体架构。
网易云的产品经历了长期的技术积累,网易在2012年开始做云计算,最早实现了IaaS,交付了公司内部的私有云基础设施服务,包括主机、网络、存储等服务;2013年8月,陆续上线了关系型数据库、负载均衡、对象存储等平台服务;2014年12月,网易内部95%以上的互联网产品都实现了上云;2015年5月,网易云对外服务于合作伙伴——网新科技、中顺易等;2016年1月,网易基于Docker实现了容器云,并在9月正式对外发布。
下图是网易云的简单架构:
网易云的技术架构从底到上分为三层:
基础设施层主要采用虚拟化技术将服务器、交换机/路由器以及硬盘等物理设备虚拟成为可以按需分配的计算/存储/网络资源。基础设施层主要包括:云主机、云网络、云硬盘等服务。基础设施层不仅为网易云容器服务运行提供计算/存储/网络资源,同时也为为数据库、缓存、负载均衡等网易云平台服务提供资源;
核心业务层主要包括两块:一是容器及容器编排:镜像仓库、日志服务、容器服务、编排服务,主要覆盖了以容器以及容器编排为中心的网易云容器服务核心功能;二是PaaS插件服务,主要包括数据库、负载均衡、对象存储、缓存等;
最上面的外围服务层,也是构成一个平台不可或缺的一部分。主要包括:认证、API服务、计费服务、安全服务、监控服务
作为网易云的核心服务之一,网易云容器服务的定位是面向高效研发而打造的新一代云计算平台,提供弹性计算、DevOps工具链及微服务基础设施等,帮助企业解决IT、架构、运维等问题,使企业更聚焦其业务。容器服务的功能包括3个方面:
提供有状态/无状态容器及其镜像加速/构建/仓库等在内的容器服务;
提供包括对象存储、CDN、关系数据库、MongoDB、负载均衡、缓存服务、安全服务等在内的完善平台服务,是实现互联网应用的通用的基础组件;
提供包括服务发现、编排服务、APM服务、持续集成、监控服务、日志服务、持续发布等在内的完整DevOps工具链。
要构建一个容器服务,需要三类核心的技术:基础设施、容器、容器编排。从整个核心技术来看,网易云容器服务基于流行的开源技术而打造,为实现极致的用户体验实施了各种优化和定制开发。
基础设施提供容器运行所需计算/存储/网络资源,高效管理这些资源并确保资源的按需分配、高效交付,同时要保证交付资源的QoS比如计算能力、网络性能、I/O能力等;
基础设施服务的技术基础是虚拟化技术,包括计算、网络、存储的虚拟化技术,计算的虚拟化无论在硬件或软件层面都相对成熟,而在网络、存储的虚拟化上网易云的选择是软件定义的技术。
在计算虚拟化方面,网易云采用的是高效稳定可靠的KVM虚拟化技术;
在网络虚拟化方面,网易云基于OpenVSwitch采用最新流行的SDN技术,获得更大的网络灵活性;
在块存储方面,网易云采用的是可扩展性较强的Ceph技术;
网易云使用开源云平台框架OpenStack实现对上述资源的高效管理;
容器是网易云容器服务资源交付的最小单位,网易云采用了最新Docker技术,实现应用交付的标准化;目前的容器服务基于Docker1.12版本打造。
要基于容器实现一个可水平扩展的产品服务端架构,需要使用容器编排技术实现对容器集群的发布、回滚、迁移、扩容、缩容等。网易云的容器编排基于开源项目Kubernetes,Kubernetes服务将资源抽象为三个层次:容器(软件及运行环境),Pod(相关联的容器组合)容纳一个或多个容器,Node(提供计算/网络/存储的资源节点)容纳一个或多个Pod。
网易云团队对这些核心技术有全面的掌控力,一方面也体现在网易云对这些开源技术的贡献和参与上:
以OpenStack和Kubernetes为例,网易从2012年4月开始对OpenStack E版本贡献代码,2016年下半年网易云开始向Kubernetes社区贡献代码,是国内最早向这2个社区贡献代码的团队之一。
使用VxLan大二层技术实现网络数据面,基于OpenVswitch开源虚拟交换机实现OpenFlow协议
基于OpenStack Neutron实现网络控制面
两类块存储后端:1)基于Ceph的普通块存储;2)基于软RAID技术的自研高性能块存储(用于高性能IO场景如数据库等)
基于OpenStack Cinder实现块存储资源管理
采用KVM虚拟化技术
基于OpenStack Nova实现虚拟机生命周期的管理
首先,容器的计算资源应该如何提供?应该跑在物理机上还是虚拟机上?从公有云层面来说,在容器的隔离性不是特别好的情况下,还是要跑在云主机上面,这是对用户最基本的安全承诺。
好处1:由于是操作系统层面的轻量级虚拟化,容器安全性一直是用户非常关心的问题,也制约着容器技术的发展。容器安全性问题以“容器逃逸”问题最有名,也就是黑客是可以通过容器的一些漏洞渗透到运行容器所在的宿主机上,对宿主机上的其他容器以及宿主机本身都造成巨大的威胁。在容器安全性问题没有得到有效解决前,将容器运行在虚拟机上,利用虚拟机的强隔离性,可以加固容器的安全性。
好处2:由于容器是轻量级虚拟化,所有容器共享宿主机的内核,宿主机上一个容器的运行异常和故障,很有可能导致宿主机内核的crash,从而影响宿主机上其他容器的正常运行;因此,将容器运行在云主机中,尽可能少的容器共享同一个内核,可以实现故障的隔离,提高系统稳定性;
好处3:由于容器运行在云主机中,我们可以大胆把一些系统的能力如设置iptables的能力开发给用户,而不用担心开放这些能力会对宿主机系统造成很大的影响。这可以使得用户得到更多的功能,对容器具有更强的掌控;
这样做的缺点在于:容器运行于云主机,要忍受硬件虚拟化技术带来一定的资源和性能开销。
私有网:虚拟平坦二层网络、租户间完全隔离,通过容器私有网卡接入
公网:允许绑定公网IP到容器,通过容器公网网卡接入
容器网络由基础设施服务来提供,并确保网络的性能、可扩展性;容器不关心和处理网络性能、可扩展性问题,只管用云提供的网络服务创建和使用相应的网络。网易云为每个租户提供一张完全隔离的私有网络以及一张所有租户共享的公网。
私有网接入:基于云主机上的网桥和容器veth pair实现
公网接入:将云主机上的公网端口置入容器的namespace中
容器的存储也是比较难解决的问题,多数容器都是无状态的,也就是说容器内部不应该保存用户有用的数据,一个容器挂掉后,用镜像能很快启动另一个容器,保证系统的正常运行。从架构上来说这个设计很好,弹性可扩展。但如果架构设计能力不是太好的情况下,很容易出现有状态容器的需求。
但不管是Docker还是Kubernetes都不解决容器的存储问题,只可以用docker -v指定一个数据目录,所以在构建容器云时有2个需求:
容器根目录rootfs会保存其运行时数据,需要用云盘保存容器rootfs数据
容器需要挂载云盘作为data盘
Docker默认会将所有容器rootfs都存储在overlay目录下,不同容器rootfs数据无法有效区分并隔离
实现Docker启动时可指定独立rootfs的功能
在启动容器前将云盘挂载到启动容器的rootfs上
网络安全也是云平台设计非常重要的一点
L2过滤:确保报文源MAC地址是系统所分配端口MAC地址,防止ARP欺骗
L3过滤:确保数据包源IP是系统所分配IP,防止IP地址欺骗
L4过滤:过滤指定的TCP/UDP端口,便于实施网络封禁
基于Intel DPDK技术实现高性能实时抗攻击
保证用户所申请网络带宽
有效利用空闲网络资源,免费提升用户带宽体验
基于Linux Traffic Control并修改OVS,实现保证速率、最大速率
将小包按照MPU(Minimum Packet Unit)大小来处理
网络QoS另一个重要问题是网络小包过载的问题,
问题:VXLAN小包处理性能不够好,网络小包过多导致宿主机CPU过载(软中断过多),影响网络性能和稳定性
方案:限制容器网络的PPS (Packet Per Second)
容器运行于云主机,容器启动依赖于云主机先启动,而基于硬件虚拟化技术的云主机启动速度较慢。
1、定制系统镜像,裁剪不必要服务启动加载项;
2、云主机IP静态化,加速网络初始化过程。IP静态化的原因:云主机网络初始化使用DHCP服务获取网络IP和路由等信息,会占用较多启动时间。在网络服务启动前使用Cloud-init和ConfigDrive完成网卡名称匹配和IP配置信息注入;
3、优化OpenStack创建云主机流程,主要是在OpenStack的计算节点上做了一些优化。
创建容器在40秒内完成
内网使用巨帧(Jumbo Frames)模式,提升数据传输的吞吐量。
使用不同内核版本和OVS版本的组合,VxLan性能差异很大,在万兆网络环境下使用3.18版本内核 + 2.6版本OVS,云主机单连接网关转发性能可近4Gbps,云主机多连接网关转发性能可达近9Gbps,云主机间互访近4Gbps
社区Ceph在osd进程重启时会出现长时间、极其严重的性能衰减(80%+),原因是osd重启时要恢复重启期间脏数据对象,会消耗大量网络/磁盘开销
在pglog记录重启期间数据对象的增量数据,在重启时增量恢复数据对象
解决效果
减少重启过程对集群正常I/O性能影响( I/O性能降低10%~20%以内)
缩短重启恢复所需时间(重启单个osd从10分钟减少到40秒左右)
原生的Kubernetes没有租户和多租户的概念,意味着要给每个用户部署一套Kubernetes的集群管理系统,网易云用一套Kubernetes集群去管理所有租户的容器,这跟社区版本中完全不一样的地方
将容器的资源按照多租户进行分类,如下图所示,将node、存储、网络等集群共享的资源实现租户隔离
实现租户资源的安全访问控制,为每个租户实现独立的认证和授权
原生K8S编排的可扩展性有瓶颈,无法支持更大规模节点的编排
K8S各组件在高水位下资源占用太大
实现调度器并行调度,提升集群调度能力
实现副本控制器多优先级处理,提升容器创建速度
精简内部负载均衡转发表
优化api-server和kubelet、kube-proxy,减少内存资源占用
问题:原生scheduler调度是全集群串行,不可并行扩展
优化:所有资源按用户分组,全并行调度,集群规模再大也能瞬间调度
问题:原生controller对副本的增量的增/删/改和全量定时任务单队列处理
优化:增加多优先级队列(Add>Update>Delete>Sync All),让实时控制流优先处理,提升容器创建速度
问题:原生使用iptable全局转发,性能随集群规模增大线性递减
优化:租户之间网络隔离后,可以将转发规则精简到各个租户内部
问题:这些服务随着集群规模增长,内存也都直线上涨
优化:agent只加载自己租户拥有的namespace下数据, apiserver增加索引降低cpu以减少并发协程数
支持3w+容器的编排
高水位下容器创建时间40s之内完成
K8S上节点占用内存优化为原来的1/4,Api-Server内存减少了1/4
数据采集:基于CAdvisor采集计算存储网络等监控如cpu/mem/io/tcp连接/网络流量
数据推送:Agent负责从CAdvisor拉取监控数据并推送到后端进行数据聚合
数据聚合:将相关监控项按照容器、pod、副本等层次聚合并展示
云计算的研发是一项系统的基础开发工作,有非常大的难度难,云计算产品最重要的是稳定性、性能和安全,后续的工作也将围绕这三方面展开。