10 张图,说透 Kubernetes 架构和数据流程

这篇关于 Kubernetes 架构的综合指南旨在通过插图详细解释每个 Kubernetes 组件。

因此,如果您希望:

  1. 了解 Kubernetes 的架构
  2. 掌握 Kubernetes 的基本概念
  3. 了解 Kubernetes 架构组件
  4. 探索连接这些组件的工作流

那么此篇 Kubernetes 架构指南将非常有价值。

注意:为了更好地理解 Kubernetes 架构,有一些先决条件请查看 Kubernetes 学习指南中的先决条件以了解更多信息。

1 什么是 Kubernetes 架构?

以下 Kubernetes 架构图显示了 Kubernetes 集群的所有组件以及外部系统如何连接到 Kubernetes 集群。

k8s-architecture.drawio-1

关于 Kubernetes,您应该了解的第一件事,它是个分布式系统。这意味着,它有多个组件分布在网络上的不同服务器上。这些服务器可以是虚拟机或裸机服务器。我们称之为 Kubernetes 集群。

Kubernetes 集群由控制平面节点和工作节点组成。

1.1 控制平面

控制平面负责容器编排和维护集群的期望状态,它具有以下组件:

  1. kube-apiserver
  2. etcd
  3. kube-scheduler
  4. kube-controller-manager
  5. cloud-controller-manager

一个集群可以有一个或多个控制平面节点。

1.2 工作节点

Worker 节点负责运行容器化应用程序,Worker 节点具有以下组件:

  1. kubelet
  2. kube-proxy
  3. Container Runtime

2 Kubernetes 控制平面组件

首先,让我们看一下每个控制平面组件以及每个组件背后的重要概念。

2.1 kube-apiserver

kube-apiserver 是公开 Kubernetes API 的 Kubernetes 集群中心枢纽。它具有高度可扩展性,可以处理大量并发请求。

最终用户和其它集群组件通过 API Server(kube-apiserver)与集群通信。在极少数情况下,监控系统和第三方服务可能会与 API Server 通信从而与集群进行交互。

因此,当您使用 kubectl​ 管理集群时,在后端,您实际上是通过 HTTP REST API 与 API Server 进行通信。但是,内部集群组件(如 Scheduler、Controller 等)使用 gRPC 与 API Server 通信。

API Server 与集群中的其它组件之间的通信通过 TLS 进行,以防止对集群进行未经授权的访问。

kube-api-server.drawio-1

Kubernetes API Server 负责以下工作

  1. API 管理:公开集群 API 端点并处理所有 API 请求;API 是版本化的,它同时支持多个 API 版本
  2. 身份验证(使用客户端证书、持有者令牌和 HTTP 基本身份验证)和授权(ABAC 和 RBAC)
  3. 处理 API 请求并验证 API 对象(如 Pods、Services 等)的数据(验证和变更准入控制器)
  4. 它是唯一与 etcd 通信的组件
  5. API Server 协调控制平面和工作节点组件之间的所有进程
  6. API Server 有一个内置的 apiserver 代理。它是 API 服务器进程的一部分;它主要用于启用从集群外部访问 ClusterIP Services,即使这些 Services 通常只能在集群内部访问
  7. API Server 还包含一个聚合层,允许您扩展 Kubernetes API 以创建自定义 API、资源和控制器
  8. API Server 还支持监视资源的更改;例如,客户端可以对特定资源建立监视,并在创建、修改或删除这些资源时接收实时通知

安全说明:为了减少群集攻击面,保护 API Server 至关重要。Shadowserver 基金会进行了一项实验,发现了 380,000 个可公开访问的 Kubernetes API Server。

2.2 etcd

Kubernetes 是分布式系统,它需要一个高效的分布式数据库,如 etcd 来支持其分布式特性。它既充当后端服务发现,又充当数据库。你可以称它为 Kubernetes 集群的大脑。

