zoukankan      html  css  js  c++  java
  • 1-2、kubernetes架构概述和kubernetes基础概念

    kubernetes

    https://draveness.me/understanding-kubernetes

    http://kubernetes.kansea.com/docs/

    master/node:

    • master:API Server、Scheduler、Controller-Manager
    • node:kubelet(集群代理)、docker(容器引擎)、kube-proxy //API Server把任务编排后由Scheduler调度,调度的结果就有kubelet执行

    Pod:Label、Label Selector    //为了统一管理在同一个集群上大量的资源,尤其像pod这样的资源,需要为pod添加一些元数据信息,而Label是其中一种 K:V格式的元数据

    • Label:key=value //在 K:V 上有一定的限制
    • Label Selector   //定义完Label后就可以使用Label Selector根据定义过的条件挑选符合条件的pod资源

    Kubernetes是一个集群,将多台主机的资源整合为一个大的资源池,并进行统一对外提供存储、计算等能力的集群。

    这个集群就是将多台主机上安装上kubernetes的相关应用程序,并通过这个应用程序协同工作,将多个主机当作一个主机来使用。

    在kubernetes集群中,主机是分角色的。一个或一组节点是主节点(两到三个),各node节点中每一个节点都有来贡献一些计算或存储能力。各node节点就是为了运行容器。

    用户如何在集群中创建、启动容器呢?

    客户端把创建、启动容器的请求先发给集群中的master,master中有一个调度器(scheduler)去分析各node节点现有可用资源状态,从中找一个最适合运行用户请求的容器的节点,然后master把这个请求调度到节点上。由被选中节点本地的docker或其他容器引擎负责把这个容器启动起来。要启动这个容器就需要镜像,镜像一般是在docker hub这样的registry当中。所以node负责启动容器时先检查本地是否有镜像,如果本地没有就需要到docker hub中下载,然后在node上启动。kubernetes cluster自身可能并没有托管所需要依赖的每一个容器镜像,就需要到registry下载。同时registry自身也可以是一个容器,因此registry也可以托管在kubernetes集群中运行。

    接受客户端请求的只能是kubernetes cluster,而提供服务让客户端远程访问一般需要一个套接字,所以kubernetes cluster把master上的一个组件称为API SERVER。API SERVER负责接收、解析和处理请求的,如果用户的请求是要创建一个容器,这个容器不应该运行在master上,而应该运行在node上。选择哪一个node更合适,就需要调度器来分析了。调度器会观测每一个node上总共可用的计算和存储资源,并根据用户所请求创建的这个容器所需要的最低资源量(CPU、内存等)来评估哪个节点最合适。注意资源请求的维度不是一个,比如至少用到的CPU或者内存,因此kubernetes设计了一个两级调度的模式,第一步先做预选,即评估每一个node,测量哪些node是符合容器运行需求(必须总共10个点节点只有3符合),第二步是优选,从符合需求的node中再选出一个最佳适配的node。至于哪个node最佳,取决于调度算法中优选算法来决定。

    kubernetes有一堆控制器的应用程序,负责监控管理的每一个容器是否正常运行,一旦发现不健康,控制器就向master发请求,调度器就会在其他node中挑一个合适的node,并在此node上重新启动挂掉的容器。控制器需要在本地不停的loop(循环),即进行周期性探测。

    控制器管理器(control mananger):负责监控每一个控制器是否健康,如果控制器不健康了,有控制器管理器确保它是健康的。为了确保控制器管理器是健康的,就要求控制器管理器是冗余的,因为master是多个节点的,所以可以确保控制器管理器是冗余的。

    Pod

    在K8S上最小运行的单元不是容器,而是pod。kubernetes并不直接调度容器的运行,而是调度pod,pod可以理解为容器的外壳,为容器做了一层抽象的封装。pod是kubernets系统上最小的调度的逻辑单元,pod内部主要就是用来放容器的。

    pod的工作特点: 将多个容器联合起来加入到同一个网络名称空间去。kubernetes做了一个逻辑组件pod,在pod内部运行容器,一个pod内部可以运行多个容器。多个容器共享同一个底层的网络名称空间:net、uts、ipc,另外三个:user、mnt、pid是互相隔离的。因此一个pod内的多个容器(容器是为了运行程序)就共享同一个主机名、同一个网络等,因此程序对外就更像是一个虚拟机,pod就是模拟传统的虚拟机的(用同一个地址对外通信,容器之间的通信是使用lo的)

    另外同一个pod内部的多个容器还共享第二种资源:存储卷。假如定义一个存储卷,让pod中第一个容器可以访问,那么第二个容器可以共享挂载同一个存储卷。可以说存储卷不再属于容器,而是属于pod,就像虚拟机的磁盘。

    调度器调度的是pod,各node主要是为了运行pod。一般一个pod中运行一个容器,如果容器之间联系特别紧密,可以在一个pod中运行多个容器。如果同一pod中放置多个容器的话,那么有一个容器是主容器,其他容器是为了辅助主容器中的应用程序完成更多功能。比如主容器中运行的是nginx,另外想要收集日志,那么就可以在辅助容器中运行收集日志的应用程序。

    为了方便控制器对pod的管理、实现pod的识别,如果一个pod宕机,新建一个同样功能的pod就不是同一个名字,无法使用pod进行识别唯一,就需要在pod上附加一些元数据,有标签(Label)和标签选择器(Label Selector)

    node

    node是kubernetes集群的工作节点,负责运行由master指派的的各种任务,最核心的任务就是以pod的形式去运行容器的。理论上将node可以是任何形式的设备,只要有cpu、内存、存储空间等可以安装kuberneters cluster的代理程序,那么就可以作为整个kubernetes cluster的一个部分进行工作。

    2、kubernetes基础概念

    Pod:

    • 自助式Pod  //pod被创建后,仍然要提交给API Server,由API Server接收后借助于调度器将此pod调度至指定的node节点,由node启动此pod。而后如果此pod中的容器出现故障,需要重启容器,就由kubelet来完成,如果node故障,pod就会消失,建议使用控制器管理的pod。
    • 控制器管理的Pod  
    • Replication Controller:副本控制器(简称RC)
    • ReplicaSet:副本集控制器
    • Deployment
    • StatefulSet
    • DaemonSet
    • Job、Ctonjob

    ReplicationController:副本控制器功能:实现启动pod副本和滚动更新

    启动副本:当启动一个pod时,如果pod不够使用,就可以再启动一个,而RC就是专门控制同一类pod对象的各种副本。一旦副本数量少了,RC就会自动增加一个,多了          就减去一个。比如pod调度到第三个node后,这个node宕机了,那么RC就会发现少了一个pod副本,RC就会重新请求API Server创建一个新的pod,              API Server借助于Scheduler调度,会找另一个node把pod再启动起来。

    RC实现滚动更新:比如更新了镜像,就需要把pod中的容器更新为新的版本的镜像,可以做滚动更新。

    有两种方式:1、先关闭其中一个pod做更新,启动后再关闭另一个;

    2、先创建一个新版本的pod,这时pod就会超出定义的数量,可以在更新过程中临时超出pod的数量。创建一个新版本的pod,去掉一个老版本的pod就可以了。同时也支持滚动更新的逆反,即回滚到老版本。

    下面是实现一种特定的应用管理,是确保不同类型的pod资源符合用户所期望的方式进行运行的:

    ReplicaSet:副本集控制器,这个控制器是不直接使用的,而是有一个声明式更新的控制器(Deployment)来进行管理

    Deployment:只能管理无状态的应用,支持二级控制器,HPA

    HPA:(HorizontalPodAutoscaler)水平Pod自动伸缩控制器,比如对应的控制器下有两个pod在运行,如果流量访问大了,原有的两个pod不足以承载访问量,就需要添加资源,那么加多少资源?HPA就可以自动判断了,且可以自动监控、自动扩展。

    StatefulSet:有状态副本集,管理有状态应用

    DaemonSet:如果需要在每一个node上运行一个副本,不是随意运行就是用DaemonSet。

    Job:运行作业,比如对一大堆数据集进行清理,就会临时启动一个pod,清理完pod就会结束,这种pod就不需要一直处于一种运行状态,就把这种运行为job。但如果还没有清理完,这个任务挂掉了,还需要把它重启起来。

    Cronjob:周期性运行作业

    service   

    http://kubernetes.kansea.com/docs/user-guide/services/

    什么是服务发现:

    pod是有生命周期的,一个pod随时可能消失,另一个pod随时也可能被添加进来。所以无论使用主机名还是IP地址,都无法使用固定的手段访问pod,这里就需要使用服务发现机制。K8S为每一组提供同类服务的pod和客户端之间添加了一层中间层,中间层是固定的,称为service,只要不被删除,它的地址和名称就是固定的,所以客户端访问服务时只需要指向服务(即service)时就行,service会把请求代理到后端的pod之上。当客户端需要访问某个服务时,客户端是不用发现服务的,客户端只需要在配置文件写明这个服务(即service)的IP地址和名称。一旦pod消失,只要新建一个pod就可以,这个新的pod立即会被service关联进来。

    service如何实现关联pod?

    service关联pod依靠固定的元数据--标签,因为service是靠标签选择器关联pod的。只要pod属于这个标签选择器,就立即可以被service挑中,并作为service的后端组件,service把pod动态关联后会探测pod的IP地址、端口,并把这些探测到的内容作为自己调度后端可用服务器主机的对象。因此客户端的请求到达service,然后由service代理至后端pod。注意客户端看到的地址都是service的。在k8s中service不是应用程序也不是实体组件,而是iptables的DNAT规则。DNAT规则中的service的IP地址只出现在规则中,并没有绑定在网卡上,所以是无法ping通的。service作为k8s的对象,是有名称的,名称是可以被解析的,即把service的名称解析为service的IP。

    service名称可以被DNS解析为IP地址,而且是自动的。比如service的名称被修改,那么DNS中的解析记录的名称也会得到相应的修改。service的地址只能手动修改,修改后会自动触发DNS中的解析记录的。客户端访问某一服务时,可直接访问服务的名称,而后由集群中专用的DNS服务负责解析,这里解析的是service的地址。因此这个访问依然是由service替代客户端实现的,这里是端口代理,由DNAT来实现。对于多目标资源,iptables已经把负载均衡的功能交由ipvs来实现。但是由于service后端的pod可能是有多个,k8s就把iptables规则进一步改为ipvs规则,即每创建一个service就相当于生成一条ipvs规则,不过是nat模型的ipvs。

    k8s基本组件

    首先是pod,由于生命周期不固定,所以为它做了一个抽象层-->service;另外如果pod一旦出现故障,就需要控制器能够把pod重建;service和控制器都是通过标签和标签选择器来关联pod资源的。每一个service要想基于名称被客户端访问,要基于DNS服务(DNS域名解析),这个DNS服务本身也是一个pod,这个pod也需要service来控制。另外每一个pod在运行时使用了多少资源、是否故障、接受多少用户访问都是需要监控的。

    k8s的网络模型和通信

    flannel是什么  https://www.huweihuang.com/kubernetes-notes/network/flannel/flannel-introduction.html

    kubernetes网络模型  https://www.huweihuang.com/kubernetes-notes/network/kubernetes-network.html

    默认的节点间数据通信方式是UDP转发,在Flannel的GitHub页面有如下的一张原理图:

    k8s的网络模型

    在k8s中要求有三种网络:

    第一种是各pod运行在一个网络中;

    第二种是service运行在另外一种网络,pod和service是不在同一网段的。pod地址是配置在pod内部的网络名称空间上,是可以ping通的,service的地址是虚拟的,只存在于iptables或者ipvs的规则当中;

    第三种是各节点都有自己的地址,节点的网段是一个网络。

    以上三种网络分别称为pod网络、集群网络(service网络)和节点网络。请求到来先到达节点网络,由节点网络代理至集群网络,再由集群网络代为代理至pod网络。

    k8s中三类通信   https://blog.csdn.net/weixin_29115985/article/details/78963125

    1、同一个pod内的多个容器间通信是依靠lo;

    2、各pod间的通信:Overlay Network(叠加网络),通过隧道的方式来转发二层报文,使得pod间虽然跨主机,但好像工作在一个二层网络上,可以转发对方的二层报文或者隧道转发对方的三层报文,实现叠加网络。

    3、pod与service之间的通信:是通过kube-proxy。pod有自己的网络,service也有自己的网络,两者如何通信?另外各pod客户端可以直接配置service名称和地址进行访问,那么pod如何可达service?由于service的IP是主机上iptables规则中的地址,某一容器在试图访问某一service地址时,会把请求送给service上的网关(每一个宿主机都应该有相应的iptables规则,只要创建了service,这个service就会反映到集群中的每一个节点上,每一个node上都应该有相关的iptables或者ipvs规则),所以一个容器试图访问service地址时,就会把请求发送给service上的网关(一般是docker0桥的地址),然后docker0桥再通过检查iptables规则表就可以知道下一级的service的IP。

    service随时可能变动,service中的pod也会变动,所以service规则中目标地址也会发生变化,那么如何改变所有节点上iptables或者ipvs规则呢?

    这就需要专门的组件kube-proxy,在每个node节点上都存在,运行为node节点的守护进程。kube-proxy随时负责与API-server进行通信,因为每一个pod发生变化后,结果需要保存在API-server,然后API-server中的结果发生变化后就会生成一个通知事件,这个事件可以被任何关联的组件所接收到,比如kube-proxy,kube-proxy一旦发现某一service中的pod的地址发生改变,那么由kube-proxy就会在本地把新的地址反映在iptables或者ipvs规则中。所以service的管理是靠kube-proxy来实现的,创建service后,service的实现要靠kube-proxy来实现,即kube-proxy在每一个节点上创建成规则,每一个service的变动也需要kube-proxy转换反映到规则上。

    API-server需要存储集群中各对象的状态信息,存储在哪里呢?那么各master需要一个共享存储,即etcd。etcd是一个键值存储数据库存储系统,etcd需要做高可用。

    整个API-server集群大概有三类节点组成,第一类是API-master,第二类是etcd,第三类是大量的node。彼此之间的通信是http或者https。

    一共需要5套CA:

    etcd集群之间的通信使用https协议,需要一套CA

    API-server(k8s客户端)与etcd(k8s后端)之间的通信使用https协议(API-server是etcd的客户端),需要一套CA

    API-server为了向真正客户端提供服务需要一套CA

    API-server需要与各node通信,因为各node上有kubelet和kube-proxy两个组件:

    (1)API-server与kubelet通信是https协议,需要一套CA

    (2)API-server与kube-proxy通信是https协议,需要一套CA

              

    整个 API-server 简化后可以分为三类集群:API-server集群、etcd集群、nodes集群

    彼此之间都是http或者https协议通信,然后在node节点上运行pod,pod和pod之间是需要通信的,同时pod内部的容器也是需要通信的,pod与service要通信,pod与集群外的客户端要通信,所以就需要构建出多个网络;

    node节点自己之间的网络、service的网络(也叫集群网络)、pod自己的网络;

    k8s集群的三种网络:

    1、节点之间的网络

    2、节点中有pod,pod之间可以通过叠加网络或者直接路由直接进行通信;

    3、service网络(集群网络):由kube-proxy来进行管控和生成,这样不同节点的pod和pod之间进行通信时,可以借助于固定的中间层(service网络)来实现;

       service网络的网段和pod的网段是不在同一个网段的;

  • 相关阅读:
    C++0x standard & features in VC10
    Win32 结构化异常处理(SEH)探秘
    What Every Programmer Should Know About Memory
    Memory leak detector(C++)
    NT's Asynchronous Procedure Call
    服务器应用程序不可用
    不安全代码只会在使用 /unsafe 编译的情况下出现
    关于“因为数据库正在使用,所以无法获得对数据库的独占访问权”的最终解决方案
    让 PowerDesigner 支持 SQLite!
    基于.Net的单点登录(SSO)解决方案
  • 原文地址:https://www.cnblogs.com/hanshanxiaoheshang/p/10846596.html
Copyright © 2011-2022 走看看