简述kubernetes(k8s)

kubernetes(简称k8s):

容器编排平台。对集群(多台机器)上的容器化应用程序进行自动化部署、扩展和管理。可自动更新、自动回滚、自动修复、可自动扩容等,根据声明式API自动完成相应操作。需会Linux命令和docker容器。

官方说明文档:https://kubernetes.io/docs/

kubernetes集群有控制平面(Control Plane)和工作节点(Node)组成。控制平面是集群的大脑,负责全局决策和响应集群事件。工作节点是真正运行容器化工作负载的节点。一个控制平面或一个工作节点就是一个物理机或虚拟机。也有轻量版的单机集群(minikube,k3s,kind等)。

控制平面的组件:

  • kube-apiserver:API server。集群的唯一入口。提供Kubernetes HTTP API(Restful API),与外部交互的接口。认证授权,处理请求,操作etcd。
  • etcd:分布式键值存储系统。存储集群中所有关键数据(状态,配置信息,元数据)。不包括节点中应用程序的数据。
  • kube-scheduler:调度器。将未绑定的pod分配到合适的节点。根据节点资源、调度策略等决策。
  • kube-controller-manager:控制器。持续监测集群状态并自动将集群当前状态向用户期望状态调整。
  • cloud-controller-manager:云服务控制器。与云服务交互的控制器。

节点的组件:

  • kubelet:节点代理。持续监听API server并确保pod健康运行,管理容器的生命周期。
  • kube-proxy:网络代理组件。维护网络规则,允许集群内外部与pod进行通信。
  • container-runtime:容器运行时。负责运行容器(下载镜像,创建容器,启动容器,停止容器等)。

API server:

集群的入口。与用户交互的统一接口,用户可以使用命令行工具(kubectl)和其它UI工具等与API server交互通信。API server接收用户的请求,并处理请求,认证用户身份和权限等。保证了安全和简化了通信。

集群的中心枢纽。其它组件(例如:kube-scheduler, kubelet, kube-control-manager)持续监听API server,执行相应操作并向API server汇报结果(作为客户端向API server发送请求)。例如,kubelet监听API service,监测到pod被调度到本节点,kubelet就会调用容器运行时创建容器,持续关注容器状态,并向API service报告状态。

集群中唯一和etcd交互的组件。存储集群中所有状态的etcd,只能由API server操作(读写etcd中的数据),etcd也是API server唯一主动并直接交互的组件。保证了状态的安全和一致性。

etcd:

集群的数据库,存储集群内所有关键数据(状态、配置数据和元数据)。是分布式键值存储系统,即数据以键值对的形式存储在分布式集群中的数据库系统。

是唯一存储集群内所有资源状态(用户期望状态和当前状态)的组件。也是API server唯一主动并直接交互的组件。API service从etcd查询各资源的状态并更新新的状态,即只有API service可以读写etcd。

若集群宕机,重启时通过API service重新读取etcd的期望状态和当前状态,kube-controller-manager检测真实状态,若真实状态和存储的当前状态严重不符,则会根据期望状态和真实状态的差异,最终将实际运行状态重建到与期望状态一致的水平。

kube-control-manager:

观察当前状态(持续监听API server),分析当前状态与用户期望状态之间的差异,将当前状态朝着期望状态调整,确保当前状态和用户的期望状态保持一致。这种机制称为控制循环。

kube-control-manager是守护进程,运行着多个后台控制器,每个控制器都是一个独立的控制循环。而每个控制器管理着不同的功能,比如节点控制器管理节点的生命周期,监控和处理所有节点的状态。副本控制器管理pod副本数量和副本状态,端点控制器管理service和pod之间的正确关联。部署控制器管理deployment的状态更新,管理部署、滚动更新和回滚。还有命名空间控制器等。

例如:节点控制器(Node Controller)。kubelet检测自身节点的变化,向API service发送相应请求,API service根据请求做相应处理。kubelet也定期检测自身节点的健康状况,并将状态上报给API server。