etcd 是一个开源的强一致性分布式键值存储。那么这意味着什么呢?

  1. 强一致性:如果对某个节点进行了更新,则强一致性将确保它立即更新到集群中的所有其它节点;另外,如果你看过 CAP 定理,实现具有强一致性和分区容错性的 100% 可用性是不可能的
  2. 分布式:etcd 被设计为在不牺牲一致性的情况下作为集群在多个节点上运行
  3. 键值存储:将数据存储为键和值的非关系型数据库;它还公开键值 API;数据存储建立在 BboltDB 之上,BboltDB 是 BoltDB 的一个分支

etcd 使用 raft 共识算法,具有很强的一致性和可用性。它以 领导者 – 成员 的方式工作,以实现高可用性并承受节点故障。

那么 etcd 是如何与 Kubernetes 一起工作的呢?

简单地说,当你使用 kubectl​ 获取 Kubernetes 对象详细信息时,你是从 etcd 获取的。此外,当您部署像 Pod 这样的对象时,会在 etcd 中创建一个条目。

简而言之,这是您需要了解的有关 etcd 的信息:

  1. etcd 存储 Kubernetes 对象的所有配置、状态和元数据(pod、secret、daemonsets、deployments、configmaps、statefulsets 等)
  2. etcd 允许客户端使用 Watch()​ API 订阅事件;Kubernetes API Server 使用 etcd 的监视功能来跟踪对象状态的变化
  3. etcd 使用 gRPC 公开键值 API;此外,gRPC 网关是一个 RESTful 代理,可将所有 HTTP API 调用转换为 gRPC 消息;这使它成为 Kubernetes 的理想数据库
  4. etcd 以键值格式存储所有对象,在 /registry​ 目录项下;例如,可以在 /registry/pods/default/nginx​ 下找到默认命名空间中名为 Nginx 的 Pod 信息

image-5

此外,etcd 是控制平面中唯一的 Statefulset 组件。

2.3 kube-scheduler

kube-scheduler 负责在 Worker 节点上调度 Kubernetes Pod。

部署 Pod 时,您可以指定 Pod 要求,例如 CPU、内存、亲和性(affinity)、污点或容忍度、优先级、持久卷(PV)等。Scheduler 的主要任务是识别创建请求,并挑选满足 Pod 要求的最佳节点。

下图显示了 Scheduler 工作原理的概述。

image-8

在 Kubernetes 集群中,将有多个 Worker 节点。那么 Scheduler 是如何从所有 Worker 节点中选择节点的呢?以下是 Scheduler 的工作原理:

  1. 为了选择最佳节点,kube-scheduler 使用过滤和评分操作
  2. 在筛选中,Scheduler 会找到最适合调度 Pod 的节点;例如,如果有 5 个节点有充足的资源来运行 Pod,则它会选择所有 5 个节点;如果没有节点,则 Pod 不可调度并移动到调度队列;如果是大型集群,假设有 100 个 Worker 节点,那么调度程序不会遍历所有节点;有一个名为 percentageOfNodesToScore​ 的调度器配置参数。默认值通常为 50%;因此,它试图以循环方式迭代超过 50% 的节点;如果 Worker 节点分布在多个区域中,则 Scheduler 将遍历不同区域中的节点;对于非常大的集群,默认 percentageOfNodesToScore​ 值为 5%
  3. 在评分阶段,Scheduler 通过向筛选的 Worker 节点分配分数来对节点进行排名;Scheduler 通过调用多个调度插件进行评分;最后,将选择排名最高的 Worker 节点来调度 Pod;如果所有节点的排名相同,则将随机选择一个节点
  4. 选择节点后,Scheduler 将在 API Server 中创建绑定事件;表示绑定 Pod 和 Worker 节点的事件

有关 Scheduler,你需要了解:

  1. 它是一个 Controller,用于侦听 API Server 中的 Pod 创建事件
  2. Scheduler 有两个阶段,调度周期和绑定周期,统称为调度上下文;调度周期选择 Worker 节点,绑定周期将该更改应用于集群
  3. Scheduler 始终将高优先级的 Pod 放在低优先级的 Pod 之前进行调度;此外,在某些情况下,Pod 开始在所选节点运行后,Pod 可能会被驱逐或移动到其它节点;如果您想了解更多信息,请阅读 Kubernetes Pod 优先级指南
  4. 您可以创建自定义 Scheduler,并在集群中运行多个 Scheduler 以及原生 Scheduler;部署 Pod 时,您可以在 Pod 配置清单中指定自定义的 Scheduler;因此,调度决策将基于自定义的调度程序逻辑进行
  5. Scheduler 具有可插拔的调度框架;这意味着,您可以将自定义插件添加到调度工作流程中

