Kubernetes生产环境经验告诉你如何实现蓝绿部署和负载均衡

编者按:Luminis Technologies从2015年初就开始将Docker和Kubernetes应用到了生产环境,本文作者为Luminis Technologies软件架构师Paul Bakker,他在文章中介绍了如何实现负载均衡,蓝绿部署和监控的。

2015年初,我们团队受命为开发团队搭建一个新的部署平台,之前我们的部署平台一直是基于AWS的EC2,很好用,但唯独部署的安装和设置阶段,需要用户写脚本和工具来实现部署的自动化,这些对于运维团队之外的人有一定难度,尤其是那些没有资源去学习这些脚本和细节的小团队。主要的问题是没有“部署单元”,在开发和运维之间存在着断层,而显然容器化的趋势正在改变这个问题。

如果你还没准备好将DockerKubernetes应用到生产环境,可以看下我们是如何成为早期的采用者的,如今我们已经在生产环境中运行Kubernetes 1年多的时间了。

从容器和容器编排工具开始

我们相信容器将是未来部署的标准格式,它们简化了应用的打包方式。类似Docker的工具提供了容器的实现,我们还需要工具来处理服务和错误等问题,以及在多个机器上实现自动化部署的API。

虽然在2015年初,像KubernetesDocker Swarm这种集群工具还很不成熟,我们依然开始尝试它们,最初用的是Docker Swarm。

起初我们用它来解决网络问题,还用脚本来自动化部署工作。这有多难呢?容器集群,网络以及自动化部署确实是非常难的问题。

我们很快意识到了这一点,并决定换个工具,Kubernetes看上去是最好的选择,因为其背后有Google,RedHat,CoreOS等公司的支持,他们清楚地知道如何做大规模部署。

Kubernetes的负载均衡

要用Kubernetes,首先要熟悉pods,service和replication controller等概念,Kubernetes的文档也是非常棒的学习资料。

一旦一个Kubernetes集群启动并运行了,就可以用kubectl(Kubernetes的CLI)部署应用了,但我们很快发现在实现自动化部署时只有kubectl还不够。但是首先我们还有一个问题要解决:如何在网上访问部署好的应用?

部署的服务有一个IP地址,但是这个地址只在Kubernetes集群内可用,这意味着网络是访问不到这个服务的。在GCE(Google Cloud Engine)上,Kubernetes可以自动配置一个负载均衡器去访问这个应用。如果不是在GCE上,就需要做一些额外的负载均衡工作。

可以在主机端口上直接开放一个服务,很多人最开始都是这样做的,但是这样做放弃了Kubernetes的很多好处。如果依赖主机的端口,随着应用的增多很可能会出现端口冲突,并且未来集群的扩展或主机的替换也会变得非常困难。

两级负载均衡配置

我们发现在Kubernetes集群前配置一个负载均衡器(比如HAProxy或NGINX)是更好的做法。我们的Kubernetes集群运行在AWS的VPN内,用AWS的Elastic Load Balancer路由外部的网络流量到内部的HAProxy集群。对于每个Kubernetes的service,HAProxy都被配置一个后端,service也代理了每个pod的流量。

这种两级负载均衡配置是为了应对AWS ELB非常有限的配置选项。其中一个限制是它不能处理多个vhosts,这也是我们在使用HAProxy的原因。只用HAProxy也可以,但是必须要在DNS级别针对动态的AWS IP做一些工作。

20160808200256

图1:我们的两级负载均衡

在任何情况下,当Kubernetes服务被创建的时候,我们都需要一种机制去动态配置负载均衡器(在这种情况下是HAProxy)。

Kubernetes社区目前正在开发一个叫ingress的功能,有了它就可以直接通过Kubernetes配置外部的负载均衡器。目前这个功能还不可用,去年我们都是通过API和一个小的开源工具去进行负载均衡的配置。

配置负载均衡

首先,我们需要一个区域去存储负载均衡器的配置,由于我们已经用了etcd,就决定存在这里。我们使用confd去监控etcd的配置变化,并基于模板生成新的HAProxy配置文件。当一个新的服务被添加到Kubernetes时,我们会向etcd添加一个新的配置,结果就是一个新的HAProxy配置文件。

逐步成熟的Kubernetes

Kubernetes还有很多待解决的问题,社区已经意识到了许多问题,还有设计文档在讨论新的feature去解决这些问题。但是开发出适用于每个人的解决方案还需要大量时间,毕竟从长期来看,用快捷方式去设计一个新功能并不是一件好事。

当然这并不意味着Kubernetes的功能有限,通过API,Kubernetes就可以做到你需要的。一旦Kubernetes的新feature上线,我们可以马上用标准的组件替换这些第三方的解决方案。

在我们开发出负载均衡的第三方解决方案后,接下来的挑战就是实现一个必要的部署技术:蓝绿部署。

Kubernetes的蓝绿部署

蓝绿部署是一种无宕机的升级技术,和滚动升级不同,蓝绿部署是启动一个运行着新版应用的副本的集群,旧版的应用依旧提供服务,直到新的应用真正启动并配置好负载均衡器。这种方式的一个好处是任何时候都只有一个版本的应用在运行,减少了处理多个并发版本带来的复杂性。当副本个数很少时,蓝绿部署也能很好地工作。

