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