Kubernetes基本概念

Kubernetes基本概念

 1 Kubernetes是什么

首先,Kubernetes是一个全新的基于容器技术的分布式领先方案,是谷歌十几年来大规模应用容器技术的经验积累和升华的重要成果。源自谷歌严格保密十几年的秘密武器--Borg的一个开源版本。Borg是谷歌一个久负盛名的内部使用的大规模集群管理系统,用于实现资源管理的自动化,以及跨多个数据中心的资源利用率最大化。十几年来,谷歌一直通过Borg系统管理着数量庞大的应用程序集群。

其次,Kubernetes提供的解决方案使我们不必再费心于负责均衡器的选型和部署,不用再考虑引入或者自己开发一个复杂的服务治理框架,也不必再头疼于服务监控和故障处理模块的开发。使我们不仅节省至少30%的开发成本,还可以使我们将精力更加集中于业务本身。Kubernetes强大的自动化机制,使得系统后期的运维难度和运维成本大幅度降低。

最后,Kubernetes是一个完备的分布式系统支撑平台。它具有完备的集群管理能力,包括多层次的安全防护和准入机制、多租户应用支撑能力、透明的服务注册和服务发现机制、内建的智能负载均衡器、强大的故障发现和自我修复能力、服务滚动升级和在线扩容能力、扩展的资源自动调度机制,以及多粒度的资源配额管理能力。同时,Kubernetes提供了晚上的管理工具,包括开发、部署、测试、运维监控在内的各个环节中的应用工具。

2 Kubernetes架构图

Kubernetes将集群中的机器划分为一个Master节点和一群Node工作节点。其中,在Master节点远行中集群管理相关的一组进程:kube-apiserver、kube-controller-manager、kube-scheduler。这些进程实现对整个集群的资源管理、Pod调度、弹性伸缩、安全控制、系统监控和纠错等管理能力,并且都是自动完成的。Node节点作为集群中的工作节点,运行真正的应用程序。在Node节点上Kubernetes管理的最小运行单元室Pod。Node节点上运行Kubernetes的kubelet、kube-proxy服务进程,这些服务进程负责Pod的创建、qid、监控、重启、销毁以及实现软件模式的负载均衡器。

