云原生的演进系列下:容器编排技术

212 阅读26分钟

本文与 云原生的演进系列上:容器化技术的诞生 一脉相承,为了更好的理解本文的内容,请先阅读该系列的上篇文章。

Kubernetes 出现的背景

技术与问题总是互为矛与盾:技术的进步推动人类向前迈进,但也伴随新的问题,这些问题反过来又驱动新技术的诞生,从而不断提升生产力。以汽车为例,它的发明解决了长途出行的问题,但普及后又带来了修建公路、制定交通规则和设置红绿灯的需求。

当我们学习新技术时,应该以问题为起点:这项技术解决了什么问题?核心矛盾点在哪里?如果是你,会如何应对?这种以问题驱动的思考方式,有助于更快速且深入地掌握技术。

以容器技术为例,它诞生于解决在一台物理机上部署多个应用进程的问题。进入分布式架构时代,成千上万的服务进程支撑着一个复杂系统的运行,也带来了管理的巨大挑战。深入理解容器技术,可以将问题进一步拆解为以下矛盾点:

  1. 资源与生命周期管理
    • 如何高效地分配和管理海量容器的生命周期?
    • 如何监控容器的运行状态?
    • 当某个容器异常消耗资源时,如何保障其他容器的稳定性?
  2. 资源隔离与共享
    • 在同一物理机上运行的容器如何实现资源共享与隔离的平衡?
    • 如何保证既能高效利用资源,又能避免互相干扰?
  3. 系统的高可用性
    • 容器长时间运行时,难免面临代码缺陷、硬件故障等问题。
    • 在成千上万个容器中发生故障时,如何确保系统依然稳定可用?
  4. 自动化与可扩展性
    • 如何实现容器的自动扩容和缩容,以应对负载的动态变化?
    • 如何通过自动化修复故障容器,减少人为干预?

容器编排技术正是为了解决这些问题而诞生的。带着这些思考学习容器编排技术,将更有助于理解其原理和设计理念。

Kubernetes 诞生的过程

Borg 系统

当谷歌的工程师面对这些问题时,他们创建了 Borg 系统,用于管理和运行谷歌内部的服务和应用。

Borg 系统是一个典型的 Mater+Agent 的设计架构

Borg 的Master (BorgMaster) 是一个全局资源的跟踪管理器,他负责调度任务,监控节点状态,并提供 api 给用户查询和操作系统状态。BorgMaster 通常是由一个主节点和多个备节点组成,主节点故障时可以快速切换。

Borg 的 Agent(Borglet) 是具体的工作负载节点,用于接收并启动任务,管理任务的生命周期,并监控资源的使用情况。

BorgMaster 主动与 Borglet 通信,而 Borglet 会定期上报信息给 BorgMaster。如下图所示。

image

图片来源

Borg 系统将计算资源分为两种:Long-Running Service 和 Batch Job。

  • Long-Running Service 譬如场景的 web 服务,数据库服务等。这种服务需要长期稳定运行,不间断的对我提供服务,因此在 borg 会倾斜资源优先保证此类任务的稳定和调度。

  • 而 BatchJob 常见的为 - Apache Hadoop 或 Spark 框架执行的各类离线计算任务。索引构建任务,这类任务在资源紧张时,可以被暂停,从而优先保障 Long-Running Service。

随着越来越多的应用部署到 brog 上,谷歌内部的各个部门围绕着 Borg 系统开发了大量的管理工具和服务。比如

  • 资源需求量预测
  • 自动扩缩容
  • 配置或者自动 job 等

Borg 系统中的管理工具最初由谷歌内部不同团队为满足自身需求而开发,缺乏统一规划。这种分散的开发模式导致用户在使用时需要查阅大量文档、修改不同类型的配置,并学习多种语言和工具与 Borg 系统交互。尽管如此,得益于 Borg 系统的强大功能和丰富特性,它仍是谷歌内部的首选容器管理系统。

值得一提的是,Borg 的诞生早于 Docker,甚至在 Borg 问世时,Linux 容器技术的核心组件 Cgroups 尚未实现。相反,谷歌通过 Borg 为 Linux 容器技术贡献了大量代码,这些代码直接推动了 Cgroups 的实现和发展。

Omega 系统

由于 Borg 生态是由谷歌各部门推动发展,其架构并非经过精心设计的整体。为打造一个更加统一的软件架构生态,谷歌设计并推出了 Omega 系统。Omega 在保留 Borg 成功模块的基础上,从零开始重新开发,使整个生态更加一致。

