文章转载自:https://mp.weixin.qq.com/s?__biz=MzI1MDgwNzQ1MQ==&mid=2247483736&idx=1&sn=0cbc3d6afe2325c1e01807781c45866d&chksm=e9fdd4acde8a5dba5a91ef4a89c33d0acadfb100357fcbabee7004a624c8182ea7df40a22a98&scene=178&cur_album_id=1341273083637989377#rd

Kubernetes是什么?

Kubernetes其实就是一个集群,从我们此前运维的角度来理解,它就是一个集群,组合多台主机的资源(内存、CPU、磁盘等)整合成一个大的资源池并统一对外提供计算存储等能力的集群。我们找很多台主机,每台主机上面安装Kubernetes的相关程序,而不同的主机程序之间相互通信,从而完成彼此之间的协调,并且通过这些应用程序之间的协同工作,把多个主机当成一个主机来使用,形成一个集群,仅此而已,但是在kubernetes集群当中主机是分角色的,即所谓的有中心结点架构的集群系统,master/nodes模型, 由一组节点用于master不需要太多,一般高可用的话需要三个(根据集群规模来判断),nodes节点(worker节点)就是干活的,Kubernetes上提供的各种资源服务,运行在node节点上面。

用户如何在kubernetes运行容器,逻辑过程是什么?

用户把创建启动容器的请求首先发给master,具体来说是发给了master节点上面的API Server组件, API Server通过调度器,按照预设的调度算法及策略,去分析各node节点上面现有的可用资源状态,然后找一个最佳适配,来运行用户所请求容器的结点,并把它调度上去(这里需要与node节点上面的kubelet交互),并由这个node节点上面本地的docker或其它容器引擎负责把这个容器启动起来,要启动容器,需要有镜像,镜像在哪里呢?在仓库上面,node上面启动容器是会先检查本地是否有镜像(根据镜像拉取策略),如果没有会docker pull下来,然后再启动,kubernetes自身并没有托管自动所依赖的每一个容器镜像,而是需要到仓库中去下载的,仓库可以是私有的,也可以是公有的。

集群在master节点上面提供一个API Server组件,它负责接受请求,解析请求,处理请求的,至于当用户请求的是创建一个容器,最好不要运行在master节点上面,而应该运行在node节点上面,确定哪个node更合适,这个时间就需要scheder调度器,它负责监控每个node节点上面总可用的计算、内存、存储等资源,并根据用户所请求创建的这个容器所需要的资源,docker容器可以做资源限制 ,但在kubernetes上面不但可以设定容器使用资源的上限(阀值),还可以设定资源使用的下限(资源请求量),调度器就是根据容器的最低需求来进行评估,哪一个节点最合适;当然了,资源的评估不只是一个维度,而是从多个维度考虑,这都是调度器scheduler根据调度策略和算法需要考虑的,如果在一个node上面把容器启动起来了,我们还需要对容器中的应用程序的健康状态做监测,我们不但能根据容器中应用程序是否运行判断它的健康状况,还可以根据额外的健康状态探测方式来探测,我们叫做可用性探测机制来探测服务的可用性。如果一旦容器中的应用挂了,我们又需要确保容器中的一个容器要运行,此时怎么办?node节点之上有一个应用程序,这个应用程序就是kebulet,这个应用程序确保容器始终处于健康状态,如果出现问题,它就会通知API Server,然后重新调度;但是有一点,很不幸,这个node节点如果宕机了,那么此前拖管在此node上面的所有容器就挂了,我们知道kubernetes具有自愈的能力,无论是单个容器,还是node节点上面的所有容器,一旦容器不见了,是不需要人工参与的,kubernetes会使用新的个体来取代它,它会在其它node上面创建出来一模一样的容器出来。如何确保这个容器是健康的呢?以及一旦出问题就可以及时被发现呢? 其实kubernetes是通过控制器组件来负责监控它所管理的每一个容器的健康状态,一旦发现不健康了,控制器向master上面 API server发请求,容器挂了一个,你帮我重新调度再启动一个,这里控制器需要在本地不停的loop循环,周期性,持续性的探测所管理的容器的健康状况,一旦不健康,或者不符合用户所定义(期望)的目标,此是调度器就会向用户期待的状态向前移,确保符合用户期望的状态;其实在kubernetes集群中我们有很多很多的控制器,假设我们有一个控制器挂了呢,用于监控容器健康的控制器不健康了,容器的健康状态就无法保证,怎么办?我们在master节点上面有一个控制器管理器,控制器管理器负责控制监控每个控制器的健康状况,控制器管理器如果出现问题怎么办,因此在这里,我们需要对控制器管理器做冗余。

