GitOps and Kubernetes Continuous Deployment with Argo CD, Jenkins X, and Flux

1、什么是可观测性

可观测性是一种系统功能,如可靠性、可扩展性或安全性,必须在系统设计、编码和测试期间设计并实现到系统中。在本节中,我们将探讨 GitOps 和 Kubernetes 为集群提供可观察性的各种方式。例如,最近将哪个版本的应用程序部署到集群?谁部署的?一个月前为应用程序配置了多少个副本?应用程序性能的下降是否与应用程序或 Kubernetes 配置的更改相关?

管理系统时,重点是控制该系统并应用以某种方式改进系统的更改,无论是通过附加功能、提高性能、提高稳定性还是其他一些有益的更改。但是如何知道如何控制系统,以及要进行哪些更改?一旦应用了更改,如何知道它们改进了系统并且没有使情况变得更糟?

我们之前讨论了 GitOps 如何在 Git 中存储系统的所需状态。 GitOps operator 更改系统的运行状态以匹配系统的所需状态。 GitOps operator 必须能够观察所管理的系统,在我们的例子中是 Kubernetes 以及在 Kubernetes 上运行的应用程序。更重要的是,GitOps operator 也必须提供可观察性,以便最终用户可以控制 GitOps。

可观察性由三个主要方面组成:事件记录、指标和跟踪。这些方面结合起来提供了可实现系统正确管理的操作见解。

1.1、事件记录

通常,调试行为不当的应用程序的第一步是查看应用程序的日志以寻找线索。日志记录是开发人员观察和调试系统和应用程序的宝贵工具。为了遵守适用的行业标准,还可能需要记录和保留记录。

对于 Kubernetes,可观察性的一个基本方面是显示集群中所有各种 Pod 的日志输出。应用程序将有关其运行状态的调试信息输出到 stdout(标准输出),由 Kubernetes 捕获并保存到运行 Pod/容器的 Kubernetes 节点上的文件中。可以使用kubectl logs <pod_name>命令显示特定 Pod 的日志。

然而,尽管日志记录至关重要且灵活,但有时它并不是观察系统某些方面的最佳工具。日志是可观察性的一个非常低级的方面。使用日志消息来获取指标(例如处理的请求数、每秒请求数等)可能非常昂贵,并且可能无法提供您需要的所有信息。此外,在不深入理解代码的情况下通过解析日志消息来确定系统在任何给定时刻的状态即使不是不可能,也是相当棘手的。通常,日志消息来自系统的不同线程和子进程,并且必须相互关联以跟踪系统的当前状态。因此,虽然 Pod 日志很重要,但它仅仅触及了 Kubernetes 可观察性功能的表面。

1.2、指标

可观察性的另一个关键方面是衡量系统或应用程序的性能和操作的指标。从根本上讲,指标是一组键值对,提供有关系统运行的信息。您可以将指标视为系统每个组件的可观察属性。适用于所有组件的一些核心资源指标包括 CPU、内存、磁盘和网络利用率。其他指标可能特定于应用程序,例如遇到的特定类型错误的数量或队列中等待处理的项目数

Kubernetes 使用称为指标服务器的可选组件提供基本指标。可以通过运行以下命令在 minikube 中启用指标服务器:

minikube addons enable metrics-server 

The 'metrics-server' addon is enabled

启用指标服务器并等待几分钟以收集足够的指标后,您可以使用命令 kubectl top Nodes 和 kubectl top pods 访问指标服务器数据。

指标本身提供了系统组件在特定时间点的性能和操作的快照。通常,指标会定期收集并存储在时间序列数据库中,以观察指标的历史趋势。在 Kubernetes 中,这通常由名为 Prometheus 的云原生计算基金会 (CNCF) 开源项目来完成。

1.3、跟踪

通常,分布式跟踪数据需要特定于应用程序的代理,该代理知道如何收集被跟踪代码的详细执行路径。分布式跟踪框架捕获系统内部运行方式的详细数据,从最初的最终用户请求到可能数百对不同微服务和其他外部依赖项的调用。指标通常提供特定系统中应用程序的聚合视图,而跟踪数据通常提供单个请求执行流的详细图片,可能跨多个服务和系统。这在微服务时代尤其重要,在微服务时代,“应用程序”可能利用数十或数百个服务的功能并跨越多个操作边界。

