K8S概述
什么是K8S?
Kubernetes是一个可移植、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。名字源于希腊语,意味”舵手”
k8s出现的必要性
按照部署的方式来进行划分,我们可以简单的划分成四个时代
传统部署时代
如图一一样,APP部署在OS上,OS跑在硬件上。这会导致一个问题,如果在同一台机器上运行多个应用程序,如果某一个APP占用了机器的大部分资源,那么就会影响到其他APP,造成性能抖动甚至饿死的严重后果
虚拟化部署时代
为了解决上述问题,虚拟化技术被引进了,虚拟化技术允许你在单个物理服务器的CPU上运行多台虚拟机(VM)。虚拟化能使应用程序在不通过的VM之间被彼此隔离,且能提供一定程度的安全性,因为一个应用程序的信息不能被另一应用程序随意访问。
虚拟化技术能够更好地利用物理服务器的资源,并且可以更加轻松地添加、更新应用程序,因此具有更强的可扩缩性,以及降低硬件成本等等的好处
容器部署时代
容器类似于VM,但是相比于VMWare生成的那种VM,容器更加轻量级,并且与VM类似,每个容器都具有自己的文件系统、CPU、内存、进程空间等等,容器之间可以共享OS。容器和基础架构是分离的,因此可以跨云和OS发行版进行移植
容器的优势
- 敏捷应用程序的创建和部署:相比于VM镜像更加简便,提高了容器镜像创建的简便性和效率
- 持续开发、集成和部署:基于镜像不可变性,通过快速简单的回滚,提供可靠且频繁的容器镜像构建和部署
- 关注开发和运维的分离:在构建、发布时创建镜像,而不是部署的时候,从而将应用与基础架构进行分离
- 可观察性:不仅可以显示OS级别的信息和指标,还能够显示应用程序的运行状态、其他指标信号
- 跨开发、测试和生产的环境一致性:在开发物理机上也可以和在云中运行一样的应用程序
- 跨云和操作系统发行版本的可移植性:可在任意环境运行
- 松耦合、分布式、弹性:一个大的单体被分解成较小的服务,并且可以动态的管理和部署,而不是在一台大型单机上整体运行
- 资源隔离:可预测的应用程序性能
- 资源利用:高效率和高密度
K8S能做什么
上文我们说到,容器是打包和运行应用程序的很好的一种方式,而在生产环境中,我们需要对很多容器(容器的集群)进行管理,保证服务不会出故障、确保服务的可靠性,稳定性。
例如一个容器发生故障,则需要把这个容器下掉,新增一个运行该服务的容器,再把它上线。而K8S就是帮助我们实现这个过程,简化操作流程的工具
K8S的功能
- 服务发现与负载均衡:K8S可以使用DNS、或者自己的IP来暴露容器,如果进入容器的流量很大,K8S通过Kube-Proxy来实现的负载均衡,可支持的负载均衡算法有(轮询、最少链接、IP哈希),默认为轮询,通过负载均衡来分配网络流量,从而使部署更加稳定
- 存储编排:K8S允许自动挂载你选择的存储系统,例如本地存储、公共云提供商等
- 自动部署和回滚:可以使用K8S描述已部署容器的所需状态,并控制状态更改的速率
- 自动完成装箱计算:当K8S拥有许多节点组成一个集群之后,在这个集群上运行容器化的任务时,可以告知K8S每个容器需要多少资源(CPU 内存等),K8S可以将这些容器按实际情况调度到节点上,以最佳方式利用分配的资源
- 自我修复:K8S将重新启动失败的容器、替换容器、杀死不响应用户定义的健康检查的容器,并且在准备好服务之前不将其通告给客户端
- 密钥与配置管理:K8S允许你存储和管理敏感信息,例如密码、OAuth令牌和SSH密钥,可以在不重建容器镜像的情况下部署和更新密钥以及应用程序配置,也无需在堆栈配置中暴露密钥
K8S组件
上述是K8S运行的架构流程图,我们可以看得出来,一个K8S集群主要由两部分组成,分别是Control Plane
控制平面,老版本也叫做Master;Node
工作节点,老版本也叫做Worker Node
我们将一组工作机器称为节点,节点会运行容器化应用程序,每个集群至少有一个工作节点。工作节点会托管Pod,控制平面管理集群中的工作节点与Pod
整体的一个典型的工作流程如下:
- 用户使用K8S API与API服务器交互,发布应用程序的描述(如Pod Service等)
- 调度器根据应用程序的要求选择合适的节点,并将任务指派给节点上的Kubelet
- Kubelet根据指令在节点上创建和管理容器,确保它们的状态与期望的状态
控制平面组件
控制平面组件会为集群做出全体决策,比如资源的调度,以及检测和响应集群事件。可以理解成K8S集群的大脑,负责管理和控制整个集群的行为。
控制平面组件可以在集群中的任何节点上运行,通常来说为了简单起见,只会在同一个计算机上启动所有的控制平面组件,并且不会在这台机器上运行任何容器
**kube-apiserver **
API服务器是K8S控制平面的组件之一,提供了与K8S集群通信的接口,允许用户和其他组件通过HTTP RESTful API与K8S进行交互,这个组件负责公开K8S API,负责处理接受请求的工作,验证并配置API对象的数据,这些对象包括pods services replicationcontrollers等,为REST操作提供服务,可以将它简单理解为K8S控制平面的前端,其他所有组件都通过该前端进行交互。
同时,API SERVER还负责验证请求的身份和权限,通过Token UserName/Password TLS证书等进行确认和交互,验证用户或者组件的身份,一旦用户验证成功,API Server会使用访问控制策略进行角色授权
并且它负责资源管理,维护一组持久化存储(etcd)来存储资源的配置、状态和元数据
它还负责记录集群中的事件和日志信息,当资源对象发生变化或者出现错误的时候,它会生成事件并将其发送给订阅者
etcd
它是一个分布式的一致且高可用的键值存储,用作k8s所有集群数据的后台数据库,存储集群的配置数据、元数据和状态信息的可靠持久化存储。etcd提供了高可用性、一致性和分布式的特性,为K8S的控制平面组件提供了一个共享的数据存储,API Server、kube scheduler 和 CM 等组件通过使用etcd来存储和检索集群的配置信息、资源对象的状态以及各种元数据,这些信息包括Pod Service Namespace PersistentVolume等的定义和状态
etcd的一些关键功能
- 分布式存储:etcd使用Raft一致性算法来实现数据的分布式存储,它将数据分片并复制到集群中的多个节点上,确保数据的可用性和容错性,这意味着即使一些节点失效,集群应该可以继续正常工作
- 一致性:etcd的Raft算法保证了数据的一致性,所有的写操作都需要经过多数节点的确认,确保数据的正确复制和同步,这样可以避免数据损坏和不一致的情况发生
- 高可用性:etcd具有高可用性,通过在集群中的多个节点上复制数据,提供了容错能力
- 快速读写:etcd通过在内存中保持数据的副本,实现了快速的读写操作,使用B+树作为底层数据结构,提供高效的索引和检索功能
- 监控和故障恢复:etcd提供了一些监控和故障恢复机制,可以监测节点的状态和健康状况。当节点发生故障或变得不可用时,集群可以自动进行重新选举,选择新的领导者节点来接管工作
**kube-scheduler **
负责监视新创建的、未指定运行节点(node)的Pods,并选择节点来让Pod运行在该节点上,以实现负载均衡、资源利用率最大化和高可用性
调度决策考虑的因素包括:单个Pod及Pods集合的资源需求、软硬件及策略约束、亲和性及反亲和性规范、数据位置、工作负载间的干扰及最后时限
scheduler的主要功能如下
- 资源调度:scheduler根据容器的资源需求(如CPU 内存)和节点的资源利用率,决定将工作负载调度到哪个节点上运行
- 节点选择:scheduler根据工作负载的要求,选择适合的节点进行调度,通过筛选和评分机制来选择节点,同时scheduler还考虑亲和性规则,以便将相关的工作负载调度到同一节点上,提高应用程序的性能和效率
- 拓展性和灵活性:scheduler具有可插拔的架构,允许用户根据自己的需求自定义和拓展调度算法,用户可以实现自定义的调度策略,通过调整评分函数和优先级规则来满足特定的业务需求
- 调度器扩展:k8s提供了灵活的调度器扩展机制,允许用户添加额外的带哦赌气,这些调度器可以根据特定的需求和场景来实现自定义的调度逻辑
工作流程如下:
- 用户创建或者更新一个工作负载的描述,例如Deployment StatefulSet等
- 当新的工作负载被提交时,Scheduler接收到这个事件,并根据工作负载的需求和集群状态进行调度决策
- Scheduler遍历集群中的可用节点,评估每个节点的适合程度,并为每个节点打分
- Schedulergenuine打分结果选择最合适的节点,并将工作负载的调度决策通知给相应的节点的Kubelet
- Kubelet在选择的节点上启动和管理容器,并把容器的状态报告给控制平面
kube-controller-manager(cm)
负责运行控制器进程,理论上来说每个控制器都是一个独立的进程,但是为了降低复杂性,它们都被编译到一个可执行文件中,并且在同一个进程中运行。
这些控制器包括
- 节点控制器(Node Controller):负责在节点出现故障时进行通知和响应
- 任务控制器(Job Controller):监测代表一次性任务的JOB对象,然后创建Pods来运行这些任务直至完成
- 端点分片控制器(EndpointSlice controller):填充端点分片对象,以提供给Service和Pod之间的链接
- 服务账号控制器(ServiceAccount controller):为新的命名空间创建默认的服务账号
工作流程如下:
- CM启动时,它的各个控制器开始监视集群中的特定资源对象
- 控制器通过API Server获取资源对象的当前状态,并将其与所需要的期望状态进行对比
- 如果二者不一致,那么控制器会触发相应的操作来使它们保持一致,这可能包括创建、更新或者删除资源对象
- 控制器通过API Server发出相应的操作请求,将更改应用于集群中的资源对象
- 控制器不断循环执行,以确保资源对象的状态和行为与期望状态保持一致
**cloud-controller-manager(ccm) **
嵌入了特定的云平台控制逻辑,云控制器管理器允许将你的集群连接到云提供商的API之上,并将与该云平台交互的组件同你的集群交互的组件分离开来。
与cm类似,ccm将若干逻辑上独立的控制回路组合到同一个可执行文件中,供你以同一进程的方式运行。你可以对其执行水平扩容以提升性能或者增强容错能力。
- 节点控制器(Node Controller): 用于在节点终止响应后检察云提供商以确定节点是否已被删除
- 路由控制器(Route Controller):用于在底层云基础架构中设置路由
- 服务控制器(Service Controller):用于创建、更新和删除云提供商负载均衡器
工作流程如下:
- CCM组件在启动的时候与云平台的API进行认证和链接,并监视云资源对象的状态
- CCM的控制器通过与云平台的API进行交互,获取云平台资源对象的状态,并将其与K8S中的对象进行比较
- 如果二者状态不一致,CCM的控制器会触发相应的操作,通过与云平台的API发出请求,将更改应用于云资源
工作节点组件
节点组件会在每个节点上运行,负责维护运行的pod并提供K8S运行环境
**kubelet **
kubelet会在集群中每个节点(node)上运行,它保证容器(containers)都运行在Pod中。
kubelet接收一组通过各类机制提供给它的PodSpecs,确保这些PodSpecs中描述的容器处于运行状态且健康,kubelet不会管理不是由k8s创建的容器,kubelet是k8s集群中的每个node上的主要组件之一,负责管理节点上的容器化工作负载,与控制平面交互,确保集群中的容器正确运行,并且维护节点的健康状态
主要功能:
- 容器管理:kubelet负责在节点上创建、启动、停止和销毁容器,它通过与容器运行时(Docker Containerd)进行交互,执行容器的生命周期管理操作
- 资源管理:Kubelet监控节点的资源使用情况,并根据预定义的资源配额和调度策略来分配资源给容器,它会定期向K8S控制平面报告节点上的资源状态
- 健康检查:Kubelet定期对节点上的容器进行健康检查,包括容器的存活状态、资源利用率等,如果容器故障或者资源不足,Kubelet会尝试重启、恢复或迁移容器
- 节点注册:Kubelet在节点启动时将自身注册到K8s控制平面,使控制平面能够管理和监控该节点上的容器化工作负载
- 网络管理:Kubelet配置节点上的网络参数,包括容器网络和节点网络。它为容器分配IP地址,并配置容器之间和容器与外部的网络通信
- 卷管理:Kubelet负责挂在和卸载容器中使用的持久卷,它与卷插件交互,使容器能访问和使用持久化存储
- 日志和监控:Kubelet收集和管理节点上容器的日志和监控数据,它可以将日志发送到集中式日志系统,并提供容器的运行指标和事件信息
工作流程如下:
- Kubelet监听来自K8S控制平面的指令和命令
- K8S获取需要在节点上运行的pod列表,并根据指定的pod规范创建和管理容器
- 对于每个容器,Kubelet通过容器运行时(如Docker)来启动和停止容器,并监控其状态
- Kubelet定期向K8s控制平面报告节点的资源使用情况和容器状态
- Kubelet定期凑够控制平面获取Pod的更新和变更,并相应地执行容器的生命周期管理操作
kube-proxy
kube-proxy是集群中每个节点(node)上所运行的网络代理,实现k8s概念的一部分,它维护节点上的一些网络规则,这些网络规则会允许从集群内部或外部的网络会话与Pod进行网络通信。运行在每个节点上,并与K8S控制平面和节点上的网络组件进行交互,以实现服务的可访问性和网络流量的转发
如果操作系统提供了可用的数据包过滤层,则kube-proxy会通过它来实现网络规则,否则,kube-proxy只做流量转发
主要功能:
- 服务代理:Kube-proxy监听K8S控制平面中的服务和短空定义,并为它们创建对应的网络代理规则,这些规则通常基于IP Tables或者IPVS,根据服务的选择器和端口信息,将流量转发到相应的后端pod
- 负载均衡:Kube-proxy实现了负载均衡功能,将来自集群内部和外部的网络请求均匀地分发到后端的Pod。它可以基于轮询、随机选择或最少连接等算法来进行负载均衡
- 服务发现:Kube-proxy监听K8S控制平面中国的服务和端口定义的变化,当服务的Pod副本数量发生变化、服务的标签或者端口信息发生变更时,Kube-proxy会相应地更新代理规则,以确保服务的访问正常
- 节点故障处理:Kube-proxy监测节点的健康状态,并在节点故障或网络中断的情况下自动更新代理规则,它会将流量重新路由到其他健康节点上的Pod,以保证服务的高可用性
- 透明代理:Kube-proxy支持透明代理模式,可以在不修改应用程序代码的情况下,将应用程序流量转发到后端Pod。这种方式对应用程序是透明的,它们无需感知代理的存在
Kube-proxy的工作流程如下:
- Kube-proxy从K8S控制平面获取服务和端口定义,并为每个服务创建代理规则
- 当有新的服务或端口定义添加到集群中,或者现有的定义发生变化时,Kube-proxy监测到变化并相应地更新代理规则
- Kube-proxy监听来自服务暴露的端口上的网络流量
- 根据代理规则,Kube-proxy将流量转发到后端Pod上的容器,实现负载均衡和服务发现的功能
Container Runtime 容器运行时
容器运行环境是负责运行容器的软件,K8S支持许多容器运行环境,例如containerd CRI-O 以及K8S CRI的其他任何实现
Container Runtime(容器运行时)是 Kubernetes 中负责管理和运行容器的核心组件。它提供了创建、启动、停止和销毁容器的功能,以及管理容器的资源和隔离性。
Kubernetes 支持多种容器运行时,其中最常用的是 Docker 和 Containerd。下面将详细介绍容器运行时的工作原理和功能:
- 容器生命周期管理:容器运行时负责与容器生命周期相关的操作。它可以根据容器镜像创建并启动容器,监控容器的运行状态,并在需要时停止或销毁容器。
- 容器隔离性:容器运行时使用 Linux 内核的命名空间和控制组(cgroup)等特性,为容器提供隔离的运行环境。每个容器都具有独立的文件系统、网络栈、进程空间和资源限制,从而实现容器之间的隔离和安全性。
- 容器网络:容器运行时负责设置和管理容器的网络。它为每个容器分配唯一的 IP 地址,并处理容器之间的网络通信。容器运行时还可以与网络插件协同工作,以实现更高级的网络功能,如跨主机的容器通信和负载均衡。
- 容器存储:容器运行时管理容器的存储。它可以为容器提供本地存储卷或挂载外部存储卷,使容器能够持久化存储和访问数据。
- 容器镜像管理:容器运行时负责下载、管理和缓存容器镜像。它可以从容器镜像仓库中拉取镜像,并将其存储在本地节点上,以便在需要时快速创建容器。
- 容器资源管理:容器运行时与 Kubernetes 的调度器和资源管理器交互,以确保容器在节点上得到适当的资源分配。它可以根据容器的资源需求和节点的可用资源进行调度和限制,以实现资源的公平分配和利用。
容器运行时在 Kubernetes 中的工作流程如下:
- Kubernetes 控制平面下发容器启动的指令,包括容器镜像、资源要求等信息。
- 容器运行时根据指令从容器镜像仓库拉取镜像,并创建容器的运行时环境。
- 容器运行时使用 Linux 命名空间和控制组等功能,为容器提供隔离的运行环境。
- 容器运行时启动容器中的应用程序,并监控容器的运行状态。
- 容器运行时与容器网络 插件协同工作,为容器分配 IP 地址,并处理容器之间的网络通信。
- 容器运行时根据 Kubernetes 控制平面的指令,停止或销毁容器。
总之,容器运行时是 Kubernetes 中关键的组件之一,它负责管理和运行容器,提供容器的隔离性、生命周期管理、网络和存储功能,与其他 Kubernetes 组件协同工作,实现容器化应用程序的高效运行和管理。
node、kubelet、pod和container之间的联系
Node:是K8S集群中的工作节点,也被称为主机或者服务器,每个Node提供容器运行的基础设施,并承载运行着的容器
Kubelet:是运行在每个Node上的K8S组件之一,是Node上的代理程序,Kubelet负责管理和运行Node上的容器,并与K8S控制平面交互
Pod:Pod是K8S的最小调度和部署单元,它是一个逻辑上相关的容器组,可以包含一个或者多个容器,Pod提供了一个抽象层,为容器提供共享的网络和存储资源,使容器之间可以进行通信和共享数据,Pod是在Node上进行调度和运行的
Container:容器是在Pod中运行的实际应用程序或服务,一个Pod可以包含一个或者多个容器,这些容器共享同一个网络命名空间和存储卷,容器被kubelet创建、启动、停止和销毁
通过这种方式,kubelet作为Node上的代理程序,负责与Kubernetes控制平面交互,并协调管理Node上的容器。Pod是在Node上调度和运行的最小单元,它可以包含一个或多个容器,这些容器共享同一个网络和存储环境。这种关系使得kubernetes可以以分布式和高可用的方式运行和管理容器化应用程序。