热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用Kubernetes和Istio构建大规模集群带来的挑战和解决方案

原文地址:https:blog.houzz.comchallenges-and-solutions-in-building-a-large-scale-cluster-with-k


原文地址:https://blog.houzz.com/challenges-and-solutions-in-building-a-large-scale-cluster-with-kubernetes-and-istio/


译者:陈龙全


为更好的管理不断增长的服务和流量,Houzz 基础架构团队最近将 Web Server 服务从 Amazon Elastic Compute Cloud(Amazon EC2)迁移到 Kubernetes 集群。 这次迁移使资源使用降低了 33%,首页延迟有了 30% 的改善。


Kubernetes 集群的整体架构包含多个应用程序,包括用 NodeJS 编写的前端(FE)应用程序和用 HHVM 编写的后端(BE)服务。FE 应用程序通过 HTTP 上的 Apache Thrift 协议与 BE 服务进行通信。每个应用程序都启用了水平 Pod 自动缩放(HPA)。集群内以及与外部服务的通信由 Istio 管理,都会经过 Envoy Sidecar。


迁移过程中有诸多挑战,本文主要是想和大家分享一下我们迁移过程中的最佳实践。


Pod 延迟启动


在开始 Kubernetes 迁移时,我们注意到 Pod 延迟启动有时会在新配置的节点上发生。Envoy 容器准备就绪大约花了六分钟,阻止了其他容器的启动。从 Envoy 日志中,我们观察到 pilot-agent 不断报告 Envoy 尚未准备就绪,并提出了检查 Istiod 是否仍在运行的建议。


我们实现了一个 DaemonSet,其唯一的工作就是解析 Istiod 服务的 FQDN。从其指标来看,我们观察到在新节点引导后 DNS 名称解析几分钟后会超时,推测 Envoy 遇到了相同的超时问题。


我们确定了导致该问题的根因是 dnsRefreshRate,其在 Istio 1.5.2 中的默认值为 5 分钟,并且与观察到的延迟大致匹配。由于在启动某些 Pod 之后新节点上的 DNS 客户端已准备就绪,因此较长的重试间隔导致 Envoy 无法及时检测到 DNS 客户端的就绪状态。通过强制 Envoy 进行更频繁的重试,将附加的 Pod 启动延迟从 360 秒减少到 60 秒。


请注意,在 Istio 1.6 中,默认的 dnsRefreshRate 已更改为 5 秒。


HHVM Pod 预热和级联伸缩


我们的 BE 服务内置于 HHVM 中,该服务在其代码缓存预热之前具有很高的 CPU 使用率和高延迟。预热阶段通常需要几分钟,因此在默认的 15 秒 HPA 同步周期或 HPA 评估 CPU 使用率指标并调整所需 Pod 数量的时间间隔内,它不能很好地工作。当由于负载增加而创建新的 Pod 时,HPA 从新 Pod 中检测到更高的 CPU 使用率,并扩展了更多 Pod。这种积极的反馈循环一直持续到新的 Pod 被完全预热或达到 Pod 的最大数量为止。新的 Pod 完全预热后,HPA 检测到 CPU 使用率显著下降,并缩减了大量 Pod。级联伸缩导致了不稳定和延迟峰值。


我们进行了两项更改以解决级联伸缩问题。我们根据官方建议改进了 HHVM 预热过程。预热期间的 CPU 使用率从正常使用的 11 倍减少到 1.5 倍。Pod 开始提供流量后的 CPU 使用率从正常使用的 4 倍降低到 1.5 倍。


此外,我们将 HPA 同步时间从 15 秒增加到 10 分钟。尽管 HPA 对负载增加的响应速度较慢,但它避免了级联扩展,因为大多数 Pod 可以在 10 分钟内完成预热并开始正常使用 CPU。我们发现这是一个值得权衡的选择。





更改之前的 HPA 活动





更改之后的活动


负载均衡


负载不均衡是我们迁移到 Kubernetes 期间遇到的最值得注意的挑战,尽管它仅在最大的虚拟服务中发生。症状是某些 Pod 在重负载下无法通过就绪检查,然后更多的请求将路由到这些 Pod,从而导致 Pod 在就绪状态和未就绪状态之间摆动。在这种情况下添加更多的节点或 Pod 将导致更多的飘动 Pod。发生这种情况时,延迟和错误计数会大大增加。缓解此问题的唯一方法是强行缩小部署规模,以杀死不断波动的 Pod,而无需添加新 Pod。但是,这不是可持续的解决方案,因为更多的 Pod 很快就开始波动。由于此问题,我们多次回退了迁移。





负载均衡


为了方便排查,我们添加了额外的日志记录,发现负载不均衡时触发,一个可用区(AZ)的请求明显多于其他两个。我们怀疑这种不均衡是由于我们当时使用的最少请求负载均衡策略中的正反馈回路造成的。我们尝试了其他几种策略(Round Robin,Locality Aware 和 Random),都没有解决问题。