以上我们通过在集群上面创建一个容器的例子,讲解了API Server、scheduler、控制器、控制管理器等。

什么是Pod?

Pod,英文意思是豆荚。大家都知道这种植物,一个豆荚中有几个豆粒。

Kubernetes上面运行的最小单元是Pod, kubernetes并不直接调度容器的运行,而调度的目标是Pod,Pod可以理解为容器的外壳,给容器做了一层抽象的封装,因此pod成为了Kubernetes集群之上最小的调度单位(逻辑单元),Pod内部主要是用来放容器的,Pod有一个特点,一个pod中可以运行多个容器,多个容器共享同一个底层的网络命名空间(底层的net, uts, IPC三个网络命名空间),另外三个命名空间相互隔离(User, mnt, pid),这样一来,同一个Pod上面的多个容器,每个容器上面跑应用程序 ,对外更像是同一台“虚拟机”,这也是kubernetes组织容器的一个非常精巧的办法,基于此我们可以构建较为精细的容器间通信,并且同一个Pod上面的容器,还共享第二种资源,叫做存储卷,存储卷不属于容器,属于Pod,Pod的磁盘,相同pod的容器共享。

各个node节点主要是用来运行Pod的,一般说来,一个Pod上面只放一个容器,除非有特别紧密的关系,需要放在同一个Pod上面,否则,不要放在同一Pod上面;如果确实有需要,将多个容器需要放在一个pod中,通常有一个容器是主容器,其它的容器为辅助容器,辅助容器中的应用程序主要是为了完成更多功能来辅佐主容器工作,这里我们调度器也是调度的pod, node节点上面也是pod, pod是一个原子单元,也就意味着一个pod中有一个容器,还是有多个容器,一旦被调度之后,相同pod上面的容器,只能在同一个node节点上面。

创建Pod时,可以直接创建,并且自主管理的,但它仍然要提交给API Server,由API Server接收以后,通过调度器调度到指定的Node节点上,而node节点启动此Pod,此后如果pod上面的容器出现故障,需要重要重启容器,需要kubelet完成,但是node节点故障了,节点就消失了。还有一种Pod的创建方式,是通过控制器来创建的,后面为讲什么是控制器,它的作用是什么?

Node节点是做什么的?

刚才说了node是kubernetes集群中的工作节点,负责运行由master节点上面指派的各种任务,而最核心的任务是以Pod的形式运行容器的,理解上讲node可以是任何形式的资源设备,只要有传统意义上的内存、CPU、存储资源即可,并且可以安装上Kubernetes集群的应用程序 ,都可以做为k8s集群的一个份子来工作,它是承载资源的。

这样一来终端用户不需要关心应用程序(Pod)在哪个Node节点上面,它就这样脱离了终端用户的视线,终端用户也无需关注应用程序部署在哪个node节点上面的pod,从而真正意义上实现了资源池,从而进行统一管理。

什么是标签,标签选择器是做什么的?

如何让一个控制器管理指定的Pod,例如,我们创建了5个Pod,Pod中运行tomcat容器,我们让一个控制器来管理这一组Pod,为了让Pod能够实现被控制器管理识别,我们需要在Pod上面附加一些元数据(标签),用标签来识别Pod,在创建Pod的时候,或者人为的打上一个标签,让控制器能够识别出标签,进而识别出Pod。我们前面创建了5个 Pod,我们在每一个pod上面加一个标签app, 标签的值叫tomcat (标签:值====> app:tomcat),我们想把这一类找出来,怎么找,我们先找拥有key是app,并且值是tomcat的pod分拣出来。标签是Kubernetes大规模集群管理、分类、识别资源使用的,标签是非常非常重要的凭证,我们是如何把我们感兴趣的标签找到的呢,我们有一个标签选择器/挑选器(selector)组件,标签选择器,简单来讲就是根据标签,过滤符合条件的资源对象的机制,其实标签不只是Pod有,很多其它资源都有,因此这种选择器叫做标签选择器,而不叫pod标签选择器,Kubernetes是Restfull 风格的API,通过http或者https对外提供服务,所以所有Restfull对外提供的服务资源都称为对象,所有的对象都可以拥有标签,所有的标签都可以使用标签选择器来选择,只不过pod是其中一种比较重要的。

