在生产环境使用Kubernetes三年后我学到的东西

新闻 前端
今天,我们的Kubernetes基础架构团队由分布在多个数据中心的400多个虚拟机组成。 该平台托管高度可用的关键任务软件应用程序和系统,以管理具有近四百万个活动设备的大型实时网络。

 [[342001]]

> Photo by Jessica Lewis on Unsplash

我们于2017年开始构建第一个Kubernetes集群1.9.4版本。 我们有两个集群,一个集群在裸机RHEL VM上运行,另一个集群在AWS EC2上运行。

今天,我们的Kubernetes基础架构团队由分布在多个数据中心的400多个虚拟机组成。 该平台托管高度可用的关键任务软件应用程序和系统,以管理具有近四百万个活动设备的大型实时网络。

Kubernetes最终使我们的生活变得更轻松,但是这一旅程是艰难的,是一种范式转变。 不仅我们的技能和工具有了彻底的转变,而且我们的设计和思维也得到了彻底的转变。 我们必须采用多种新技术并进行大量投资,以提高和提高我们的团队和基础架构的技能。

回顾三年来,Kubernetes在生产中运行了三年,这是我们日记中的重要课程。

1. Java应用程序的奇怪案例

在微服务和容器化方面,工程师倾向于避免使用Java,这主要是由于Java臭名昭著的内存管理。 但是,现在情况发生了变化,多年来Java的容器兼容性得到了改善。 毕竟,无所不在的系统(例如Apache Kafka和Elasticsearch)在Java上运行。

回顾2017-18年度,我们有一些应用程序在Java版本8上运行。这些应用程序通常很难理解Docker等容器环境,并因堆内存问题和异常的垃圾收集趋势而崩溃。 我们了解到,这是由于JVM无法使用Linux cgroup和命名空间(它们是容器化技术的核心)造成的。

但是,从那时起,Oracle一直在不断提高Java在容器领域的兼容性。 甚至Java 8的后续补丁都引入了实验性JVM标志来解决这些问题,XX:+ UnlockExperimentalVMOptions和XX:+ UseCGroupMemoryLimitForHeap

但是,尽管有了所有的改进,但无可否认的是,与Python或Go等同行相比,Java在占用内存和启动速度慢方面仍然享有不良声誉。 这主要是由JVM的内存管理和类加载器引起的。

今天,如果我们必须选择Java,请确保它的版本为11或更高。 并且我们的Kubernetes内存限制在JVM最大堆内存(-Xmx)之上设置为1GB,以留有余量。 也就是说,如果JVM使用8GB的堆内存,则我们对该应用程序的Kubernetes资源限制为9GB。 这样,生活会更好。

2. Kubernetes生命周期升级

Kubernetes生命周期管理(例如升级或增强功能)非常繁琐,尤其是如果您已在裸机或VM上构建了自己的集群。 对于升级,我们已经意识到,最简单的方法是使用最新版本构建新集群,并将工作负载从旧版本过渡到新版本。 就地节点升级所做的努力和计划是不值得的。

Kubernetes具有多个移动部件,需要与升级保持一致。 从Docker到Calico或Flannel之类的CNI插件,您都需要仔细地将它们拼凑在一起才能正常工作。 尽管像Kubespray,Kubeone,Kops和Kubeaws这样的项目使它变得更容易,但它们都有缺点。

我们在RHEL VM上使用Kubespray构建了集群。 Kubespray非常棒,它具有用于构建,添加和删除新节点,升级版本的手册,以及我们在生产环境中操作Kubernetes所需的几乎所有内容。 但是,升级手册附带了免责声明,可防止我们跳过次要版本。 因此,必须经过所有中间版本才能达到目标版本。

要点是,如果您打算使用Kubernetes或已经在使用Kubernetes,请考虑生命周期活动以及您的解决方案如何解决这一问题。 构建和运行集群相对容易一些,但是生命周期维护是一个全新的游戏,具有多个活动部分。

3.构建和部署

准备重新设计整个构建和部署管道。 我们的构建过程和部署必须经历Kubernetes世界的完整转型。 不仅在Jenkins管道中进行了大量的重组,而且还使用了诸如Helm之类的新工具,对新的git流和构建进行了策略化,标记了docker映像,并对helm部署chart进行了版本控制。

您不仅需要维护代码,还需要维护Kubernetes部署文件,Docker文件,Docker映像,Helm chart的策略,并设计一种将所有这些链接在一起的方法。

经过几次迭代,我们决定采用以下设计。

· 应用程序代码及其Helm Chart位于单独的git存储库中。 这使我们可以分别对它们进行版本控制。 (语义版本控制)

· 然后,我们将Chart版本的映射与应用程序版本一起保存,并使用它来跟踪发布。 因此,例如,app-1.2.0部署有Charts-1.1.0。 如果仅更改Helm值文件,则仅更改Chart的补丁程序版本。 (例如,从1.1.0到1.1.1)。 所有这些版本均由每个存储库RELEASE.txt中的发行说明规定。

· 我们未构建或修改其代码的Apache Kafka或Redis等系统应用程序的工作方式有所不同。 也就是说,我们没有两个git存储库,因为Docker标签只是Helm chart版本控制的一部分。 如果我们更改了docker标签以进行升级,则会在图表标签中增加主要版本。

4.Liveness和Readiness就绪探针(双刃剑)

