Kubernetes投入生产已经3年了:这就是我们得到的

大约翻译:在另一篇“经验教训”类别的文章中,澳大利亚公司的DevOps工程师分享了长期在负载服务生产中使用Kubernetes的主要结论。作者介绍了Java,CI / CD,网络以及K8的复杂性。



我们于2017年开始创建第一个Kubernetes集群(来自K8s 1.9.4版本)。我们有两个集群。一个工作在裸机上,在RHEL虚拟机上,另一个工作在AWS EC2云上。



如今,我们的基础架构拥有分布在多个数据中心的400多个虚拟机。该平台是高可用性的关键任务应用程序和系统的基础,这些应用程序和系统驱动着将近400万个活动设备的庞大网络。



最终,Kubernetes使我们的生活更轻松,但是要实现这一目标的道路是棘手的,需要彻底改变范例。不仅对一套技能和工具进行了彻底的转换,而且对设计和思考的方法也进行了彻底的转换。我们必须掌握许多新技术,并在基础设施开发和团队开发方面进行大量投资。



这是我们三年来在生产中使用Kubernetes的主要经验教训。



1. Java应用程序的有趣故事



当涉及微服务和容器化时,工程师倾向于回避Java,这主要是因为Java的内存管理不完善。但是,今天的情况有所不同,并且Java与容器的兼容性近年来有所提高。毕竟,即使是流行的系统,例如Apache Kafka和Elasticsearch也都在Java中运行。



在2017-2018年,我们的某些应用程序以Java版本8运行。他们经常拒绝在诸如Docker这样的容器化环境中运行,并由于堆内存问题和垃圾收集器不足而崩溃。事实证明,这些问题是由于JVM无法运行Linux容器化机制(cgroupsnamespaces)引起的。



从那时起,Oracle致力于提高Java与容器世界的兼容性。早在Java版本8上,试验性的JVM标志就似乎可以解决这些问题:XX:+UnlockExperimentalVMOptions而且,XX:+UseCGroupMemoryLimitForHeap.



尽管进行了所有改进,但没有人会说Java相对于Python而言过于占用内存并且启动速度较慢,因此声誉仍然很差。或去。这主要是由于JVM和ClassLoader中的内存管理的细节。



今天,如果我们必须使用Java,我们至少尝试使用版本11或更高版本。而且我们在Kubernetes中的内存限制比JVM中的最大堆内存限制高1 GB(-Xmx) (以防万一)。也就是说,如果JVM使用8 GB的堆内存,则该应用程序的Kubernetes内存限制将设置为9 GB。由于有了这些措施和改进,生活变得更加轻松。



2.与Kubernetes生命周期有关的更新



Kubernetes生命周期管理(更新,添加)是一件繁琐而困难的事情,尤其是在集群基于裸机或虚拟机的情况下事实证明,要升级到新版本,举起一个新集群然后将工作负载转移到该集群要容易得多。升级现有站点根本是不切实际的,因为这需要大量的精力和仔细的计划。



这是因为Kubernetes升级时要考虑的“运动”部分太多。为了使集群正常工作,您必须将所有这些组件收集在一起-从Docker到Calico或Flannel等CNI插件。诸如Kubespray,KubeOne,kops和kube-aws之类的项目在某种程度上简化了该过程,但它们并非没有缺点。



我们使用Kubespray在RHEL虚拟机中部署了集群。他证明自己很出色。Kubespray具有用于创建,添加或删除节点,更新版本的脚本,以及在生产环境中使用Kubernetes所需的几乎所有内容。就是说,升级脚本伴随着警告,不要跳过次要版本。换句话说,要获得所需的版本,用户必须安装所有中间版本。



这里的主要收获是,如果您打算使用或已经在使用Kubernetes,请仔细考虑K8s的生命周期步骤以及它如何适合您的解决方案。创建和运行集群通常比保持最新状态容易。



3.构建和部署



为必须修改构建和部署管道这一事实做好准备。随着向Kubernetes的过渡,我们对这些过程进行了根本性的转变。我们不仅重组了Jenkins管道,还借助Helm之类的工具,开发了构建和使用Git,标记Docker映像和对Helm图表进行版本控制的新策略。



您将需要一个策略来维护您的代码,Kubernetes部署文件,Dockerfiles,Docker映像,Helm图表,以及将它们捆绑在一起的方法。



