远程Kubernetes开发一年的经验

通过艰辛的实践总结出几乎零痛苦的集群内开发最佳实践和陷阱。

作者 Eythor Magnusson 是 Garden 的首席技术官和联合创始人,Garden 开发了一个开源工具,用于加速在 Kubernetes 上的开发和测试。 Eythor 是一位全栈开发者,拥有十年的行业经验,他正在努力将开发者体验和生产力放在任何云原生技术栈的首位。 在不开发复杂系统时,Eythor 更喜欢简单的事物,比如在他现居的柏林城内骑自行车。译自 One Year of Remote Kubernetes Development: Lessons Learned

想象一下,你是一个分布式系统开发者。在清晨,你打开笔记本电脑,启动你的开发环境。不仅仅是环境的一部分,而是用完整的服务、消息队列和数据库启动整个系统。

你的笔记本平稳运行着——整个系统都在一个远程的Kubernetes(K8s)集群中运行。

你对正在开发的服务做了一些更改,并使用Grafana和Jaeger等工具实时观察这些更改如何影响系统的其他部分,这些工具通常仅在生产环境中使用。

测试你的更改非常简单。无论是端到端测试、集成测试还是压力测试,你都可以直接在笔记本上编写代码时运行它们。 代码评审和结对编程也变得无比容易,因为你的团队中的任何人都可以访问一个完全运行的包含你所做修改的系统。

一旦你对工作感到满意,可以放心推送到CI环境,其设置方式与开发环境相同。可以确信不会有任何意外。 当你的更改正式投入生产时,你也可以放心,因为类生产环境往往能够像生产环境一样运行。

采用远程开发

在Garden,我们的开发人员在过去一年中就是以这种方式工作的。 将Kubernetes用于开发确实具有挑战性——但绝对是值得的。

先明确说明,Garden我们正在构建一个DevOps自动化平台,可以实现这种工作流程。 但我不打算在这里讨论我们的平台,而是分享使用Kubernetes(及其所有怪癖和复杂性)作为开发环境的经验。 我将解释我们的设置方式,以及我们如何能够实现向左转移和赋能开发人员,而不会增加认知负荷和上下文切换。

为什么需要远程开发环境?

如果你正在阅读这篇文章,那么你可能已经在生产环境中使用了Kubernetes。 这意味着你可能已经拥有可重现的基础设施、所需的配置(Dockerfiles、清单等)以及操作Kubernetes集群的内部专业知识。

使用 Kubernetes 远程开发的思想是将这些资源向左转移,并为开发人员提供与站点可靠性工程师(SRE)和运维人员相同的工具。

消除软件交付不同阶段之间的摩擦可以帮助更快地将软件投产。 对我们来说确实如此。 此外:

  • 类生产开发环境可以减少生产故障。这是事实。
  • 开发人员不需要等待CI运行端到端和集成测试——编写新测试也非常简单。
  • 所有交付阶段可以使用相同的配置和工具,减少维护和偏差
  • 分布式系统非常复杂,存在许多失败模式。 从一开始就能调试和交互整个系统,可以帮助开发人员理解系统,避免陷阱,并在生产中出现问题时更快地修复故障。
  • 开发集群与生产集群有不同的特点,可能会暴露一些Kubernetes的怪异行为。 这可以提供宝贵的学习经验,并很好地准备应对生产问题。

下面我将分享一些最佳实践和避免常见陷阱的方法。

远程 Kubernetes 的设置和最佳实践

以下是基于我们的经验提供的建议。

  • 使用现有的工具和配置:Helm和Kustomize都非常适合在其他环境中覆盖生产值。 例如,您可能要求开发环境中副本数为1。
  • 实现 “一步部署”:由于各种问题,开发人员可能需要一天之内重新部署他们的堆栈几次。 多步骤部署会带来很大的开发阻力。
  • 使用 Kubernetes 命名空间进行环境隔离:您可以将开发人员的shell用户名模板化到命名空间名称中,给每个开发人员的堆栈提供唯一的命名空间。 例如,部署脚本可能运行 kubectl apply --namespace my-project-$USER <其他参数>。 很多工具可以自动完成此操作(见下文)。
  • 通过 Ingress 确保唯一主机名:想象一下,Erica 和 Enes 都在开发一个名为 Furby 的应用。 如果您添加通配符 DNS 条目和针对*.furby.dev.company.com 的 TLS 证书,那么 Erica 和 Enes 就可以分别使用指向 erica.furby.dev.company.comenes.furby.dev.company.com 的 Ingress 来部署自己版本的应用。 Helm 或 Kustomize 可以用来进行模板化。
  • 确保团队具备支持:出现问题时开发人员会被阻塞。 理想情况下,团队内或邻近的某人可以立即提供帮助。
  • 优先考虑开发者体验:调优这些事项需要持续投入,所以请在冲刺计划中考虑开发者体验。

远程 Kubernetes 开发的陷阱

以下是一些需要避免的问题——我们通过痛苦的实践才了解到这些。

  • 避免将工作负载附加到临时命名空间的持久存储卷上。 即使它预计是一个长期运行的开发命名空间,您也可能需要在某个时候删除它——这时事情往往会出问题。 短暂和有状态的结合通常不太协调。 可以考虑使用 Kubernetes 的 VolumeSnapshots 功能快速从共享存储卷中恢复开发数据库。
  • CPU 和内存的资源请求和限制与生产环境会有所不同,获得最佳设置也比较困难。 Goldilocks 是一个开源工具,可以帮助您自动检测合适的配置。
  • 如果所有开发人员在同一时间启动环境(例如早上),可能会遇到调度问题。 虽然自动扩缩可以帮助缓解,但总有一些滞后。
  • 即使使用了托管的云解决方案(如 Amazon EKS、Google GKE或 Azure AKS),也仍需要进行维护工作,例如版本更新。 从好的方面来说,这可以提前在生产环境出现问题之前发现问题。
  • 有时事情就是无法正常工作。 我们见过 Azure 上的 I/O 饱和问题,或者 AWS 上的 CNI 插件无法分配 IP。 有时是 Kubernetes 的问题,有时是使用错误。 但这确实突显了具备支持人员并实现简单幂等重新部署的重要性。

总结

在 Garden,我们已经在完全远程的环境中开发了一年多时间。 过程中确实伴随着许多头疼的问题。 但这么做值得吗?绝对值得!

过程中的每一个障碍都让我们学习到了东西,并使我们为运行生产系统做得更好。

如果您正在考虑在远程 Kubernetes 集群中进行开发,我建议您看看 Garden。 它通过一个配置就可以自动化解决 Kubernetes 中的许多痛点,在开发、测试和生产中部署整个堆栈,消除配置偏差,并让开发人员可以启动类生产环境用于开发和 CI/CD。

我也要感谢 Garden 的 SRE 团队,他们不断致力于改进开发者体验,以及开发人员在我们的集群出现问题时表现出的耐心和幽默感。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注