0

Kubernetes架构原理详解

 1 year ago
source link: https://www.jdon.com/64368.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Kubernetes架构原理详解


K8S是什么,为什么上手这么难?
K8S是一个基于容器技术的分布式集群管理系统。它是谷歌在大规模应用容器技术方面数十年经验的实际成果。因此,支持大规模的集群管理承载着非常多的组件,分布式本身的复杂度非常高。

接下来我们一步步来看看K8S到底有什么?
首先,既然是分布式系统,那么肯定有多个Node节点(物理主机或者虚拟机),它们共同构成了一个分布式集群,而这些节点之间会有一个Master节点,统一管理Node节点.
如图所示:

v2-a4faad940c8adb0c72af27b57aa64566_720w.jpg?source=d16d100b

问题一:master节点和worker节点如何通信?
首先,当Master节点启动时,会运行一个Kube-apiserver进程,它提供了集群管理的API接口,是集群中各个功能模块之间进行数据交互和通信的中心枢纽,同时也提供了一个完善的集群安全机制。

在Node节点上,利用K8S中的kubelet组件,每个Node节点上都会运行一个kubelet进程,负责向Master汇报本节点的运行状态,如Node节点注册、终止、定期健康报告等,等,并接收来自Master的命令并创建相应的Pod。

在K8S中,Pod是最基本的运行单元。它与docker容器略有不同,因为pod中可能包含一个或多个容器(可以是Docker容器),这些容器内部共享网络资源,即可以通过localhost相互访问。

关于如何在Pod中实现网络共享,每个Pod启动,内部都会启动一个pause容器(谷歌的image)。它使用默认的网络模式,其他容器的网络设置为它,完成网络共享问题。

如图所示:

v2-8a48a64e1c81a7765b75095321771023_720w.jpg?source=d16d100b

问题2:Master如何将Pod调度到指定的Node上?
这项工作由 Kube-scheduler 完成。整个调度过程通过执行一系列复杂的算法,最终为每个Pod计算出一个最优的目标Node,这是由 Kube-scheduler 进程自动完成的。

最常见的是循环调度 (RR)。当然也有可能我们需要将Pod调度到指定的Node上。我们可以通过将节点的标签(Label)与Pod的节点选择器属性进行匹配来达到指定的效果。

如图所示:

v2-3809b6eb3257b00c8b18ee2b80b9687e_720w.jpg?source=d16d100b

问题三:各个节点和Pod的信息统一在哪里维护,谁来维护?
从上面的Pod调度来看,我们必须有一个存储中心来存储每个节点的每个Pod的资源使用情况、健康状态和基本信息,这样Pod调度才能正常进行。

在 K8S 中,etcd 组件被用作高可用和一致的存储库。该组件可以内置在K8S中,也可以外部构建供K8S使用。

集群上的所有配置信息都存储在etcd中。考虑到各个组件的相对独立性和整体的可维护性,这些存储的数据的增删改查都是统一由Kube-apiserver来调用的,并且apiserver还提供了REST支持,不仅为各个内部组件提供服务但也向集群外的用户公开服务。

外部用户可以通过 REST 接口或 kubectl 命令行工具管理集群,该工具内部与 apiserver 通信。

如图所示:

v2-9e552dfa812c0b290152e15a8356936d_720w.jpg?source=d16d100b

问题四:外部用户如何访问集群中运行的Pod?
前面我们讲了外部用户如何管理K8S,但我们更关心的是内部运行的Pod如何对外访问。

用过Docker的同学应该都知道,如果使用bridge模式,在创建容器的时候会分配一个虚拟IP,外部无法访问该IP。我们需要做一层端口映射,将容器中的端口映射到宿主机的端口Map并绑定,这样外部就可以通过访问宿主机的指定端口来访问容器内部的端口。

那么,K8S的外部访问也是这样实现的吗?答案是否定的,K8S中的情况更加复杂。
因为上面说的Docker是单机模式,一个容器对外暴露一个服务。在分布式集群中,服务往往由多个应用提供,以分担访问压力,而这些应用可能分布在多个节点上,这就涉及到跨主机通信。

这里K8S引入了Service的概念,将多个相同的Pod包装成一个完整的服务,对外提供服务。
至于获取这些相同的Pod,每个Pod在启动时都会设置labels为attribute。在服务中,我们传递选择器Selector,选择与整体服务具有相同Name标签属性的Pod,将服务信息通过Apiserver存储到etcd中,由Service Controller完成。同时在每个节点上启动一个kube-proxy进程,负责从服务地址到Pod地址的代理和负载均衡。

如图所示:

v2-43c22d4add78ea99f22a14124b999d29_720w.jpg?source=d16d100b

问题五:Pod如何动态扩容和伸缩?
既然我们知道服务是由Pod组成的,那么服务的扩展也意味着Pod的扩展。通俗地说,就是在需要的时候将Pod做多个副本,在不需要的时候将Pod缩减到指定的副本数。
在K8S中,使用Replication Controller进行管理,为每个Pod设置一个预期的副本数。当实际副本数量不符合预期时,动态调整数量以达到预期值。所需值可以由我们手动更新,也可以由自动缩放代理更新。

如图所示:

v2-cc38b79a9860bfbdcfc675192eaf93fe_720w.jpg?source=d16d100b

问题 6:各个组件如何协同工作?
最后说一下Kube-controller-manager进程的作用。
我们知道:

  • ectd是作为集群数据的存储中心,
  • 而apiserver是用来管理数据中心,充当其他进程与数据中心通信的桥梁。
  • Service Controller 和 Replication Controller 由 Kube-controller-manager 管理。作为一个守护进程,每个Controller都是一个控制回路,通过apiserver监控集群的共享状态,并尝试将实际状态中不符合预期的变化。
  • 关于Controller,管理器还包括Node Controller、ResourceQuota Controller、Namespace Controller等。

如图所示:

v2-d616ba03d12eded777d6fab8b8d53c8f_720w.jpg?source=d16d100b

总结
本文通过问答的方式不涉及任何深入的实现细节。从整体的角度,从概念上介绍了K8S涉及的基本概念。相关用途包括:

  • Label
  • Selector
  • Replication Controller
  • Service Controller
  • ResourceQuota Controller
  • Namespace Controller
  • Node Controller

与运行过程相关的是:

  • kube-apiserver
  • kube-controller-manager
  • kube-scheduler
  • kubelet
  • kube-proxy
  • pause

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK