共计 5560 个字符,预计需要花费 14 分钟才能阅读完成。
客座文章最后由 Andrew Seigner 在 Bouyant 博客上发表
这篇文章是 Andrew 在 2020KubeCon 欧洲上的演讲。
介绍
在 2019 年中,Linkerd 我的项目的继续集成(CI)花了 45 分钟,所有的测试都在一个 Kubernetes 集群上串行化,多小时的备份也很常见。迁徙到 Kubernetes in Docker(kind)集群和 GitHub Actions 使 CI 不到 10 分钟,并且能够并行。
这篇文章将具体介绍 Linkerd 从一个繁多的、长久的 Kubernetes 集群,到实践上有限的一次性类型集群的 CI 旅程。这段旅程蕴含了一些对于哪些模式和工具在 Linkerd 的用例中工作得好(或者不太好)的弯路。
Linkerd 是什么?
尽管本文的指标是具体阐明最终用户,如何在 CI 中高效地测试 Kubernetes 应用程序,但一些无关 Linkerd 的背景常识会有所帮忙。Linkerd 是一个开源的服务网络,也是一个 CNCF 成员我的项目。想要更多地理解什么是服务网格,请查看“The Service Mesh: What Every Software Engineer Needs to Know about the World’s Most Over-Hyped Technology”。出于这篇文章的目标,有必要理解一些对于 Linkerd 的简略事实:
- 它是用 Rust、Go 和 Javascript 编写的。
- 它在 Kubernetes 中以多部署(deployment)的模式运行。
- 它通过插入到你的 pod 中的代理来治理你的服务之间的所有流量。
Linkerd 架构
测试 Linkerd
既然 Linkerd 负责管理 Kubernetes 集群中的所有流量,那么 Linkerd 的正确性和性能就十分要害了。为了帮忙确保这一点,咱们的 CI 包含一系列动态、单元和集成测试,包含 Rust、Go 和 JavaScript 测试。这篇文章次要关注集成测试。咱们将介绍这些测试的三个迭代。
测试 Linkerd。集成测试能够在左下角的绿色框中看到。
迭代一:在 GKE + Travis 上运行 CI
2019 年中,Linkerd 的集成测试以作业(job)的形式在 Travis 上运行。每个作业将构建 Linkerd Docker 镜像,将其推到 gcr.io,并在单个 GKE 集群上执行集成测试。因为它是一个繁多的 Kubernetes 集群,所以咱们必须确保每个集成测试在卸载了 Linkerd 之后本人清理洁净。随着工夫的推移,咱们须要测试在不同配置下装置 Linkerd。例如,应用 Helm,或者通过降级门路。这意味着咱们当初要装置 Linkerd,运行集成测试,每次 CI 运行要卸载 Linkerd 五次。整个过程大概花了 45 分钟。将此与同时呈现的多个拉申请(PR)联合起来,多个小时的备份就变得很常见了。在这一点上,咱们采取了禁用对 PR 的集成测试的选项,咱们将只在合并时运行它们。当然,从咱们这么做的那一刻起,咱们的次要分支就开始一直地失败集成测试,因为直到合并时才会发现失败。
迭代一:GKE + Travis
对 CI 需要排优先级
在这一点上,咱们意识到咱们须要后退一步,从新评估咱们对于测试 Linkerd 的抉择。咱们列出了这张需要优先级列表:
需要 1:可重现的构建和测试
Linkerd 的集成测试套件包含在 Kubernetes 集群上装置大量资源,并验证流量是否正确流动。如果咱们在 CI 中察看到测试失败,最重要的是确保咱们能够在 CI 和本地开发中轻松地重现该失败。
需要 2:浏览构建和测试历史的 UI
对于 CI 零碎来说,浏览测试历史的 UI 仿佛是不言而喻的,然而当咱们收集需要时,咱们并没有认为任何事件都是天经地义的。咱们思考了查看构建和测试历史的其余办法,包含后台作业和脚本,能够通过电子邮件状态或向 PR 公布 GitHub 评论。最终,咱们晓得咱们须要一种简略的办法来共享测试失败的链接,咱们互相 ping 的时候能够应用指向特定集成测试失败中的特定线路的 URL。
需要 3:GitHub/PR 集成
预先看来,咱们还须要整合咱们目前的 PR 零碎,GitHub。咱们之前曾经尝试过本人构建这些集成,但咱们心愿可能找到一些开箱即用的货色,而不是给本人更多的保护工作。
需要 4:密封建造和测试
许多 Linkerd 的 PR 来自社区,通常来自咱们以前从未共事过的人。咱们心愿确保咱们的测试在一个尽可能隔离的环境中运行,因为咱们在咱们花钱保护的硬件上运行不受信赖的代码。咱们还心愿在运行测试之前不须要保护人员对每个 PR 进行抽查。
需要 5:快
测试的周转工夫对于开发人员的生产力总是至关重要的。有时须要五次或更多的尝试来修复一个测试。如果每个测试运行须要一个小时,那么你就损失了将近一天。这一要求被转化为一个打算,以防止在 internet 上推 Docker 镜像,反对增量重建,并尽可能在近程机器上构建 Linkerd。
需要 6:便宜或收费
作为一个开源我的项目,咱们心愿在估算很少或没有估算的状况下满足上述所有需要。
需要 7:OSS
作为开源维护者,咱们总是更喜爱应用开源工具。然而请留神,这是咱们最初的要求。咱们会在可能的状况下应用开源工具,然而如果闭源工具满足了所有其余需要,咱们不会主动放弃它。
CI 技术评估
思考到需要的优先级,咱们开始评估咱们在这个畛域能够找到的任何工具:
k8s 发行版:kind、k3d、k3s、GKE、AKS、EKS、DigitalOcean K8s
计算:Packet
构建:skaffold、Bazel
作业管理:GitHub Actions、Prow、Travis、CircleCI、Azure Pipelines、Jenkins X、Gitlab CI、garden.io
公布 /CD:Kubernetes Release、werf.io
咱们用所有这些工具在不同水平上构建了概念证实。过后,咱们不晓得本人会抉择其中的一种还是五种,并放弃凋谢。(对咱们未抉择到的工具的任何作者:请留神,这并非打击你的任何作品,咱们对技术的抉择在很大水平上取决于咱们的用例,其中包含下面列出的优先需要,无限的工夫和估算,以及咱们对现有工具的相熟水平。)
差点错过:Prow
思考到这一点,我想谈谈一个咱们十分喜爱但最终没有抉择的工具:Prow。
Prow 是一个弱小的基于 Kubernetes 的 CI/CD 零碎。它由 Kubernetes 社区保护,并用于测试 Kubernetes 自身,每天通过数千个作业进行测试。这对咱们很有吸引力。如果工具对 Kubernetes 是足够好,它必定能解决 Linkerd。
咱们用 Prow 构建了一个端到端的概念验证,所有的 Linkerd Docker 构建和集成测试都运行在 Prow 集群上。最终,因为对正在进行的保护和反对的关注,咱们转向了不同的方向。Prow 十分弱小,然而像 Kubernetes 和大多数生产零碎一样,须要继续保护以确保衰弱状态。咱们的 CI 系统对咱们来说很重要,然而咱们想要一些可能在咱们的小型开发团队很少或没有留神的状况下持续运行的零碎。而 Prow 的确有一个丑陋的仪表盘:
prow.k8s.io
最初,咱们从技术评估中抉择了三种工具:kind(Kubernetes in Docker)、Packet 和 GitHub Actions。
kind
kind(Kubernetes in Docker)是咱们抉择的第一个工具。它容许你在大概 30 秒外在 Docker 容器中启动 Kubernetes 集群。这满足了咱们的许多要求。最重要的是,kind 是一种能够轻松编写脚本,并在本地和 CI 中运行的工具。这意味着咱们能够像 CI 零碎那样在开发机器上运行集成测试。它提供了一个自蕴含的 Kubernetes 集群,咱们能够在每次测试后抛弃它。它也十分快的启动和删除,它容许咱们运行 Kubernetes,无论咱们在哪里构建 Docker 镜像。不再在互联网上推送镜像。还有一个微小的益处:它是测试 Kubernetes 我的项目自身的核心技术,而且它是开源的!甚至在咱们抉择其余工具之前,咱们就晓得咱们想要围绕 kind 来构建 CI 零碎。
Packet
Packet 提供高性能裸金属服务器,看起来可能是一个令人诧异的抉择。通过与 CNCF 的伙伴关系,Packet 为 CNCF 我的项目提供收费的按需硬件。这意味着咱们能够在一个高性能的 Packet 主机上运行疾速、缓存的 Docker 构建和 kind 集群。这些主机的性能足以让咱们并行地运行所有的集成测试,并在此之上并行地运行多个 PR。
GitHub Actions
当咱们评估技术时,GitHub Actions 才刚刚实现 beta。这里有几个属性促成了咱们的抉择。最间接的是,它曾经集成到 GitHub 的 PR 中,这意味着少了一个集成点。它反对矩阵构建,在这里咱们能够轻松地参数化咱们的 8 个集成测试,每个 kind 集群一个。它还反对工作之间灵便的依赖关系。例如,咱们能够让两个工作并行运行,一个用来启动一个 kind 集群,另一个用来构建 Docker。当两者都实现时,咱们就能够开始集成测试了。另外,GitHub Actions 对开源我的项目是收费的。尽管它自身不是开源的,但这是次好的事件。
迭代二:应用 kind + Packet + GitHub Actions 的 CI
选定技术后,咱们施行并推出了第二代 CI 零碎:
迭代二:kind + Packet + GitHub Actions
GitHub Actions 提供了 PR 集成和作业管理,咱们应用他们的矩阵构建来启动咱们的 8 个 kind 集群:
通过 GitHub Actions 矩阵构建启动 8 个 kind 集群
这整个设置容许所有集成测试(和 PR)并行运行,应用疾速、缓存的 Docker 构建包。咱们的 CI 工夫从小时缩小到大概 10 到 15 分钟!
请留神,尽管工作是由 GitHub 治理的,但沉重的工作是在 Packet 主机上进行的。为了实现这一点,咱们应用了一种聪慧的(hacky)技术来创立近程类集群并与之交互。要通过 SSH 连贯到近程 Docker,能够将 DOCKER_HOST 环境变量设置为 SSH://[PACKET_HOST]。这容许你在近程主机上创立类集群。然而,本地 kubectl 配置依然冀望类集群在本地主机上。为了解决这个问题,咱们从 kubectl 配置中读取近程类型集群的端口,并将端口转发给它。这里有一个演示视频来演示这个:
https://www.youtube.com/embed…
咱们不确定这是否是一个已知的模式,或者是否有更好的办法,所以我跳到 Kubernetes Slack 上的 #kind 频道去问。侥幸的是,kind 的创建者立刻回复了咱们,通知咱们尽管咱们所做的并不是齐全意料之中的事件,但它看起来相当失常:
kind FTW
对这个凶恶的 kind 社区(以及它的创建者)大声鸣谢,因为它发明了一个欢送和反对的环境。正是这些交互作用让开源变得很棒,也是咱们试图在 Linkerd 社区中模拟的货色。
迭代三:kind + buildx + GitHub Actions
敏锐的读者可能曾经留神到,在迭代儿中,咱们只在 Packet 上运行非分叉的 PR(non-forked PRs)。这是因为咱们之前的要求,即不心愿不受信赖的代码运行在咱们负责的硬件上。这并不现实,因为这意味着 forked PR 依然须要很长时间能力通过 CI,这对我的项目老手来说不是很好的体验。几个月过来了,咱们的团队开始试验 Docker Buildx。这个工具使咱们可能将 Docker 构建缓存保留到一个文件中,以便在随后的 GitHub Actions 作业中重用。这容许咱们删除对 Packet 的依赖,并在 GitHub 口头主机上全速运行所有的构建:
迭代三:kind + buildx + GitHub Actions
这里有一个视频演示了 Linkerd 的端到端教训,即推一个提交,并察看 8 个 Kubernetes 集群并行启动:
https://www.youtube.com/embed…
总结
在所有这些工作之后,一些要害的经验教训:
应用 kind
Kind 是一个很好的工具,不仅对于 CI,对于本地的开发也是如此。Kubernetes 也有相似格调的发行版,比方 Minikube 和 k3d。咱们抉择 kind 是因为它被 Kubernetes 社区用于测试 Kubernetes 自身。同时,也大声鸣谢 Kubernetes Slack 中的 #kind 频道。
缓存你的 [docker] 构建
在 CI 运行之间缓存 Docker 构建是放慢 CI 周转工夫的关键因素 – 这实用于所有模式的构建缓存。
DOCKER_HOST=ssh://
通过 SSH 应用 Docker 十分不便。我集体曾经有好几个月没有在本人的开发零碎上运行 Docker 了。
Docker Buildx
Docker Buildx 不仅提供缓存,而且反对跨平台构建。这使得 Linkerd 最近开始构建、测试和公布 arm 构建。
鸣谢 Packet 和 GitHub Actions 对 OSS 的反对
尽管他们本人不是开源的,像 Packet 和 GitHub 这样的公司,为开源我的项目提供的反对,对于像 Linkerd 这样的我的项目来说是无价的。非常感谢他们!
还有一件事:Linkerd CI 指标
咱们十分喜爱 Prow 的一点是它能够显示构建历史。咱们想要相似的货色,所以咱们的一个维护者 Alejandro 设计了一个 Linkerd CI 指标仪表盘。来看看。
Linkerd CI 指标仪表盘
点击浏览网站原文。
CNCF (Cloud Native Computing Foundation)成立于 2015 年 12 月,隶属于 Linux Foundation,是非营利性组织。
CNCF(云原生计算基金会)致力于培养和保护一个厂商中立的开源生态系统,来推广云原生技术。咱们通过将最前沿的模式民主化,让这些翻新为公众所用。扫描二维码关注 CNCF 微信公众号。