3 Master节点

  • Etcd(数据库):是一个高可用的键值数据库,存储Kubernetes的资源状态信息和网络信息,Etcd中的数据变更是通过API Server进行的。
  • API Server(资源操作入口):整个系统的对外接口,提供资源操作的唯一入口。供客户端和其它组件调用,提供了K8s各类资源对象(Pod、Deployment、Service等)的增删改查操作。是整个系统的数据总线和数据中心。提供认证、授权、访问控制、API注册和发现等机制,并将操作对象持久化到Etcd中。API Server工作原理:

 

    1.  API层:提供针对资源的CRUD和监控接口以及健康检查、日志、性能指标等运维相关接口。
    2. 访问控制层:当客户端访问API接口时,访问控制层负责对用户身份鉴权,验明用户身份,核准用户对K8s资源对象的访问权限,然后根据配置的各种资源访问许可逻辑(Admission Control),判断是否允许访问。
    3. 注册表层:K8s把所有资源对象都保存在注册表中,针对注册表中的各种资源对象定义了相关数据类型及创建、转换和编码的方法。
    4. Etcd数据库层:用于持久化存储K8s资源对象的KV数据库。Etcd的watch API接口对于API Server来说至关重要,因为通过这个接口,API Server 创新性地设计了List-Watch这种高性能的资源对象实时同步机制,使用K8s可以管理超大规模的集群,及时响应和快速处理集群中的各种事件。
  •  Controller Manager(控制管理器):Controller Manager在pod工作流中的作用是管理和控制整个集群,主要对资源对象进行管理,当Node节点中运行的Pod对象或者是Node自身发生故障时,Controller Manager会及时发现并处理,以确保整个集群处于理想的工作状态。Controller Manager架构图:

 每个Controller通过API Server提供的接口实时监控整个集群的每个资源对象的当前状态,当发生各种故障导致系统状态发生变化时,会尝试将系统状态修复到“期望状态”,而Controller Manager是这些Controller的核心管理者。

  1. Replication Controller:称为副本管理控制器,在Pod工作流中主要保证集群中Replication Controller所关联的Pod副本数始终保持在预期值,比如若发生节点故障的情况导致Pod被意外杀死,Replication Controller会重新调度保证集群仍然运行指定的副本数,另外还可以通过调整Replication Controller中的spec.replicas属性来实现扩容或缩容。
  2. Node Controller:kubelet在启动时会通过API Server注册自身的节点信息,并定时向API Server汇报状态信息,API Server接收到信息后将信息更新到Etcd中,包括节点健康状况、节点资源、节点名称、节点地址信息、操作版本、Docker版本、kubelet版本等信息。Node Controller通过API Server实时获取Node的相关信息,实现管理和监控集群中各个Node节点的相关控制功能。
  3. Resource Quota Controller(资源配额管理):资源配额管理确保指定的资源对象在任何时候都不会超量占用系统物理资源,避免由于某些业务进程设计或实现上的缺陷导致整个系统运行紊乱甚至宕机,对整个集群平稳运行和稳定性都有非常重要的作用。
  4. Namespace Controller:用户通过API Server可以创建新的Namespace并保存在Etcd中,Namespace Controller定时通过API Server读取这些Namespace信息来操作Namespace,比如Namespace被API标记为删除,则将该Namespace状态设置为Terminating并保存到Etcd中。同时Namespace Controller删除Namespace下的ServiceAccount、RC、Pod等资源对象。
  5. Service Account Controller (服务账号控制器):主要在命名空间内管理 ServiceAccount,以保证名为 default 的 ServiceAccount 在每个命名空间中存在。
  6. Token Controller(令牌控制器):作为 Controller Manager 的一部分,主要用作:监听 serviceAccount 的创建和删除动作以及监听 secret 的添加、删除动作。
  7. Service Controller:Service Controller是属于 K8s 集群与外部的云平台之间的一个接口控制器。Service Controller 监听 Service 变化,如果是一个 LoadBalancer 类型的 Service,则确保外部的云平台上对该 Service 对应的 LoadBalancer 实例被相应地创建、删除及更新路由转发表。

  8. Endpoints Controller:Endpoints 表示了一个 Service 对应的所有 Pod 副本的访问地址,而 endpoints controller 就是负责生成和维护所有 Endpoints 对象的控制器。负责监听 Service 和对应的 Pod 副本的变化,如果 Service 被删除,删除和该 Service 同名的 Endpoints 对象。如果新的 Service 被创建或者修改,根据该 Service 信息获得相关的 Pod 列表,然后创建或者更新 Service 对应的 Endpoints 对象。如果监测到 Pod 的事件,则更新它所对应的 Service 的 Endpoints 对象,每个 Node 上的 kube-proxy 进程获取每个 Service 的 Endpoints,实现 Service 的负载均衡。

  • Scheduler(集群分发调度器):Scheduler 调度器是 K8s 的核心组件;用户或者控制器创建 Pod 之后,调度器通过 K8s 的 watch 机制来发现集群中新创建且尚未被调度到 Node 上的 Pod。调度器会将发现的每一个未调度的 Pod 调度到一个合适的 Node 上来运行。整个调度流程分为两个阶段:预选策略(Predicates)和优选策略(Priorities):
  1. 预选(Predicates):输入是所有节点,输出是满足预选条件的节点。Scheduler 根据预选策略过滤掉不满足策略的 Node。例如,如果某节点的资源不足或者不满足预选策略的条件如 “Node 的 label 必须与 Pod 的 Selector 一致”时则无法通过预选。
  2. 优选(Priorities):输入是预选阶段筛选出的节点,优选会根据优先策略为通过预选的 Nodes 进行打分排名,选择得分最高的 Node,最后 Scheduler 会将 Pod 调度到得分最高的 Node 上,例如,资源越富裕、负载越小的 Node 可能具有越高的排名。

  1.  Scheduler 监听到 Pod Queue 有新的 Pod 需要创建。
  2. 通过检测 NodeList 以及相应的调度算法和策略绑定到集群中某个合适 Node 上,并将绑定信息保存到 Etcd 中。
  3. Node 上的 kubelet 通过 API Server 监听到 K8s Scheduler 产生的 Pod 绑定事件,获取到对应的 Pod 清单,下载 image 镜像,启动容器。

 4 Node节点

  • kubelet(集群管理命令行工具集):每个 Node 节点上的 kubelet 定期就会调用 API Server 的 REST 接口报告自身状态,API Server 接收这些信息后,将节点状态信息更新到 Etcd 中,kubelet 也通过 API Server 监听 Pod 信息,从而对 Node 机器上的 Pod 进行管理,如创建、删除、更新 Pod。
  • Proxy(负载均衡、路由转发):Proxy 提供网络代理和负载均衡,是实现 service 的通信与负载均衡机制的重要组件,kube-proxy 负责为 Pod 创建代理服务,从 API Server 获取所有 service 信息,并根据 service 信息创建代理服务,实现 service 到 Pod 的请求路由和转发,从而实现 K8s 层级的虚拟转发网络,将到 service 的请求转发到后端的 Pod 上。

