支撑大规模公有云的Kubernetes改进与优化 (3) 下篇

勿忘初心2018-11-08 15:52

此文已由作者刘超授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验


六、通过优化Controller加快新任务的调度速度


Kubernetes采用的是微服务常使用的基于事件的编程模型。


当有增量事件产生的时候,则controller根据事件进行添加,删除,更新等操作。


但是基于事件的模型的一个缺点是,总是通过delta进行事件触发,过了一段时间,就不知道是否同步了,因而需要周期性的Resync一下,保证全量的同步之后,然后再进行增量的事件处理。


然而问题来了,当Resync的时候,正好遇到一个新容器的创建,则所有的事件在一个队列里面,拖慢了新创建容器的速度。


通过保持多个队列,并且队列的优先级ADD优于Update优于Delete优于Sync,保证相应的实时性。


七、通过优化虚拟机启动速度加速容器启动速度


前面说了,为了保证安全性,容器是启动在虚拟机里面的,然而如果虚拟机的启动速度慢了,容器的启动速度就会被拖慢。


那么虚拟机的启动速度为什么会慢呢?



比较慢的一个是网卡的初始化速度比较慢,在OpenStack里面,往往需要通过访问DHCP Sever获取IP地址和路由信息,把IP静态化可以解决这个问题。



另外一个比较慢的是Cloud-init,这个是在虚拟机启动之后做初始化的一个工具,是为了能够在虚拟机启动后做灵活的配置,比如配置key,或者执行一些脚本。


在AWS里面,cloudformation编排工具在虚拟机启动后的一些编排工作是通过cloud-init来做的,弹性伸缩机制通过虚拟机镜像复制多份,复制后做的少量的配置工作也是cloud-init来做的。


OpenStack继承了AWS的这个机制,是通过Metadata Server来对虚拟机进行灵活的配置,包括OpenStack编排机制Heat也是通过Cloud-init进行配置。



对于Metadata Server的机制,可以看这篇文章当发现你的OpenStack虚拟机网络有问题,不妨先试一下这16个步骤


然而在虚拟机里面跑容器的方式,是不需要cloud-init的,因为灵活定制化的事情由里面的容器来做,用户使用的也是里面的容器,而不是虚拟机,因而虚拟机可以做的十分的精简,将不需要的服务全部删除。


八、通过使用IaaS层的高性能网络提供给容器高速互联能力


上一节我们讲过,使用Flannel和Calico都仅仅适用于裸机容器,而且仅仅用于容器之间的互通。



一旦有IaaS层,就会存在网络二次虚拟化的问题。


虚拟机之间的互联是需要通过一个虚拟网络的,例如vxlan的实现,而使用Flannel或者Calico相当于在虚拟机网络虚拟化的上面再做一次虚拟化,使得网络性能大幅度降低。


而且如果使用Flannel或者Calico,那容器内的应用和虚拟机上的应用相互通信的时候,则需要出容器平台,多使用node port,通过NAT的方式访问,或者通过外部负载均衡器的方式进行访问。在现实应用中,不可能一下子将所有的应用全部容器化,部分应用容器化,部分应用部署在虚拟机里面是常有的现象。然而通过NAT或者外部负载均衡器的方式,对应用的相互调用有侵入,是的应用不能像原来一样相互调用,尤其是当应用之间使用Dubbo或者SpringCloud这种服务发现机制的时候尤其如此。



网易开发了自己的NeteaseController,在监听到有新的Pod创建的时候,调用IaaS的API创建IaaS层的虚拟网卡,然后在虚拟机内部,通过调用Netease CNI插件将虚拟网卡添加到容器里面。添加的技术用的就是上一节提到的setns命令。



通过这个图我们可以看出,容器的网卡是直接连接到虚拟私有网络的OVS上的,和虚拟机是一个平的二层网络,在OVS来看,容器和虚拟机是在同一个网络里面的。


这样一方面没有了二次虚拟化,只有OVS一层虚拟化。另外容器和虚拟机网络打平的好处是,当部分应用部署容器,部分应用部署虚拟机的时候,对应用没有侵入,应用原来如何相互访问,现在还是如何访问,有利于应用逐步容器化。


容器还可以有一个网卡直接连接到公网,这一点能够保持公网IP在容器内部可见,容易使用,而且可以保证在容器的生命周期内,公网IP可以保持。


另外这个网卡在负载均衡可以使用,下面我们详细说。


使用OVS的二层网络,可以很好的实现多租户,高性能互联,QoS,安全过滤,放ARP和IP欺骗等。


九、通过优化kube-proxy优化内部相互访问



默认的容器之间的相互访问通过服务进行。


一旦创建一个服务,就会创建一个Endpoint,kube-proxy能够在api-server监听到这个服务的创建,则需要监听服务的端口,并且设置iptables将对这个服务对应的VIP的访问转发到kube-proxy的这个端口上。


当一个客户端要访问这个服务的时候,首先通过DNS,将服务名转化为VIP,然后VIP通过iptables规则转发到kube-proxy的监听端口,kube-proxy将这个包随机转发给后端的一个Pod。


当Pod无论IP如何变,如何弹性伸缩,只要有服务名,都能够访问到。


仅仅通过DNS,是能够做的服务名和IP的对应,也是可以基于DNS进行负载均衡的,这就是基本的基于DNS的服务发现。然而这种方式的缺点是不能够流控,所以最好中间有一个proxy,这就是kube-proxy。


就像Mesos中原来的服务发现是通过Mesos-DNS进行,后来改用了minuteman做这件事情,minuteman的实现机制和kube-proxy很像很像。


然而这种方式的问题是,当集群规模很大的时候,服务创建的很多的时候,kube-proxy会牵扯到大量的iptables和监听端口。


然而在我们的设计中,租户之间的容器网络应该是完全隔离的,在某个租户的虚拟机上的Kube-proxy是无需包含另一个租户的转发规则的。


所以这里做的一个优化是只监听本租户的service,并且创建转发规则就好,因为每个租户的节点数目有限,转发规则也不会很多。


十、通过LVS和haproxy进行外部负载均衡器优化



Kubernetes默认的外部负载均衡是用ingress做的,性能不是很高。


一般公有云要求负载均衡能够承载的吞吐量非常的大,不能用纯软的方式。


在网易的方案中,最外层有两个LVS,部署在物理机上,通过多个万兆上行口进行转发,可以承载非常大的吞吐量。


对于不同的租户,可以创建不同的软负载均衡,通过创建多个haproxy,构成一个集群,由于haproxy是基于虚拟机的,可以弹性伸缩,使得他也不会成为瓶颈。


haproxy是后端和容器进行二层互联,是通过虚拟网络进行的,然而haproxy连接LVS是需要通过物理网络的,这就需要haproxy通过上面的机制,通过两张网卡,一张卡连接到物理网络,作为前端,一张卡连接到虚拟网络,作为后端连接容器。



最后给一张优化总图。


容器服务是网易云提供的无服务器容器服务,让企业能够快速部署业务,轻松运维服务。容器服务支持弹性伸缩、垂直扩容、灰度升级、服务发现、服务编排、错误恢复及性能监测等功能。 点击可免费试用


免费体验云安全(易盾)内容安全、验证码等服务

更多网易技术、产品、运营经验分享请点击