经过几次迭代,我们决定下图:



  • 应用程序代码及其Helm图表位于不同的存储库中。这使我们可以彼此独立地对它们进行版本控制语义版本控制)。
  • , , . , , app-1.2.0 charts-1.1.0. (values) Helm, patch- (, 1.1.0 1.1.1). (RELEASE.txt) .
  • , Apache Kafka Redis ( ), . , Docker- Helm-. Docker- , .


(. .: Open Source- Kubernetes — werf — , .)



4. Liveness Readiness ( )



Kubernetes的活动性和就绪性检查非常适合自主处理系统问题。他们可以在发生故障时重新启动容器,并从“运行状况不佳”的实例重定向流量。但是在某些情况下,这些检查可能会变成一把双刃剑,并影响应用程序的启动和恢复(对于诸如消息传递平台或数据库之类的有状态应用程序尤其如此)。



我们的卡夫卡成了他们的受害者。我们有一组3Broker和3的有状态集合,Zookeeper其中replicationFactor= 3和minInSyncReplica=2。在随机崩溃或崩溃后重新启动Kafka时发生了问题。在启动时,Kafka运行其他脚本来修复损坏的索引,这花费了10到30分钟,具体时间取决于问题的严重性。这种延迟导致活动性测试不断失败,从而导致Kubernetes“杀死”并重新启动Kafka。结果,Kafka不仅可以修复索引,甚至可以启动。



当时唯一的解决方案是initialDelaySeconds在活动性测试设置中配置参数,以便仅在容器启动后才进行检查。当然,最大的挑战是确定设置哪个延迟。失败后的个人启动可能需要一个小时的时间,因此必须考虑到这一点。另一方面,更多initialDelaySeconds,较慢的Kubernetes将在容器启动期间响应故障。



在这种情况下,initialDelaySeconds最有效的选择就是最适合您的弹性要求的值,同时仍然为应用程序留出足够的时间在所有故障情况下成功启动(磁盘故障,网络问题,系统崩溃等)。



更新:在最新版本的Kubernetes中,出现第三种类型的测试,称为启动探针。1.16版本开始它可以作为Alpha版本使用,而从1.18版本开始,它可以作为Beta版本。



启动探针通过禁用就绪性和活动性检查直到容器启动来解决上述问题,从而允许应用程序正常启动。


5.使用外部IP



事实证明,使用静态外部IP访问服务给内核的连接跟踪机制带来了巨大压力。如果您不仔细考虑,它可能会“崩溃”。



在我们的集群中,我们同时使用CalicoCNI和BGP作为路由协议,并与边界路由器进行交互。已启用Kube代理模式iptables。我们通过外部IP开放访问Kubernetes中非常繁忙的服务(每天处理数百万个连接)。由于来自软件定义网络的SNAT和屏蔽,Kubernetes需要一种机制来跟踪所有这些逻辑流。对于这个K8S使用这些核心工具onntracknetfilter...在他们的帮助下,它管理与静态IP的外部连接,然后将其转换为服务的内部IP,最后转换为Pod的IP地址。所有这些都是通过使用表conntrack和iptables完成的。



但是,表格的可能性不是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年首次成立时,这完全使我们感到困惑。然而,相对最近(2019年4月日)«印花布项目公布下适当命名的详细调查为什么conntrack的是不再是你的朋友电邮» (有这样的翻译-约Perevi ..成俄文)



您真的需要Kubernetes吗?



三年过去了,但我们仍然每天继续发现/学习新知识。 Kubernetes是一个复杂的平台,具有其自身的一系列挑战,特别是在启动环境并保持其运行方面。它将改变您的思维,建筑,对设计的态度。您将不得不处理扩大和升级团队。



另一方面,在云中工作并能够将Kubernetes用作服务将为您节省与维护平台相关的大多数担忧(例如扩展内部网络的CIDR和更新Kubernetes)。



今天,我们已经认识到,要问自己的主要问题是真的您需要Kubernetes吗?它可以帮助您评估问题的严重程度,以及Kubernetes是否可以帮助您解决问题。



问题是,迁移到Kubernetes的成本很高。因此,用例的优势(以及使用平台的程度和方式)必须证明您所付出的代价是合理的。如果是这样,Kubernetes可以大大提高您的生产率。



请记住,出于技术考虑,技术是没有意义的。



译者的PS



另请参阅我们的博客:






All Articles