什么是控制器,控制器是做什么的,有哪些控制器?

我们刚才讲Pod的时候 ,讲到了创建Pod时,一种是直接创建Pod,Pod删除后,不会自动创建,还有一种创建Pod的方式,是通过控制器创建的Pod,这种控制器管理的Pod, 正是控制器管理器机制的使用。在Kubernetes设计中,Pod完全可以叫做有生命周期的对象,而后由调度器将其调度至集群中的某节点,运行以后,任务终止也就被删除停掉了,但是有一些任务,比如nginx,或者运行一个tomcat,他们是做为守护进程来运行的,这种程序,我们要确保这种pod随时运行,一旦出现故障,需要第一时间发现,要么取代它,要么重启它,要么重建一个新的pod,这种靠人的右眼是无法保证的,而Kubernetes提供了具备这种工作能力的组件叫Pod控制器。

Pod控制器最早的一种叫ReplicationController (副本控制器,早期版本的控制器,也称为Pod控制器), 当我们启动一个pod时,一个不够了,可以再启动一个副本,控制器就是控制同一类资源对象的副本,一旦副本数量少了,就会自动加一个,能够定义要求的副本数,多了就删除,精确符合人们期望的数量,它还可以实现滚动更新,它允许临时添加副本,然后把旧版本的去掉,实现滚动更新;它也允许回滚操作,后来的版本中新加了ReplicaSetController(副本集控制器),而ReplicaSetController也不直接使用,而是有一个声明式更新的控制器叫Deployment,用它来进行管理控制, 我们使用的最多的也是Deployment控制器,而Deployment控制器只能管理哪些无状态的应用,哪么有状态的应用如何控制管理呢?我们使用新的控制器,叫StatefulSet有状态副本集,另外如果我们需要在每个node上面运行一个Pod,而不是随意运行,我们还需要一个DaemonSet,如果我们运行作业,还需要Job, 周期性作业,Cronjob, 这些是常见的Pod控制器;后面的这些控制器都是实现一种特定的应用管理,比如临时运行一个容器去完成删除日志的功能,这个运行完就删除了,我们就可以使用Job控制器管理Pod, 但是如果Job没有运行完挂了,需要重新启动,如果运行完,就删除了,再比如nginx一直需要处于运行状态,就不能使用Job控制器,所以说这么多的控制器是用于确保不同类型的Pod资源,来符合用户所期望的方式来运行,像Deployment控制器还支持二级控制器,叫HPA,叫水平Pod,自动伸缩控制器,比如我们一个控制器控制两个副本在运行,但在资源利用率高的时候,可以自动的伸缩控制,就是使用HPA进行控制,一旦利用率低了,可以自动减少,但要符合我们预期的最小值。

Serveice是什么,为什么需要Service?