2.4 kube-controller-manager

什么是 Controller?Controller 是运行无限控制循环的程序。这意味着它连续运行并监视对象的实际和期望状态。如果实际状态和期望状态存在差异,则确保 Kubernetes 资源/对象处于期望状态。

根据官方文件:

在 Kubernetes 中,Controller 是监视集群状态的控制循环,在需要时进行变更或请求变更。每个 Controller 都尝试将当前集群状态移近至期望状态。


假设要创建 Deployment,在清单 YAML 文件中指定期望的状态(声明式方法)。例如,2 个 Replicas、1 个 Volume 挂载、Configmap 等。内置的 Deployment Controller 可确保 Deployment 始终处于期望状态。如果用户使用 5 个 Replicas 更新 Deployment,则 Deployment Controller 会识别并确保所需的状态为 5 个 Replicas。

Kube Controller Manager 是管理所有 Kubernetes Controller 的组件。Kubernetes 资源/对象(如 Pod、名称空间、Jobs、Replicaset )由各自的 Controller 管理。此外,kube-scheduler 也是一个由 Kube Controller Manager 管理的 Controller。

image-9

以下是 Kubernetes 的重要内置 Controller 列表

  1. Deployment Controller
  2. ReplicaSet Controller
  3. DaemonSet Controller
  4. Job Controller
  5. CronJob Controller
  6. Endpoints Controller
  7. Namespace Controller
  8. ServiceAccount Controller
  9. Node Controller

以下是您应该了解的有关 Kube Controller Manager 的信息:

  1. 它管理所有 Controller,Controller 尝试将集群保持在理想状态
  2. 您可以使用与 CRD 关联的自定义 Controller 来扩展 Kubernetes

2.5 cloud-controller-manager(CCM)

在云环境中部署 Kubernetes 时,Cloud Controller Manager 充当云平台 API 和 Kubernetes 集群之间的桥梁。

这样,Kubernetes 核心组件可以独立工作,并允许云提供商使用插件与 Kubernetes 集成。(例如,Kubernetes 集群和 AWS 云 API 之间的接口)

云控制器集成允许 Kubernetes 集群预置云资源,例如 Instances(用于 Nodes)、Load Balancers(用于 Services)和 Storage Volumes(用于 PV)。

Cloud-Controller-Manager

Cloud Controller Manager 包含一组特定于云平台的 Controller,可确保特定于云的组件( Nodes、Load Balancers、Storage 等)处于期望状态。以下是 Cloud Controller Manager 中的三个主要 Controller。

  1. Node controller(节点控制器):此 Controller 通过与云提供商 API 通信来更新与 Node 相关的信息;例如,Node 标签和注解,获取主机名,CPU 和内存可用性,Nodes 运行状况等
  2. Route controller(路由控制器):负责在云平台上配置组网路由;这样不同节点的 Pod 就可以相互通信
  3. Service controller(服务控制器):它负责为 Kubernetes Services 部署 Load Balancers、分配 IP 地址等

以下是 Cloud Controller Manager 的经典示例:

  1. 部署 LoadBalancer 类型的 Kubernetes Service;Kubernetes 预置了特定于云的 Load Balancer,并与 Kubernetes Service 集成
  2. 由云存储解决方案为 Pods 提供存储卷 (PV)

总体而言,Cloud Controller Manager 管理 Kubernetes 使用的云端特定资源的生命周期。

3 Kubernetes 工作节点组件

现在,我们来看一下 Worker 节点上的组件。

3.1 kubelet

Kubelet 是一个 Agent 组件,运行在集群中的每个节点上。Kubelet 不作为容器运行,而是作为守护进程运行,由 systemd 管理。