Omega 相较于 Borg 具有以下显著改进:

  1. 去中心化设计
    • Borg 中的 BorgMaster 是单体架构,而 Omega 将其功能模块化拆分。
    • 这种去中心化设计使得各功能模块的修改和迭代更加灵活、方便。
  2. 提升资源调度效率
    • 随着系统规则的增加,Borg 的资源调度效率可能下降。
    • Omega 采用乐观并发控制机制,支持多个调度器并行工作,从而大幅提高了调度效率和资源利用率。

通过这些改进,Omega 系统不仅继承了 Borg 的优势,还通过更先进的设计克服了其局限,成为谷歌内部更高效的资源调度和容器管理平台。

Kubernetes 系统

Kubernetes是谷歌开发的第三套容器管理系统,其大量设计来源于 Borg/Omega 系统。不过与 Borg 和 Omega 不同的是:Kubernetes 是开源的,不是 Google 内部系统。

2013 年夏,Google 的工程师们开始讨论借鉴 Borg 的经验开发新一代容器编排系统,希望通过十几年的技术积累影响云计算市场格局。Kubernetes 项目获批后, 2014 年 6 月 Golang 完全重写后开源。并在 2017 年发布了第一个正式版本 1.0 版本,并托管到了 CNCF,成为其第一个项目。

CNCF:Cloud Native Computing Foundation 。Google 与 Liunx 共同筹建的云原生基金会,用于推动云原生的发展和普及,为开发者和企业提供云原生应用的标准化工具和最佳实践

Kubernetes 不仅有 Google 深厚的技术功底作支撑,有领先时代的设计理念,更加关键的是 Kubernetes 的出现符合所有云计算大厂的切身利益。

首先 Kubernetes 具有一个较高的技术起点:Kubernetes 的架构设计和理念直接继承了 Borg 和 Oemga 系统的成熟实践,并能能够紧密结合 docker 技术,提供了完整的容器生命周期管理能力。

其次 Kubernetes 的开源战略和平台无关性支持多种基础设施可以让其一避免锁定单一供应商。极大的降低了社区和企业的使用门槛。从而吸引了大量开发者和企业参与,行程了一个良好的社区活力。

最后Google联合多家顶级科技公司(如Red Hat、IBM等)推动K8s发展,形成了一个强大的供应商生态。成为了一个行业标准,而且 Kubernetes 中在开源后保持高频更新,并且其全面的教程、指南和工具,让开发者上手更容易。

因此 Kubernetes 诞生后便以摧枯拉朽之势覆灭了容器编排领域的其他竞争对手。

Kubernetes 的设计理念

资源和调度是编排系统中最重要的两个命题。

资源模型

资源计量

这里的资源模型主要是狭义上的物理资源,是哪些能够与真实物理底层硬件对应起来的资源,譬如处理器资源、内存资源、磁盘存储资源,网络带宽资源。

在 Kubernetes 中作为调度的最小单位是一个 pod。在 Kubernetes 中,一个物理机 Node上可以运行多个 pod,一个 pod 内有多个容器,多个容器共享资源和数据,被称为超亲密容器。 从编排系统的角度来看,Node 是资源的提供者,Pod 是资源的使用者,调度是将两者进行恰当的撮合。

Node 通常能够提供的三方面的资源

  1. 计算资源(如处理器、图形处理器、内存)
  2. 存储资源(如磁盘容量)
  3. 网络资源(如带宽、网络地址)

其中与调度关系最密切的是处理器和内存。虽然他俩同属于计算资源,但两者在调度时,有一些微妙的差别。

处理器,图形处理器这样的资源被称为可压缩资源。当资源不足时,Pod 只会处于"饥饿状态",运行变慢,但并不会被系统杀死。

内存这样的资源为不可压缩资源,当资源不足时,或者申请的资源超过 node 能够提供的最大的资源时,Pod 就会因为内存溢出(OOM)而被系统直接杀掉。

Kubernetes 给 cpu 资源设定的记录单位是"逻辑处理核心个数"。但至于具体的 1 个单位的“逻辑处理核心”是如何解释的,通常就需要依赖实际的宿主机。一般来说是 /proc/cpuinfo 里的处理器数量。但它实际上可能是多路处理器系统上的一个处理器,或者处理器核心中的一个超线程。也就是,Kubernetes 只是按照资源单位进行调度,而具体的一个 cpu 资源的代表真实算力可能是完全不一样的。(cpu 资源配置支持小数)

