k8s的学习思考
2024-04-25 11:31:24 17 举报
AI智能生成
具体内容主要描述了k8s master里面中的主要组件 和service的简单描述
作者其他创作
大纲/内容
Service
主要作用:kubernetes为Pod分配的、固定的、基于iptables(或者IPVS)的访问入口。
而这些访问入口代理的Pod信息,来自于Etcd,由kube-proxy通过控制循环来维护。
而这些访问入口代理的Pod信息,来自于Etcd,由kube-proxy通过控制循环来维护。
原理
给Service分配一个VIP,然后增加iptables规则将该IP的请求转发到后续的iptables链
iptables链实际上是一个集合,包含了各个PodIP(这些称之Service的Endpoints),使用Round Robin方式的负载均衡。
KUBE-SEP-(hash) 规则对应的 DNAT 链,这些规则应该与 Endpoints 一一对应;
KUBE-SVC-(hash) 规则对应的负载均衡链,这些规则的数目应该与 Endpoints 数目一致;
这些Endpoints对应的iptables规则,正式kube-proxy通过监听Pod变化事件,在宿主机上生成并维护。
IPVS模式
因为要维护iptables,在大量的pod的情况下,性能不佳,于是出现了IPVS模式。以创建虚拟网卡,
并分配虚拟IP的形式,直接使用Linux的IPVS模块,由于讲转发逻辑放到了Linux内核中执行,性能有所提升。
并分配虚拟IP的形式,直接使用Linux的IPVS模块,由于讲转发逻辑放到了Linux内核中执行,性能有所提升。
Service的访问模式
ClusterIP
通过集群的内部IP暴露服务,只能够在内部访问
NodePort
通过每个节点上的IP和静态端口,暴露服务。NodePort服务会路由到自动创建的ClusterIP服务。
通过请求 节点IP:节点端口,你可以从寄存的外部访问一个NodePort服务
通过请求 节点IP:节点端口,你可以从寄存的外部访问一个NodePort服务
LoadBalancer
使用云提供商的负载均衡器向外部暴露服务。 外部负载均衡器可以将流量路由
到自动创建的 NodePort 服务和 ClusterIP 服务上。
到自动创建的 NodePort 服务和 ClusterIP 服务上。
ExternalName
通过返回 CNAME 和对应值,可以将服务映射到 externalName 字段的内容
(例如,foo.bar.example.com)。 无需创建任何类型代理。 (简单理解为域名访问)
(例如,foo.bar.example.com)。 无需创建任何类型代理。 (简单理解为域名访问)
APIServer
api层: 主要提供对外的 rest api
访问控制层: 验证身份与鉴权,根据配置的各种资源访问许可逻辑(Adminssion control) ,判断是否允许访问
注册表层: K8S 将所有对象都保存在registry 中, 针对 registry 中的各种资源对象,
都定义对象类型, 如何创建资源对象, 如何转换不同版本, 以及如何将资源编码和解码为json 或protobuf 格式进行存储.
都定义对象类型, 如何创建资源对象, 如何转换不同版本, 以及如何将资源编码和解码为json 或protobuf 格式进行存储.
etcd 数据库: 用于持久化存储资源对象.
在比较小的项目过程中就使用的是内部etcd模式
大项目可以使用外部etcd集群模式
在比较小的项目过程中就使用的是内部etcd模式
大项目可以使用外部etcd集群模式
核心功能是提供kuberrnetes各类资源对象(Pod、RC、service等)的增删改查以及watch等HTTPRest接口。
apiserver作为统一入口,任何对数据的操作都必须经过apiserver。apiserver负责个模块之间的通信,
集群里的功能模块通过apiserver将信息存入etcd中,etcd存储集群的数据信息,其他模块通过apiserver读取这些信息,来实现模块之间的交互。
(会导致apiserver压力太大 所以使用了 list-wathch机制 本地缓存机制)
集群里的功能模块通过apiserver将信息存入etcd中,etcd存储集群的数据信息,其他模块通过apiserver读取这些信息,来实现模块之间的交互。
(会导致apiserver压力太大 所以使用了 list-wathch机制 本地缓存机制)
kubelet每隔一个时间周期都会调用一次APIServer的REST接口报告自身的状态
apiserver接收到这些信息后,将节点信息更新到etcd中。
kubelet通过apiserver的watch接口舰艇pod信息,比如创建pod副本绑定到本节点,
则执行pod对应的容器创建和启动操作。
apiserver接收到这些信息后,将节点信息更新到etcd中。
kubelet通过apiserver的watch接口舰艇pod信息,比如创建pod副本绑定到本节点,
则执行pod对应的容器创建和启动操作。
kube-controller-manager中的node controller模块
通过apiserver模块提供watch接口,监控弄的信息。
通过apiserver模块提供watch接口,监控弄的信息。
scheduler通过APIservr的Watch接口监听新建Pod副本的信息后,
它会检索所有符合该Pod要求的Node列表,开始执行Pod调度逻辑,
调度成功后将Pod绑定到目标节点上。
它会检索所有符合该Pod要求的Node列表,开始执行Pod调度逻辑,
调度成功后将Pod绑定到目标节点上。
list Watch机制
List-watch机制满足异步消息系统
消息可靠性
ListAPI维持的是Http短链接 获取全量的数据,watchAPI维持http长连接,来获取增量的数据
消息实时性
list-watch机制下,每个apiserver的资源产生的状态变更,
都会将事件推送给客户端,从而保证信息的实时性。
kubernetes服务器只会保证一定时间内变化的变更列表。
都会将事件推送给客户端,从而保证信息的实时性。
kubernetes服务器只会保证一定时间内变化的变更列表。
消息顺序性
k8s在每个资源的事件都带一个resourceVersion的标签,
这个标签是递增的数字,可以通过比较version来确定信息是否一致。
这个标签是递增的数字,可以通过比较version来确定信息是否一致。
高性能
watch作为异步消息通知机制,服用一条http长连接,保证实时性与高性能。
控制器,调度器,kubelet都使用了apiserver提供的list- watch机制
在这里表现为api server 通过etcd的watch 接口监听资源的变更情况,
当事件发生时 etcd 会通知 api server 比如上图的3,7,11步骤, api server 模仿etcd 提供了watch 机制,
当事件发生时,通知对应的组件 比如上图0 表示最开始进行watch 监控。
在这里表现为api server 通过etcd的watch 接口监听资源的变更情况,
当事件发生时 etcd 会通知 api server 比如上图的3,7,11步骤, api server 模仿etcd 提供了watch 机制,
当事件发生时,通知对应的组件 比如上图0 表示最开始进行watch 监控。
informer 本地缓存与索引机制
informer 主要用于在 Kubernetes 集群中对资源对象进行监视和管理
主要作用是:Informer 是 Kubernetes 中用于从 Kubernetes API Server 获取对象列表(List)或单个对象(Get)的一种机制。
Informer 是 Kubernetes 中的一种控制器,它会定期向 API Server 发送请求,获取特定类型的资源对象的列表或单个对象的详细信息,
并将这些信息保存在本地的缓存中。
主要作用是:Informer 是 Kubernetes 中用于从 Kubernetes API Server 获取对象列表(List)或单个对象(Get)的一种机制。
Informer 是 Kubernetes 中的一种控制器,它会定期向 API Server 发送请求,获取特定类型的资源对象的列表或单个对象的详细信息,
并将这些信息保存在本地的缓存中。
workqueue
主要作用:每个controller都有一个工作队列。从eventHandler触发事件会先放入队列中,
然后由controller中的processltem函数取出来。
workqueue是一个去重队列,内部除了item列表外还带有一个processing和dirty set记录,
用来实现同一个资源对象多次时间出发,
入队列后去重,不会被多个work同时处理,解决了并发处理问题。
然后由controller中的processltem函数取出来。
workqueue是一个去重队列,内部除了item列表外还带有一个processing和dirty set记录,
用来实现同一个资源对象多次时间出发,
入队列后去重,不会被多个work同时处理,解决了并发处理问题。
scheduler
scheduler调度策略(创建的POD为什么都会在同一节点上)
步骤
predicate(预选择)
选择标准
资源需求
资源限额
GeneralPredicates
(podFistResources :资源要求)判断资源是否满足条件
(podSelectorMatches:标签匹配) pod 没有制定spec.nodeSelector标签选择器,则返回ture
如果获得被选节点的标签信息,判断节点是否包含被选pod的标签选择器所指的标签,包含:ture or false
如果获得被选节点的标签信息,判断节点是否包含被选pod的标签选择器所指的标签,包含:ture or false
podFitsHost,判断被选pod的spec.nodeName域所指定的节点名称和被选节点的名称是否一致,
如果一致返回true,否则返回false。
如果一致返回true,否则返回false。
podFitsPorts,判断被选pod所用的端口列表的端口是否在被选节点中被占用,
如果被占用,则返回false,否则返回ture。
如果被占用,则返回false,否则返回ture。
podFitsHostPorts,节点上已经使用的port是否和pod申请的port冲突
Volume
noDiskconflict 磁盘冲突 :步骤,读取被选pod的volume信息,
再读取备选node上所有的pod的每一个volume进行比较,如果有冲突返回false知道找到合适的NODE。
再读取备选node上所有的pod的每一个volume进行比较,如果有冲突返回false知道找到合适的NODE。
maxPDVlumeCountPredicate:查看一个节点上某中类型的持久化volume是不是超过一定数量了,
超过了则不会调度到这个node上。
超过了则不会调度到这个node上。
volumeZonePredicate:检查持久化volume的Zone标签,是否与待考察节点的Zone标签匹配。
宿主机
考察调度pod是否满足node本身的某些机制,比如node的“污点”机制。
只有当pod的toleration字段与Node的taint字段能够匹配的时候,这个pod才能背调度到该节点上。
只有当pod的toleration字段与Node的taint字段能够匹配的时候,这个pod才能背调度到该节点上。
priority(优选择)
通过对预选择的节点进行评分,选出最高分数的节点(最高分数节点可能不止一个)
leatRequestedPriority (打分机制)
计算出所有备选节点上运行的pod和备选pod的CPU占用量
计算出所有备选节点上运行的pod和备选pod的memory占用量
计算方式如下:
score = (cpu((capacity-sum(requested))10/capacity) + memory((capacity-sum(requested))10/capacity))/2
score = (cpu((capacity-sum(requested))10/capacity) + memory((capacity-sum(requested))10/capacity))/2
BalancedResourceAllocation
公式如下:
score = 10 - variance(cpuFraction,memoryFraction,volumeFraction)*10
score = 10 - variance(cpuFraction,memoryFraction,volumeFraction)*10
与leatRequestedPriority不同的是 此计算方法所算出来的是资源分配最均衡的节点
select (最终选择)
主要作用:经过优选择评分机制可能会有多台分数一样,
一样的话就在其中最终选择一台。
一样的话就在其中最终选择一台。
可以指定Node节点调度
nodeSelector:只调度到指定label的node上
kubectl label nodesnode-01 disktype=ssd 首先给Node打上标签
然后在daemonset中指定nodeSelector为disktype=ssd:
spec:
nodeSelector:
disktype: ssd
更具默认调度器PodSelectorMatches策略选出合适的节点,然后打分进行分配。
spec:
nodeSelector:
disktype: ssd
更具默认调度器PodSelectorMatches策略选出合适的节点,然后打分进行分配。
nodeAffinity:功能更丰富的Node选择器,比如支持集合操作
requiredDuringSchedulingIgnoredDuringExecution(必选条件),
preferredDuringSchedulingIgnoredDuringExecution(优选条件)
preferredDuringSchedulingIgnoredDuringExecution(优选条件)
podAffinity:调度到满足条件的Pod所在的Node上
podAffinity(调度到含有某一标签且在运行的pod对应的Node上)
podAntiAffinity(不调度到含有某一标签的pod对应的Node上)
总结
node affinity 在deployment的调度的时候说明过亲和性调度的使用,主要是两个策略:强制和优先。调度到符合条件的node上去。
pod affinity 用于调度pod可以和哪些pod部署在同拓扑结构之下。
podAntiAffinity相反 用于规定pod不可以和哪些pod部署在同一拓扑结构下。AntiAffinity同样有两个策略:强制和优先。
屏蔽Node节点调度
taints和tolerations用于保证pod不被调度到不合适的Node哈桑,其中taint应用于Node上,二toleration则应用于pod上。
taints的三种类型
NoSchedule:新的Pod不调度到该Node上,不影响正在运行的Pod
PreferNoSchedule:soft版的NoSchedule,尽量不调度到该Node上
NoExecute:新的Pod不调度到该Node上,并且删除已经在运行的Pod。Pod可以增加一个时间(tolerationSeconds)
Scheduling 原理
Scheduling主要分为两条路 和一个中间层:
informer主要作用用于监听 Etcd有关于pod、node、service的调度变化
并将调度资源放到对了中,将调度信息放到scheduler cache中
并将调度资源放到对了中,将调度信息放到scheduler cache中
Scheduling Path主要作用 从Queue中Pop需要调度的资源,从SchedulerCache获取对应的信息,(Predicates,Priorities)用于打分算法和匹配调度,最后进行绑定操作(调度算法执行完成后,调度器就需要将 Pod 对象的 nodeName 字段的值,修改为上述 Node 的名字 称之为Bind)。
值得注意的是:所有的信息都是从cache中获得的(这大大提高了执行的效率)事实上,Kubernetes 调度部分进行性能优化的一个最根本原则,就是尽最大可能将集群信息 Cache 化,以便从根本上提高 Predicate 和 Priority 调度算法的执行效率。
并且:在predicates于priorities的并发于并行操作时才用了无锁的操作(原因:调度器会避免设置任何全局的竞争资源,从而免去加锁产生的性能损耗)。
在整个过程中,只有对cache更新缓存才会有加锁的行为。
值得注意的是:所有的信息都是从cache中获得的(这大大提高了执行的效率)事实上,Kubernetes 调度部分进行性能优化的一个最根本原则,就是尽最大可能将集群信息 Cache 化,以便从根本上提高 Predicate 和 Priority 调度算法的执行效率。
并且:在predicates于priorities的并发于并行操作时才用了无锁的操作(原因:调度器会避免设置任何全局的竞争资源,从而免去加锁产生的性能损耗)。
在整个过程中,只有对cache更新缓存才会有加锁的行为。
Bind操作更新的信息只会更新Scheduler Cache里面的Pod和Node的信息 (避免在关键路径中远程访问APIServer 减少关键路径中的消耗)。
这种基于“乐观”假设的 API 对象更新方式,在 Kubernetes 里被称作 Assume。
Assume 之后 调度器会创建一个Goroutine来异步的向APIServer发起更新请求。
这种基于“乐观”假设的 API 对象更新方式,在 Kubernetes 里被称作 Assume。
Assume 之后 调度器会创建一个Goroutine来异步的向APIServer发起更新请求。
Controller Manager
是控制器的控制者,使用集群管理控制中心
Replication Controller控制器
副本控制器。副本控制器的核心作用是确保任何使用集群中的一个RC所关联的Pod副本数量保持设定的阈值。
node controller 节点管理
主要作用:nodestatusmap中状态,对于状态不对的node节点加入一个队列,等待确认node是否有问题,有问题就进行信息同步,并且删除节点。
nodeController管理的主要过程
如果controller manager在启动时设置了–cluster-cidr,那么为每一个没有设置spec.PodCIDR的节点生成一个CIDR地址,
并用该地址设置节点的spec.PodCIDR属性。
并用该地址设置节点的spec.PodCIDR属性。
逐个读取节点信息,此时node controller中有一个nodestatusMap,里面存储了信息,
与新发送过来的节点信息做比较,并更新nodestatusMap中的节点信息。
Kubelet发送过来的节点信息,有三种情况:未发送、发送但节点信息未变化、发送并且节点信息变化。
此时node controller根据发送的节点信息,更新nodestatusMap,如果判断出在某段时间内没有接受到某个节点的信息,则设置节点状态为“未知”。
与新发送过来的节点信息做比较,并更新nodestatusMap中的节点信息。
Kubelet发送过来的节点信息,有三种情况:未发送、发送但节点信息未变化、发送并且节点信息变化。
此时node controller根据发送的节点信息,更新nodestatusMap,如果判断出在某段时间内没有接受到某个节点的信息,则设置节点状态为“未知”。
最后,将未就绪状态的节点加入到待删除队列中,待删除后,
通过API Server将etcd中该节点的信息删除。如果节点为就绪状态,
那么就向etcd中同步该节点信息。
通过API Server将etcd中该节点的信息删除。如果节点为就绪状态,
那么就向etcd中同步该节点信息。
resourceQuota controller资源配置
作用:它确保任何对象任何时候都不回超量占用资源,确保了系统的稳定性。
支持三层资源配置:
容器级别 可以限制cpu和memory
pod级别 对pod内所有容器的可用资源进行限制
namespaces级别 pod数量,rc数量 service数量,rq数量,secret数量,presistenVolume数量
(RQ ResourceQuota:设置命名空间的资源配额,限制这些资源的总使用量)
(secret:用于存储敏感数据,例如密码和 API 密钥)
支持三层资源配置:
容器级别 可以限制cpu和memory
pod级别 对pod内所有容器的可用资源进行限制
namespaces级别 pod数量,rc数量 service数量,rq数量,secret数量,presistenVolume数量
(RQ ResourceQuota:设置命名空间的资源配额,限制这些资源的总使用量)
(secret:用于存储敏感数据,例如密码和 API 密钥)
实现资源配置机制:准入机制(admission control),admission control当前提供了两种方式的配额约束
分别是limitRange、resouceQuota。limitRange作用与pod和容器上。ResourceQuota作用于namespace上,
用于限定一个namespace里的各种资源的使用总额。
分别是limitRange、resouceQuota。limitRange作用与pod和容器上。ResourceQuota作用于namespace上,
用于限定一个namespace里的各种资源的使用总额。
通过流程图可以看到三条线路,这三条线路对于resourceQuota Controller很重要
当用户给pod定义了limitRange的时候 会通过API创建或者修改对象,
admission control会计算当前的资源配合的使用情况,如果不符合约束条件而创建或者修改失败。
admission control会计算当前的资源配合的使用情况,如果不符合约束条件而创建或者修改失败。
ResourceQuotaController会定期读取ResourceQuota信息,统计后在写入etcd中
对于定义了resource Quota的namespace,resourceQuota controller会定期统计和生成该namespace下的各类对象资源使用总量,统计结果包括:pod、service、RC、secret和PV等对象的实例个数,以及该namespace下所有的container实例所使用的资源量(CPU,memory),然后会将这些结果写入到etcd中,写入的内容为资源对象名称、配额制、使用值,然后admission control会根据统计结果判断是否超额,以确保相关namespace下的资源配置总量不会超过resource Quota的限定值。
如果资源请求超额,admission 控制器通常会根据定义的策略
拒绝请求
修改请求
动态调整
记录和通知
namespace controller
作用:namespace controller主要是监控namespace的状态,在其失效的情况下,对其进行处理。
通过API Server可以创建新的namespace并保存在etcd中,namespace controller定时通过API Server读取这些namespace信息。
如果namespace被API标记为优雅删除(通过设置删除周期),则将该namespace的状态设置为“terminating”并保存到etcd中。
同时namespace controller删除该namespace下的serviceAccount,RC,pod,secret,PV,listRange,resourceQuota和event等资源对象。
当状态为“terminating”后,由admission controller的namespaceLifecycle插件来阻止为该namespace创建新的资源。同时在namespace controller删除完该namespace中的所有资源对象后,namespace controller对该namespace 执行finalize操作,删除namespace的spec.finallizers域中的信息。
当然这里有一种特殊情况,当个namespace controller发现namespace设置了删除周期,并且该namespace 的spec.finalizers域值为空,那么namespace controller将通过API Server删除该namespace 的资源。
如果namespace被API标记为优雅删除(通过设置删除周期),则将该namespace的状态设置为“terminating”并保存到etcd中。
同时namespace controller删除该namespace下的serviceAccount,RC,pod,secret,PV,listRange,resourceQuota和event等资源对象。
当状态为“terminating”后,由admission controller的namespaceLifecycle插件来阻止为该namespace创建新的资源。同时在namespace controller删除完该namespace中的所有资源对象后,namespace controller对该namespace 执行finalize操作,删除namespace的spec.finallizers域中的信息。
当然这里有一种特殊情况,当个namespace controller发现namespace设置了删除周期,并且该namespace 的spec.finalizers域值为空,那么namespace controller将通过API Server删除该namespace 的资源。
service controller 和endpoint controller
Service Controller 的主要作用监听Service的变化
endPoints Controller的作用:监测新的Service创建或者修改后,则根据该service的信息获取到相关的pid列表,
然后创建或更新service对应的endpoint对象,如果service被删除,则删除该servide同名的endpoints对象
endPoints Controller的作用:监测新的Service创建或者修改后,则根据该service的信息获取到相关的pid列表,
然后创建或更新service对应的endpoint对象,如果service被删除,则删除该servide同名的endpoints对象
service 和endpoint与pod的关系,endpoints表示一个service对应的所有pod副本的访问地址,
而endpoints controller就是负责生成和维护所有的endpoints对象的控制器,
service和pod通过label关联之后,我们访问service的clusterIP对应的服务,就能通过kube-proxy将路由转发到对应的后端的endpoint(pod IP +port)上,
最终访问到容器中的服务,实现了service的负载均衡功能
而endpoints controller就是负责生成和维护所有的endpoints对象的控制器,
service和pod通过label关联之后,我们访问service的clusterIP对应的服务,就能通过kube-proxy将路由转发到对应的后端的endpoint(pod IP +port)上,
最终访问到容器中的服务,实现了service的负载均衡功能
ServiceAccountController和TokenController
ServiceAccountController和TokenController主要作用都是身份认证和授权机制的组成部分,
他们却暴露集群中个个组件的安全通信,并管理ServiceAccount的身份验证和授权所需的凭据。
他们却暴露集群中个个组件的安全通信,并管理ServiceAccount的身份验证和授权所需的凭据。
TokenController
每个 ServiceAccount 都有一个关联的 Secret,其中包含用于身份验证的 Token。
Token Controller 负责为每个 ServiceAccount 创建、更新和删除相应的 Token。
Token Controller 负责为每个 ServiceAccount 创建、更新和删除相应的 Token。
Token Controller 为集群中的各个组件提供了一种安全的身份验证机制,
它们可以使用 ServiceAccount Token 与 API Server 进行通信,并执行权限相对应的操作。
它们可以使用 ServiceAccount Token 与 API Server 进行通信,并执行权限相对应的操作。
ServiceAccount Controller
ServiceAccount 是 Kubernetes 中的一种身份认证机制,用于识别 Pod 运行时所使用的身份。
ServiceAccount Controller 负责创建、更新和删除 ServiceAccount 对象,并确保它们与命名空间中的相关资源一致。
ServiceAccount Controller 负责创建、更新和删除 ServiceAccount 对象,并确保它们与命名空间中的相关资源一致。
ServiceAccount Controller 确保 Pod 使用的 ServiceAccount 具有适当的访问权限,
以访问其需要的其他 Kubernetes 资源,如 Secrets 和 ConfigMaps。
以访问其需要的其他 Kubernetes 资源,如 Secrets 和 ConfigMaps。
0 条评论
下一页