在排除了负载均衡策略之后,我们在其他两个方面寻找了积极的反馈循环:重试失败的请求和异常检测。


尽管 Istio 的官方文档中指出默认情况下不会对失败的请求进行重试,但实际的默认重试次数设置为 2。重试会导致级联失败,因为某些请求失败后会发送更多请求。此外,我们观察到异常检测中的某些行为(也称为被动健康检查)无法解释,因此我们决定禁用这两个功能。之后,不平衡问题消失了,我们能够将 95%的请求迁移到 Kubernetes。我们在旧平台上保留 5%的资源用于性能比较和调整。最初,我们不确定重试或异常检测这两个功能中的哪一个是造成负载不均衡的原因,尽管我们现在认为它与重试有关。


在将 Istio 升级到 1.6 版,进行了一些性能改进并将 100%的请求迁移到 Kubernetes 之后,我们尝试重新启用离散值检测 - 我们愿意承担这种风险,因为更改可以在几秒钟内恢复。在撰写本文时,我们还没有遇到负载不均衡的问题。就是说,我们用以下事实证明了我们的理论,即当前 Istio 版本的集群配置与发生不均衡时的配置不同。


发布后性能下降


我们观察到,每次发布后,Kubernetes 上的延迟都会随时间而增加,因此我们创建了一个仪表板来显示 Envoy 在 Ingress 网关,FE 应用程序和 BE 服务 Pod 中报告的入站 / 出站延迟。仪表盘表明,总体增加是由 Envoy 在 BE Pod 中报告的入站延迟的增加所驱动的,这包括服务延迟和 Envoy 本身的延迟。由于服务延迟没有显着增加,因此代理延迟被认为是延迟增加的驱动力。我们发现,每个版本发布后,Envoy 在 BE Pod 中的内存使用量也随着时间增加,这使我们怀疑延迟增加是由于 BE Pod 中的 Envoy 的内存泄漏引起的。我们 exec 到一个 BE Pod,并列出了 Envoy 和主容器中的连接,发现 Envoy 中有大约 2800 个连接,主容器中有 40 个连接。在 2800 个连接中,绝大多数是与 FE Pod(BE Pod 的客户)连接的。


为了解决 Envoy 内存泄漏问题,我们做了一些更改,包括:


将 FE Pod 到 BE Pod 之间的连接的 idleTimeout 从默认的 1 小时减少到 30 秒。此更改减少了错误数量并提高了请求成功率,但同时也增加了 FE 和 BE 容器之间每秒的连接请求数量。  将 Envoy 的并发或线程数从 FE Pod 中的 16 减少到 2。该更改取消了自第一次更改以来每秒大多数连接请求数量的增加。  在 BE Pod 中将 Envoy 内存限制设置为 300MB。观察到预期的行为,并且 Envoy 的内存使用量超出限制时重新启动。容器继续运行,但是内存使用率较低。重新启动 Envoy 时,有些 Pod 有短暂的准备就绪时间,这是对前两个更改的补充。虽然前两个更改减少了 Envoy 的内存使用量,但第三个更改将在 Envoy 的内存使用量超出限制时重新启动。与重新启动主容器相比,重新启动 Envoy 所导致的停机时间明显更少,因为后者会在 HHVM 中产生几分钟的预热时间。





变更之前的延迟





变更之前内存变化





变更之后的延迟


解决了发布后的性能下降问题之后,我们将 100%的请求迁移到 Kubernetes 并关闭了旧主机环境。


集群的瓶颈


随着我们将更多请求迁移到 Kubernetes 中最大的虚拟服务,我们遇到了跨集群范围的资源的问题,这些资源在虚拟服务之间共享,包括 APIServer,DNS 服务器和 Istio 控制平面。在事件期间,观察到持续了一两分钟所有虚拟服务的错误峰值,我们发现这是由于未能解析 FE Pod 中 BE 虚拟服务的 DNS 名称所致。错误峰值还与 DNS 解析错误和 DNS 请求下降有关。Ingress 服务调用不应依赖于 DNS。相反,应该将 FE Pod 中的 Envoy 定向为将出站 HTTP 请求定向到 BE 服务中的端点的 IP 地址。但是,我们发现 NodeJS Thrift 客户端库对无用的服务 IP 进行了 DNS 查找。为了消除 DNS 依赖性,我们部署了 Sidecar,将 Virtual Service 中 BE 服务的主机绑定到本地套接字地址。





Sidecar 清单示例


尽管 Istio 从应用程序角度最大程度地提高了透明度,但除了在应用程序代码中用本地 IP 地址和端口号替换 DNS 名称之外,我们还必须显式添加 Host 标头。值得一提的是,sidecar 的一个附带好处是可以优化内存使用。默认情况下,无论是否需要,Istio 都会将跨 Kubernetes 集群的每个服务的上游集群添加到 Envoy。维护那些不必要的配置的一项重大成本是 Envoy 容器的内存使用。使用 sidecar 解决方案,我们将 DNS 服务器故障与关键路径中的服务调用隔离开来,将 DNS 服务器上的 QPS 从 30,000 减少到 6,000,并将 Envoy 的平均内存使用量从 100MB 减少到 70MB。