它负责向 API Server 注册 Worker 节点,主要使用来自 API Server 的 podSpec(Pod 规范 – YAML 或 JSON)。podSpec 定义了应在 Pod 内运行的容器、相关的资源(例如 CPU 和内存限制)以及其它设置,例如环境变量、卷和标签。

而后,它依据 podSpec 的期望状态创建容器。

Kubelet 负责以下工作:

  1. 为 Pod 创建、修改和删除容器
  2. 负责处理 liveness(存活状态)、readiness(就绪状态)和启动探针
  3. 负责挂载卷,通过读取 Pod 配置并在主机上为卷挂载创建相应的目录来实现
  4. 通过调用 API Server,收集、报告节点和 Pod 的状态 ,实现方式为 cAdvisor 和 CRI

Kubelet 也是一个 Controller,它监视 Pod 的变化,并利用节点上的 Container Runtime 来拉取镜像、运行容器等。

除了来自 API Server 的 PodSpec 之外,Kubelet 还可以接受来自文件、HTTP 端点和 HTTP 服务器的 podSpec。创建 Kubernetes 静态 pod 是“来自文件的 podSpec”的一个很好的例子。

静态 Pod 由 Kubelet 控制,而不是由 API Server 控制。这意味着您可以通过向 Kubelet 组件指定 Pod YAML 文件的位置来创建 Pod。但是,Kubelet 创建的静态 Pod 不受 API Server 的管理。

静态 Pod 的真实用例:在启动控制平面各组件时,Kubelet 从 /etc/kubernetes/manifests​ 读取 podSpecs,启动 kube-apiserver、kube-scheduler 和 kube-controller-manager 作为静态 pod。

以下是关于 Kubelet 的一些关键内容

  1. Kubelet 使用 CRI(容器运行时接口)gRPC 接口与 Container Runtime 通信
  2. Kubelet 暴露 HTTP 端点用于流式传输日志,并为客户端提供 exec 会话
  3. Kubelet 使用 CSI(容器存储接口)gRPC 接口配置块存储卷
  4. Kubelet 使用集群中配置的 CNI 插件来分配 Pod IP 地址,并为 Pod 设置任何必要的网络路由和防火墙规则

kubelet-architecture

3.2 kube-proxy

要了解 Kube Proxy,您需要对 Kubernetes 的 Service 和 Endpoint 对象有基本的了解。

Kubernetes 中的 Service,是一种向内部或外部流量公开一组 Pod 的方法。创建 Service 对象时,会为其分配一个 Virtual IP,称为 ClusterIP。ClusterIP 只供 Kubernetes 集群内部访问。

Endpoint 对象包含 Service 对象下 Pod 组的所有 IP 地址和端口。Endpoints Controller 负责维护 Pod 的 IP 地址列表(Endpoints)。Service Controller 负责为 Service 配置 Endpoints。

您无法 ping 通 ClusterIP,因为它仅用于服务发现,这与可 ping 的 Pod IP 不同。

现在让我们了解一下 Kube Proxy。

kube-proxy 是一个守护进程,它以 Daemonset 对象的方式在每个节点上运行。它是一个代理组件,用于实现 Pod 的 Kubernetes Service 概念。(为一组 Pod 提供负载均衡功能的单个 DNS。)它主要代理 UDP、TCP 和 SCTP,不具备 HTTP 代理能力。

当您使用 Service(ClusterIP)公开 Pod 时,kube-proxy 会创建网络规则,将流量发送到 Service 对象下分组的后端 Pod(Endpoints)。这意味着,所有负载均衡和服务发现都由 Kube Proxy 处理。

那么 kube-proxy 是如何工作的呢?

Kube Proxy 与 API Server 通信,以获取有关 Service(ClusterIP)和相应 Pod IP 及端口(Endpoints)的详细信息。它还监视 Service 和 Endpoints 的变化。

