K8S系列:集群架构与组件

云计算 云原生
本文将深入探讨K8s集群的架构以及核心组件,帮助读者更好地理解Kubernetes的工作原理和设计思想。

Kubernetes(K8s)作为当今最流行的容器编排引擎之一,其集群架构和组件扮演着关键角色,为现代化云原生应用的部署、扩展和管理提供了强大的支持。本文将深入探讨K8s集群的架构以及核心组件,帮助读者更好地理解Kubernetes的工作原理和设计思想。

Kubernetes 架构

Kubernetes集群由多个节点组成,其中包括Master节点和Worker节点。Master节点负责集群的控制平面,而Worker节点负责运行实际的应用程序容器。

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

1.控制平面

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

  • kube-apiserver
  • etcd
  • kube-scheduler
  • kube-controller-manager
  • cloud-controller-manager

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

2.工作节点

工作节点负责运行容器化的应用程序。工作节点包括以下组件:

  • kubelet
  • kube-proxy
  • 容器运行时(Container runtime)

分层架构

Kubernetes 设计理念和功能其实就是一个类似 Linux 的分层架构,如下图所示:

分层架构

  • 核心层:Kubernetes 最核心的功能,对外提供 API 构建高层的应用,对内提供插件式应用执行环境
  • 应用层:部署(无状态应用、有状态应用、批处理任务、集群应用等)和路由(服务发现、DNS 解析等)
  • 管理层:系统度量(如基础设施、容器和网络的度量),自动化(如自动扩展、动态 Provision 等)以及策略管理RBAC、Quota、PSP、NetworkPolicy 等
  • 接口层:kubectl 命令行工具、客户端 SDK 以及集群联邦
  • 生态系统:在接口层之上的庞大容器集群管理调度的生态系统,可以划分为两个范畴。

控制面板组件

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

1.kube-apiserver

kube-api服务器是公开Kubernetes API的Kubernetes集群的中心枢纽。它具有高度的可扩展性,可以处理大量并发请求。最终用户和其他集群组件通过API服务器与集群通信。监控系统和第三方服务很少会与API服务器通信,与集群进行交互。因此,当您使用kubectl来管理集群时,在后端您实际上是通过HTTP REST API与API服务器通信。然而,集群内部的组件如调度器、控制器等使用gRPC与API服务器通信。API服务器和集群中的其他组件之间通过TLS进行通信,以防止对集群的未授权访问。

Kubernetes api-server负责以下工作:

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

2.etcd

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

Etcd是一个开源的强一致性分布式键值存储。它具体意味着什么?

  • 强一致性:如果对一个节点进行了更新,强一致性将确保该节点立即更新到集群中的所有其他节点。此外,如果你看看CAP定理,在强一致性和分区容忍下实现100%的可用性是不可能的。
  • 分布式:etcd被设计成在多个节点上作为一个集群运行,而不会牺牲一致性。
  • 键值存储(Key Value Store) :一种非关系型数据库,以键和值的形式存储数据。它还公开了一个key-value API。该数据存储构建在BoltDB的一个分支BboltDB之上。

Etcd采用raft共识算法实现强一致性和可用性。它以领导者-成员的方式工作,以获得高可用性和抵御节点故障。

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

简单地说,当你使用kubectl来获取kubernetes对象的细节时,你是从etcd中获取它。此外,当部署pod等对象时,会在etcd中创建一个条目。

简而言之,以下是您需要了解的关于etcd的内容:

  • etcd存储Kubernetes对象的所有配置、状态和元数据(pods、secrets、daemonsets、deployment、configmaps、statefulsets等)。
  • etcd允许客户端使用Watch() API订阅事件。Kubernetes api-server使用etcd的watch功能来跟踪对象状态的变化。
  • etcd使用gRPC提供了key-value API。此外,gRPC网关是一个RESTful代理,它将所有HTTP API调用转换为gRPC消息。这使得它成为Kubernetes的理想数据库。
  • Etcd以键值格式将所有对象存储在/registry目录下。例如,默认命名空间中名为Nginx的pod的信息可以在/registry/pods/default/Nginx下找到

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

3.kube-scheduler