Kubernetes 给内存,硬盘设定的计量单位是其已经的广泛使用的记录单位,Bytes,如果配置中不明确标准单位就会默认使用 Bytes,除此之外,可以使用 K,M,G,T 等常用的内存和磁盘容量单位。

在 Kubernetes 中,Pod 是最小的调度单元,因此调度和资源管理相关的属性应包含在 Pod 对象的字段中。下面是一个 pod 资源配置的示例。

apiVersion: v1                # 指定 Kubernetes API 版本
kind: Pod                     # 定义资源类型为 Pod
metadata:                     # 元数据部分
  name: qos-demo-5            # Pod 的名称
  namespace: qos-example      # Pod 所属的命名空间
spec:                         # Pod 的规格
  containers:                 # 定义容器列表
    - name: qos-demo-ctr-5    # 容器的名称
      image: nginx            # 使用的容器镜像为 nginx
      resources:              # 定义资源配置
        limits:               # 容器可使用的最大资源限制
          memory: "200Mi"     # 最大内存限制为 200 MiB
          cpu: "700m"         # 最大 CPU 限制为 700 millicores (0.7 核)
        requests:  

设定资源计量单位的目的是为了管理员能够限制某个 Pod 对资源的过度占用,避免影响到其他 Pod 的正常运行。

资源分配

在日常开发和部署中,资源申请通常并不会仅根据当前的实际需求评估,而是会预留一定余量,考虑未来用户增长或应对突发流量的高峰。为了避免资源不足,开发者往往倾向于“多多益善”,适当超额申请资源。

如果 Kubernetes 按照用户申请的资源直接进行分配,可能会导致大量硬件资源在大部分时间内处于闲置状态,从而降低集群的整体资源利用率。为提高利用率,Kubernetes 会采用 超售策略,即虚拟资源(如 CPU、内存、存储)的分配总量可以超过实际物理资源总量的一定比例。

当极端情况发生时,例如所有 Pods 同时达到资源请求的峰值,节点实际可用的资源可能不足。此时,Kubernetes 必须采取措施。杀掉部分 Pods,腾出资源,保证剩余 Pods 的正常运行。这一过程被称为 驱逐机制(Eviction)

为了合理决定哪些 Pods 可以被驱逐,以及哪些必须被优先保留,Kubernetes 引入了 服务质量等级(QoS)优先级 的概念。

服务质量等级和优先级

回到上面的 pod 资源配置的示例 yaml 文件,我们可以看到 Kubernetes 使用下面两个属性描述 Pod 的资源分配和限制。

  • requests:表示容器请求的资源量,Kubernetes 会确保 Pod 能获得这些资源。Kubernetes 选择哪个节点运行 Pod,只会根据requests的值来进行决策
  • limits:表示容器可使用资源的上限,以防止容器过度消耗资源,导致节点宕机。是给 cgroups 用的,Kubernetes 在向 cgroups 的传递资源配额时,会按照limits的值来进行设置。

requests 和 limits 的配置,除了用于表明资源需求和限制资源使用之外,还有一个隐含的作用:它决定了 Pod 的 QoS(Quality of Service,服务质量)等级。

Kubernetes 目前提供的服务质量等级一共分为三级,由高到低分别为 Guaranteed、Burstable 和 BestEffort。

  • Guaranteed:Pod 中所有的容器都设置了 limitsrequests,且两者的值相等,那此 Pod 的服务质量等级便为最高的 Guaranteed。

  • Burstable: Pod 中有部分容器的 requests 值小于 limits 值,或者只设置了 requests 而未设置 limits,那此 Pod 的服务质量等级为第二级 Burstable

  • BestEffort:limitsrequests 两个都没设置就是最低的 BestEffort

如果没有设置 requests 和 limits,那就意味着资源申请没有上限,该 pod 可以使用节点上的所有资源。但往往也就是这类的 pod 上最不稳定的风险来源,因此当资源不足的时候,会优先驱逐 BestEffort 这一类 pod。因此,根据实际资源使用需求合理配置 requests 和 limits 参数,能让调度更准确,也能让服务更稳定。

除了服务质量等级外,Kubernetes 还允许管理员自己决定 pod 的优先级。当多个 Pod 同时被调度的话,高优先级的 Pod 会优先被调度。Pod 越晚被调度,就越大概率因节点资源已被占用而不能成功。同时,当高优先级的 pod 的资源不足时,Kubernetes 会驱逐低优先级 Pod,释放资源以保证高优先级的 pod 运行。