到这里我们想到一个问题,Pod是由生命周期的,万一Pod所在Node节点宕机了,Pod有可能需要在其它的 Node节点上面重新创建,而重新创建完成后的pod,跟之前的不是一个,只不过是应用程序一样而已,提供相同的服务,由于每个pod中容器的IP地址就不一样,这样一来就有一个问题,我们客户端怎么去访问这些Pod呢?是利用服务发现机制,首先客户端每一次去访问服务时,客户端是不知道后端的服务是谁的(不知道pod的存在),他需要找一个地方问一句,发现一下,有没有这种服务,这些服务是Pod启动的时候注册到一个类似总线地址上,客户端直接去总线位置去问,有没有,有的话,给一个Pod地址,客户端与Pod地址进行通信;因此尽可能降低这种复杂度,Kubernetes为每一组提供相同功能的Pod和客户端之间添加了一个中间层,这个中间层是固定的,这个中间层就叫service,只要service不删除,它就是固定的,名称也是固定的,当客户端需要访问时,只需要在客户端写上service 主机名|服务器|地址即可,也不需要发现,而这个服务service 是一个调度器,不但提供一个固定稳定的访问入口,只要不删除,它就是稳定的,客户端只需要写service名称即可,服务再把请求代理到后面的pod上面,那么Pod宕机了,新创建的pod会被service立即给关联进来;还会把新加的pod作为service后面的可用资源对象之一,怎么实现的呢?我们知道 客户端与服务器通信是通过IP:Port或者域名:Port形式,而service与后面的pod不是依靠IP:Port的形式(因为pod的主机名和IP经常要变),而是通过Pod上面固定的标签来识别,只要是相同标签的pod,不管主机名和IP怎么变,都会被service通过标签识别,service是通过标签选择器来关联pod的;这样一来,只要pod属于这个标签选择器,就能立即被service能选中,并且做为service后端组件存在,关联进来以后,再动态探测这个pod的IP地址是什么,端口是什么,并做为自己后端可调度的服务器,资源对象, 最后,客户端是通过service代理至后端pod进行通信;意味着客户端看到的地址就是service的地址,而在kubernetes集群上service可不是什么应用程序 ,也不是一个实体组件,它只不过是一个iptables DNAT规则;我们创建一个DNAT 规则 ,我们所有到达xxx地址的,都统统被目标地址转换成yyy地址,DNAT规则只是一个规则 ,而service地址,事实上并没有配置到任何一张网卡上,是不存在的,它仅仅出在规则中,可以ping通的,并且可以做请求中转,能ping通是因为有TCP/IP协议栈。这个IP地址,仅出现在规则中,更重要的是service做为Kubernetes中的对象来讲,它有名称,就相当于这个服务的名字,名称可以被解析,就是把service名称解析成IP,名称解析靠DNS,没错,我们安装完k8s后,第一件事,就是让部署一个DNS Pod,以确保service被解析,这个Pod是Kubernetes自身的服务就需要的pod,所以我们称之为基础性的系统架构级的pod或对象,而且称他们叫集群的附件。

集群附件DNS

DNS附件只是Kubernetes集群中纵多附件中的一个,并且这种DNS有一个很有意义的特点,可以动态的创建,动态的改变,动态的更新,动态的变动,比如,你更新了service名称,DNS中的记录即就会被改变,再比如我们手动修改了service IP ,他会自动触发DNS 服务中的解析记录的更改,所以以后客户端访问service时,可以直接访问服务的名称 ,而由集群中专门的DNS服务来负责解析,解析的是service的地址,不是pod地址,再由service代理访问pod,刚才也说了,这种代理是端口代理,由DNAT实现,可不能忘记service后面中两个或者多个pod,这里的DNAT就是多个目标了,多目标调度,对于linux来讲,大家知道对于iptables来讲,已经把负载均衡的功能主要交给了IPVS,因此如果service背后的同一个服务有多个Pod,并且由DNAT来实现,可能在调度效果上并不尽人意,因此在 Kubernetes 1.11版本以后,已经把iptables规则改成了IPVS规则,也就相当于,当你创建一条service规则时,就创建了一条IPVS规则 ,只不过是NAT模型的IPVS规则,因此还支持用户可以指定任意的调度算法,如轮询、加权、最小连接等,所以你就会发现LVS是我们的基础性服务,以上就是我们所讲的service组件。