coreDNS QPS 的变化





变更前内存使用情况





变更后内存使用情况


我们遇到的另一个错误高峰与不一致的集群成员身份(节点终止时出现这种情况)有关。尽管 Kubernetes 应该能够优雅地处理节点终止,但是节点终止时有一种特殊情况会导致错误尖峰:在终止的节点上运行 Istiod pod。节点终止后,一些 FE Pod 花费了大约 17 分钟的时间从新的 Istiod Pod 接收更新。在他们收到更新之前,他们对 BE 集群成员身份看法不一致。鉴于此,这些有问题的 FE Pod 中的集群成员很可能已过时,导致它们向终止或未就绪的 BE Pod 发送请求。





集群成员身份不一致且是旧数据


我们发现 tcpKeepalive 选项在检测终止的 Istiod Pod 中起作用。在我们的 Istio 设置中,将 keepaliveTime,keepaliveProbes 和 keepaliveInterval 分别设置为默认值 300 秒,9 秒和 75 秒。理论上讲,Envoy 可


能需要至少 300 秒加 9,再乘以 75 秒(16.25 分钟),才能检测到终止的 Istiod Pod。我们通过将 tcpKeepalive 选项自定义为更低的值来解决了这个问题。


建立大规模的 Kubernetes 集群具有挑战性,并且对大家来说非常有意义。希望你从我们的经验中找到有用的信息。


加入云原生社区 Istio SIG


扫描下面的二维码加入云原生社区 Istio SIG, 与 Istio 专家及爱好者们共同交流。




首届 IstioCon 演讲嘉宾招募中 ,议题提交截止时间为北京时间 2021 年 1 月 19 日 15:59。


点击下方“阅读原文”查看更多


↓↓↓




推荐阅读
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • PHP 5.5.0rc1 发布:深入解析 Zend OPcache
    2013年5月9日,PHP官方发布了PHP 5.5.0rc1和PHP 5.4.15正式版,这两个版本均支持64位环境。本文将详细介绍Zend OPcache的功能及其在Windows环境下的配置与测试。 ... [详细]
  • 本文探讨了领域驱动设计(DDD)的核心概念、应用场景及其实现方式,详细介绍了其在企业级软件开发中的优势和挑战。通过对比事务脚本与领域模型,展示了DDD如何提升系统的可维护性和扩展性。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • DNN Community 和 Professional 版本的主要差异
    本文详细解析了 DotNetNuke (DNN) 的两种主要版本:Community 和 Professional。通过对比两者的功能和附加组件,帮助用户选择最适合其需求的版本。 ... [详细]
  • 尽管某些细分市场如WAN优化表现不佳,但全球运营商路由器和交换机市场持续增长。根据最新研究,该市场预计在2023年达到202亿美元的规模。 ... [详细]
  • 作为一名新手,您可能会在初次尝试使用Eclipse进行Struts开发时遇到一些挑战。本文将为您提供详细的指导和解决方案,帮助您克服常见的配置和操作难题。 ... [详细]
  • ASP.NET MVC中Area机制的实现与优化
    本文探讨了在ASP.NET MVC框架中,如何通过Area机制有效地组织和管理大规模应用程序的不同功能模块。通过合理的文件夹结构和命名规则,开发人员可以更高效地管理和扩展项目。 ... [详细]
  • Symfony是一个功能强大的PHP框架,以其依赖注入(DI)特性著称。许多流行的PHP框架如Drupal和Laravel的核心组件都基于Symfony构建。本文将详细介绍Symfony的安装方法及其基本使用。 ... [详细]
  • 本文探讨了2019年前端技术的发展趋势,包括工具化、配置化和泛前端化等方面,并提供了详细的学习路线和职业规划建议。 ... [详细]
  • Spring Cloud学习指南:深入理解微服务架构
    本文介绍了微服务架构的基本概念及其在Spring Cloud中的实现。讨论了微服务架构的主要优势,如简化开发和维护、快速启动、灵活的技术栈选择以及按需扩展的能力。同时,也探讨了微服务架构面临的挑战,包括较高的运维要求、分布式系统的复杂性、接口调整的成本等问题。最后,文章提出了实施微服务时应遵循的设计原则。 ... [详细]
  • 本文探讨了如何在Node.js环境中,通过Tor网络使用的SOCKS5代理执行HTTP请求。文中不仅提供了基础的实现方法,还介绍了几种常用的库和工具,帮助开发者解决遇到的问题。 ... [详细]
  • 了解如何快速搭建属于自己的个人博客,无需编程基础,适合Mac和Windows用户。通过本文,您将学会使用GitHub Pages和Hexo构建一个完全自主的在线空间。 ... [详细]
author-avatar
手机用户2502872401
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有