Kubernetes的活跃性和就绪性探查是自动解决系统问题的出色功能。 他们可以在发生故障时重新启动容器,并从不正常的实例转移流量。 但是,在某些故障情况下,这些探测可能会变成一把双刃剑,并会影响应用程序的启动和恢复,尤其是有消息的应用程序,例如消息平台或数据库。

我们的Kafka系统就是这个受害者。 我们运行了一个3 Broker 3 Zookeeper状态集,该状态集的ReplicationFactor为3,而minInSyncReplica为2。当Kafka在意外的系统故障或崩溃后启动时,就会发生此问题。 这导致它在启动期间运行其他脚本来修复损坏的索引,根据严重性,此过程可能需要10到30分钟。 由于增加了时间,生动性探针将不断失败,从而向Kafka发出终止信号以重新启动。 这阻止了Kafka修改索引并完全启动。

唯一的解决方案是在实时探针设置中配置initialDelaySeconds,以在容器启动后延迟探针评估。 但是,当然,问题在于很难对此加以说明。 有些恢复甚至需要一个小时,因此我们需要提供足够的空间来解决这一问题。 但是,增加initialDelaySeconds的次数越多,弹性的速度就越慢,因为在启动失败期间Kubernetes需要更长的时间来重新启动容器。

因此,中间的目的是评估initialDelaySeconds字段的值,以使其在您在Kubernetes中寻求的弹性与应用程序在所有故障情况(磁盘故障,网络故障,系统崩溃等)下成功启动所花费的时间之间取得更好的平衡 )

更新:如果您使用的是最新的最新版本,Kubernetes引入了第三种探针类型,称为"启动探针",以解决此问题。 从1.16版开始提供alpha版本,从1.18版开始提供beta版本。

启动探针会禁用就绪性和活动性检查,直到容器启动为止,以确保应用程序的启动不会中断。

5.公开外部IP

我们了解到,使用静态外部IP公开服务会对内核的连接跟踪机制造成巨大损失。 除非进行彻底计划,否则它只会按比例分解。

我们的集群在Kubernetes内的路由协议上运行在Calico for CNI和BGP上,并与边缘路由器对等。 对于Kubeproxy,我们使用IP Tablesmode。 我们在Kubernetes中托管着庞大的服务,该服务通过每天处理数百万个连接的外部IP公开。 由于来自软件定义网络的所有SNAT和伪装,Kubernetes需要一种机制来跟踪所有这些逻辑流。 为此,它使用内核的Conntrack和netfilter工具管理与静态IP的这些外部连接,然后将其转换为内部服务IP,然后转换为您的pod IP。 这全部通过conntrack表和IP表完成。

但是,此conntrack表有其局限性。 一旦达到限制,您的Kubernetes集群(位于下面的OS内核)将不再能够接受新连接。 在RHEL上,您可以通过这种方式进行检查。

$ sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_maxnet.netfilter.nf_conntrack_count = 167012
net.netfilter.nf_conntrack_max = 262144

解决此问题的一些方法是使用边缘路由器对等多个节点,以使到您的静态IP的传入连接遍及整个群集。 因此,如果您的集群中有大量的计算机,则累积起来,您可以拥有一个大的conntrack表来处理大量的传入连接。

早在2017年成立之初,这一切就让我们望而却步,但最近,Calico在2019年对此进行了详细研究,标题为"为什么conntrack不再是您的朋友"。

您绝对需要Kubernetes吗?

三年过去了,我们仍然每天继续发现和学习新知识。 它是一个复杂的平台,具有自己的一系列挑战,尤其是在构建和维护环境方面的开销。 它将改变您的设计,思维,架构,并需要提高技能和扩大团队规模以适应转型。

但是,如果您在云上并且能够将Kubernetes用作"服务",则可以减轻平台维护带来的大部分开销,例如"如何扩展内部网络CIDR?"。 或"如何升级我的Kubernetes版本?"

今天,我们意识到,您需要问自己的第一个问题是"您是否绝对需要Kubernetes?" 这可以帮助您评估您所遇到的问题以及Kubernetes解决该问题的重要性。

Kubernetes转型并不便宜。 您为此支付的价格必须确实证明"您的"用例及其如何利用该平台。 如果可以,那么Kubernetes可以极大地提高您的生产力。

记住,为了技术而技术是没有意义的。

本文翻译自Komal Venkatesh Ganesan的文章《3 Years of Kubernetes in Production–Here's What We Learned》

 

责任编辑:张燕妮 来源: 今日头条
相关推荐

2021-08-08 11:10:23

Kubernetes工具容器

2020-03-13 09:38:45

离职创业感受

2020-10-13 18:10:46

Kubernetes容器化云计算

2020-09-22 08:09:13

Kubernetes 集群裸机

2022-09-04 21:17:03

高可用Linkerd

2011-09-19 10:43:19

Nuget

2020-12-25 09:00:00

Kubernetes容器开发

2015-07-20 10:02:57

Java团队领导人

2021-11-05 10:28:12

GitHub首席产品官

2009-11-05 09:02:57

HTML 5

2022-10-31 15:42:22

2020-02-25 15:47:05

ElasticsearLucene地方

2013-07-17 09:13:19

2021-02-27 09:26:54

Kubernetes容器化云计算

2017-10-30 12:00:05

2022-05-26 09:00:00

网站抓取Lightrun开发

2021-12-03 07:27:29

EFCore生产环境

2012-05-04 09:35:40

云计算中国云

2019-03-25 08:30:20

腾讯互联网

2012-05-30 09:13:32

点赞
收藏

51CTO技术栈公众号