1.通俗易懂理解Kubernetes核心组件及原理的更多相关文章

  1. kubernetes应用部署原理

    Kubernetes应用部署模型解析(原理篇) 十多年来Google一直在生产环境中使用容器运行业务,负责管理其容器集群的系统就是Kubernetes的前身Borg.其实现在很多工作在Kubernet ...

  2. 后端技术杂谈11:十分钟理解Kubernetes核心概念

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 本文转自 https://github.com/h2pl/Java-Tutorial 喜欢的 ...

  3. 第16 章 : 深入理解 etcd:基于原理解析

    深入理解 etcd:基于原理解析 本文将主要分享以下三方面的内容: 第一部分,会为大家介绍 etcd 项目发展的整个历程,从诞生至今 etcd 经历的那些重要的时刻: 第二部分,会为大家介绍 etcd ...

  4. Kubernetes Job Controller 原理和源码分析(一)

    概述什么是 JobJob 入门示例Job 的 specPod Template并发问题其他属性 概述 Job 是主要的 Kubernetes 原生 Workload 资源之一,是在 Kubernete ...

  5. Kubernetes Job Controller 原理和源码分析(二)

    概述程序入口Job controller 的创建Controller 对象NewController()podControlEventHandlerJob AddFunc DeleteFuncJob ...

  6. Kubernetes Job Controller 原理和源码分析(三)

    概述Job controller 的启动processNextWorkItem()核心调谐逻辑入口 - syncJob()Pod 数量管理 - manageJob()小结 概述 源码版本:kubern ...

  7. Atitit 深入理解耦合Coupling的原理与attilax总结

    Atitit 深入理解耦合Coupling的原理与attilax总结     耦合是指两个或两个以上的电路元件或电网络等的输入与输出之间存在紧密配合与相互影响,并通过相互作用从一侧向另一侧传输能量的现 ...

  8. [diango]理解django视图工作原理

    前言:正确理解django视图view,模型model,模板的概念及其之间的关联关系,才能快速学习并上手使用django制作网页 本文主要讲解自己在学习django后对视图view的理解 在进入正文之 ...

  9. ch01.深入理解C#委托及原理(转)

    ch01..深入理解C#委托及原理_<没有控件的ASPDONET> 一.委托 设想,如果我们写了一个厨师做菜方法用来做菜,里面有 拿菜.切菜.配菜.炒菜 四个环节,但编写此方法代码的人想让 ...

随机推荐

  1. JDK9对集合添加的优化of方法和Debug追踪

    JDK9对集合添加的优化(of方法) JDK9的新特性: 1.List接口,Set接口,Map接口:里边增加了一个静态的方法of,可以给集合一次性添加多个元素 2.static List of (E- ...

  2. Identity Server 4客户端认证控制访问API

    项目源码: 链接:https://pan.baidu.com/s/1H3Y0ct8xgfVkgq4XsniqFA 提取码:nzl3 一.说明 我们将定义一个api和要访问它的客户端,客户端将在iden ...

  3. FastASR——PaddleSpeech的C++实现

    FastASR 基于PaddleSpeech所使用的conformer模型,使用C++的高效实现模型推理,在树莓派4B等ARM平台运行也可流畅运行. 项目简介 本项目仅实现了PaddleSpeech ...

  4. 比起网易有数BI,也许这款数据可视化软件更适合你!

    有数BI是网易推出的面向企业客户的可视化敏捷BI产品.拥有数据填报和自助式商业智能分析产品,提供网页端和手机端应用,帮助客户快速实现数据填报.多维分析.大数据探索.实时大数据展示和成员分享. 山海鲸可 ...

  5. VMware 无法为处于开启或挂起状态的去你及或快照创建克隆

    VMware 要克隆的时候出现 无法为处于开启或挂起状态的去你及或快照创建克隆 因为属于挂起或者运行中的不能克隆,因为会发生数据的变化

  6. 带你熟悉云网络的“电话簿”:DNS

    摘要:无论你域名怎么解析,最终我还是要用IP和别人通信的.域名只是你的皮囊,IP才是你的灵魂. 本文分享自华为云社区<<跟唐老师学习云网络> - DNS电话簿>,作者: tsj ...

  7. rust中的ref

    理解Rust的引用与借用(好文链接) #![feature(core_intrinsics)] fn print_type_of<T>(_: T) { println!("{}& ...

  8. Docker非root用户使用

    Docker 用户管理 安装Docker后docker相关命令都需要加上sudo才能执行,这里为特定用户添加下权限 Docker群组 不过一般安好docker后该群组已创建 sudo groupadd ...

  9. linux学习随笔2之防火墙

    centos7默认使用的防火墙是firewalld 查看所有打开的端口: firewall-cmd --zone=public --list-ports 更新防火墙规则: firewall-cmd - ...

  10. React报错之Property 'X' does not exist on type 'HTMLElement'

    正文从这开始~ 总览 在React中,当我们试图访问类型为HTMLElement 的元素上不存在的属性时,就会发生Property 'X' does not exist on type 'HTMLEl ...