驱逐机制

上面提到过,像内存和硬盘这样的资源为不可压缩资源,在一个 pod 运行中,这些资源是会被逐渐使用的,而且是可以被耗尽的。当不可压缩资源不足是,为了保证节点稳定,那么就需要驱逐一些不重要的 pod。能够使其重新调度到其他的 pod 上。

上面也提高过 Kubernetes 吸收了 borg 系统的部分设计理念,Borg 的 Agent(Borglet)可以监控节点的状态并上报,在 Kubernetes 中也有 kubelet 用于感知节点的资源使用情况。当 kubelet 发现资源即将耗尽时,会触发两类驱逐策略。

  • 软驱逐 :由于节点资源的耗用情况可能是临时性的波动,通常在几十秒后就会恢复。因此,当发现资源耗用达到设定阈值(比如 20%)时,不应立即触发驱逐操作,而是应该观察一段时间后再做决定
  • 硬驱逐:发现节点资源的耗用情况达到硬驱逐阈值(比如 10%)时,会立即杀死相应的 Pod

把资源耗尽的 pod 通常是因为本身是坏代码,有大量无序意外的消耗资源的程序,因此 当 Kubelet 驱逐一部分 Pod 后,如果快速重新调度这个 pod,那么可能节点的资源耗用情况可能在一段时间后再次达到阈值,从而重新触发新的驱逐,形成循环。为了避免这种情况发生,kubelet 预留了两个参数。

  • --eviction-minimum-reclaim:该参数决定每次驱逐时至少要回收的资源量,以停止驱逐操作。

  • --eviction-pressure-transition-period:该参数决定 Kubelet 上报节点状态的时间间隔。如果上报周期较短,频繁更改节点状态可能导致驱逐波动。

调度

共享状态的双循环调度

容器编排的核心在于将 PodNode 高效匹配。在几个或十几个节点的小型集群中,调度的实现相对简单。然而,当集群规模扩大到数千甚至更多节点时,实现高效调度变得极为复杂。

每次创建 Pod 时,调度器需要基于各节点的实时资源状态确定目标节点。由于节点资源状态随时变化,如果调度器在每次调度时都需要汇总所有节点的状态信息,将带来巨大的计算压力和时间开销,使调度器成为系统的瓶颈。

为解决这一问题,Google 在 Omega 系统中提出了共享状态的双循环调度机制,有效分担调度压力并提升效率。Kubernetes 后来也继承了这一机制,成功应对大规模集群的调度挑战。

image.png

图片来源:7.7.3 调度器与扩展设计 | 深入高可用系统原理与设计

  1. 第一个循环(informer 循环):这些 Informer 持续监控节点的相关资源的变化情况(主要是 Pod 和 Node 的变化)。当资源变化时,触发 Informer 的回调。将 pod 入队到第二个循环,调度队列中。同 informer 会更新自己的节点资源信息缓存以尽量减少远程调用的情况。(我们可以理解为,informer 内部也缓存了一份节点的资源信息,当资源信息变更时,将增量信息合并到自己缓存的资源信息中)
  2. 第二个循环(Scheduling):该循环从调度队列中出对一个 Pod,然后触发两个核心的调度阶段。预选阶段和优选阶段。
    1. 预选阶段:通过相关过滤插件来筛选出符号 pod 要求的 Node 节点集合。Kubernetes 中会有一批内置的筛选插件供我们使用。预选阶段结束以后,会有一个可供调度的 node 列表。如果列表为空,代表这个 node 不可调度。否则进入优选阶段
    2. 优选阶段:优选阶段是一个打分阶段,Kubernetes 会内置一系列的打分插件来给可调度的 node 进行打分加权求和。最终选择出分数最高的节点来运行 pod。值得注意的是,k 8 s 倾向于调 pod 分配到 cpu 和内存资源更加充分的节点上,避免节点资源过载。

在这个两个循环阶段,informer 和 scheduling 所需要的节点信息都是通过自己的缓存来获取,不会去访问节点本身,因此就保证了算法的执行效率。 当选择好了 Node,剩下的就是通知节点内的 Kubelet 来创建 Pod。

控制回路与声明式设计

