在这里插入图片描述
k8s采用主从式分布式架构

master node

  • API server 与所有组件进行通信
  • Scheduler 调度应用,为应用的每个部署组件分配一个节点
  • Controller Manager 执行集群级别的功能,如复制,跟踪工作节点,处理节点失败
  • etcd 分布式数据存储,持久化存储集群配置

worker node

  • kubelet 与API服务器通信,管理它所在节点的容器
  • kube-proxy 负责组件之间的负载均衡

k8s组件的分布式特性

组件之间的通信
  • 组件之间只能通过 API Server 进行通信
  • 其中etcd 不会和其他组件直接通信
单组件运行多实例
  • 工作节点的组件都需要运行在同一个节点上
  • master的组件可以分布在不同的节点上运行
  • 而且master的每个组件都可以有多个实例,其中etcd和API Server可以多实例并行工作
  • 但是调度器和controller manager 只能运行一个实例,其他实例待命
组件的运行
  • master的组件与kube-proxy既可以直接部署在系统上,也可以直接作为pod来运行
  • 如果要把master的组件作为pod来运行,kubelet需要部署在master节点上
  • Kubelet是唯一作为常规系统组件运行的组件,把其他组件作为pod来运行

etcd

  • k8s中创建的所有对象:pod,ReplicationController,服务和私密凭据等,都需要持久化存储在底层,这样当API Server重启失败的时候,能够迅速找到这些对象的信息
  • etcd是一个分布式,一致的key-value存储
  • k8s架构里面,只有api server能够与它通信,这样可以增加乐观锁系统的健壮性
  • etcd是k8s存储集群状态和元数据的唯一的地方
  • 一个etcd条目代表一个对象(如pod),API Server把资源的完整Json形式存储到etcd中.Json的层级关系就对应了etcd的层级建空间
  • 乐观锁机制
  • 确保etcd集群的一致性
    为了实现高可用,多个etcd实例会同时运行,这时候需要RAFT一致性算法来保证这一点.

一致性算法要求集群超过一半的节点参与才能下一个状态.即如果集群分裂为两个互不相连的节点组,只有过半数的节点组才能参与状态变更,当两个组重新恢复连接的时候,第二个组的节点才会更新为第一个组的节点状态.

  • 因此etcd实例数量应该为奇数

API-Server

API server负责存储资源到etcd和通知客户端有变更的工作

  • 作为K8s的中心组件,由其他组件或者客户端都会调用它
  • 以RESTful API形式提供了可以查询,修改集群状态的CRUD,然后把状态存储到etcd中

调度器

调度器把Pod分配的节点

  • 调度器的任务是通过API Server 更新Pod的定义,然后API Server再去通知Kubelet这个Pod已经被调度过,当目标节点上的Kubelet发现这个pod被调度到本节点的时候,就会创建并且运行pod的容器

Controller-Manager

确保系统的真实状态朝API服务器定义的期望状态收敛

控制器干了啥?

通过API Server监听资源,然后执行相应的变更操作

Kubelet

  • 负责所有运行在工作节点上的内容的组件
  • 第一个任务就是在API Server服务器中创建一个Node资源,然后注册这个节点
  • 持续监控API Server判断是否把pod分配到该节点
  • 启动pod容器,然后kubelet持续监控运行的容器,并且向API Server 报告他们的状态,事件和资源消耗
  • Kubelet也是运行容器存活探针的组件,探针报错的时候会重启容器,最后当Pod从API Server删除的时候,由Kubelet来执行终止容器的任务,并且告知API Server,pod已经终止了

K8s Service Proxy的作用

  • 每个工作节点还会运行kube-proxy,用于确保客户端可以通过K8s API来连接到定义的服务
  • kube-proxy确保对服务IP和端口的链接最终能到达支持服务的某个Pod处,如果有多个Pod支撑一个服务,那么代理就会发挥对pod的负载均衡作用
  • userspace代理模式

请求要经过kube-proxy,请求会轮训选择后端Pod

  • iptables代理模式

请求不需要经过kube-proxy,仅仅通过iptables规则重定向数据包到一个随机选择的后端pod,而不会传递到一个实际的代理服务器。

DNS服务器

集群中的pod默认配置使用集群内部的DNS服务器,使得pod能够轻松通过名称查询到服务

Ingress控制器

运行一个反向代理服务器,根据集群定义的Ingress,Service以及Endpoint资源来配置控制器,需要通过监听机制订阅这些资源。然后每次发生变化的时候更新代理服务器的配置。

尽管Ingress资源定义指向一个Service,Ingress控制器会直接把流量转到服务的pod而不经过服务IP,当外部客户端通过Ingress控制器连接的时候,还会对客户端的IP进行保存。

补充知识

乐观锁与悲观锁

悲观锁
  • 每次访问数据,都会悲观地认为别的线程会修改,因此每次在拿数据的时候都会上锁,这样别的线程访问它的时候将会阻塞,然后用完之后再把资源转让给其他线程

  • Java 中的synchronized和ReentrantLock就是悲观锁思想的体现

乐观锁
  • 假设最好的情况,访问数据的时候不会上锁,但是在更新的时候,会判断在此期间别人有没有更新过这个数据.
  • 可以使用版本号机制和CAS算法来实现
  • Java中的原子变量类就是用了CAS算法来实现
使用场景比较
  • 乐观锁用于多读的场景
  • 悲观锁用于多写的场景
版本号机制

一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时,或者说当前修改后的数据的version大于现在数据库的version的时候才更新,否则重试更新操作,直到更新成功。

CAS算法

compare and swap,是无锁算法,要求在没有线程被阻塞的情况下实现变量的同步.

CAS算法涉及到三个操作数

  • 需要读写的内存值 V
  • 进行比较的值 A
  • 拟写入的新值 B

当且仅当V的值等于A的时候,CAS通过原子方式用B来更新V
一般情况下是一个自旋操作,会不断地重试

值得一提的是,k8s的API Server 就实现了乐观锁机制

ref

https://www.imooc.com/article/details/id/44217

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