Junedayday Blog

六月天天的个人博客

0%

五分钟技术小分享 - 2022Week09

2022-02

2022-02-28 CNCF-OpenTelemetry等

今天,我们会以OpenTelemetry的三个核心Metrics、Logs、Traces为切入点,来看看OpenMetrics、Fluentd、Jaeger这三个具有代表性的项目。

OpenTelemetry

OpenTelemetry主要分为三大块:Metrics、Logs、Traces。

  • Metrics指标:程序将运行中关键的一些指标数据保存下来,常通过RPC的方式Pull/Push到统一的平台
  • Logs日志:依赖程序自身的打印。可通过ELK/EFK等工具采集到统一的平台并展示
  • Traces分布式追踪:遵循Dapper等协议,获取一个请求在整个系统中的调用链路

OpenTelemetry有多语言的、具体落地的现成库,供业务方快速落地实践。

更多可以参考 https://junedayday.github.io/2021/10/14/readings/go-digest-2/

Metrics - OpenMetrics

Evolving the Prometheus exposition format into a standard.

这个项目更多的是一种规范性质,基本就是以Prometheus的指标为标准。

更多的信息可以参考 https://prometheus.io/docs/instrumenting/exposition_formats/。

Logs - Fluentd

unified logging layer 统一的日志层

我们这里谈的Logs并不是指各编程语言的日志库,更多是指对日志产生后,如何进行解析与采集,而Fluentd就是一个代表性的项目。

当前主流的日志采集与分析方案,也由ELK转变成了EFK,也就是Logstash被Fluentd所替代。

Fluentd最核心的优势,在于它提供了大量的可供快速接入的插件 - https://www.fluentd.org/plugins。

Traces - Jaeger

open source, end-to-end distributed tracing

jaeger

Jaeger为OpenTracing提供了一套具体落地的方案,在Jaeger-Client侧也提供了多语言的SDK,我们就可以在分布式系统中查到请求的整个生命周期的具体数据。但落地到平台时,我们要重点思考以下两点:

  1. Traces与Logs的关联:两者的收集、推送、分析、展示的整个链路非常相似,而且我们也往往希望在Trace里查询信息时,能查到应用程序中自行打印的日志;
  2. Traces与Service Mesh的关联:Jaeger-Agent与Service Mesh的Sidecar模式非常类似,两者该怎么配合实践

我们可以独立建设Traces、Logs、Service Mesh这三块技术,但如果能将它们有机结合起来,有助于整个基础平台的统一化。

小结

OpenTelemetry提倡的可观测性在复杂工程中非常重要,能大幅提高程序的可维护性。如果有机会实践,建议大家应优先理解它的理念,再结合当前开源生态进行落地。

2022-03-01 CNCF-Litmus/ChaosMesh

随着Kubernetes的落地,混沌工程在近几年越来越流行,CNCF也将它作为重点项目。如果用一个词概括混沌工程,最常用的就是 故障注入

今天我将针对其中两个重要项目 - Litmus 和 ChaosMesh 做简单介绍,让大家对混沌工程有基本理解。

Litmus

litmus

Litmus的架构分为控制平面和执行平面。前者更多是提供可交互的web界面与整体的功能管理;而后者更专注于具体故障功能的实现。

整体来说,Litmus的架构是比较重量级的:

  1. 平台组件复杂
  2. 和Argo/Prometheus等软件有一定的交叉

ChaosMesh

chaos-mesh

相对而言,Chaos Mesh是一个比较轻量级的实现,整体的架构分为三块:

  1. Dashboard - 提供界面化交互能力
  2. Controller Manager - 统一管理多种CRD
  3. Daemon - 负责Pod端具体的故障注入

我们可以仔细分析这里的三大块,都有不少的扩展点:

  1. 可通过kubectl或自定义客户端下发指令
  2. Controller Manager 可实现工作流等复杂CRD
  3. Daemon可通过直接请求、容器运行时和Sidecar三种方式注入错误

故障注入能力

我个人更看好ChaosMesh这个项目,它的架构图中所呈现的扩展性非常棒。那么,接下来我就以Chaos Mesh为例,看看它所提供的的故障注入能力:

要覆盖基本故障这些case,已经需要投入非常多的人力物力了。

小结