节点控制器监听API service,关注节点状态以及标注的污点,结合容忍期处理不健康的节点,保证节点持续健康。比如在规定时间内以及等待时间内都没有收到节点的心跳,节点控制器会将节点标识为不健康,在一定时间会给节点添加污点,立即驱逐该节点上无法容忍该污点的pod(删除pod)并在健康的节点重建新的pod。

又例如:Endpoints Controller通过Endpoints对象维护Service和pod之间的关联,Endpoints对象中包含所有匹配pod的ip地址和端口列表。新版本中EndpointSice Controller功能类似但更高效,将大型的Endpoints对象拆分成更小的EndpointSlice对象中。

kube-scheduler:

调度器。确保各节点工作负载均衡,避免某节点过载或闲置。最大化利用集群资源。

持续监听API service,若有新创建的、未绑定的pod,则根据可用资源和调度策略,将pod调度到合适的节点运行。过程:先检查所有节点,排除内存不足或不能容忍节点污点等不合适的节点,再通过打分挑选分数最高的节点,则将pod绑定到该节点。

kubelet:

节点的代理。持续监听API service,执行相关操作并向其汇报状态,检测本节点是否健康并检测pod是否健康,管理节点内的pod生命周期。

检测本节点健康,主要检测节点资源(磁盘、内存、PID、网络等)、依赖服务(容器运行时、CNI网络插件等)。检测有两种:一是按照固定的时间间隔,向API service发送心跳证明自己存活,使用PATCH请求汇报。二是全面检查节点状态,定期向API service汇报状况,主要也是使用PATCH请求汇报。

检测节点内pod健康,通过探针来检测。有三种探针:一是启动探针,二是存活探针,三是就绪探针。启动探针用于启动较慢的应用,此时其他探针都禁用直到启动探针成功完成。存活探针通过HTTP请求、建立TCP连接、在容器内执行命令来检测pod是否存活着,若检测失败表示不存活则kubelet会重启容器。就绪探针也通过HTTP请求、建立TCP连接、在容器内执行命令来检测是否准备好接收流量,若没有准备好则上报给API service,从Service(API对象,不是API service)的Endpoints对象中移除pod,发往该Service的流量将不再路由到该pod。

管理pod生命周期,包括拉取镜像、创建容器、启动容器、停止容器、删除容器等。具体执行由container runtime完成。

container-runtime:

容器运行时。是实际操作容器的组件,即真正执行创建、运行、管理和销毁容器的组件。简言之,kubelet管理容器生命周期,但真正执行操作的是container runtime。附:运行时是指让程序运行所需的环境和引擎。容器运行时通常指高级运行时(包含完整功能的守护进程,负责从镜像拉取、存储管理到最终运行容器的全生命周期管理)。

kubelet通过CRI接口(标准gRPC接口)与容器运行时通信,通过高级运行时containerd或者CRI-O来实现CRI并负责完整的容器管理,高级运行时调用底层运行时runc(遵循OCI标准)执行具体的容器操作。例如:kubelet向containerd发送创建容器(若没有镜像则拉取镜像)并启动容器的命令,containerd拉取镜像、创建容器文件系统并调用runc,runc创建namespaces实现隔离、创建cgroups实现资源限制、启动容器进程。

kube-proxy:

网络代理组件。是实现Service抽象的关键。因为节点故障、滚动更新、扩缩容等原因,pod很容易创建和销毁,pod的IP地址也会随之改变,为了保持集群内部网络稳定,只需知道稳定的Service对象的IP地址或DNS名,而Service对象会负责分发到健康的pod上。

维护网络规则。为当前节点制定流量转发规则,使流量负载均衡到后端的pod。kube-proxy配置iptables/IPVS等底层网络设施来转发流量,不直接处理数据包。iptables模式中数据包完全由内核层iptables处理,但负载均衡算法单一(随机算法)。而Linux内核的IPVS模块专为负载均衡设计,适合大规模集群,但需要节点内核支持。

持续监听API service,若检测到Service对象新建、改变、删除或者Service对象的Endpoints对象发生变化等,kube-proxy立即更新本节点的网络规则。例如:新建Service对象的命令,kube-control-manager中的Endpoints/EndpointSlices-controller检测到新的Service,找到所有匹配的pod,创建同名的Endpoints/EndpointSlices对象,所有节点的kube-proxy检测到Service或ServiceEndpoints/EndpointSlices的创建事件,获取完整路由信息,并在本节点配置相应的iptables/IPVS规则。

简言之,**kube-control-manager中的Endpoints/EndpointSlices-controller维护Service和pod之间的关联,kube-proxy为本节点配置网络规则(流量转发规则),kubelet节点的代理、管理pod生命周期并网络规则的维护(基础网络设置),CNI插件保证底层网络通路的稳定。**而实现这些复杂的协作,除了具有匹配标签的pod,只需要一个声明式的文档--Service。

Service:

Service是一个声明式的文档,是访问pod的稳定抽象方式。

前面介绍过pod很容易销毁和重建,pod的ip地址也会改变,直接绑定pod就很容易出现问题,而Service是解决这种问题的方式。Service给内部其他组件或外部提供稳定的虚拟ip地址、稳定的DNS名和固定的端口,客户只需访问这个稳定的端口,Service就会通过其他组件(Kube-proxy, Endpoints-controller等)的协作自动将流量负载均衡到健康的pod。

Service的声明(YAML文件 )中内容主要包括Service的基础信息 (版本apiVersion、kind为Service、元数据metadata)、pod标签 (spec下的selector,定义需要匹配哪些pod)、端口 (spec下的port,定义如何将接受到的流量转发到pod)、类型(spec下的type,定义Service的暴露范围)等。类型有四种:CluserIP(默认,仅限集群内部)、NodePort(多用于开发、测试等,通过Node的IP和端口访问,默认端口范围30000-32767)、LoaderBalancer(用于云服务)、ExternalName(集群外部访问,例如网址)。其中,当访问集群外部而不是内部pod时则无需定义selector,需在文档内手动创建同名的Endpoints指定外部地址,但若直接使用类型ExternalName,可通过ExternalName指定外部域名。

无selector+手动Endpoints(外部地址) 类型ExternalName(外部域名)
apiVersion: v1 kind: Service metadata: name: external-api-service spec: ports: - port: (Service端口,例如80) targetPort: (外部服务端口,例如8080) apiVersion: v1 kind: Endpoints metadata: name: external-api-service subsets: - addresses: - ip: (外部服务的IP地址) ports: - port: (外部服务端口,与spec:ports:targetPort一致) apiVersion: v1 kind: Service metadata: name: external-db-service spec: type: ExternalName externalName: (外部域名,例如production.example.com)
[集群外部访问的Service举例]

pod:

集群中最小可部署的计算单位。K8S调度的最小单位是pod而不是容器。一般不直接创建pod,而是通过更高级的资源Service或Deployment等来管理pod的声明周期。

一个pod里可以有一个或多个紧密关联的容器。大多数情况下一个pod运行一个容器。而如果是紧密关联的多个容器(应用程序、日志等)也可以在一个pod中,且多容器一起被创建一起被销毁,多容器的主要模式为Sidecar 模式。

pod有完整的生命周期(创建、销毁等)。pod有一个IP地址,但因为pod容易创建和销毁,IP地址会变化。一个pod内的容器共享网络、文件系统、资源等环境。使用标签来标记pod,便于Service中查找合适的pod。

相关推荐
eddy-原2 小时前
云原生分布式系统综合实战:微服务网关、日志监控与对象存储架构
微服务·云原生·架构
飞Link2 小时前
【Wandb】Linux环境下通过Docker部署Wandb教程
运维·docker·容器·数据挖掘
汪碧康2 小时前
【k8s-1.34.2安装部署】十.gateway Api v1.4.0和istio安装
云原生·容器·kubernetes·gateway·istio·cilium·xkube
幺零九零零4 小时前
Docker底层-User Namespace
运维·docker·容器
原神启动14 小时前
Docker 构建前后端项目Ruo-Yi
运维·docker·容器
叽里咕噜怪13 小时前
docker-compose 编排ruoy实践
运维·docker·容器
深耕AI17 小时前
【Docker命令】以LocalAI部署为例
运维·docker·容器
深耕AI17 小时前
如何深入理解 `docker ps` 输出:从容器健康状态变化说起
docker·容器·rpc