提高 K8S 容器运行时的可观察性最佳方法之一

提高 K8S 监控可观察性最佳方式实战教程

当谈到云原生可观察性时,可能每个人都会提到OpenTelemetry (OTEL),因为社区需要依赖标准来将所有集群组件开发指向到同一方向。OpenTelemetry 使我们能够将日志、指标(metrics)、跟踪(traces)和其他上下文信息组合到一个资源中。集群管理员或软件工程师可以使用此资源来获取在定义的时间段内集群中正在发生的事情的视图。

但是 Kubernetes 本身如何利用这个技术栈呢?

Kubernetes 由多个组件组成,其中一些组件是独立的,而另一些组件则堆叠在一起。从容器运行时的角度来看架构,那么从上到下有:

  • kube-apiserver:验证和配置 API 对象的数据
  • kubelet:在每个节点上运行的代理
  • CRI 运行时:容器运行时接口 (CRI) 兼容的容器运行时,如CRI-Ocontainerd
  • OCI 运行时:较低级别的开放容器倡议 (OCI)运行时,如runccrun
  • Linux 内核Microsoft Windows:底层操作系统

这意味着如果我们在 Kubernetes 中运行容器时遇到问题,那么我们就会开始查看其中一个组件。随着当今集群架构复杂性不断增加,查找问题的根本原因是我们面临的最耗时的操作之一。即使知道可能导致问题的组件,仍须考虑其他组件。

我们如何做到这一点?大多数人可能会坚持抓取日志,过滤它们并在组件边界上将它们组装在一起。我们也有 metrics 指标,但是将指标值与普通日志相关联使跟踪正在发生的事情变得更加困难。一些指标也不是为了调试目的而制定的。

OpenTelemetry 应运而生。该项目旨在将 traces~跟踪metrics~指标logs~日志 等信号组合在一起,以维护集群状态的统一视图。

Kubernetes 中 OpenTelemetry 跟踪的当前状态是什么?从 API server 的角度来看,自 Kubernetes v1.22 以来,我们对 tracing 提供了 alpha 支持,它将在即将发布的其中一个版本中升级为 beta。不幸的是,beta 毕业错过了 Kubernetes v1.26 版本。可以在 API Server Tracing Kubernetes Enhancement Proposal (KEP)中找到该设计提案,其中提供了更多相关信息。

kubelet tracing 部分 在另一个 KEP 中进行跟踪,该 KEP 在 Kubernetes v1.25 中以 alpha 状态实现。撰写本文时并未计划进行 Beta 毕业,但 v1.27 发布周期中可能会有更多。除了两个 KEP 之外还有其他方面的努力,例如 klog 正在考虑 OTEL 支持,这将通过将日志消息链接到现有跟踪来提高可观察性。在 SIG Instrumentation 和 SIG Node 中,我们还在讨论 如何将 kubelet traces 链接在一起,因为现在他们专注于 kubelet 和 CRI 容器运行时之间的 gRPC 调用

CRI-O 从 v1.23.0 开始就支持 OpenTelemetry 跟踪,并致力于不断改进它们,例如通过 将日志附加到跟踪 或将 spans 扩展到应用程序的逻辑部分。这有助于跟踪的用户获得与解析日志相同的信息,但具有增强的范围界定和过滤其他 OTEL 信号的能力。CRI-O 维护者还在开发conmon的容器监控替代,称为 conmon-rs 并且纯用 Rust 编写。使用 Rust 实现的一个好处是能够添加诸如 OpenTelemetry 支持之类的功能,因为这些功能的库已经存在。这允许与 CRI-O 紧密集成,并让消费者从容器中看到最低级别的跟踪数据。

containerd 从 v1.6.0 开始添加了 tracing 支持,可通过使用插件 获得。较低级别的 OCI 运行时,如 runccrun,根本不支持 OTEL,而且似乎不存在这方面的计划。我们必须考虑到在收集 traces 并将它们导出到数据接收器时会产生性能开销。我仍然认为在 OCI 运行时扩展的遥测收集看起来是值得评估的。让我们看看 Rust OCI 运行时 youki 将来是否会考虑类似的事情。

下面我会展示如何做。对于下面演示,我将坚持使用 runc、conmon-rs、CRI-O 和 kubelet 的单个本地节点堆栈。要在 kubelet 中启用跟踪,需要在KubeletConfiguration中配置以下内容:

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
featureGates:
  KubeletTracing: true
tracing:
  samplingRatePerMillion: 1000000

等于一samplingRatePerMillion百万将在内部转化为对所有内容进行采样。必须将类似的配置应用于 CRI-O;我可以使用 and 启动二进制 crio文件,或者我们使用这样的嵌入式配置:--enable-tracing``--tracing-sampling-rate-per-million 1000000

一个 samplingRatePerMillion 等于 100 万将在内部转化为对所有内容的抽样。必须对 CRI-O 应用类似的配置;我可以使用参数 --enable-tracing--tracing-sampling-rate-per-million 1000000 启动 crio 二进制文件,或者使用这样的插入式配置:

cat /etc/crio/crio.conf.d/99-tracing.conf
[crio.tracing]
enable_tracing = true
tracing_sampling_rate_per_million = 1000000

要将 CRI-O 配置为使用 conmon-rs,至少需要最新的 CRI-O v1.25.x 和 conmon-rs v0.4.0。然后像下面这样配置插件可以让 CRI-O 使用 conmon-rs:

cat /etc/crio/crio.conf.d/99-runtimes.conf
[crio.runtime]
default_runtime = "runc"

[crio.runtime.runtimes.runc]
runtime_type = "pod"
monitor_path = "/path/to/conmonrs" # or will be looked up in $PATH

默认配置将指向的 OpenTelemetry 收集器 gRPC 端点:localhost:4317,它也必须启动并运行。如文档中所述 有多种运行 OTLP 的方法,但也可以通过 kubectl proxy 进入在 Kubernetes 中运行的现有实例。

如果一切都已设置好,那么收集器应该记录有传入的跟踪:

ScopeSpans #0
ScopeSpans SchemaURL:
InstrumentationScope go.opentelemetry.io/otel/sdk/tracer
Span #0
    Trace ID       : 71896e69f7d337730dfedb6356e74f01
    Parent ID      : a2a7714534c017e6
    ID             : 1d27dbaf38b9da8b
    Name           : github.com/cri-o/cri-o/server.(*Server).filterSandboxList
    Kind           : SPAN_KIND_INTERNAL
    Start time     : 2022-11-15 09:50:20.060325562 +0000 UTC
    End time       : 2022-11-15 09:50:20.060326291 +0000 UTC
    Status code    : STATUS_CODE_UNSET
    Status message :
Span #1
    Trace ID       : 71896e69f7d337730dfedb6356e74f01
    Parent ID      : a837a005d4389579
    ID             : a2a7714534c017e6
    Name           : github.com/cri-o/cri-o/server.(*Server).ListPodSandbox
    Kind           : SPAN_KIND_INTERNAL
    Start time     : 2022-11-15 09:50:20.060321973 +0000 UTC
    End time       : 2022-11-15 09:50:20.060330602 +0000 UTC
    Status code    : STATUS_CODE_UNSET
    Status message :
Span #2
    Trace ID       : fae6742709d51a9b6606b6cb9f381b96
    Parent ID      : 3755d12b32610516
    ID             : 0492afd26519b4b0
    Name           : github.com/cri-o/cri-o/server.(*Server).filterContainerList
    Kind           : SPAN_KIND_INTERNAL
    Start time     : 2022-11-15 09:50:20.0607746 +0000 UTC
    End time       : 2022-11-15 09:50:20.060795505 +0000 UTC
    Status code    : STATUS_CODE_UNSET
    Status message :
Events:
SpanEvent #0
     -> Name: log
     -> Timestamp: 2022-11-15 09:50:20.060778668 +0000 UTC
     -> DroppedAttributesCount: 0
     -> Attributes::
          -> id: Str(adf791e5-2eb8-4425-b092-f217923fef93)
          -> log.message: Str(No filters were applied, returning full container list)
          -> log.severity: Str(DEBUG)
          -> name: Str(/runtime.v1.RuntimeService/ListContainers)

可以看到 spans 有一个 trace ID,并且通常有一个附加 attached。日志等事件也是输出的一部分。在上述情况下,kubelet 的 Pod 生命周期事件生成器 (PLEG) 定期触发 ListPodSandbox 调用 CRI-O 的 RPC。可以通过例如 Jaeger 来显示这些 traces 。在本地运行跟踪堆栈时,默认情况下应公开一个 Jaeger 实例地址为:http://localhost:16686

这些ListPodSandbox请求在 Jaeger UI 中直接可见:

Jaeger UI 中的 ListPodSandbox RPC

这并不太令人兴奋,所以我将直接通过kubectl运行工作负载:

kubectl run -it --rm --restart=Never --image=alpine alpine -- echo hi
hi
pod "alpine" deleted

现在查看 Jaeger,我们可以看到有 conmonrscrio以及kubeletRunPodSandboxCreateContainer CRI RPC 的 traces:

Jaeger UI 中创建容器 traces

kubelet 和 CRI-O spans 相互连接,使调查更容易。如果我们现在仔细查看这些 spans,可以看到 CRI-O 的日志正确地包含了相应的功能。例如,可以像这样从 traces 中提取 container user:

Jaeger UI 中的 CRI-O Traces

较低级别的 conmon-rs spans 也是此跟踪的一部分。例如 conmon-rs 维护一个内部 read_loop 处理容器和最终用户之间的 IO。读取和写入字节的日志是 spans 的一部分。这同样适用于 wait_for_exit_code span,它告诉我们容器成功退出,code 为0

Jaeger UI 中的 conmon-rs Traces

将所有这些信息与 Jaeger 的过滤功能放在一起,使整个堆栈成为调试容器问题的绝佳解决方案!提到“整个堆栈”也显示了整体方法的最大缺点:与解析日志相比,它在集群设置之上增加了明显的开销。用户必须维护一个像 Elasticsearch 这样的接收器来持久化数据,暴露 Jaeger UI 并可能考虑到性能缺陷。无论如何,它仍然是提高 Kubernetes 可观察性方面的最佳方法之一。

感谢您阅读这篇博文,我很确定大家正在展望 Kubernetes 对 OpenTelemetry 支持的光明前景,以简化故障排除。

译自

作者:Sascha Grunert
原文:https://kubernetes.io/blog/2022/12/01/runtime-observability-opentelemetry/

说明

请关注 危 ❤ 工中号【进击云原生】,更有free资源供您学习

本文由mdnice多平台发布

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容