然后,kube-proxy 使用以下任一模式创建或更新规则,将流量路由到 Service 后面的 Pod。

  1. iptables:这是默认模式;在 iptables 模式下由 iptables 规则处理;这意味着,对于每个 Service,都会创建 iptables 规则;这些规则捕获进入 ClusterIP 的流量,然后将其转发给后端 Pod;此外,在这种模式下,kube-proxy 会随机选择后端 Pod 进行负载均衡,建立连接后,请求将转到同一 Pod,直到连接终止
  2. ipvs:对于 Services 超过 1000 的集群,ipvs 提供更佳的性能;它支持以下后端负载均衡算法
    1. rr :轮询;默认模式
    2. lc :最少连接数(最小打开连接数)
    3. dh :目标哈希
    4. sh :源哈希
    5. sed :最短的预期延迟
    6. nq :从不排队
  3. Userspace:用户空间(旧版本,不推荐)
  4. Kernelspace:此模式仅适用于 Windows 系统

image-14

如果您想了解 Kube Proxy iptables 和 ipvs 模式之间的性能差异,请阅读本文

此外,您可以通过将 Kubernetes 集群替换为 Cilium 来运行没有 kube-proxy 的 Kubernetes 集群。

1.29 Alpha 功能:Kube Proxy 拥有基于 nftables 的新后端;nftables 是 iptables 的继任者,旨在更简单、更高效。

3.3 Container Runtime

您可能了解 Java 运行时(JRE),它是在主机上运行 Java 程序所需的软件组件。同样,Container Runtime(容器运行时)是运行容器所需的软件组件。

Container Runtime 在 Kubernetes 集群中的所有节点上运行。它负责从 Registry 中拉取镜像、运行容器、分配和隔离容器资源,以及管理主机上容器的整个生命周期。

为了更好地理解这一点,让我们看一下两个关键概念:

  1. 容器运行时接口(CRI):它是一组 API,允许 Kubernetes 与不同的 Container Runtime 进行交互;CRI 定义了用于创建、启动、停止和删除容器,以及管理镜像和容器网络的 API
  2. 开放容器倡议(OCI):它是一组容器格式和运行时的标准

Kubernetes 支持多种符合容器运行时接口(CRI)的容器运行时(CRI-O、Docker Engine、containerd 等)。这意味着,所有这些 Container Runtime 都实现了 CRI 接口,并公开了 gRPC CRI API(运行时和镜像服务端点)。

那么 Kubernetes 是如何利用 Container Runtime 的呢?

正如我们在 Kubelet 部分所了解的,Kubelet 负责使用 CRI API 与 Container Runtime 进行交互,以管理容器的生命周期。它还从 Container Runtime 获取所有容器信息,并将其提供给控制平面。

我们以 CRI-O CRI 为例,下面是 Container Runtime 如何与 Kubernetes 配合使用的高级概述。

image-5 (1)

  1. 当 kubelet 从 API Server 得知有创建新 Pod 的请求时,则通过 Kubernetes CRI 与 CRI-O 守护进程通信,启动所需的容器
  2. CRI-O 会使用 containers/image 库从配置的容器 Registry 检查并拉取所需的容器镜像
  3. 然后为容器生成 OCI 运行时规范(JSON)
  4. 之后通过与 OCI 兼容的运行时(runc),启动符合运行时规范的容器进程

4 Kubernetes 集群的 Addon 组件

除了核心组件之外,Kubernetes 集群还需要附加组件才能完全运行。所选插件取决于项目需求和应用场景。

以下是集群上可能需要的一些常用插件组件:

  1. CNI 插件(容器网络接口)
  2. CoreDNS(用于 DNS 服务):CoreDNS 充当 Kubernetes 集群中的 DNS 服务器;通过启用此插件,您可以启用基于 DNS 的服务发现
  3. Metrics Server(用于资源指标):此插件可帮助您收集集群中 Nodes 和 Pods 的性能数据和资源使用情况
  4. Web UI( Kubernetes Dashboard ):此插件启用 Kubernetes Dashboard,通过 Web UI 管理对象

4.1 CNI Plugin

