这篇关于 Kubernetes 架构的综合指南旨在通过插图详细解释每个 Kubernetes 组件。
因此,如果您希望:
- 了解 Kubernetes 的架构
- 掌握 Kubernetes 的基本概念
- 了解 Kubernetes 架构组件
- 探索连接这些组件的工作流
那么此篇 Kubernetes 架构指南将非常有价值。
注意:为了更好地理解 Kubernetes 架构,有一些先决条件请查看 Kubernetes 学习指南中的先决条件以了解更多信息。
1 什么是 Kubernetes 架构?
以下 Kubernetes 架构图显示了 Kubernetes 集群的所有组件以及外部系统如何连接到 Kubernetes 集群。
关于 Kubernetes,您应该了解的第一件事,它是个分布式系统。这意味着,它有多个组件分布在网络上的不同服务器上。这些服务器可以是虚拟机或裸机服务器。我们称之为 Kubernetes 集群。
Kubernetes 集群由控制平面节点和工作节点组成。
1.1 控制平面
控制平面负责容器编排和维护集群的期望状态,它具有以下组件:
- kube-apiserver
- etcd
- kube-scheduler
- kube-controller-manager
- cloud-controller-manager
一个集群可以有一个或多个控制平面节点。
1.2 工作节点
Worker 节点负责运行容器化应用程序,Worker 节点具有以下组件:
- kubelet
- kube-proxy
- 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 进行,以防止对集群进行未经授权的访问。
Kubernetes API Server 负责以下工作
- API 管理:公开集群 API 端点并处理所有 API 请求;API 是版本化的,它同时支持多个 API 版本
- 身份验证(使用客户端证书、持有者令牌和 HTTP 基本身份验证)和授权(ABAC 和 RBAC)
- 处理 API 请求并验证 API 对象(如 Pods、Services 等)的数据(验证和变更准入控制器)
- 它是唯一与 etcd 通信的组件
- API Server 协调控制平面和工作节点组件之间的所有进程
- API Server 有一个内置的 apiserver 代理。它是 API 服务器进程的一部分;它主要用于启用从集群外部访问 ClusterIP Services,即使这些 Services 通常只能在集群内部访问
- API Server 还包含一个聚合层,允许您扩展 Kubernetes API 以创建自定义 API、资源和控制器
- API Server 还支持监视资源的更改;例如,客户端可以对特定资源建立监视,并在创建、修改或删除这些资源时接收实时通知
安全说明:为了减少群集攻击面,保护 API Server 至关重要。Shadowserver 基金会进行了一项实验,发现了 380,000 个可公开访问的 Kubernetes API Server。
2.2 etcd
Kubernetes 是分布式系统,它需要一个高效的分布式数据库,如 etcd 来支持其分布式特性。它既充当后端服务发现,又充当数据库。你可以称它为 Kubernetes 集群的大脑。
etcd 是一个开源的强一致性分布式键值存储。那么这意味着什么呢?
- 强一致性:如果对某个节点进行了更新,则强一致性将确保它立即更新到集群中的所有其它节点;另外,如果你看过 CAP 定理,实现具有强一致性和分区容错性的 100% 可用性是不可能的
- 分布式:etcd 被设计为在不牺牲一致性的情况下作为集群在多个节点上运行
- 键值存储:将数据存储为键和值的非关系型数据库;它还公开键值 API;数据存储建立在 BboltDB 之上,BboltDB 是 BoltDB 的一个分支
etcd 使用 raft 共识算法,具有很强的一致性和可用性。它以 领导者 – 成员 的方式工作,以实现高可用性并承受节点故障。
那么 etcd 是如何与 Kubernetes 一起工作的呢?
简单地说,当你使用 kubectl
获取 Kubernetes 对象详细信息时,你是从 etcd 获取的。此外,当您部署像 Pod 这样的对象时,会在 etcd 中创建一个条目。
简而言之,这是您需要了解的有关 etcd 的信息:
- etcd 存储 Kubernetes 对象的所有配置、状态和元数据(pod、secret、daemonsets、deployments、configmaps、statefulsets 等)
- etcd 允许客户端使用
Watch()
API 订阅事件;Kubernetes API Server 使用 etcd 的监视功能来跟踪对象状态的变化 - etcd 使用 gRPC 公开键值 API;此外,gRPC 网关是一个 RESTful 代理,可将所有 HTTP API 调用转换为 gRPC 消息;这使它成为 Kubernetes 的理想数据库
- etcd 以键值格式存储所有对象,在
/registry
目录项下;例如,可以在/registry/pods/default/nginx
下找到默认命名空间中名为 Nginx 的 Pod 信息
此外,etcd 是控制平面中唯一的 Statefulset 组件。
2.3 kube-scheduler
kube-scheduler 负责在 Worker 节点上调度 Kubernetes Pod。
部署 Pod 时,您可以指定 Pod 要求,例如 CPU、内存、亲和性(affinity)、污点或容忍度、优先级、持久卷(PV)等。Scheduler 的主要任务是识别创建请求,并挑选满足 Pod 要求的最佳节点。
下图显示了 Scheduler 工作原理的概述。
在 Kubernetes 集群中,将有多个 Worker 节点。那么 Scheduler 是如何从所有 Worker 节点中选择节点的呢?以下是 Scheduler 的工作原理:
- 为了选择最佳节点,kube-scheduler 使用过滤和评分操作
- 在筛选中,Scheduler 会找到最适合调度 Pod 的节点;例如,如果有 5 个节点有充足的资源来运行 Pod,则它会选择所有 5 个节点;如果没有节点,则 Pod 不可调度并移动到调度队列;如果是大型集群,假设有 100 个 Worker 节点,那么调度程序不会遍历所有节点;有一个名为
percentageOfNodesToScore
的调度器配置参数。默认值通常为50%
;因此,它试图以循环方式迭代超过50%
的节点;如果 Worker 节点分布在多个区域中,则 Scheduler 将遍历不同区域中的节点;对于非常大的集群,默认percentageOfNodesToScore
值为5%
- 在评分阶段,Scheduler 通过向筛选的 Worker 节点分配分数来对节点进行排名;Scheduler 通过调用多个调度插件进行评分;最后,将选择排名最高的 Worker 节点来调度 Pod;如果所有节点的排名相同,则将随机选择一个节点
- 选择节点后,Scheduler 将在 API Server 中创建绑定事件;表示绑定 Pod 和 Worker 节点的事件
有关 Scheduler,你需要了解:
- 它是一个 Controller,用于侦听 API Server 中的 Pod 创建事件
- Scheduler 有两个阶段,调度周期和绑定周期,统称为调度上下文;调度周期选择 Worker 节点,绑定周期将该更改应用于集群
- Scheduler 始终将高优先级的 Pod 放在低优先级的 Pod 之前进行调度;此外,在某些情况下,Pod 开始在所选节点运行后,Pod 可能会被驱逐或移动到其它节点;如果您想了解更多信息,请阅读 Kubernetes Pod 优先级指南
- 您可以创建自定义 Scheduler,并在集群中运行多个 Scheduler 以及原生 Scheduler;部署 Pod 时,您可以在 Pod 配置清单中指定自定义的 Scheduler;因此,调度决策将基于自定义的调度程序逻辑进行
- 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。
以下是 Kubernetes 的重要内置 Controller 列表
- Deployment Controller
- ReplicaSet Controller
- DaemonSet Controller
- Job Controller
- CronJob Controller
- Endpoints Controller
- Namespace Controller
- ServiceAccount Controller
- Node Controller
以下是您应该了解的有关 Kube Controller Manager 的信息:
- 它管理所有 Controller,Controller 尝试将集群保持在理想状态
- 您可以使用与 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 包含一组特定于云平台的 Controller,可确保特定于云的组件( Nodes、Load Balancers、Storage 等)处于期望状态。以下是 Cloud Controller Manager 中的三个主要 Controller。
- Node controller(节点控制器):此 Controller 通过与云提供商 API 通信来更新与 Node 相关的信息;例如,Node 标签和注解,获取主机名,CPU 和内存可用性,Nodes 运行状况等
- Route controller(路由控制器):负责在云平台上配置组网路由;这样不同节点的 Pod 就可以相互通信
- Service controller(服务控制器):它负责为 Kubernetes Services 部署 Load Balancers、分配 IP 地址等
以下是 Cloud Controller Manager 的经典示例:
- 部署 LoadBalancer 类型的 Kubernetes Service;Kubernetes 预置了特定于云的 Load Balancer,并与 Kubernetes Service 集成
- 由云存储解决方案为 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 负责以下工作:
- 为 Pod 创建、修改和删除容器
- 负责处理 liveness(存活状态)、readiness(就绪状态)和启动探针
- 负责挂载卷,通过读取 Pod 配置并在主机上为卷挂载创建相应的目录来实现
- 通过调用 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 的一些关键内容
- Kubelet 使用 CRI(容器运行时接口)gRPC 接口与 Container Runtime 通信
- Kubelet 暴露 HTTP 端点用于流式传输日志,并为客户端提供 exec 会话
- Kubelet 使用 CSI(容器存储接口)gRPC 接口配置块存储卷
- Kubelet 使用集群中配置的 CNI 插件来分配 Pod IP 地址,并为 Pod 设置任何必要的网络路由和防火墙规则
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。
- iptables:这是默认模式;在 iptables 模式下由 iptables 规则处理;这意味着,对于每个 Service,都会创建 iptables 规则;这些规则捕获进入 ClusterIP 的流量,然后将其转发给后端 Pod;此外,在这种模式下,kube-proxy 会随机选择后端 Pod 进行负载均衡,建立连接后,请求将转到同一 Pod,直到连接终止
- ipvs:对于 Services 超过 1000 的集群,ipvs 提供更佳的性能;它支持以下后端负载均衡算法
- rr :轮询;默认模式
- lc :最少连接数(最小打开连接数)
- dh :目标哈希
- sh :源哈希
- sed :最短的预期延迟
- nq :从不排队
- Userspace:用户空间(旧版本,不推荐)
- Kernelspace:此模式仅适用于 Windows 系统
如果您想了解 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 中拉取镜像、运行容器、分配和隔离容器资源,以及管理主机上容器的整个生命周期。
为了更好地理解这一点,让我们看一下两个关键概念:
- 容器运行时接口(CRI):它是一组 API,允许 Kubernetes 与不同的 Container Runtime 进行交互;CRI 定义了用于创建、启动、停止和删除容器,以及管理镜像和容器网络的 API
- 开放容器倡议(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 配合使用的高级概述。
- 当 kubelet 从 API Server 得知有创建新 Pod 的请求时,则通过 Kubernetes CRI 与 CRI-O 守护进程通信,启动所需的容器
- CRI-O 会使用
containers/image
库从配置的容器 Registry 检查并拉取所需的容器镜像 - 然后为容器生成 OCI 运行时规范(JSON)
- 之后通过与 OCI 兼容的运行时(runc),启动符合运行时规范的容器进程
4 Kubernetes 集群的 Addon 组件
除了核心组件之外,Kubernetes 集群还需要附加组件才能完全运行。所选插件取决于项目需求和应用场景。
以下是集群上可能需要的一些常用插件组件:
- CNI 插件(容器网络接口)
- CoreDNS(用于 DNS 服务):CoreDNS 充当 Kubernetes 集群中的 DNS 服务器;通过启用此插件,您可以启用基于 DNS 的服务发现
- Metrics Server(用于资源指标):此插件可帮助您收集集群中 Nodes 和 Pods 的性能数据和资源使用情况
- 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 配合使用?
- kube-controller-manager 负责为每个节点分配 Pod 网段;每个 Pod 从 Pod CIDR 获取 1 个唯一的 IP 地址
- Kubelet 与 Container Runtime 交互,运行已调度的 Pod;作为 Container Runtime 一部分的 CRI 插件与 CNI 插件交互,以配置 Pod 网络
- CNI 插件支持使用叠加网络在相同或不同节点上分布的 Pods 之间进行联网
以下是 CNI 插件提供的高级功能:
- Pod 网络
- 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/