kube-scheduler负责在工作节点上调度Kubernetes pods。

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

下图概述了调度器的工作原理:

在Kubernetes集群中,将有多个工作节点。那么,调度器如何从所有工作节点中选择节点呢?

下面是调度器的工作原理:

  • 为了选择最佳节点,Kube-scheduler使用过滤和评分操作。
  • 在筛选过程中,调度器找到可以调度pod的最适合的节点。例如,如果有5个可用资源运行pod的工作节点,它会选择所有5个节点。如果没有节点,那么pod是不可调度的,并移动到调度队列。如果是一个大型集群,假设有100个工作节点,调度器不会遍历所有节点。有一个调度器配置参数,名为percentageOfNodesToScore。默认值通常为50%。因此,它尝试以轮询方式迭代超过50%的节点。如果工作节点分布在多个内存域,那么调度器会遍历不同内存域中的节点。对于非常大的集群,默认percentageOfNodesToScore是5%。
  • 在评分阶段,调度器通过为过滤后的工作节点分配分数来对节点进行排名。调度器通过调用多个调度插件进行评分。最后,选择级别最高的工作节点进行pod调度。如果所有节点的相同,则随机选择一个节点。
  • 一旦节点被选中,调度器就会在API服务器中创建一个绑定事件。意味着绑定pod和node的事件。

下面是你需要知道的关于调度器的事情:

  • 它是一个在API服务器中监听pod创建事件的控制器。
  • 调度器有两个阶段。调度周期和绑定周期。它们合起来称为调度上下文(scheduling context)。调度周期选择一个工作节点,然后绑定周期将其应用到集群上。
  • 调度器总是将高优先级的pods放在低优先级的pods之前进行调度。此外,在某些情况下,在pod开始在选定节点中运行后,pod可能会被删除或移动到其他节点。如果你想了解更多,请阅读Kubernetes pod优先级指南[1]
  • 用户可以创建自定义调度器,并在集群上运行多个调度器。当你部署pod时,你可以在pod清单中指定自定义调度器。因此,调度决策将基于自定义调度器逻辑进行。
  • 调度器有一个可插拔的调度框架。这意味着你可以将自定义插件添加到调度工作流中。

4.kube-controller-manager

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

根据官方文件:在Kubernetes中,控制器是监视集群状态的控制循环,然后在需要时进行更改或请求更改。每个控制器都试图将当前集群状态移动到期望状态。

假设你想要创建一个部署,你在manifest YAML文件中指定所需的状态(声明方式)。例如,2个副本,1个卷挂载,configmap等。内置的部署控制器确保部署始终处于所需的状态。如果用户用5个副本更新部署,部署控制器将识别它并确保所需状态为5个副本。

kube-controller-manager是一个管理所有Kubernetes控制器的组件。Kubernetes资源/对象,如pods,命名空间,作业,replicaset由各自的控制器管理。此外,Kube调度器也是由Kube控制器管理器管理的控制器。

以下是重要的内置Kubernetes控制器列表:

  • Deployment Controller
  • ReplicaSet Controller
  • DaemonSet Controller
  • Job Controller
  • CronJob Controller
  • Endpoints Controller
  • Namespace Controller
  • Service Accounts Controller
  • Node Controller

以下是关于Kube控制器管理器您应该了解的内容:

  • 它管理所有控制器,而这些控制器则试图保持集群处于期望的状态。
  • 你可以通过自定义资源定义(Custom Resource Definition)来扩展 Kubernetes,关联自定义控制器。

5.cloud-controller-manager(CCM)

  • 当kubernetes部署在云环境中时,云控制器管理器充当云平台api和kubernetes集群之间的桥梁。
  • 这样,核心kubernetes的核心组件可以独立工作,并允许云提供商使用插件与kubernetes集成。(例如,kubernetes集群和AWS cloud API之间的接口)
  • 集成云控制器允许Kubernetes集群提供云资源,如实例(用于节点)、负载均衡器(用于服务)和存储卷(用于持久卷)。