首先,您需要了解容器网络接口 (CNI)。它是一个基于插件的架构,具备独立的第三方规范和库,用于为容器创建网络接口。它不是 Kubernetes 特有的,基于 CNI,容器网络可以在 Kubernetes、Mesos、CloudFoundry、Podman、Docker 等容器编排工具之间实现标准化。

在容器网络方面,各家公司可能有不同的要求,例如网络隔离、安全性、加密等。随着容器技术的进步,许多网络提供商为容器创建了基于 CNI 的具有广泛网络功能的解决方案,你可以称它为 CNI-Plugins。

这使用户可以从不同的提供商选择最适合其需求的网络解决方案。

CNI 插件如何与 Kubernetes 配合使用?

  1. kube-controller-manager 负责为每个节点分配 Pod 网段;每个 Pod 从 Pod CIDR 获取 1 个唯一的 IP 地址
  2. Kubelet 与 Container Runtime 交互,运行已调度的 Pod;作为 Container Runtime 一部分的 CRI 插件与 CNI 插件交互,以配置 Pod 网络
  3. CNI 插件支持使用叠加网络在相同或不同节点上分布的 Pods 之间进行联网

image-18

以下是 CNI 插件提供的高级功能:

  1. Pod 网络
  2. Pod 网络安全和隔离,使用网络策略来控制 Pods 之间及名称空间之间的流量

一些流行的 CNI 插件包括:

  • Calico
  • Flannel
  • Weave Net
  • Cilium (Uses eBPF)
  • Amazon VPC CNI (For AWS VPC)
  • Azure CNI

5 Kubernetes 原生对象

到目前为止,我们已经了解了核心 Kubernetes 组件以及每个组件的工作原理,所有这些组件都致力于管理以下关键 Kubernetes 对象:

  • Pod
  • Namespace
  • Replicaset
  • Deployment
  • Daemonset
  • Statefulset
  • Jobs & Cronjobs
  • ConfigMaps & Secrets

在网络方面,以下 Kubernetes 对象起着关键作用:

  • Service
  • Ingress
  • NetworkPolicy

此外,Kubernetes 可以使用 CRD(自定义资源定义)和自定义控制器进行扩展。因此,集群组件还管理使用自定义控制器和 CRD 创建的对象。

6 Kubernetes 架构常见问题解答

Kubernetes 控制平面的主要用途是什么?

控制平面负责维护集群及其上运行的应用程序的期望状态,它由 API Server、etcd、Scheduler 和 Controller Manager 等组件组成。

Kubernetes 集群中工作节点的用途是什么?

Worker 节点是在集群中运行容器的服务器(裸机或虚拟机),它们由控制平面管理,并从控制平面接收有关如何运行属于 Pod 的容器的指令。

如何在 Kubernetes 中保护控制平面和工作节点之间的通信?

控制平面和工作节点之间的通信使用 PKI 证书进行保护,不同组件之间的通信通过 TLS 进行,这样,只有受信任的组件才能相互通信。

Kubernetes 中 etcd 键值存储的目的是什么?

Etcd 主要存储集群的 Kubernetes 对象、集群信息、节点信息以及集群的配置数据,例如集群上运行的应用程序的期望状态。

如果 etcd 宕机,Kubernetes 应用程序会发生什么?

虽然 etcd 遇到中断,正在运行的应用程序不会受到影响,但如果没有正常运行的 etcd,将无法创建或更新任何对象。

7 总结

了解 Kubernetes 架构有助于您进行日常 Kubernetes 实施和操作。在实施生产级集群设置时,对 Kubernetes 组件有正确的了解将有助于你运行应用程序并对其进行故障排除。

来源:http://i7q.cn/5M2T8F
翻译:http://i7q.cn/61PVyG
校正:https://www.jeffnotes.net/930

参考资料

[1]​ gRPC 网关: https://etcd.io/docs/v3.3/dev-guide/api_grpc_gateway/
[2]​ Kubernetes Pod 优先级指南: https://devopscube.com/pod-priorityclass-preemption/
[3]​ kube-proxy​: https://www.tigera.io/blog/comparing-kube-proxy-modes-iptables-or-ipvs/

发表评论

邮箱地址不会被公开。