我个人认为,混沌工程更多地是面向Iaas/Paas/Saas这类通用服务而提供的能力:

  1. Iaas/Paas/Saas这类服务是大规模共用的,对稳定性要求极高,才能体现出混沌工程的价值;
  2. 在业务系统中引入混沌工程有两大问题:
    1. 一方面,ROI是非常低的,业务变化多、迭代快,从业务开发的角度来看,更希望基础平台侧能覆盖这些异常情况
    2. 另一方面,混沌工程会带来很多不确定性,可能导致业务受损

对大部分的开发者来说,可以学习混沌工程的理念,提高自己设计系统时的健壮性,但不要过于追求完美。

2022-03-02 CNCF-Rook/Longhorn

今天,我们一起看看CNCF中存储这块。在云原生的环境下,分布式存储绝对是排名前三的技术难点,我也不可能通过短短五分钟描述清楚。

所以,我将针对性地介绍核心概念,帮助大家有个初步印象。

CSI - Container Storage Interface

容器存储之所以能在市场中蓬勃发展,离不开一个优秀的接口定义 - CSI。有了标准可依,各家百花齐放、优胜劣汰。

CSI规范链接 - https://github.com/container-storage-interface/spec/blob/master/spec.md

CSI整套规范内容很多,非存储这块的专业人士无需深入研究。不过,我们可以将它作为一个学习资料,花10分钟看看如下内容:

  1. 记住核心术语概念 - https://github.com/container-storage-interface/spec/blob/master/spec.md#terminology
  2. 了解架构 - https://github.com/container-storage-interface/spec/blob/master/spec.md#architecture
  3. 学习核心RPC的命名 - https://github.com/container-storage-interface/spec/blob/master/spec.md#rpc-interface

Ceph

开源中最有名的分布式存储系统当属Ceph了。它并没有被捐献给CNCF组织,所以我们无法在全景图里找到它。

https://docs.ceph.com/en/latest/start/intro/

这里不会讨论Ceph的细节,但还是希望大家能够了解:Ceph的维护成本不低,不要把它当作分布式存储的“银弹”。

所以,对于中小型公司来说,核心业务优先考虑使用公有云的存储产品。

Rook

Rook这个项目其实分为两类概念:

  1. 云原生存储编排引擎 - Rook
  2. 对接具体文件系统的实现 - rook-ceph/rook-nfs

Rook将Ceph的存储抽象为了Kubernetes系统中的Pod,进行统一调度,更加贴合云原生的设计理念。

Rook在市场上的应用基本集中在rook-ceph上,不太建议使用rook-nfs。

Longhorn

CNCF中另一个项目 - Longhorn则选择脱离Ceph的生态,实现了一整个从编排到具体存储的链路。

从其官方介绍来说,它更聚焦于微服务的场景,也就是能调度更大量级的Volume。

关于Longhorn的实践资料并不多,很难对其下结论,不过官方提供了完善的文档资料,给对应的开发者不小信心。

官网 - https://longhorn.io/

小结

分布式存储是一块仍在快速发展的领域,对大部分公司或团队来说选择比较有限:

  1. 优先考虑云服务
  2. 有Ceph维护经验+一定二次开发能力的,考虑rook+ceph
  3. 有强烈的技术信心的,可以考虑小规模落地Longhorn体验

到这里,我再补充一点:我们千万不要过度迷恋分布式存储中的“分布式”这个词,很多时候单点存储(本地存储和远程存储)就能满足我们的开发要求了。

2022-03-03 CNCF-containerd/cri-o

容器的运行时是Kubernetes运行容器的基础。与CSI类似,Kubernetes提出了CRI - Container Runtime Interface的概念。

今天,我们会更多地关注到CRI这个规范,而不会对这两个项目底层进行分析 - 毕竟,虽然提供了开放的接口,但目前绝大部分的k8s依然是以Docker容器作为具体实现的,并且这现象会持续相当一段时间。

我会侧重讲讲它们之间的联系。

CRI

CRI主要是针对的是Kubernetes中kubelet这个组件的,它用于在各个Node节点管理满足标准的OCI容器。

OCI是一个容器界的事实标准,主流的容器都满足该规范,我们在这里了解即可。

CRI最新的版本可以参考这个链接 - https://github.com/kubernetes/cri-api/blob/release-1.23/pkg/apis/runtime/v1alpha2/api.proto

CRI主要分为如下:

  1. RuntimeService 运行时服务
    1. PodSandbox 相关,即Pod中的根容器,一般也叫做pause容器;
    2. Container 相关,即普通的容器;
  2. ImageService 镜像服务