云控制器管理器包含一组特定于云平台的控制器,确保特定于云的组件(节点、负载均衡器、存储等)的所需状态。以下是云控制器管理器的三个主要控制器:

  • 节点控制器:该控制器通过与云提供商API通信更新节点相关信息。例如,节点标记和注释、获取主机名、CPU和内存可用性、节点健康状况等。
  • 路由控制器:负责在云平台上配置网络路由。这样不同节点中的pods就可以相互通信。
  • 服务控制器:它负责为kubernetes服务部署负载均衡器,分配IP地址等。

下面是云控制器管理器的一些经典示例:

  • 部署负载均衡器类型的Kubernetes服务。在这里,Kubernetes提供了一个特定于云的负载均衡器,并与Kubernetes服务集成。
  • 为云存储解决方案支持的pods配置存储卷(PV)。

整体云控制器管理器管理kubernetes使用的特定云资源的生命周期。

节点组件

现在让我们看看每个工作节点组件。

1.kubelet

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

它负责向API服务器注册工作节点,并主要从API服务器使用podSpec (Pod规范- YAML或JSON)。podSpec定义了应该在pod中运行的容器、它们的资源(例如CPU和内存限制)以及其他设置,如环境变量、卷和标签。

然后,它通过创建容器将podSpec带到所需状态。

简而言之,kubelet负责以下工作:

  • 为pod创建、修改和删除容器。
  • 负责处理活性,准备和启动探针。
  • 通过读取pod配置和在主机上为卷挂载创建相应的目录来负责挂载卷。
  • 通过调用API服务器(如cAdvisor和CRI)来收集和报告节点和pod状态。
  • Kubelet也是一个控制器,它监视pod的变化,并利用节点的容器运行时来拉取图像,运行容器等。

除了来自API服务器的podSpec, kubelet还可以接受来自文件、HTTP端点和HTTP服务器的podSpec。“podSpec from a file”的一个很好的例子是Kubernetes static pods。

静态pods由kubelet控制,而不是API服务器。

这意味着你可以通过向Kubelet组件提供pod的YAML位置来创建pods。然而,Kubelet创建的静态pods并不由API服务器管理。

这是一个静态pod的真实示例。

在引导控制平面时,kubelet从位于/etc/kubernetes/manifest的podSpecs中将 api-server、scheduler 和 controller manager作为静态 pod。

以下是kubelet的一些关键内容:

  • Kubelet使用CRI(容器运行时接口)gRPC接口与容器运行时进行通信。
  • 它还向流日志公开HTTP端点,并为客户端提供exec会话。
  • 使用CSI (container storage interface) gRPC配置块卷。
  • 它使用集群中配置的CNI插件来分配pod的IP地址,并为pod设置必要的网络路由和防火墙规则。

2.kube-proxy

要理解Kube-proxy,你需要对Kubernetes服务和端点对象有基本的了解。

Kubernetes中的服务是一种向内部或外部流量暴露一组pods的方法。当您创建服务对象时,它将获得分配给它的虚拟IP。它被称为clusterIP。它只能在Kubernetes集群内访问。

Endpoint对象包含一个服务对象下pod组的所有IP地址和端口。端点控制器负责维护pod IP地址(端点)列表。服务控制器负责配置服务的端点。

你不能ping ClusterIP,因为ClusterIP只用于服务发现,不像pod ip可以ping。

现在让我们了解一下Kube-proxy。

Kube-proxy是一个守护进程,在每个节点上作为守护进程运行。它是一个为pods实现Kubernetes服务概念的代理组件。(一组具有负载均衡的pods的单一DNS)。它主要代理UDP、TCP和SCTP,但不支持HTTP。

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

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

Kube代理与API服务器通信以获取服务(ClusterIP)以及相应的pod ip和端口(endpoints)的详细信息。它还监视服务和端点的变化。

然后,Kube-proxy使用以下任意一种模式来创建/更新规则,将流量路由到服务背后的pods:

(1) IPTables:默认模式。IPTables模式下,流量通过IPtable规则进行处理。这意味着对于每个服务,都创建了IPtable规则。这些规则捕获到达ClusterIP的流量,然后将其转发到后端pods。在这种模式下,kube-proxy随机选择后端pod进行负载均衡。连接建立后,请求会发送到同一个pod,直到连接终止。