5 Pod

Pod 是 K8s 中能够创建和部署的最小单元,当指派容器时,容器实际上并不会指派到物理硬件上,容器会被分配到一个 Pod 里面。一个 Pod 代表着集群中运行的一个进程,一个Pod封装一个容器(可以封装多个容器),Pod 里的容器共享存储、网络等。也就是说,应该把整个 Pod 看作虚拟机,然后每个容器相当于运行在虚拟机的进程。

在一些小公司里面,一个 Pod 就是一个完整的应用,里面安装着各种容器,一个 Pod 里面可能包含 Redis、MySQL、Tomcat 等等,当把这一个 Pod 部署以后就相当于部署了一个完整的应用,多个 Pod 部署完以后就形成了一个集群,这是 Pod 的第一种应用方式,还有一种使用方式就是在 Pod 里面只服务一种容器,比如在一个 Pod 里面我只部署 Redis,具体怎么部署 Pod 里面的容器,是按照我们项目的特性和资源的分配进行合理选择的。

 

  从上面的结构图可知,在每一个 Pod 中都有一个特殊的 Pause 容器和一个或多个业务容器,Pause 来源于 pause-amd64 镜像,Pause 容器在 Pod 中具有非常重要的作用:

  • Pause 容器作为 Pod 容器的根容器,其本地于业务容器无关,它的状态代表了整个 Pod 的状态。
  • Pod 里的多个业务容器共享 Pause 容器的 IP,每个 Pod 被分配一个独立的 IP 地址,Pod 中的每个容器共享网络命名空间,包括 IP 地址和网络端口。Pod 内的容器可以使用 localhost 相互通信。K8s 支持底层网络集群内任意两个 Pod 之间进行通信。
  • Pod 中的所有容器都可以访问共享 Volume,允许这些容器共享数据。Volume 也可以用来持久化 Pod 中的存储资源,以防容器重启后文件丢失。

上图中如果没有Pause容器,nginx和ghost在Pod内容器间想要彼此通信的话,都需要使用自己的的IP地址和端口。如果有Pause容器,对于整个Pod来说,可以看做一个整体,也就是nginx和ghost直接使用localhost就可以访问,他们唯一不同的就只剩端口了。

6 ReplicaSet

 ReplicaSet是K8s中的一种副本控制器,简称RS,是新一代的Replication Controller,K8s中的ReplicaSet主要作用是维持一组Pod副本的运行,保证一定数量的Pod能够在集群中正常运行,它会持续监听这些Pod的运行状态,在Pod发生故障重启或数量减少时重新运行新的Pod副本。

官方不推荐直接使用ReplicaSet,而用Deployment取代。Deployment是比ReplicaSet更高级的概念,它会管理ReplicaSet并提供很多其它有用的特性,最重要的是Deployment支持声明式更新,声明式更新的好处是不会丢失历史变更。所以Deployment控制器不直接管理Pod对象,而是由Deployment管理ReplicaSet,再由ReplicaSet负责管理Pod对象。

 ReplicaSet控制器由三部分组成:

  • replicas(用户期望的Pod副本数):期望的Pod副本数,指定该ReplicaSet应该维持多少个Pod副本,默认为1。
  • selector(标签选择器):选定哪些Pod是自己管理的,如果通过标签选择器选到的Pod副本数量少于我们指定的数量,则徐用到下面的组件。
  • template(Pod资源模版):如果集群中现存的Pod数量少于期望副本数量时,就需要启动Pod模版。新建的Pod是基于模版来创建的。

7 Deployment

 为了更好地解决服务编排问题,K8s在V1.2版本开始,引入了Deployment控制器,但这种控制器不直接管理Pod,而是通过管理ReplicaSet来间接管理Pod。即,Deployment管理ReplicaSet、ReplicaSet管理Pod。所以Deployment比ReplicaSet的功能更强,可实现滚动升级和回滚应用、扩容和缩容以及声名式配置。

 以上图升级版本为例。通过Deployment控制器来动态更新Pod版本,Deployment下有众多的ReplicaSet,但更改配置文件中的镜像版本后,就会一个个删除ReplicaSet v1版本中的Pod,自动创建新的Pod就会变成v2版本,当Pod全部变成v2版本后,ReplicaSet v1不会被删除,因为一旦发现v2版本有问题,还可以回滚到v1版本。通常情况下,Deployment默认保留10个版本的ReplicaSet。