1.4、可视化

所有讨论的可观察性方面实际上都是关于系统提供有关自身的数据。它加起来会产生大量难以理解的数据。可观察性的最后一个方面是可视化工具,可帮助将所有可观察性数据转换为信息和见解。

许多工具提供可观测性数据的可视化。让我们看看提供 Kubernetes 集群当前运行状态可视化的工具,即 K8s Dashboard。

Kubernetes 仪表板提供 Kubernetes 集群许多不同方面的可视化,包括 Deployment、Pod 和 ReplicaSet 的状态。

2、GitOps 和可观测性

使用 Kubernetes 的声明式配置可以精确定义系统的所需状态。但如何知道系统的运行状态是否已经收敛到期望的状态呢?如何知道特定部署是否成功?更广泛地说,如何判断您的系统是否按预期工作?这些都是 GitOps 和可观察性应该帮助回答的关键问题。

Kubernetes 中的可观察性有几个方面对于 GitOps 系统良好运行并回答有关系统的关键问题至关重要:

  • Application health:应用程序运行正常吗?如果使用 GitOps 部署应用程序的新版本,系统是否比以前“更好”?

  • Application sync status:应用程序的运行状态是否与部署 Git 存储库中定义的所需状态相同?

  • Configuration drift:应用程序的配置是否在声明性 GitOps 系统之外进行了更改(例如手动或强制)?

  • GitOps change log:GitOps 系统最近发生了哪些变化?谁制造了它们,出于什么原因?

2.1、应用程序健康

可观察性与 GitOps 相关的第一个也是最重要是观察应用程序运行状况的能力。 GitOps 是将系统的所需状态提交到 Git 存储库的关键,然后 GitOps operator 将该所需状态应用于系统,使其成为当前状态。

通过 GitOps,我们至少希望检测到部署后系统比以前“更差”的情况,并至少提醒用户也许他们应该考虑回滚最近的更改。只有当系统和应用程序具有 GitOps 操作员可以观察到的强大可观察性特征时,这才有可能。

2.1.1、资源状态

Kubernetes 实现其内部状态可观察性的一个关键功能是如何通过声明性配置来维护所需的配置和活动状态。这使得可以随时检查每个 Kubernetes 资源,看看该资源是否处于所需状态。每个组件或资源在任何给定时间都将处于特定的操作状态。例如,资源可能处于 INITIALIZED 或 NOT READY 状态。它也可能处于 PENDING、RUNNING 或 COMPLETED 状态。通常,资源的状态特定于其类型。

应用程序健康状况的第一个方面是确定与应用程序相关的所有 Kubernetes 资源都处于良好状态。例如,所有Pod是否都已成功调度,是否处于Running状态?我们来看看如何确定这一点。

Kubernetes 为每个 Pod 提供附加信息,指示 Pod 是否健康:kubectl describe

阶段

描述

Pending

Kubernetes系统已接受Pod,但尚未创建一个或多个容器镜像。这包括计划之前的时间以及通过网络下载图像所花费的时间,这可能需要一段时间。

Running

Pod 已绑定到节点,并且所有容器已创建。至少有一个容器仍在运行或者正在启动或重新启动。

Succeeded

Pod 中的所有容器已成功终止,并且不会重新启动。

Failed

Pod 中的所有容器均已完成,并且至少有一个容器因故障而终止。容器要么以非零状态退出,要么被系统终止。

Unknown

由于某种原因,无法获取 Pod 状态,通常是由于与 Pod 主机通信出错

这就是可观察性:可以轻松查询 Pod 的内部状态,以便做出有关控制系统的决策。对于 GitOps,如果部署了应用程序的新版本,那么查看生成的新 Pod 的状态以确保其成功非常重要。

2.1.2、Readiness and liveness

参考 探针 | www.wuyq.net

2.1.3、应用监控和警报

除了状态和就绪/活跃性之外,应用程序通常还具有可用于确定其整体运行状况的重要指标。这是操作监控和警报的基础:观察一组指标,并在它们偏离允许值时发出警报。但是应该监控哪些指标以及允许的值是多少?

“四个黄金信号”描述为高层关注的最重要指标。这为思考指标提供了一个有用的框架:

  • 延迟 - 处理请求所需的时间

  • 流量 - 系统需求量的衡量标准

  • 错误 - 请求不成功的比率

  • 饱和度 - 您的服务的“满”程度