(2) IPVS:对于超过1000个业务的集群,IPVS提供了性能提升。它支持以下后端负载平衡算法。

  • rr:round-robin:默认模式。
  • Lc:最小连接数(最小打开连接数)
  • Dh:目标哈希
  • Sh:源散列
  • Sed:预期的最短延迟
  • Nq:永不排队

(3) 用户空间:(遗留&不推荐)

(4) 内核空间:该模式仅适用于Windows系统。

如果您想了解kube-proxy IPtables和IPVS模式之间的性能差异,请阅读这篇文章。此外,您可以通过将其替换为ciilium来运行Kubernetes集群,而无需kube-proxy。

1.29 Alpha特性:Kubeproxy有一个新的基于𝗻𝗳𝘁𝗮𝗯𝗹𝗲𝘀的后端。nftables是IPtables的继承者,旨在更简单、更高效。

3.container runtime

你可能知道Java运行时(JRE)。它是在主机上运行Java程序所需的软件。以同样的方式,容器运行时是运行容器所需的软件组件。

容器运行时运行在Kubernetes集群中的所有节点上。它负责从容器注册表中拉取映像,运行容器,为容器分配和隔离资源,以及管理主机上容器的整个生命周期。

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

  • 容器运行时接口(CRI) :它是一组api,允许Kubernetes与不同的容器运行时交互。它允许不同的容器运行时与Kubernetes互换使用。CRI定义了用于创建、启动、停止和删除容器以及管理映像和容器网络的API。
  • 开放容器计划(Open Container Initiative, OCI):它是一组容器格式和运行时的标准

Kubernetes支持与容器运行时接口(CRI)兼容的多个容器运行时(CRI-O, Docker Engine, containerd等)。这意味着,所有这些容器运行时都实现了CRI接口并公开了gRPC CRI api(运行时和映像服务端点)。

那么Kubernetes如何利用容器运行时呢?

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

让我们以CRI-O容器运行时接口为例。以下是容器运行时如何与kubernetes一起工作的高级概述。

  • 当从API服务器有对pod的新请求时,kubelet通过Kubernetes容器运行时接口与CRI-O守护进程通信,以启动所需的容器。
  • CRI-O使用容器/映像库从配置的容器注册表中检查并提取所需的容器映像。
  • 然后CRI-O为容器生成OCI运行时规范(JSON)。
  • 然后,CRI-O启动一个oci兼容运行时(runc),根据运行时规范启动容器进程。

附加组件

  • kube-dns: 负责为整个集群提供 DNS 服务
  • Ingress Controller: 为服务提供外网入口
  • Prometheus: 提供资源监控
  • Dashboard: 提供 GUI
  • Federation: 提供跨可用区的集群
  • Fluentd-elasticsearch: 提供集群日志采集、存储与查询

参考文档:

[1]Kubernetes pod优先级指南: https://devopscube.com/pod-priorityclass-preemption/

责任编辑:赵宁宁 来源: 攻城狮成长日记
相关推荐

2019-09-09 09:53:52

K8s集群架构

2023-07-04 07:30:03

容器Pod组件

2023-09-03 23:58:23

k8s集群容量

2023-03-05 21:50:46

K8s集群容量

2021-03-11 12:31:33

K8sCoreDNSDNS服务器

2021-04-22 09:46:35

K8SCluster Aut集群

2022-04-22 13:32:01

K8s容器引擎架构

2022-02-11 23:11:09

Kubernetes集群容器化

2022-12-28 10:52:34

Etcd备份

2021-11-04 07:49:58

K8SStatefulSetMySQL

2023-09-07 08:58:36

K8s多集群

2022-06-14 07:56:15

Kubernetes存储架构K8S

2023-11-06 07:16:22

WasmK8s模块

2022-10-10 12:54:00

Flink运维

2024-05-20 15:39:00

Karmada混合云多云

2019-10-31 09:03:12

Java集群微服务

2022-01-02 08:42:50

架构部署容器

2023-11-01 07:55:44

K8sKubernetes

2023-09-06 08:12:04

k8s云原生
点赞
收藏

51CTO技术栈公众号