20160808200310

图2:Kubernetes蓝绿部署

图2展示了“Deployer”组件是如何编排部署的。我们基于Apache协议开源了它的实现,作为Amdatu项目的一部分,大家基于这个可以很容易地实现,它还有一个在线UI来配置部署。

这种实现机制中要特别注意在配置负载均衡器之前,对pods的健康检查,我们为每个应用组件都添加了一个可通过HTTP来访问的健康检查。

让部署自动化

有了Deployer,就可以将部署集成到build流程中了。我们的build服务器可以在build成功后,push新的镜像到registry中,然后build服务器能调用Deployer自动将新版应用部署到测试环境中。同一个镜像也可以通过触发生产环境中的Deployer被推送上生产。

20160808200317

图3:我们的容器自动化部署流程

知道你的资源限制

当我们开始用Kubernetes的时候,知道你的资源限制是非常关键的。你可以在每个pod上配置资源请求和CPU/内存限制,还可以控制资源保障和暴增限制。这些配置对于高效运行多个容器非常重要,如果我们不能进行正确的设置,容器会由于未被分配到足够的内存,而经常意外停止。

应该尽早开始设置和测试资源限制,没有限制的情况下,看起来应用运行得很好,一旦将重要的负载放到其中几个容器上,很有可能会出问题。

如何监控Kubernetes

当Kubernetes开始启动后,我们很快意识到在这个新的动态环境中,监控和日志是非常重要的一环。但当你面对的是大规模的服务和节点的时候,进入服务器查看日志文件也是不现实的,应该着手构建一个中心化的日志和监控系统。

日志

有很多做日志的开源工具,我们选择的是Graylog,还有Apache Kafka作为消息系统,收集和分析容器中的日志。容器将日志发送给Kafka,Kafka将它们提交给Graylog去做索引。我们选择了让应用组件将日志打给Kafka,这样方便将日志流式化,成为易于索引的格式。还有其它工具可以从容器外收集日志,然后发送给日志系统。

监控

Kubernetes有很好的故障恢复机制,当pod意外停止时,Kubernetes会重启它们,用户甚至对这个过程毫无察觉。所以我们曾遇到过由于内存泄露,容器在一天内宕机n次的情况,而当时我们完全没有发现。

Kubernetes能做到这一点确实非常厉害,但从用户的角度来说,遇到问题即使被及时处理了,也希望被告知。我们使用了一个第三方的健康检查工具来监控Kubernetes节点和pod,还有数据存储的服务。Kubernetes的API可以和这些工具做到很好的集成。

我们认为检测负载,吞吐量,应用错误和其它状态同样重要,也有很多开源软件可以做。我们用了Heapster去收集Kubernetes的度量,用InfluxDB时序存储来做存储,用Grafana实现可视化。

Kubernetes和数据存储

容器一旦重启,所有的数据都会丢失,对于无状态的组件这没有什么影响,但是对于持久化数据存储显然不行,这就要用到容器的volume机制。Volume可以通过多种形式备份,包括主机文件系统,AWS的EBS(Elastic Block Store)和nfs等。关于Volume的详情可以看《深入浅出Docker Volume》这篇文字。

副本的问题

在大多数的部署中,数据存储都是有备份的。这带来了一些问题,首先,数据存储集群中的每个节点都被备份在不同的volume中,向同一个volume中写数据会造成冲突。另一个问题是大部分数据存储需要明确的配置才能保证集群的运行,而节点的自动发现和配置并不通用。

同时,一个运行着数据存储的机器通常会针对某种工作负载进行调优,比如更高的IOPS。扩展(添加/删除节点)对于数据存储来说,也是一个昂贵的操作。这些都和Kubernetes部署的动态本质不相符。

于是我们决定不在生产环境中的数据存储中使用Kubernetes,我们在不同的主机上手动启动这些集群,然后和Kubernetes上的服务联通。现在我们的服务除了数据存储和HAProxy服务器,都运行在Kubernetes中,包括监控和日志。

未来展望

看看我们现在的部署方式,我总会由衷感慨Kubernetes真是非常棒,Kubernetes的API在实现部署流程的自动化方面提供了很大的帮助。现在部署不但更可靠了,也更快了,因为我们不需要处理VM了。我们的构建和部署变得更可靠了,因为容器的测试和交付更简单。这种新的部署方式也让我们能够紧跟开发团队的脚步,在第一时间将他们的成果push到生产环境。

开销计算

在开销上主要包括两个方面:为了运行Kubernetes,需要一个etcd集群和一个master节点,对于很小的部署来说,这个开销相对还是比较大的,所以这种情况下放在云上更合适。

对于规模较大的部署,etcd和master节点的开销就微不足道了。Kubernetes让很多容器在一个主机上运行变得非常简单,最大程度地利用现有资源,减少了服务器的个数,从而降低了成本。但是运维一个这样的集群需要投入很大的精力,如果有更方便的云服务能帮你做到这些也是一个不错的选择,比如灵雀云。

K8S中文社区微信公众号
分享到:更多 ()