Pod 是脆弱的,无论是软件缺陷、意外操作或者硬件故障,都可能导致在复杂协作的过程中某个 Pod 出现异常,进而出现系统性的崩溃。追求一个永远都不会出错的应用服务,让 k 8 s 将所有的意外因素都消灭掉保证应用永远正常运行是不切实际都,但我们可以退一步来讲。让编排系统在 pod 意外宕机时,能够自动把它们重新调整为可用状态是可行的。这个就是编排系统的 控制回路 设计。

K 8 s 中以房间的空调为例子介绍了控制回路的工作流程。你设置一个目标温度,空调的传感器会测量出的房间实际温度。根据当前状态与期望状态的差距,空调的控制器对制冷的开关进行调节控制,就能让其当前温度接近目标温度。

image

K 8 s 为每一种资源附加了一个期望状态和实际状态两个属性。用户想要这些资源来实现某种需求,就需要通过描述文件来声明这些资源的期望状态,而 k 8 s 会通过控制器来驱动资源的实际状态向期望状态靠拢,而这种交互风格就称为是 Kubernetes 的声明式 API。

例如,一个应用期望的副本数量为 3,那么就会有对应的控制器 ReplicaSet 来负责维持副本的数量。流程如下。

  1. 编写声明文件。
apiVersion: apps/v1
kind: ReplicaSet # 副本控制器
metadata:
  name: nginx-replicaset
  labels:
    app: nginx
spec:
  replicas: 3  # 期望的副本数量
  selector:
    matchLabels:
      app: nginx  # 匹配的 Pod 标签
  template:
    metadata:
      labels:
        app: nginx  # Pod 的标签
    spec:
      containers:
      - name: nginx
        image: nginx:1.21.6  # 使用的容器镜像
        ports:
        - containerPort: 80
  1. 用户通过 kubectl apply -f replicaset.yaml 提交该声明文件。配置最终会被保存在 etcd

etcd 是一个分布式键值对数据存储系统,用来存储 的集群状态)

  1. ReplicaSet 控制器监听资源变化,然后控制器开始检测当前集群中当前 pod 的实际数量,若 pod 过多,则删除多余的 pod,否则创建更多的 pod。
  2. 新创建的 pod 会被调度器分配和合适的节点。节点上的 kubelet 监视到 pod 信息后,会拉取镜像,启动容器,同时将实际状态上报给 ReplicaSet。

上述内容仅揭示了 Kubernetes 在容器编排领域中的部分问题。除此之外,诸如容器间的网络通信、容器中产生的有价值数据(如日志信息、埋点数据、加工后的结果)如何存储,容器的持久化存储方式等,都是十分复杂且关键的领域。由于篇幅限制,本文主要聚焦于 Kubernetes 的核心理念——资源和调度,其他内容暂不展开。

尽管 Kubernetes 被誉为分布式时代的“操作系统”,其强大的编排能力为开发者屏蔽了容器粒度的调度和管理复杂性,但在更细粒度的层面,仍存在许多技术挑战。例如:

  • 系统模块的领域划分。
  • 服务间的通信管理。
  • 日志采集与管理。
  • 服务安全性校验。
  • 性能监控与优化。

这些问题超出了容器编排系统的能力范围,Kubernetes 无法完全解决。

随着技术的发展,人们开始追求进一步的抽象,期望不仅对容器编排透明化,也能让容器之下的技术细节同样透明化。为此,服务网格(Service Mesh) 的概念应运而生,并逐渐成为技术社区关注的热点。服务网格旨在接管服务间通信、安全、观测等功能,为开发者提供更高效、更便捷的分布式系统管理能力。

服务网格

现代软件开发早已经进入微服务时代。当你设计一个稍微复杂一些的软件系统时,我们不再创建一个庞大臃肿的单体应用,而是会按照功能模块进行业务领域的划分,而划分后的各个子领域的应用之间通过 RPC 通信。这样做有明显的几个好处。

  1. 模块化:每一个模块独立开发和部署,可以灵活使用不同的技术栈。单个服务故障不会影响整个系统。
  2. 领域边界清晰:各个团队可以更加专注自己的领域。利于团队沟通成本的收敛。
  3. 云环境友好:可以使用 k 8 s 等编排技术,方便部署和管理。