CRI里的内容很多,我这边分享个人阅读大型protobuffer文件的两个技巧:

  1. 弄懂高频词汇,如上面的Sandbox
  2. 聚焦核心的枚举enum

这里有两个枚举值得关注:

1
2
3
4
5
6
7
8
9
10
11
enum PodSandboxState {
SANDBOX_READY = 0;
SANDBOX_NOTREADY = 1;
}

enum ContainerState {
CONTAINER_CREATED = 0;
CONTAINER_RUNNING = 1;
CONTAINER_EXITED = 2;
CONTAINER_UNKNOWN = 3;
}

看到这两个定义,如果你对容器/Pod有一定的了解,能很快地联系到它们的生命周期管理了。

containerd

我们看看Docker与Kubernetes的分层:

  • Docker Engine -> containerd -> runc

  • Kubernetes(Kubelet组件) -> containerd -> runc

所以,containerd的作用很直观:对上层(Docker Engine/Kubernetes)屏蔽下层(runc等)的实现细节。

cri-o

LIGHTWEIGHT CONTAINER RUNTIME FOR KUBERNETES

从定义不难看出,它是面向Kubernetes的、更为轻量级的CRI。cri-o属于我们前面聊过的OCI项目之一。

对应上面的分层,cri-o封装的是runc这种具体的实现,让上层(Kubernetes)不需要关心下层具体运行容器的引擎。

小结

今天涉及的概念有很多,其实问题起源是 Docker没有捐献给CNCF基金会,为了摆脱不确定性,Kubernetes想解耦Docker这个强依赖。

无论是抽象出标准接口,还是通过分层设计,从理论上的确可以脱离了对Docker的依赖,但现实情况依旧有相当一段路要走,毕竟Docker的存量市场实在太过庞大。

2022-03-04 CNCF-CNI/Cilium

之前我们了解了CSI和CRI这两大块,今天我们将接触到Kubernetes另一个重要规范 - CNI,也就是Container Network Interface。

了解分布式系统的同学都深有体会,网络绝对是最复杂的因素,无论是拥塞、延迟、丢包等常规情况,还是像网络分区等复杂难题,都需要大量的学习成本。无疑,CNI的学习难度也是非常高的。而Cilium作为CNI的一种实现,我今天依然会简单带过。

CNI规范

官方链接 - https://github.com/containernetworking/cni

解决什么问题

CNI没有像CSI/CRI那样有一个明确的接口定义。要想了解它,我们先要理解它要解决的问题。

简单来说,就是在Kubernetes的容器环境里, 分配容器网络并保证互相联通

核心五个规范

  1. A format for administrators to define network configuration. 网络配置的格式
  2. A protocol for container runtimes to make requests to network plugins. 执行协议
  3. A procedure for executing plugins based on a supplied configuration. 基于网络配置的执行过程
  4. A procedure for plugins to delegate functionality to other plugins. 插件授权
  5. Data types for plugins to return their results to the runtime. 返回的格式

CNI插件

我们通常谈到CNI的插件,会存在歧义,主要有两种理解:

  1. 一种是涉及到CNI底层开发的插件,可参考 https://www.cni.dev/plugins/current/ , 主要为自研提供基础能力;
  2. 另一种是已经实现CNI的现有项目,如 Flannel、Calico、Canal 和 Weave 等

CNI项目对比

CNI的可选项目有很多,如市场上主流的Flannel和Calico,CNCF中的Cilium等。

对于绝大多数的用户,我们不会关心具体实现,更多地是希望找到一个最适合自己的。横向对比的网络资料有很多,我这里提供一张图作为参考。

链接 - https://itnext.io/benchmark-results-of-kubernetes-network-plugins-cni-over-10gbit-s-network-updated-august-2020-6e1b757b9e49

benchmark-cni

这里面的对比维度会让我们在选型时有所启发:

  • 配置
  • 性能(带宽)
  • 资源消耗
  • 安全特性

注意,表格里的快与慢、高与低都是相对值,在Kubernetes集群规模较大时才有明显差异。

小结

在落地Kubernetes时,我们不要盲目地追求速度快、性能高的方案,尤其是对规模小、没有资深运维经验的团队,应该优先实现最简单、最容易维护的方案。

基于CNI的容器网络解决方案,替换性会比较强,可以在后续有了足够的经验、遇到了相关的瓶颈后,再考虑针对性地迁移。

Github: https://github.com/Junedayday/code_reading

Blog: http://junes.tech/

Bilibili: https://space.bilibili.com/293775192

公众号: golangcoding

二维码