Kubernetes是一个开源容器编排引擎,用于容器化应用程序的自动部署、扩展和管理。然而,并不是所有的项目都需要微服务,也不是所有的项目都需要Kubernetes。比如管理后台、定时任务服务、非分布式数据库等不需要容器化部署。Kubernetes更适合部署分布式微服务应用。这两天,笔者看完了《Kubernetes源码剖析》这本书。由于Kubernetes是用go语言编写的,所以很多Java程序员可能没有学过go语言。为了分享这本书,作者将书中的一些关键知识点提取出来,整理成本文,也希望能通过本文帮助大家了解Kubernetes。(之前公司内部技术分享画的学习路线思维导图)Kubernetes架构图(图片来源:《Kubernetes源码剖析》.Kubernetes架构图)Kubernetes系统采用C/S架构设计,系统架构分为Master和Node.Server端(主节点),Node是Client端(工作节点)。主控节点作为集群的大脑,负责管理所有工作节点(Nodes),调度Pod在哪些工作节点上运行,控制集群运行过程中的所有状态,其中节点代表云虚拟服务器。Nodeworker节点负责管理容器,监控和报告运行在该节点上的所有Pod的运行状态。主控节点上运行的组件包括kube-apiserver、kube-controller-manager、kube-scheduler组件。kube-apiserver负责以RESTful方式暴露Kubernetes“资源组/资源版本/资源”并提供服务。集群中的所有组件都通过kube-apiserver组件来操作资源对象。kube-apiserver组件也是集群中唯一与Etcd集群交互的核心组件。kube-controller-manager管理着Kubernetes集群中的节点(Node)、Pod副本、服务、端点(Endpoint)、命名空间(Namespace)、服务账户(ServiceAccount)等。负责确保Kubernetes系统的实际状态收敛到期望的状态。它默认提供了一些控制器(Controllers),如DeploymentControllers控制器、StatefulSet控制器、Namespace控制器和PersistentVolume控制器。每个controller通过kube-apiserver组件提供的接口实时监控整个集群中各个资源对象的当前状态,当出现导致系统状态发生变化的故障时,尝试将系统状态恢复到想要的状态。kube-scheduler调度器组件负责在Kubernetes集群中为Pod资源对象寻找合适的节点并在该节点上运行。调度器一次只调度一个Pod资源对象,为每个Pod资源对象寻找合适节点的过程就是一个调度周期。调度器组件监控整个集群的Pod资源对象和Node资源对象,当监控到新的Pod资源对象时,通过调度算法为其选择最优节点。运行在Node工作节点上的组件包括kubelet、kube-proxy和container组件。kubelet负责接收、处理和上报kube-apiserver组件下发的任务。kubelet进程启动时,会向kube-apiserver注册节点自身的信息。主要负责节点(Node)上Pod资源对象的创建、修改、监控、删除、驱逐和Pod生命周期管理。kubelet组件实现了三个开放接口,分别是CRI(ContainerRuntimeInterface)、CNI(ContainerNetworkInterface)和CSI(ContainerStorageInterface)。kube-proxy作为节点上的网络代理运行在每个Kubernetes节点上。它监控kube-apiserver服务和端点资源变化,通过iptables/ipvs配置负载均衡器,为一组Pod提供统一的TCP/UDP流量转发和负载均衡功能,但只向Kubernetes服务及其后端Pod发出请求。资源概念在kubernetes中,资源是核心概念,整个生态系统围绕资源运行。Kubernetes本质上是一个资源控制系统,负责注册、管理、调度资源和维护资源的状态。Kubernetesgroupsandversionsresources:Group:资源组Version:资源版本Resource:ResourceKind:资源类型(category)资源对象和资源操作方式:ResourceObject(资源对象):一个资源对象包含资源组,资源版本等字段,资源类型;资源操作方法(Verbs):每个资源都有一个资源操作方法来实现对Etcd的CURD操作。kubernetes支持的八种资源操作方式分别是create、delete、deletecollection、get、list、patch、update、watch。Kubernetes支持两种类型的资源组,带组名的资源组和不带组名的资源组:带组名的资源组:它们的表示形式是//,比如apps/v1/deployments;没有组名的资源组:一个核心资源组,用/表示,比如/v1/pods。Kubernetes提供的RestfulAPI使用GVR(资源分组/资源版本/资源)生成路径,如下表所示:PATH资源资源操作方法/api/v1/configmapsConfigMapcreate,delete,deletecollection,get,list,patch,update,watch/api/v1/podsPodcreate,delete,deletecollection,get,list,patch,update,watch/api/v1/servicesServicecreate,delete,deletecollection,get,list,patch,update,watch资源groupwithgroupname资源组的路径以/apis为前缀,没有组名的资源组的路径以/api为前缀。以/api/v1/configmaps为例,v1为资源版本号,configmaps为资源名称。资源也可以有子资源,例如pod有日志子资源。使用kubectl查询日志,命令为kubectllogs[pod],对应的API路径为:/api/v1/pods/logs。Kubernetes支持8种资源操作方式,但并不是每个资源都需要支持8种资源操作方式。比如pods/logs子资源只有get操作方法,因为log只需要进行查看操作。Kubernetes系统支持命名空间(Namespace),每个命名空间相当于一个“虚拟集群”,不同的命名空间可以相互隔离。命名空间经常用来划分不同的环境,比如生产环境、测试环境、开发环境等使用不同的命名空间,也可以用来划分不相关的项目,比如项目A和项目B。资源对象描述文件定义Kubernetes资源可以分为内置资源和自定义资源,都是通过资源对象描述文件来定义的。一个资源对象需要用五个字段来描述,分别是Group/Version、Kind、MetaData、Spec、Status。以Service资源描述文件为例,配置如下:apiVersion:v1kind:Servicemetadata:name:test-servicenamespace:defaultspec:....apiVersion:Group/Version,Service在核心资源组中,所以有为无资源组名,v1为资源版本;Kind:资源类型;MetaData:定义元数据信息,如资源名称、命名空间等;Spec:描述Service的预期状态;Status:描述资源对象的实际状态,隐藏,无需配置,由Kubernetes系统提供并更新。Pod调度Pod资源对象支持优先级和抢占机制。kube-scheduler调度器运行时,会根据Pod资源对象的优先级进行调度。高优先级的Pod资源对象排在调度队列的前面,先得到合适的节点(Node),然后低优先级的Pod资源对象选择合适的节点。当高优先级的Pod资源对象没有找到合适的节点时,调度器会尝试抢占低优先级的Pod资源对象的节点。抢占过程是将低优先级的Pod资源对象逐出节点,让高优先级的Pod资源对象运行在本节点上,被逐出的低优先级Pod资源对象会重新进入调度队列等待再次选择合适的节点。默认情况下,如果不开启优先级功能,则现有Pod资源对象的优先级为0。为Pod资源配置优先级的步骤如下:1.通过PriorityClass资源对象描述文件创建一个PriorityClass资源对象。配置文件如下:apiVersion:scheduling.k8s.io/v1kind:PriorityClassmetadata:name:MainResourceHighPriorityvalue:10000globalDefault:falseddescription:"highestpriority"value:表示优先级,值越大优先级越高;globalDefault:是否是全局默认,当Pod没有指定优先级使用时,默认使用这个优先级。2.修改Pod资源对象描述文件,为Pod指定优先级。通过Deployment配置Pod资源时,只需要在Deployment描述文件的Spec下的Spec中添加一个名为priorityClassName的配置,如下:apiVersion:apps/v1kind:Deploymentmetadata:name:test-servernamespace:defaultspec:replicas:1#配置podspec:containers:-name:test-server-podimage:test-server:latestimagePullPolicy:IfNotPresentports:-name:http-portcontainerPort:8080envFrom:-configMapRef:name:common-configserviceAccountName:admin-sapriorityClassName:MainResourceHighPriority亲和调度还有affinityscheduling与调度相关。kube-scheduler调度器自动为Pod资源对象选择全局最优或局部最优的节点(即节点的硬件资源足够,节点负载足够小等)。在生产环境中,一般希望能够更多地干预Pod资源对象的调度。例如,为没有GPU硬件资源的节点分配不需要依赖GPU硬件资源的Pod资源对象,为需要依赖GPU硬件资源的Pod资源对象分配。分配给具有GPU硬件资源的节点。开发者只需要对这些节点进行相应的标注,调度器就可以通过标注对Pod资源对象进行调度。这种调度策略称为亲和性和反亲和性调度。Affinity:用于多服务就近部署,例如让两个服务(如广告点击服务和IP查询服务)的Pod资源对象尽可能调度在同一个节点上,减少网络开销;anti-affinityAnti-Affinity:允许一个业务Pod资源对象的多个副本被调度到不同的节点上,实现高可用。比如订单服务的POD期望有3个副本,这3个副本分别部署在不同的节点上。在节点上。Pod资源对象目前支持两种亲和和一种反亲和:NodeAffinity:节点亲和,将Pod资源对象调度到特定节点,比如将需要GPU的POD调度到有GPU的节点;PodAffinity:Pod资源对象亲和性,将一个Pod资源对象调度到与另一个Pod资源对象相邻的位置,比如调度到同一主机,调度到同一硬件集群,调度到同一机房,缩短网络传输Delay;PodAntiAffinity:Pod资源对象反亲和性,将一个Pod资源对象的多个副本调度到不同的节点,调度到不同的硬件集群等,可以降低风险,提高Pod资源对象的可用性。内置调度算法kube-scheduler调度器默认提供两种调度算法,分别是预选调度算法和首选调度算法。预选调度算法:检查节点是否满足运行“待调度的Pod资源对象”的条件,如果满足则加入可用节点列表;最优调度算法:为每个可用的节点计算一个最终的分数,kube-scheduler调度控制器会把分数最高的节点作为最优运行“待调度的Pod资源对象”的节点。本文转载自微信?「爪哇艺术」,可通过以下二维码关注。转载本文请联系爪哇艺术公众号。
