上一章 对k8s理论做了一些说明,为了更透彻讲述k8s 的工作过程,本章将详细阐述 k8s 的数据流向 与 核心概念供君参考。
一 k8s 数据流向
1,超级详细版
1.首先Kubectl通过Auth认证,访问到Master节点的APIserver。
2.APIserver会先将访问数据发送给ETCD存储,相当于将Kubectl发送的请求,例如创建服务的指令形成一个类似与模板的数据,进行存储
3.ETCD会将请求重新发送给APIserver
4.APIserver会先调用controller-manager组件去执行ETCD模板请求,类似与生成一条指令,但是它没有执行的目标
5.controller-manager组件并不能直接在Node节点上创建服务,它会将类似于执行命令的数据发送给APIserver
6.APIserver再将该数据发送到ETCD,ETCD会记录操作请求,而后会将指令需求发送给scheduler组件
7.scheduler组件会kubelet监控,并发送给APIserver的节点信息,而后根据预选、优选策略去选择合适的节点去执行指令,但是它也无法直接将指令发送给kubelet,而是将指令发送给APIserver
8.APIserver将指令发送给kubelet
9.kubelet会在每一个node节点上执行,它将APIserver发送的指令在其所在的node节点上执行,同时它还会负责监控所在节点的Pod实例状态,管理所有Pod实例的生命周期。在执行完指令后,会将执行记录返回给APIserver,APIserver会将记录存储在ETCD当中。并负责与master进行通信。
10.此时用户访问服务,会通过kube-proxy来访问pod实例
注释:
①所有的执行操作与访问数据,都会记录到ETCD当中
②master组件之间并不会互相进行通信与调用,所有的操作都会通过APIserver进行调用执行
2,核心主键及含义
- apiserver:接入的唯一入口,集群的大脑,负责所有操作的读写,增删改查
- kube-comtroller-manager:增删改查,创建pod的资源模板,一个资源一个控制器,资源控制器,任务控制
- kube-scheduler:调度器,根据模板初选节点pod,以实现最优资源利用
- kubelet:API小弟,节点代理,监视 管理 反馈管理节点上容器和资源,接收指令跟容器引擎交互实现容器生命周期管理
- kube-proxy:为pod提供网络代理和负载均衡,负责写入规则到iptables或ipvs实现服务映射和访问容器
- ETCD:分布式键值对存储重要信息,并持久化
3,K8S 创建Pod 流程
kubectl 创建一个Pod(在提交时,转化为json格式)
- 首先经过auth认证(鉴权),然后传递给api-server进行处理
- api-server 将请求信息提交给etcd
- scheduler和controller-manager 会watch(监听) api-server ,监听请求
- 在scheduler 和controller-manager监听到请求后,scheduler 会提交给api-server一个list清单——》包含的是获取node节点信息
- 此时api-server就会向etcd获取后端node节点信息,获取到后,被scheduler watch到,然后进行预选优选进行打分,最后将结果给与api-server
- 此时api-server也会被controller-manager watch(监听) controller-manager会根据请求创建Pod的配置信息(需求什么控制器)将控制器资源给与api-server
- 此时api-server 会提交list清单给与对应节点的kubelet(代理)
- kubelet代理通过K8S与容器的接口(例如containerd)进行交互,假设是docker容器,那么此时kubelet就会通过dockershim 以及runc接口与docker的守护进程docker-server进行交互,来创建对应的容器,再生成对应的Pod
- kubelet 同时会借助于metrics server 收集本节点的所有状态信息,然后再提交给api-server
- 最后api-server会提交list清单给与etcd来存储(最后api-server会将数据维护在etcd中)
4,用户访问流程
- 假设用户需创建 nginx资源(网站/调度)kubectl ——》auth ——》api-server
- 基于yaml 文件的 kubectl create run / apply -f nginx.yaml(pod 一些属性,pod )
- 请求发送至master 首先需要经过apiserver(资源控制请求的唯一入口)
- apiserver 接收到请求后首先会先记载在Etcd中
- Etcd的数据库根据controllers manager(控制器) 查看创建的资源状态(有无状态化)
- 通过controllers 触发 scheduler (调度器)
- scheduler 通过验证算法() 验证架构中的nodes节点,筛选出最适合创建该资源,接着分配给这个节点进行创建
- node节点中的kubelet 负责执行master给与的资源请求,根据不同指令,执行不同操作
- 对外提供服务则由kube-proxy开设对应的规则(代理)
- container 容器开始运行(runtime 生命周期开始计算)
- 外界用户进行访问时,需要经过kube-proxy -》service 访问到container (四层)
- 如果container 因故障而被销毁了,master节点的controllers 会再次通过scheduler 资源调度通过kubelet再次创建容器,恢复基本条件限制(控制器,维护pod状态、保证期望值-副本数量)
- pod ——》ip 进行更改——》service 定义统一入口(固定被访问的ip:端口)
二 Kubernetes 核心概念
Kubernetes 包含多种类型的资源对象:Pod、Label、Service、Replication Controller 等。
所有的资源对象都可以通过 Kubernetes 提供的 kubectl 工具进行增、删、改、查等操作,并将其保存在 etcd 中持久化存储。
Kubernets其实是一个高度自动化的资源控制系统,通过跟踪对比etcd存储里保存的资源期望状态与当前环境中的实际资源状态的差异,来实现自动控制和自动纠错等高级功能。
1,Pod
1.1 Pod 是什么
Pod是 Kubernetes 创建或部署的最小/最简单的基本单位,一个 Pod 代表集群上正在运行的一个进程。
可以把 Pod 理解成豌豆荚,而同一 Pod 内的每个容器是一颗颗豌豆。
1.2 pod 与容器的关系
一个 Pod 由一个或多个容器组成,Pod 中容器共享网络、存储和计算资源,在同一台 Docker 主机上运行。
一个 Pod 里可以运行多个容器,又叫边车模式(SideCar)。而在生产环境中一般都是单个容器或者具有强关联互补的多个容器组成一个 Pod。
互联: 收集日志 nginx 和filebeat
边车:小日子的载人摩托车
1.3 pod中容器 的通信
同一个 Pod 之间的容器可以通过 localhost 互相访问,并且可以挂载 Pod 内所有的数据卷;但是不同的 Pod 之间的容器不能用 localhost 访问,也不能挂载其他 Pod 的数据卷。
2, Pod 控制器
Pod 控制器是 Pod 启动的一种模版,用来保证在K8S里启动的 Pod 应始终按照用户的预期运行(副本数、生命周期、健康状态检查等)。
K8S 内提供了众多的 Pod 控制器,常用的有以下几种:
2.1 Deployment
无状态应用部署。Deployment 的作用是管理和控制 Pod 和 ReplicaSet,管控它们运行在用户期望的状态中。
无状态:
你访问得页面 没有提供任何的保存数据 和提供其他的应用
类似百度 主页
有状态:
每天有数据变化
2.2 Replicaset
2.21 Replicaset 是什么
确保预期的 Pod 副本数量。ReplicaSet 的作用就是管理和控制 Pod,管控他们好好干活。但是,ReplicaSet 受控于 Deployment。
可以理解成 Deployment 就是总包工头,主要负责监督底下的工人 Pod 干活,确保每时每刻有用户要求数量的 Pod 在工作。如果一旦发现某个工人 Pod 不行了,就赶紧新拉一个 Pod 过来替换它。而ReplicaSet 就是总包工头手下的小包工头。
从 K8S 使用者角度来看,用户会直接操作 Deployment 部署服务,而当 Deployment 被部署的时候,K8S 会自动生成要求的 ReplicaSet 和 Pod。用户只需要关心 Deployment 而不操心 ReplicaSet。
资源对象 Replication Controller 是 ReplicaSet 的前身,官方推荐用 Deployment 取代 Replication Controller 来部署服务。
2.22 Replicaset 和 Deployment 关系
Deployment 控制ReplicaSet 让Pod 运行在用户期望的状态中
2.3 Daemonset
确保所有节点运行同一类 Pod,保证每个节点上都有一个此类 Pod 运行,通常用于实现系统级后台任务。
它的主要用途是部署和管理那些需要在每个节点上作为后台服务运行的应用,比如日志收集、监控代理、网络配置或者安全软件等。
2.4 Statefulset
有状态应用部署
有状态:
每天有数据变化
2.5 job
一次性任务。根据用户的设置,Job 管理的 Pod 把任务成功完成就自动退出了
2.6 Cronjob
周期性计划性任务
3, Label 标签
3.1 Label 作用
标签,是 K8S 特色的管理方式,便于分类管理资源对象。
Label 可以附加到各种资源对象上,例如 Node、Pod、Service、RC 等,用于关联对象、查询和筛选。
一个 Label 是一个 key-value 的键值对,其中 key 与 value 由用户自己指定。
一个资源对象可以定义任意数量的Label,同一个Label 也可以被添加到任意数量的资源对象中,也可以在对象创建后动态添加或者删除。
可以通过给指定的资源对象捆绑一个或多个不同的 Label,来实现多维度的资源分组管理功能。
3.2 Label 格式
Label有效的标签值必须为63个字符或更少,并且必须为空或以字母数字字符([a-z0-9A-Z])开头和结尾,中间可以包含横杠(-)、下划线(_)、点(.)和字母或数字。
与 Label 类似的,还有 Annotation(注释)。注释值则没有字符长度限制。
4, Label 选择器(Label selector)
给某个资源对象定义一个 Label,就相当于给它打了一个标签;随后可以通过标签选择器(Label selector)查询和筛选拥有某些 Label 的资源对象。
标签选择器目前有两种:基于等值关系(等于、不等于)和基于集合关系(属于、不属于、存在)。
5, Service
理解为 四层网络代理
5.1 Service概念
在K8S的集群里,虽然每个Pod会被分配一个单独的IP地址,但由于Pod是有生命周期的(它们可以被创建,而且销毁之后不会再启动),随时可能会因为业务的变更,导致这个 IP 地址也会随着 Pod 的销毁而消失。
Service 就是用来解决这个问题的核心概念。
K8S 中的 Service 并不是我们常说的“服务”的含义,而更像是网关层,可以看作一组提供相同服务的Pod的对外访问接口、流量均衡器。
Service 作用于哪些 Pod 是通过标签选择器来定义的。
5.2 Service 功能其一
在 K8S 集群中,Service 可以看作一组提供相同服务的 Pod 的对外访问接口。客户端需要访问的服务就是 Service 对象。每个 Service 都有一个固定的虚拟 ip(这个 ip 也被称为 Cluster IP),自动并且动态地绑定后端的 Pod,所有的网络请求直接访问 Service 的虚拟 ip,Service 会自动向后端做转发。
5.3 Service 功能其二
Service 除了提供稳定的对外访问方式之外,还能起到负载均衡(Load Balance)的功能,自动把请求流量分布到后端所有的服务上,Service 可以做到对客户透明地进行水平扩展(scale)。
而实现 service 这一功能的关键,就是 kube-proxy。kube-proxy 运行在每个节点上,监听 API Server 中服务对象的变化, 可通过以下三种流量调度模式: userspace(废弃)、iptables(濒临废弃)、ipvs(推荐,性能最好)来实现网络的转发。
#
#iptables 是从上而下 高并发 承受不注 ipvs 直接转发
IPVS(IP Virtual Server)是Linux内核中实现的高效网络负载均衡技术。它作为Netfilter框架的一部分,专为大规模、高性能的负载均衡场景设计。IPVS主要用于将客户端请求智能地分发到后端的一组服务器上,以此来提升服务的可用性和扩展性。以下是IPVS的一些关键特性:
- 高性能: IPVS利用哈希表(hash table)来存储和快速查找规则,这使得它在处理大量并发连接和规则时比iptables更加高效。哈希表的使用减少了查找时间,提高了数据包的转发速度,特别适合大规模服务集群。
- 负载均衡算法: IPVS支持多种负载均衡算法,包括轮询(Round Robin)、最少连接(Least Connections)、加权轮询、加权最少连接、局部性导向的最少连接(Locality-based Least Connections)等,可以根据实际需求选择最合适的负载分发策略。
- 服务器健康检查: IPVS能够定期检查后端服务器的健康状态,自动将请求从故障服务器上移除,确保客户端请求总是被转发到活跃的服务实例上。
- 连接重试与会话保持: IPVS可以处理连接重试,并且支持会话保持(Session Persistence),确保来自同一客户端的请求尽可能被发送到同一服务器,这对于维持会话状态或优化数据库交互等场景非常关键。
- 透明性与灵活性: IPVS可以在网络层(Layer 3)和传输层(Layer 4)上工作,支持TCP、UDP协议,且对用户透明,无需修改客户端或服务器应用程序。
- 可扩展性: 由于其高效的实现和内核级的支持,IPVS能够轻松处理数以万计的并发连接,支持大规模服务部署。
在Kubernetes中,从1.8版本开始引入了对IPVS模式的支持,作为kube-proxy的一种实现方式,用以替代或补充iptables,以提高服务发现和负载均衡的性能,尤其是在大规模集群环境下。
5.4 Service 优势
Service 是 K8S 服务的核心,屏蔽了服务细节,统一对外暴露服务接口,真正做到了“微服务”。比如我们的一个服务 A,部署了 3 个副本,也就是 3 个 Pod; 对于用户来说,只需要关注一个 Service 的入口就可以,而不需要操心究竟应该请求哪一个 Pod。
优势非常明显:一方面外部用户不需要感知因为 Pod 上服务的意外崩溃、K8S 重新拉起 Pod 而造成的 IP 变更, 外部用户也不需要感知因升级、变更服务带来的 Pod 替换而造成的 IP 变化。
6, Ingress
Service 主要负责 K8S 集群内部的网络拓扑,那么集群外部怎么访问集群内部呢?这个时候就需要 Ingress 了。Ingress 是整个 K8S 集群的接入层,负责集群内外通讯。
Ingress 是 K8S 集群里工作在 OSI 网络参考模型下,第7层的应用,对外暴露的接囗,典型的访问方式是 http/https。
Service 只能进行第四层的流量调度,表现形式是 ip+port。Ingress 则可以调度不同业务域、不同URL访问路径的业务流量。
比如:客户端请求 http://www.kgc.com:port ---> Ingress ---> Service ---> Pod
7, Ingress 与 service
7.1 外部访问 数据流向
当有请求 到 app:nginx 标签 的流向
不会到 第三个 pod 因为没有标签
一个标签对应 一个集群ip(让别人访问) 也相当于一个负载均衡器
7.2 Ingress 与 service 区别
在Kubernetes(K8s)中,Service
和 Ingress
都是用于处理网络流量和对外暴露服务的重要资源,但它们的作用层次和应用场景有所不同:
Service
- 目的:Service 主要用于定义如何访问在Pod中运行的多个副本(实例),提供一种抽象层,使得服务的消费者不需要直接了解后端Pods的细节,如IP地址或端口号的变化。它为Pods提供了一个稳定的服务访问入口。
- 功能:实现负载均衡,自动分发请求到后端Pods,支持服务发现,以及定义不同类型的访问方式(ClusterIP, NodePort, LoadBalancer, ExternalName)。
- 范围:主要关注于集群内部的服务发现和通信,尽管LoadBalancer和NodePort类型可以让服务从集群外部访问,但其主要设计目的是为了集群内的服务调用。
Ingress
- 目的:Ingress 是更高级的网络抽象层,用于管理进入集群的外部HTTP和HTTPS流量。它定义了外部访问集群内服务的规则,比如基于URL路径或主机名将流量路由到不同的Services。
- 功能:提供七层(应用层)的路由,可以根据HTTP请求的Host头或路径将流量路由到不同的Service,支持TLS终止(即SSL卸载),以及更复杂的路由规则配置。
- 范围:侧重于外部流量管理,尤其是Web流量。Ingress资源本身不实现路由逻辑,而是由Ingress Controller(如Nginx Ingress Controller、Traefik等)来实际执行路由和负载均衡策略。
区别总结
- 层次不同:Service工作在第四层(传输层,TCP/UDP),主要关注于服务间通信;而Ingress工作在第七层(应用层,HTTP/HTTPS),关注于外部到集群的HTTP(S)流量路由。
- 作用域不同:Service主要是内部或有限度的外部访问控制,而Ingress专门用于处理外部用户到集群服务的访问请求,提供更精细的入口流量管理。
- 实现方式:Service依赖于kube-proxy进行服务发现和负载均衡;而Ingress需要一个独立的Ingress Controller来解读Ingress规则并实施路由策略。
8, Name
由于 K8S 内部,使用 “资源” 来定义每一种逻辑概念(功能),所以每种 “资源”,都应该有自己的 “名称”。
“资源” 有 api 版本(apiversion)、类别(kind)、元数据(metadata)、定义清单(spec)、状态(status)等配置信息。
“名称” 通常定义在 “资源” 的 “元数据” 信息里。在同一个 namespace 空间中必须是唯一的。
9, Namespace
隔离技术
随着项目增多、人员增加、集群规模的扩大,需要一种能够逻辑上隔离 K8S 内各种 “资源” 的方法,这就是 Namespace。
Namespace 是为了把一个 K8S 集群划分为若干个资源不可共享的虚拟集群组而诞生的。
不同 Namespace 内的 “资源” 名称可以相同,相同 Namespace 内的同种 “资源”,“名称” 不能相同。
合理的使用 K8S 的 Namespace,可以使得集群管理员能够更好的对交付到 K8S 里的服务进行分类管理和浏览。
K8S 里默认存在的 Namespace 有:default、kube-system、kube-public 等。
查询 K8S 里特定 “资源” 要带上相应的 Namespace。
三 常见的K8S按照部署方式
●Minikube
Minikube是一个工具,可以在本地快速运行一个单节点微型K8S,仅用于学习、预览K8S的一些特性使用。
部署地址:https://kubernetes.io/docs/setup/minikube
●Kubeadmin
Kubeadmin也是一个工具,提供kubeadm init和kubeadm join,用于快速部署K8S集群,相对简单。
https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/
●二进制安装部署
生产首选,从官方下载发行版的二进制包,手动部署每个组件和自签TLS证书,组成K8S集群,新手推荐。
https://github.com/kubernetes/kubernetes/releases
小结:Kubeadm降低部署门槛,但屏蔽了很多细节,遇到问题很难排查。如果想更容易可控,推荐使用二进制包部署Kubernetes集群,虽然手动部署麻烦点,期间可以学习很多工作原理,也利于后期维护。