8 Service

有个疑问,Pod是应用程序的载体,我们可以通过pod的IP来访问应用程序,ReplicaSet定义了Pod的数量是2,当其中一个Pod由于某种原因停止了,ReplicaSet会新建一个新的Pod,以确保运行中的Pod数量始终是2.但每个Pod都有自己的IP,前端请求不知道这个新的Pod的IP是什么,那前端的秦秋如何发送到新的Pod中呢?

为了解决这个问题,K8s提供了Service。Service是K8s中最重要的资源对象,Service定义了一个服务的访问入口地址,前端的应用通过这个入口地址访问其背后的一组由Pod副本组成的集群实例,来自外部的访问请求被负载均衡到后端各个容器应用上。Service与其后端Pod副本集群之间则是通过Label Selector实现关联。简单来说前端请求不直接发给Pod,而是发送到Service,Service再将请求转发给Pod。

 Service在很多情况下只是一个概念,而真正将server的作用实现的是Kube-proxy服务进程。

9 Kube-proxy

 在K8s集群中每个Node上都会运行一个kube-proxy服务进程,每个kube-proxy都充当一个负载均衡器,这个是分布式的负载均衡器。我们可以把这个进程看作是透明代理兼负载均衡器,其核心功能就是访问到某个Service的请求转发到该Service对应的真实后端Pod上。

目前kube-prox有三种工作模式:

  • userspace模型

 userspace模式下,Kube-proxy会为每个Service创建一个监听端口,发往Cluster IP的请求被Iptables规则重定向到Kube-proxy监听的端口上,Kube-proxy根据LB算法选择一个提供服务的Pod并和其建立连接,以将请求转发到Pod上。该模式下,Kube-proxy充当了一个四层负载均衡器的角色。由于Kube-proxy运行在userspace中,在进行转发处理时会增加内核和和用户空间之间的数据拷贝,虽然比较稳定,但是效率比较低。

  •  Iptables模式

为了避免增加内核和用户空间的数据拷贝操作,提高转发效率,Kube-proxy提供了Iptables模式。在该模式下,Kube-proxy为Service后端的每个Pod创建一个对应的Iptables规则,直接将发往Cluster IP 的请求重定向到一个Pod IP。该模式下Kube-proxy不承担四层代理的角色,至负责创建Iptables规则。该模式的优点是较userspace模式效率高,但不能提供灵活的LB策略,当后端Pod不可用时也无法进行重试。

  •  ipvs模式

该模式和Iptables类似,Kube-proxy监控Pod的变化并创建相应的ipvs rules。ipvs也是在kernel模式下通过netfilter实现的,但采用了hash table来存储规则,因此在规则较多的情况下,ipvs相对Iptables转发效率更高。除此以外,ipvs支持更多的LB算法。如果要设置Kube-proxy为ipvs模式,必须在操作系统中安装IPVS内核模块。

 那么Service和Kube-Proxy在K8s集群中的工作原理是怎样的呢?以Iptables模式为例进行说明:

  1.  运行在每个Node节点的Kube-Proxy会实时的watch Service和Endpoints对象。
  2. 当用户在K8s集群中创建了含有label的Service之后,会同时在集群中创建出一个同名的Endpoints对象,用于存储改Service下的Pod IP。
  3. 每个运行在Node节点的Kube-Proxy感知到Service和Endpoints的变化后,会在各自的Node节点设置相关的Iptables转发规则,用于之后用户通过Service 的Cluster IP去访问Service下的服务。
  4. 当Kube-proxy把需要的规则设置完成后,用户就可以在集群内部的Node或客户端Pod上通过Cluster IP经过该节点下的Iptables设置的规则进行路由转发后,直接将请求发送到真实的后端Pod中。

 10 Service暴露服务的方式

在K8s中Service主要有4中不同的类型:

  •  Cluster IP是Service默认的类型,每个Node分配一个集群内部的IP,该IP为私有,内部可以互相访问,外部无法访问集群内部。
  • Node Port:基于Cluster IP,另外在每个Node上开放一个端口,将Service的Port映射到每个Node的指定内部Port上,映射的每个Node的内部Port都一样。将向端口的流量导入到Kube-proxy,然后由Kube-proxy进一步导给对应的Pod。可以从所在的位置访问这个地址。

  •  LoadBalancer:基于Node Port,云服务商在外边创建了一个负载均衡层,会向cloud provider申请映射到Service本身的负载均衡,将流量导入对应Port,但是要收费。

 

posted @ 2024-04-11 14:03  钟齐峰  阅读(22)  评论(0编辑  收藏  举报