Kubernetes 学习1 Devops 核心要点和k8s架构概述
一、概述
1、我们以往在去实现安装部署应用程序时我们要去实现部署实现应用手动去做会非常麻烦,所以我们后来便有了工具,像ansible等等,这个工具其实就是一个应用编排工具。他能够安装,配置,服务启动,甚至能够让你按照所定义的Playbok完成对多种应用程序在实现有依赖关系时将我们手工需要配置的工作反应在ansible配置文件playbox中,让其按照playbox定义的方式进行执行,从而完成我们人需要手工执行的运维任务。所以他能够实现把我们手动执行的编排应用程序的任务转化为应用程序本身能够实现的功能。把我们日常应用运维任务注入到这个应用程序中来实现。
二、docker 编排工具
1、同样的,我们讲到了docker,以往我们手工管理的对象是直接部署在操作系统中的应用程序,但是有了docker以后我们的应用程序被容器化了。各种应用程序都被封装在容器中执行。那么我们去使用ansible编排应用程序的时候你会发现他的对象已经发生变化了,这个时候就已经不再是ansible或puppet这样的工具特别适用应用程序的场景。另外,容器化所提供的接口与我们早期传统意义上应用程序的访问,控制,和管理接口是有所不同的。所以docker时代就呼唤新式的面向容器化应用程序的编排工具的实现。所以docker出现等容器化技术出现以后编排工具也随即而来。早期我们在编排上接触的有三款产品:
a、docker compose,他更适合于单机编排。他只能面向一个docker host来执行编排操作。或者说更适用于这种情景,
b、docker swarm,因此docker就不得不额外提供一款工具能够将多主机的docker host,假如我们有多个docker主机,我们期望编排的时候不是面向一台而是拥有一定意义上或一定程度上的调度效果,真正意义上面对集群的编排效果,于是便有了另外一款工具叫docker swarm,我们可以理解为他就是一个能够将多个docker host整合为同一平台之下的管理机制的一个集群工具,能将多个docker host提供的计算资源整合在一起。整合成一个资源池,随后docker compose去编排时只需要面向swarm整合出来的这些资源池编排即可。无论底层是什么或者有几个docker主机
c、docker machine:当然,docker swarm也是一个应用程序可以理解为是docker 自身的一个应用程序。那么对于每一个主机从开始的时候怎么去把它安装成为docker 主机就很关键了,因为这个主机要加入docker swarm资源池成为docker swarm的成员,他首先自己得是一个docker 主机,docker 如何安装上去,如何初始化成它能够直接加入成为docker swarm中的一个成员主机呢?此时我们需要另外一个工具docker machine,他能够将一个主机迅速初始化为能加入docker swarm集群中的先决条件,从而能够成为docker swarm集群的一份子的这么一个预处理工具。
d、这就是人们口中所谓的docker 编排的三剑客。我们知道docker compose面向单个docker host工作。像docker sawrm和docker machine等编排工具就已经不再是面向单机之上去编排应用程序。就像我们的ansible本来就可以面向多台主机执行应用程序编排的。容器化的编排工具也需要面向多机执行编排,而且更重要的是将来我们运行容器时这个容器在不同主机上编排时可能运行同一应用程序,而且同一应用程序如何编排在不同主机上不相冲突等各种任务也都需要由容器编排工具来实现。
2、除了上面所述docker 自身这一组工具之外还有第二类工具。
a、mesos,它是一个IDC的OS,也叫做IDC的操作系统,能够把一个IDC中的所有硬件所提供的计算资源统一调度和分配。但是他所面向的上层接口所提供的不是容器运行的接口,而只是一个资源分配工具。非能够直接托管运行容器的,所以mesos基础之上还必须提供一个面向容器编排的框架,叫做marathon
3、kubernetes
4、早期时候就是上面所述三款工具,当然后来的事实是k8s在这个领域中已经牢牢占据了据说百分之八十以上的份额。一个产品能占据35%以上的市场份额基本就成为自然垄断,80%的话其重要程度就可想而知了。
三、DevOps
1、除了容器编排之外我们在IT的工作领域中通常还有另外几个概念,如DevOps,微服务MicroService,容器,云计算等等。出于业务本身迭代的需要我们对应的开发模式也在不停的发生变化。比如早期从瀑布式的开发模式到后来的敏捷开发。再到后来的精益开发,再到现在我们把运维和开发整合起来形成DevOps,这就是应用模式的开发。而应用程序的架构从早期的单体架构,即一个应用程序把所有功能做在一个软件程序中,早期我们应用程序复杂度相对来说还是比较简单的,所以做成单体架构时没问题,可是后来人们发现单体应用程序难以承载了,因为单体应用程序可能只能装在一个主机上,就算我们横向扩展单体应用程序内部的业务复杂度会导致他的扩展很容易达到上限。于是我们就把单体给分开,比如我们经常用到的AMP,这叫分层架构,单体架构下一个时代就是分层架构。再往后就是微服务。现在为止,人们不只是分层,而是把每一个应用都拆解成一个微小的服务,只干一件事,而后很有可能我们传统上的一个单体应用程序到今天为止需要拆成100个至数百个微型服务,彼此之间进行协作,这样各个微服务彼此之间的调用关系就变得极其复杂了。谁该调用谁,如何确保调用者与被调用者始终是存在的。因此微服务几乎天然和容器相关,因此现在很多微服务架构都是构建在容器之上。因为利用容器本身的特性,分发和部署起来是非常方便的。所以利用此特性将微服务和对应的容器结合起来以后迅速的让他们找到了一个适用于自己落地的实现方案。包括DevOps也是如此。
2、另外,docker技术的出现之前DevOps中的交付环节和部署环节因为环境因素异构的环境导致部署起来及其困难,恰好容器技术的出现完全弥补了这个困难,使得DevOps就非常容易实现了。
3、那么怎么叫DevOps呢?
a、CI:持续集成,从运维的角度来讲,程序员给我们一块新的应用程序,我们需要将其发布到线上,而发布到线上的做法我们可以用蓝绿部署,灰度发布,金丝雀发布等。但是这个应用程序交付到我们运维人员手中之前他们经历了什么呢?一般来讲我们可以理解为有一个开发团队他们首先要做计划,然后做架构设计,然后开始做开发,开发后就开始构建,这个构建的过程我们可以用构建工具进行,我们拿到一个源代码时候就要先编译,这个编译的过程就可以理解为构建的过程。完以后我们还要做测试(单元测试,集群测试,功能测试,技术测试等等),测试完后如果有问题就需要打回去重新修复开发。完成后我们就应该将代码交付给运维了。
假如当程序员写完代码以后的后续过程能自动实现的话我们就称之为持续集成。比如我们用git这样的工具,当我们本地程序员开发完一段代码以后,在本地做完代码存盘并提交以后一旦代码提交到代码仓库中我们有一款构建工具能自动看到他能触发相关的操作,即用户提交代码构建工具会自动从里面拖出来做构建,构建完了以后接下来能够再被测试工具部署到测试环境中自动进行测试,把各种测试都做完。其实他提交存盘后到构建之前还有其它测试,但是此处不说太复杂。这两个维度的测试都没有问题后就进入下一步。如果测试有问题就报告给程序员说这个有问题,就拿回去修复,修复完成后就再次提交再次触发,就再次循环构建,测试,构建测试这么一个过程,最后可以发现这个过程任何一个环节出问题都会打回给程序员让其重新提交。这个过程就是持续集成的过程。整个环节需要人工参与的就是我们的程序开发。对不同的程序来讲他的测试方式是不一样的,因此我们通常需要做自己应用程序的全方位测试的时候还需要开发一些自动化测试工具。所以我们通常可能还有测试开发工程师。有一些程序写完以后完全可以使用市面上一些通用工具里面写一些测试代码来完成测试。
b、CD(Delivery):持续交付。集成完以后就应该交付给运维来实现部署了,那么应该怎么交付呢?如果这里测试完以后还能自动打包到一个可以被运维得到的,或者可以被客户拿到的共享的文件服务器上,或者是一个仓库中,那么让我们的运维工程师能从中得到相关的打包好的最终产品,把这步也能自动实现那就叫持续交付。
c、CD(Deployment):持续部署。同样的逻辑,假如说我们交付完后发布过程也不需要运维工程师做了。交付完后我们有一款运维工具能够自动把这个东西拖出来,把它自动触发以后发布到线上去,那么这就叫持续部署。
d、而这一切能自动循环实现持续不断的每一个环节都向前进行反馈,比如部署完以后在运维过程中会发现可能会触发一些此前未曾发生的bug,把这个信息快速反馈给研发,让研发进行修复,修复完以后再上线又是一系列自动化过程实现。这个过程我们就通常可以将其称为DevOps,其打通了运维和研发的边界,甚至把运维给干掉了。以后对整个持续化的自动化的流水线中的作业这就是作为一个运维工程师应该关注的位置。
4、正是由于容器技术的出现和容器编排工具的实现使得上面这一切容易落地了,原因在于我们构建好的产品要部署在目标平台上,假如目标平台环境各不相同,比如不同版本的linux或windows等,这样我们构建时面向不同的平台可能都会有细微的差别,甚至于显著的差别,没法通过,因此在这里在实现自动构建并实现自动交付的时候这个环节是特别困难的,因此这儿要实现自动部署是特别困难的。我们要在每一个目标环境都构建出一个适用的版本来,但是有了容器后就没问题了。只要目标平台能够运行容器,那么我们应用程序测试完以后打包好以后直接做成一个镜像,而后不管是什么平台我们只需要把镜像运行为容器就可以了。所以使得自动部署本来是一个非常非常难的环节在有了容器后这个问题几乎就迎刃而解。因此正是容器技术的出现使得在DevOps在落地上就完全实现了可能。这就是容器技术带来的好处。
5、以后如果我们把大量的应用都构建在容器中的话很显然他不可能运行在单个主机上,如果运行在多个主机上哪些容器和哪些容器直接需要内部通信或面向对外的客户端进行通信他们如何进行编排,谁被谁所依赖,这是一个非常麻烦的关系,我们要人工管理这几乎是一个无法完成的任务。因为我们在走向微服务化以后,假如有两百个服务,出故障是必然的,指不定每一天都有几个或者十几个出故障,人工去监控或修复是完全来不及的,而且内部的复杂度靠人来梳理也几乎是无法完成的任务。我们必须要用容器编排工具来实现。容器编排工具自身并不能提供DevOps环境,我们需要在掌握了容器编排工具以后把DevOps这种文化构建落地于容器编排平台之上。这儿需要强调的是DevOps本身并不是一种技术。他是一种文化,是一种运动,是一种趋势。就是以往我们需要手工解决的问题用自动化或工具化的方式来突破Dev和Ops之间的范围和屏障。
四、kubernetes
1、kubernetes出现的时间并不长,只有几年的时间,他翻译为中文为舵手,飞行员。他主要是由谷歌的几位工程师所创立,在2014年才首次对外宣布,至目前才5年的时间,kubernetes的开发深受谷歌内部一个叫做Borg(博格)系统的影响。他是谷歌内部已经工作了十几年的容器编排工具。这个新型的技术我们国人倾注了大量的精神和心血,在这个项目的参与中可以算的上是非常不容易。也就是因为kubernetes本身就是站在博格系统的肩上的所以从一出世开始就吸引了太多的目光和关注。因为他翻译为剁手因此他对应的标志也就是一个舵。他的1.0版本大概在2015年7月才发布,至今天已经到了1.16,他的代码托管在github之上。在2017年,亚马逊,微软,阿里云都宣布在其云平台上原生支持k8s。即他支持用户买了云主机后只需一个按钮就可以快速部署出k8s应用,除此之外,有些平台还可以对外提供k8s服务,即用户在上面可以直接部署应用程序。提供容器即服务的环境。也正是这些大型云厂商的支持让k8s本身在业内受到了广泛的认可和支持。而且大概在2017年的10月,docker宣布同时在他们的平台上支持swarm和k8s两种工具,本来swarm是docker试图拿来竞争容器编排工具标准的一款工具。但是docker原生在其企业版发行中同时支持swarm和k8s,同时还有一款容器叫Rocket,他也有一个比较烂的编排工具叫fleet,他直接就放弃了fleet原生使用k8s。他本来也属于coreOs的,CoreOs本来也就是谷歌大力扶持的对象,而且coreOs在2018年已经被红帽收购了,也就意味着红帽准备花大价钱押注在容器编排工具之上了。这还表现在k8s本身也已经成为红帽中Paas Openshift底层核心架构,所以从这个角度来讲k8s只是一个容器编排工具,他还没有到完整的paas这种云计算平台的标准,Openshift就是其中一个实现。我们也可以理解为Openshift就是k8s的发行版。同样的,k8s是很底层的,真正离用户的终端使用,你要自己使用k8s你还需要部署很多工具来解决DevOps或Paas平台的需要。Openshift就是一个集成的解决方案,他里面拥有了Paas平台,DevOps平台中所需要的一切工具链都直接整合进去了。
2、kubernetes的特性
a、自动装箱:基于资源依赖及其约束能够自动完成容器的部署而且不影响其可用性。
b、自我修复:即自愈能力,一旦一个容器崩了,由于容器非常轻量的特点他可以在一秒钟启动。假设镜像是做好的并下载完成的。因此有了k8s这样的容器编排平台以后我们更多关注的是群体而不再是个体。当一个个体坏了后干掉就行了。
c、水平扩展:自动实现水平扩展,一个容器不够再启一个,还不够就再启一个就行了,只要物理平台资源充足就可以无限扩展。
d、服务发现和负载均衡:当我们需要在k8s上运行很多应用程序时程序和程序之间的关系像微服务化以后一个微服务如果依赖于其它服务他可以通过服务发现的方式找到依赖到的服务。更重要的是每一个服务如果我们启用了多个容器他能实现自动做负载均衡。
e、自动发布和回滚
f、秘钥和配置管理:容器化应用程序最大的问题在于我们所配置容器内的应用程序比较困难,我们基于一个镜像启动一个容器以后我们如果期望这个容器中的应用程序换一种配置来运行怎么换呢?在讲dockerfile的时候我们特别讲到说如果我们定义一个entrypoint脚本,这个脚本能够接受用户传递给容器一些变量,把这个变量的值转换为容器内的应用程序可读取的配置信息,从而能完成容器化应用配置。之所以这么麻烦是因为早期的应用程序是面向云原生而开发的。所以这些应用程序通过读取配置文件来获取配置,而云原生开发的最好是能够基于环境变量来获取配置。所以直接改了环境变量的值容器的应用启动起来时就拥有了你所传递给环境变量的配置。但是传统的非云原生的应用程序我们也需要运行在云环境中,也需要让他们能够通过环境变量来获取要怎么办呢?一个折中的办法就是要用entrypoint脚本里面可以写一些exec 这样的语句,而后把用户传递过来的环境变量的值用sed等工具将其替换到应用程序的配置文件中。从而也能使得应用程序启动加载配置文件时能获取到用户通过环境变量传递而来的外部配置信息。这种配置就使得一个镜像能满足用户在不同环境下运行同一个镜像为不同配置容器的容器化应用这样的一个需求。但是在一个编排工具中这种方式肯定是有问题的。毕竟你的配置信息保存到哪儿去?如果我们要用容器编排平台让容器启动自动化了,但每次启动容器时我还要手工去传环境变量的值这是一个很麻烦的事。所以我们需要一个外部的组件自动的组件保存这些配置信息。当镜像启动为容器时,我们只需要让镜像去加载外部的配置中心中的配置信息就能完成配置。配置中心的概念即在大规模管理的应用程序环境中,比如你有20个nginx服务器,这20个nginx就是我们水平扩展以后用来解决同一问题的负载均衡后的upstream server,如果我们要改了一下他的配置文件,那么我们就不得不使用ansible这样的工具将这一类配置推送到每一个服务器上,而后还要让每个服务器重载生效。需要自己去推过去。有一种简单的方法我们可以实现让应用程序加载配置信息时根本就不是通过配置文件来获取。我完全可以把应用程序的配置信息放在一个服务器中,应用程序启动时不是通过本地文件来加载配置信息而是通过另一个三方服务器上所提供的配置信息直接获取。这种好处就是配置的集中化,以后想改配置文件只需要把配置中心中的配置改掉就好了。像这种功能在k8s上可以实现,直接就把这个所谓的配置信息保存在k8s之上的一个对象中,能让每一个用到此配置对象的容器启动时直接加载,模拟了类似于配置中心的作用。
g、存储编排:把存储卷动态供给。也就意味着某一个容器需要用到存储卷时根据容器自身的需求创建能够满足他的需要的存储卷。
h、批处理执行:任务的批量处理
3、kubernetes其实就是一个集群,从我们此前的运维角度来理解的话他就是一个集群,要组合多台主机的资源整合成一个大的资源池并同一对外提供计算,存储等能力的集群。这个集群说白了就是我们找许多台主机每一个主机上都安装上kubernetes的相关应用程序,并通过这个应用程序协同工作。把多个主机当一个主机来使用,仅此而已。前提是我们在每一个主机上都要安装相关的应用程序,让大家在这个应用程序级别上通信从而完成彼此之间的协调。但是在k8s集群中主机是分角色的,我们集群有两种常用模型,一种是P2P的,像redis cluster这种没有中间节点。每一个节点都能直接接收用户请求,能路由请求。第二种就是有中心节点的集群,比如像mysql的主从复制,有一个节点是主节点,其它节点和其进行同步。 在分布式系统时说过像hdfs这种文件系统它们也是有中心节点的,也称之为名称节点。 k8s就属于一个有中心节点架构的集群系统。从这个维度来讲他其实被称为叫 master/nodes模型,即一组节点用来扮演主节点, 主节点不需要太多,一般用来做冗余,有三个就够了,而nodes(worker)指真正提供工作的节点。
上图就反应了k8s的架构特点,有一个或一组节点是主节点,是整个集群的唯一入口,各node节点每一个值都是用来贡献一部分计算能力,存储能力等相关资源的节点。即运行容器的节点。那么用户怎么在这个集群中运行容器呢?很简单,用户请求先发送创建或启动容器的请求给master,master中有一个调度器去分析各node现有的可用资源状态,找一个最佳适配运行用户所请求的容器的节点并把它调度上去由这个node本地的docker或其它容器引擎负责把这个容器启动起来。要启动这个容器肯定是需要镜像的,镜像在何处呢?在docker hub的registry中,所以这个node启动时先检查本地是否有镜像,如果没有的话就先把镜像拖下来再启动。因此我们k8s cluster自身可能并没有托管所需要依赖的每一个容器镜像。而是需要到registry上下载的。不过我们自己也可以建私有registry,registry自己也可以是一个容器。因此我们完全可以把registry托管在k8s集群中。
4、相关组件
a、API Server:刚刚提到了两个概念,第一就是接收请求的只能是k8s cluster,大家知道提供服务让客户端能够远程访问我们一般要通过套接字,套接字提供服务一般都是通过API接口,所以我们客户端要么编程访问要么通过专门编好的客户端程序,比如mysql,mysqlserver监听在3306接口上。我们通过使用mysql客户端程序或PHP或JSP等等代码来连接。所以从这个角度来讲,mysql服务提供的3306端口可以理解为是mysql的api server,对外输出的是API服务。k8s把master之上的一个组件称之为API Server。
b、调度器(Scheduler):API Server只是负责接收请求解析请求处理请求的,如果用户这次的请求是要创建一个容器,这个容器不应该运行在master之上而是应该运行在node之上。那么哪一个node合适呢?那就由调度器来决定,即Scheduler,他负责去观测每一个node之上总共可用的CPU,内存,资源并根据用户所请求创建的这个容器所需要的资源量来进行评估哪一个节点最合适。为此kubernetes设计了一个两级调度的方式来完成调度。第一步先做预算,即评估到底有多少个节点是符合这个容器运行需求的。第二步再做优选,从预选中选出来的节点根据优选算法决定在哪个最佳节点上运行。
c、kubelet:如果我们在某个node上把容器启动起来了,容器中应用程序可以做健康状态检查,我们可以根据容器中定义的健康状态探测方式即可用性探测机制来探测容器的可用性。即一旦容器挂了,我们又需要这个容器始终是运行的要怎么办呢?node上有一个kubelet组件会确保这个容器始终处于健康运行状态的。
d、控制器:但如果这个node节点宕机了那么此前运行在此node上的所有容器也就不见了,刚刚我们说过kubernetes也要有自愈能力,一旦这个容器不见了不需要用户人工参与,只需要用另外一个新的同样的个体来取代他就行了,接下来需要在其它节点上创建出一个一模一样的容器来,问题是如何确保这个容器始终是健康的呢?他一旦故障时候怎么知道他故障了?需不需要持续监控着他呢?所以k8s还有一大堆叫控制器的应用程序,负责去监控他所管理的每一个容器是否是健康的,一旦发现不健康了控制器就负责向API Server发送请求说我的容器挂了一个,你帮我再调度重新启动一个,于是由Scheduler在其它节点中挑一个合适的并启动起来。因此有一个组件叫控制器,他需要在本地不停的loop即周期性探测,比如持续性探测他所管理的容器是否是健康的,一旦不健康或不符合用户所定义的目标工作状态就需要确保他始终不断的向用户所期望的状态靠近,以确保他是符合用户期望的。
e、控制器管理器:现在假如我们有很多很多控制器,那么如果控制器挂了呢?控制器有问题了他又怎么去监控这些应用呢?因此,用于监控容器健康的控制器不健康了那么容器的健康也就无法保证了,那么怎么办呢?在master上我们有第三个组件叫控制器管理器,负责监控着每一个控制器是健康的,如果控制器不健康了由控制器管理器确保他是健康的就可以了。那么如果控制器管理器不健康了呢?因此要在控制器管理器级别做冗余。因此master 是三节点。master每个节点上都有控制器管理器,大家都在的时候这三个控制器管理器只有一个正常工作,他是主节点,其它的都是做冗余的,万一他挂了就在其它节点上启动起来了,因此控制器管理器也被做了高可用。
5、所以从这个角度来讲可以理解为master是集群的大脑,他有三大组件,第一为API Server负责接收并处理请求。第二为Scheduler,调度容器创建的请求。第三为控制器管理器,确保已经创建的容器处于健康状态。当然,控制器管理器是确保控制器健康的,而控制器才是用来确保容器监控的,不过k8s支持众多类型的控制器,控制容器自身健康的只是其中一种,他还有很多种其它的控制器,另外我们以后在k8s之上就不能再这么称呼容器了,因为k8s上最小运行的单元不是容器而是pod。k8s并不直接调度容器的运行,其调度的目标叫pod,其可以理解为容器的外壳,给容器做了一层抽象的封装,所以pod便成了k8s之上最小的调度的逻辑单元。pod内部主要就是用来放容器的,但是pod有一工作特点,他可以将多个容器联合起来加入到同一个网络名称空间中,所以这是pod的特点。也就意味着k8s做了一个逻辑组件叫pod,在pod内用来运行容器。但是一个pod中可以包含多个容器。这多个容器共享同一个底层的网络名称空间。他们共享底层的NET,UTS和IPS三个网络名称空间,另外三个User,mnt,PID是互相隔离的。所以这样一来你会发现一个pod内的多个容器,大家知道容器是为了运行程序的,这多个程序就共享同一个主机名,同一个网络等,对外他们更像是同一个虚拟机,所以Pod是用来模拟传统的虚拟机的。即一个虚拟机上可以运行多个程序,这多个程序拥有同一组地址对外通信,他们彼此之间可以使用lo通信。这算是k8s在组织容器时一个非常非常精巧的办法使得我们可以构建较为精细的容器间通信。这就叫pod,而且同一个Pod内的各容器还共享第二种资源叫存储卷,假如我们要定义一个存储卷,让一个pod的第一个容器能访问,那么第二个容器可以共享挂载同一个存储。所以他们还要共享存储卷,存储卷此时不再属于容器,而是属于Pod。就好像是虚拟机的磁盘,大家知道同一个虚拟机上的多个进程可以访问同一个目录。
6、所以各node主要是为了运行pod,不过一般说来一个pod只放一个容器,除非容器之间有特别特别紧密的关系需要放在同一个pod中。另外如果在同一个pod中需要放多个容器,我们通常只有一个主容器,其它容器是为了辅助这个主容器中的应用程序完成更多功能来实现的。比如elk中,假如我们这个容器中跑的是个nginx,他会生成很多日志,我们要收集日志,通常需要在目标服务器上部署一个日志收集的agent,filbet或logstash,一个容器中只运行一个程序,如果运行了nginx就不能再运行日志收集程序了,因此此时logstash就需要运行在另一个容器中。因此nginx就是主容器,logstash等就是辅助容器,也叫边车。他只是为了辅助主容器的主程序的某些功能而设置的。所以我们的调度器调度的也是pod,我们的node运行也是Pod,并且Pod是一个原子单元,也就意味着一个Pod内无论运行一个容器还是多个容器,一旦我们把某一个pod调度到某node上运行后这一个Pod的所有容器只能运行在同一个node之上。
7、node:node是k8s集群的工作节点,负责运行由master指派的各种任务,而最根本的是他的最核心的任务就是以pod的形式去运行容器。理论上讲node可以是任何形式的其它设备,只要能够装上k8s集群单元程序和存在对应的资源就可以作为k8s集群的一份子来进行工作。
8、所有的pod都运行在一个集群中我们将来想分类管理怎么办呢?比如我们想删除某一类pod要怎么删呢?我想让某个控制器只管理其中一部分Pod,他怎么管理能识别出来这一堆pod呢?这么多pod我们不可能靠pod的名称来识别,pod随时创建一个名称假如是一个独有标识符,那么一个pod因为故障而被重新删除以后重新创建一个新pod这个新pod和原Pod可能名称不一样只不过他内部运行的应用程序是一样的。所以我们不能靠名称来识别,一般而言他不是固定唯一的标识符。同时我们又需要将一类pod归组,比如我们创建四个nginx pod,将来我期望对他们同一管理使用一个控制器,如果我们把控制器删了就把这四个nginx pod同时也删掉了,控制器还需要确保这四个nginx pod都是在的,缺一个就补一个,多一个就杀一个,精确符合我们期望的四个才行。因此他怎么认为目前符合我们期望的有几个他必须要做识别。因此为了能够实现pod识别,我们需要在pod上附加一些元数据。可以直接给其打上标签,这个标签就是key value类型的数据。当然我们在k8s之上标识pod的标签和容器标签是两回事。我们只是是类似的效果,用标签来识别pod,我们创建完Pod后可以直接给pod打上标签,让人能够基于这个标签的值来识别出Pod来,比如我们创建了四个nginx pod我们可以给这四个pod每一个上都加一个标签叫做app。他的值都等于nginx,所以我们将来想把这一类挑出来怎么挑呢?条件就是拥有key叫app,这个app的值就是nginx,这样就可以把其分拣出来了。所以标签是我们在k8s之上管理大规模pod资源并且能够分类识别和管理的非常非常重要的途径和凭证。问题是我们怎么能把这些pod挑出来呢?这种筛选机制就需要标签选择器来实现。即selector。因此简单来讲标签选择器就是一种根据标签来过滤符合条件的资源对象的机制。其实标签不只是Pod能用,很多其它资源都能用,因此这种选择器我们应该叫做标签选择器而不是Pod 标签选择器。因为k8s是一个restful风格的api,通过http或https对外提供api服务。因此restful风格中几乎所有被操作的目标都是对象。所有对象都可用标签选择器来选择,只不过pod是其中最重要的一类对象。