写点什么

Kubernetes 投入生产的 3 年,我们得到的一些经验教训

  • 2020-09-23
  • 本文字数:3516 字

    阅读完需:约 12 分钟

Kubernetes投入生产的3年,我们得到的一些经验教训

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


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


Kubernetes 最终使我们变得更轻松,但是这个过程很艰难,是一种思维上的转变。 不仅让我们的技能和工具有了彻底的转变,还让我们的设计和思维也得到了彻底的转变。 我们不得不采用多种新技术,并进行大量投资以扩展和提高我们的团队和基础架构的技能。


回顾 Kubernetes 在生产环境中运行的这三年,我们记下了一些很重要的经验教训。


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


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


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


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


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


现在,如果我们必须选择 Java,请确保版本为 11 或更高。 并且 Kubernetes 的内存限制要在 JVM 最大堆内存(-Xmx)的基础上增加 1GB,以留有余量。 也就是说,如果 JVM 使用 8GB 的堆内存,则我们对该应用程序的 Kubernetes 资源限制为 9GB。


  1. Kubernetes 生命周期管理:升级


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


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


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


关键是,如果你打算使用 Kubernetes 或已经在使用 Kubernetes,请考虑生命周期活动以及解决这一问题的方案。 构建和运行集群相对容易一些,但是生命周期维护是一个全新的体验,具有多个活动组件。


  1. 构建和部署


在准备重新设计整个构建和部署流水线之前, 我们的构建过程和部署必须经历 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 的 values 文件,则只更改 chart 的补丁版本(例如,从1.1.01.1.1)。所有这些版本均由每个存储库中的RELEASE.txt中的发行说明规定。

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


  1. 存活和就绪探针(双刃剑)


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 版本。

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


  1. 公开外部 IP


我们了解到,使用静态外部 IP 公开服务会对内核的连接跟踪机制造成巨大代价。除非进行完整的计划,否则它很轻易就破坏了扩展性。


我们的集群运行在Calico for CNI上,在 Kubernetes 内部采用BGP作为路由协议,并与边缘路由器对等。对于 Kubeproxy,我们使用IP Tables模式。我们在 Kubernetes 中托管着大量的服务,通过外部 IP 公开,每天处理数百万个连接。由于来自软件定义网络的所有 SNAT 和伪装,Kubernetes 需要一种机制来跟踪所有这些逻辑流。为此,它使用内核的Conntrack and 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 = 167012net.netfilter.nf_conntrack_max = 262144
复制代码


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


回到 2017 年我们刚开始的时候,这一切就让我们望而却步,但最近,Calico 在 2019 年对此进行了详细研究,标题为“为什么conntrack不再是你的朋友”。

你是否一定需要 Kubernetes 吗?

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


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


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


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


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


原文链接:


3 Years of Kubernetes in Production–Here’s What We Learned


2020-09-23 17:264840

评论

发布
暂无评论
发现更多内容

CloudWeGo 2025 黑客松报名指南

字节跳动开源

字节跳动 黑客马拉松 CloudWeGo hertz Eino

低代码平台终极拷问:NocoBase 像「乐高套装」,iVX 更像「3D 打印机」?

代码制造者

低代码开发 无代码平台

2025Q1大模型中标成绩出炉,百度智能云成为大模型“标王”

科技热闻

手把手教你用爬虫技术抓取1688商品详情与实现关键字搜索API——实战干货分享

代码忍者

1688API接口

如何使用通义灵码辅助开发微信小程序

阿里巴巴云原生

手把手教你用爬虫抓取1688商品详情和店铺全量商品API接口——从零到实战

代码忍者

1688API接口

腾讯Bugly:当AI大模型为鸿蒙应用体验注入「智慧基因」

新消费日报

计算机网络协议介绍

京东科技开发者

音乐NFT项目的技术架构

北京木奇移动技术有限公司

区块链技术 软件外包公司 音乐NFT

谁在买王兴兴的机器人?「宇树科技」百笔订单梳理、分析!

机器人头条

科技 大模型 人形机器人 具身智能

诚邀加入天翼云用户体验官计划:您的洞察,重塑科技边界!

天翼云开发者社区

云计算

AI口语练习App的技术架构

北京木奇移动技术有限公司

AI技术 软件外包公司 AI口语练习

快速业务扩张下,App混合开发成必然选择

xuyinyin

zk基础—zk实现分布式功能

不在线第一只蜗牛

分布式

企业上云后,SRE认证为何成为企业“新宠”?

雅菲奥朗

SRE ITIL SRE培训 SRE认证

如何使用通义灵码辅助开发微信小程序

阿里云云效

微信小程序 云计算

11Labs 发布 MCP 服务器,在 Claude 秒建语音智能体;通义开源 3D 数字人,集成实时互动对话全链路 SDK

声网

shopeeAPI 系列:商品列表接口接入与应用

tbapi

Shopee shopee商品列表接口

2025年智能ITSM产品推荐

云智慧AIOps社区

ITSM ITSM软件 工单管理 工单系统

智能制造常见系统,ERP、MES、WMS、SCM、PLM,一文吃透!

积木链小链

2025年GitHub Star增长最快的15个开源低代码项目

NocoBase

GitHub 开源 低代码 零代码 无代码

【解决方案】DistilQwen2.5-R1蒸馏小模型在PAI-ModelGallery的训练、评测、压缩及部署实践

阿里云大数据AI技术

人工智能 深度思考 大模型 模型蒸馏 DistilQwen2.5

区块链智能合约的安全性

北京木奇移动技术有限公司

智能合约 区块链技术 软件外包公司

为什么学习设计模式?

电子尖叫食人鱼

学习 设计模式

CrossOver玩游戏兼容性怎么样?CrossOver无法运行游戏怎么办?

阿拉灯神丁

游戏 兼容性测试 M2芯片 CrossOver Mac下载 Mac电脑软件

2025 中国人工智能教育大会召开,和鲸x智谱推出人工智能通识教育方案

ModelWhale

人工智能 高等教育 通识课 人工智能通识课

通义灵码 - HTML智能编码辅助AI工具

阿里云云效

人工智能 云计算

添加DNS解析记录提示解析冲突是怎么回事?(国科云)

国科云

安全运营 | 第十期「纵深防护·极智运营」度安讲技术沙龙成功举办

百度安全

鸿蒙APP开发的技术架构

北京木奇移动技术有限公司

鸿蒙app 软件外包公司 APP外包公司

虚拟表 + 高效写入 + 流计算优化,时序数据库 TDengine 3.3.6.0 重构核心体验

TDengine

数据库 tdengine 时序数据库

Kubernetes投入生产的3年,我们得到的一些经验教训_架构_Komal Venkatesh Ganesan_InfoQ精选文章