但是当我们需要管理的微服务数量增加时,数据的一致性,集群的通信能力,集群可观测性就会变更复杂,成本上升。在日常的软件开发中,工程师的主要工作是为了实现业务提出的需求,但是由于微服务的应用,工程师还不得不考虑微服务的本身带来的问题。那么能不能讲与业务实现无关的微服务本身带来的问题给隔离处理并使用设计良好的架构系统来使其透明呢?这个就是服务网格要做的事情。服务网格其实就是一个代理模式。 在服务网格中,将网络代理(边车代理)以一个进程的的形式注入到应用容器,自动劫持应用的网络流量,应用查询只和网络代理进行网络通信,而外部通信的可靠性通过专门的基础设施来进行保障。这个边车的网络代理对应用来说是透明的,从应用的视角来看,仿佛微服务的网络通信问题都是不存在的,网络是完美可靠的一样。

虽然边车代理解决了透明通信的问题,但边车代理本身也需要管理,需要足够的信息才能完成透明通信的工作。因此从总体来看,服务网格包含两大部分的模块:由一系列与微服务共同部署的边车代理(被称为数据平面),以及用于控制这些代理的管理器所构成(被称为控制平面)。

image.png

数据平面

数据平面由一系列边车代理所构成,核心职责是转发应用的入站(Inbound)和出站(Outbound)数据包。为了在不可靠的物理网络中保证程序间通信最大的可靠性,数据平面必须根据控制平面下发策略的指导,在应用无感知的情况下自动完成服务路由、健康检查、负载均衡、认证鉴权、产生监控数据等一系列工作。

控制平面

控制平面的特点是不直接参与程序间通信,而只会与数据平面中的代理通信,在程序不可见的背后,默默地完成下发配置和策略,指导数据平面工作。

FaaS 和 Serverless

服务网格解决了微服务间复杂、不可靠的网络通信问题,使其对开发者透明化。那么是否可以更进一步,让微服务中的应用本身也变得透明呢?实际上,一个程序的本质工作无非是“输入—处理—输出”,对于应用的每一次请求来说,其过程可以抽象为“触发—处理—反馈”。如果开发工程师能够专注于这一核心逻辑,而无需关心其他技术细节,这正是 FaaS(Function as a Service,功能即服务)的理念所在:开发者只需专注于逻辑实现,无需管理底层的基础设施。

在传统应用部署中,我们需要完成大量琐碎的工作:准备服务器、配置环境、购买域名、配置 Nginx 等。应用上线后,还需持续关注运维问题,如监控、扩缩容、容灾等。然而,借助 FaaS,这些繁琐环节都可以被省略,开发者只需专注于业务逻辑实现即可。FaaS 平台会自动为用户提供计算资源,并以弹性可靠的方式运行代码。开发者仅需按函数实际运行时间付费,从而显著提高开发与交付效率,同时降低成本。

然而,FaaS 也有其局限性或不适用的场景:

  1. 冷启动延迟:由于函数采用自动扩缩容机制,冷启动可能需要一定时间,突发流量会对服务性能造成影响。
  2. 无状态限制:函数本身无状态,需借助数据库或缓存系统管理状态,增加开发复杂度。
  3. 厂商绑定:FaaS 强依赖云服务商提供的接口能力,不同厂商实现存在差异,迁移成本较高。

需要注意的是,Serverless 是一种更广义的架构理念,旨在让用户无需管理底层服务器资源,只需专注于业务逻辑开发。FaaS 则是 Serverless 的一种具体实现形式——Serverless 是范畴,而 FaaS 是其实现之一。

云原生

本文围绕容器编排技术展开讨论,同时延伸介绍了服务网格和 Serverless,旨在更全面地阐释云原生的核心理念。

根据 CNCF(云原生计算基金会)的定义,云原生是一种构建和运行应用程序的方法,它充分利用云计算的弹性、分布式特性与自动化能力,从而实现更快的开发速度、更高的可扩展性和可靠性。云原生代表着一系列技术,包括不可变基础设施、容器、服务网格、微服务以及声明式 API。

从容器编排到服务网格,再到 Serverless,云原生为开发者提供了更加高效、灵活的开发与运维模式。然而,这些技术的本质依然是为了解决软件开发与部署中的复杂问题,让开发者能够更加专注于业务逻辑,实现更高的生产力。

image.png

图片来源:1.3 云原生的定义 | 深入高可用系统原理与设计

不过云原生是什么并不重要,关键还是理解实施云原生有什么好处,各个技术解决了什么问题,有产生了什么新的问题。而科技的进步不断解决问题,发现问题的循环中,逐步推进向前。

未来,云原生技术将继续演进,引领我们迈向更加智能、自动化的分布式系统时代。希望本文的分享,能为你打开云原生世界的大门,助力在这片技术蓝海中探索与实践。