一旦确定了评估应用程序运行状况的指标,就需要对其进行监控,并在它们超出允许值时生成警报。在传统的操作环境中,这通常由操作员盯着仪表板来完成,但也可能由自动化系统来完成。如果监控检测到问题,则会发出警报,触发待命工程师检查系统。值班工程师分析系统并确定解决警报的正确行动方案。这可能是为了停止向服务器群推出新版本,甚至可能回滚到以前的版本。

所有这些都需要时间并延迟系统恢复到最佳运行状态。如果 GitOps 系统可以帮助改善这种情况呢?

2.2、应用程序同步状态

GitOps operator 必须提供的最重要的状态是 Git 存储库中应用程序的所需状态是否与应用程序的当前状态相同(同步)或不同(不同步)。如果应用程序不同步,则应提醒用户可能需要部署(或重新部署)。

但是什么会导致应用程序不同步呢?这是 GitOps 常规操作的一部分;用户提交对系统所需状态的更改。在提交更改时,应用程序的当前状态与所需状态不匹配。

Kubernetes 提供了kubectl diff 命令,该命令将文件或目录作为输入,并显示这些文件中定义的资源与实际资源之间的差异。

GitOps operator 能够确定包含 Git 中所需状态的部署存储库何时与 Kubernetes 集群的当前实时状态不同步。更重要的是,kubectl diff 输出提供了在同步部署存储库时将应用于集群的更改的预览。这是 GitOps 可观察性的一个重要特征。

2.3、配置漂移

但是应用程序怎么可能与 Git 存储库中定义的所需状态不同步呢?用户可能直接修改正在运行的应用程序(例如通过对部署资源执行 kubectl 编辑),而不是将所需的更改提交到 Git 存储库。我们称这种配置漂移。

当使用 GitOps 管理系统时,这通常是一个很大的“禁忌”;应该避免在 GitOps 之外直接修改系统。例如,Pod 容量不足,执行 kubectl 来增加副本数量。

这种情况有时会发生。当发生这种情况时,GitOps operator 将需要“观察”当前状态并检测与所需状态的差异,并向用户指示应用程序不同步。特别激进的 GitOps operator 可能会自动重新部署上次部署的配置,从而覆盖手动更改。

配置漂移与应用程序不同步非常相似。配置的当前实时状态与 Git 部署存储库中定义的所需配置不同。不同之处在于,当新版本提交到尚未部署的 Git 部署存储库时,应用程序通常会不同步。

相反,当在 GitOps 系统外部对配置进行更改时,就会发生配置漂移。一般来说,当遇到配置漂移时,必须发生以下两种情况之一:

(1)将配置漂移视为错误状态,并允许启动自我修复过程以将系统同步回声明的状态。

(2)检测到这种偏差,并允许将手动更改集成回 Git 中保存的声明状态(例如双向同步)。

然而,我们的观点是,双向同步是不可取的,因为它允许并鼓励对集群进行手动更改,并绕过 GitOps 提供的作为其核心优势之一的安全和审查流程。

2.4、GitOps 变更日志

对于 GitOps,“事件日志”主要由 Git 库的提交记录组成。由于对应用程序部署的所有更改都是通过更改代表应用程序所需状态的文件来进行的,因此通过观察 commit、PR 和 MR,我们可以了解集群中发生了哪些更改。

例如,在存储库上运行git log命令会显示自创建以来对此存储库所做的所有提交。

3、总结

  • 可观察性的各个方面可以通过事件记录、指标和跟踪来衡量。

  • 使用 kubectl 日志观察应用程序输出。

  • Prometheus 从节点和 Pod 收集指标,以提供所有系统组件的性能和操作的快照。

  • 使用 Jaeger(开放跟踪)监控分布式调用,以获得错误和延迟等系统洞察。

  • 使用 kubectl describe 监控应用程序运行状况。

  • 应用程序同步状态:应用程序的运行状态是否与部署 Git 存储库中定义的所需状态相同?

  • 配置漂移:应用程序的配置是否在声明性 GitOps 系统之外进行了更改(例如手动或强制)?

  • 使用 kubectl diff 和 kubediff 检测应用程序同步状态和配置漂移。