(1) Kubernetes基本概念和术语

    xiaoxiao2024-11-15  100

    目录

    前言

    1、kubernetes架构图

    2、kubernetes基本概念和术语

    2.1 Master

    2.2 Node

     2.3 Pod

    2.4 Label(标签)

    2.5 Replication Controller(副本控制器,RC)

    2.6 Service(服务)

    2.6.1 概念

    2.6.2 kubernetes的服务发现机制

    2.6.3 外部系统访问Service的问题

    2.7 Namespace(命名空间)

    2.8 Annotation(注解)

    3、 Kubernetes工作流程


    前言

    kubernetes是一个完备的分布式系统支撑平台,大部分概念如Node、Pod、Replication Controller、Service等都可以看作是一种“服务”几乎所有的资源对象都可以通过kubernetes提供的kubectl工具(或API编程调用)执行增、删、改、查操作并将其保存在etcd中持久化存储。从这个角度看kubernetes其实就是一个高度自动化的资源控制系统,它通过跟踪对比etcd库里保存的“资源期望状态”与当前环境中的“实际资源状态”的差异来实现自动控制和自动纠错的高级功能。

    1、kubernetes架构图

    更加通俗的展示:

    在集群管理方面,kubernetes将集群中的机器划分为一个Master节点和一群工作节点(Node)。

    其中,在Master节点上运行着集群管理相关的一组进程kube-apiserver、kube-controller-manager、kube-scheduler,这些进程实现了整个集群的资源管理、Pod调度、弹性伸缩、安全控制、系统监控和纠错等管理功能,并且都是全自动完成的。

    Node作为集群中的工作节点,运行真正的应用程序,在Node节点上kubernetes管理的最小运行单元是Pod。Node上运行着kubernetes的kubelet、kube-proxy服务进程,这些服务进程负责Pod的创建、启动、监控、重启、销毁,以及实现软件模式的负载均衡器。

    2、kubernetes基本概念和术语

    2.1 Master

    K8S中的Master指的是集群控制节点,每个k8s集群里都需要有一个master节点来负责整个集群的管理和控制,基本上k8s所有的控制命令都是发给它,由它来负责具体的执行过程,我们后面所有执行的命令基本都是在Master节点上运行的。

    Master节点通常会占据一个独立的X86服务器/一个虚拟机,主要是因为它太重要了,它是整个集群的“首脑”,如果它宕机或者不能用,那么所有控制命令都将失效。

    Master节点上运行着以下一组关键进程:

    kube-apiserver:提供了HTTP Rest接口的关键服务进程,是k8s中所有资源的增、删、改、查等操作的唯一入口,也是集群控制的入口进程,任何对资源的增删该查都要交给APIServer处理后再交给etcd,如上图,kubectl(kubernetes提供的客户端工具,该工具内部是对kubernetes API的调用)是直接和APIServer交互的。kube-controller-manager:如果APIServer做的是前台的工作的话,那么controller manager就是负责后台的。每一个资源都对应一个控制器。而control manager就是负责管理这些控制器的,比如我们通过APIServer创建了一个Pod,当这个Pod创建成功后,APIServer的任务就算完成了。它作为k8s里所有资源对象的自动化控制中心,可理解为资源对象的“大总管”。kube-schedule:负责资源调度进程,相当于“调度室”。kube-schedule负责调度Pod到合适的Node上,如果把scheduler看成一个黑匣子,那么它的输入是pod和由多个Node组成的列表,输出是Pod和一个Node的绑定。 kubernetes目前提供了调度算法,同样也保留了接口。用户根据自己的需求定义自己的调度算法。etcd:etcd是一个高可用的键值存储系统,kubernetes使用它来存储各个资源的状态数据,从而实现了Restful的API。

    2.2 Node

    除了Master,kubernetes集群中的其他机器被称为Node节点,在较早版本中称之为Minion。

    与Master一样,Node节点可以是一台物理机,也可是虚拟机。Node节点才是kubernetes集群中的工作负载节点,每个Node都会被Master分配一个工作负载(Docker容器),当Node节点宕机时,其工作负载会被Master自动转移至其它节点上去。

    Node节点上运行着以下一组关键进程:

    kubelet:负责Pod对应的容器创建、启停、资源监控等任务。同时与Master节点密切协作,实现集群管理的基本功能。kube-proxy:实现kubernetes Service的通信与负载均衡机制的重要组件Docker Engine(docker):Docker引擎,负责本机的容器创建和管理工作。

    Node节点可以在运行期间动态增加到kubernetes集群中,前提是这个节点已经正确安装、配置和启动了上述关键进程,默认情况下kubelet会向Master注册自己,这也是kubernetes推荐的Node管理方式一旦Node被纳入集群管理范围,kubelet进程就会定时向Master节点汇报自身的情报,如操作系统、Docker版本、机器的CPU和内存情况,以及之前有哪些Pod在运行等,这样Master可以获知每个Node的资源使用情况,并实现高效负载均衡的资源调度策略,而某个Node超过指定时间不上报信息时,会被Master判定为“失联”,Node的状态被标记为不可用(Not Ready),随后Master会触发“工作负载大转移”的自动流程

    查看集群Node数量:

    #kubectl get nodes

    通过#kubectl describe node <node_name>查看某个Node详细信息:

    #kubectl describe node kubernetes-node1

     

    [root@master01 /]# kubectl describe node 192.168.0.143 Name: 192.168.0.143 Roles: <none> Labels: beta.kubernetes.io/arch=amd64 beta.kubernetes.io/os=linux kubernetes.io/arch=amd64 kubernetes.io/hostname=192.168.0.143 kubernetes.io/os=linux Annotations: node.alpha.kubernetes.io/ttl: 0 volumes.kubernetes.io/controller-managed-attach-detach: true CreationTimestamp: Sun, 18 Aug 2019 09:49:47 -0400 Taints: <none> Unschedulable: false Conditions: Type Status LastHeartbeatTime LastTransitionTime Reason Message ---- ------ ----------------- ------------------ ------ ------- MemoryPressure False Tue, 20 Aug 2019 08:50:16 -0400 Sun, 18 Aug 2019 09:56:11 -0400 KubeletHasSufficientMemory kubelet has sufficient memory available DiskPressure False Tue, 20 Aug 2019 08:50:16 -0400 Sun, 18 Aug 2019 09:56:11 -0400 KubeletHasNoDiskPressure kubelet has no disk pressure PIDPressure False Tue, 20 Aug 2019 08:50:16 -0400 Sun, 18 Aug 2019 09:56:11 -0400 KubeletHasSufficientPID kubelet has sufficient PID available Ready True Tue, 20 Aug 2019 08:50:16 -0400 Sun, 18 Aug 2019 09:56:11 -0400 KubeletReady kubelet is posting ready status Addresses: InternalIP: 192.168.0.143 Hostname: 192.168.0.143 Capacity: cpu: 1 ephemeral-storage: 17394Mi hugepages-1Gi: 0 hugepages-2Mi: 0 memory: 995892Ki pods: 110 Allocatable: cpu: 1 ephemeral-storage: 16415037823 hugepages-1Gi: 0 hugepages-2Mi: 0 memory: 893492Ki pods: 110 System Info: Machine ID: 03ce6afdf7054de9bf5f87af0eb4ea90 System UUID: E5DF4D56-FB56-A086-30FC-3FACB8DC1DEF Boot ID: 729e4b1a-51d3-4753-b1ec-8e510692140a Kernel Version: 3.10.0-957.21.2.el7.x86_64 OS Image: CentOS Linux 7 (Core) Operating System: linux Architecture: amd64 Container Runtime Version: docker://18.3.1 Kubelet Version: v1.14.2 Kube-Proxy Version: v1.14.2 Non-terminated Pods: (0 in total) Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE --------- ---- ------------ ---------- --------------- ------------- --- Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) Resource Requests Limits -------- -------- ------ cpu 0 (0%) 0 (0%) memory 0 (0%) 0 (0%) ephemeral-storage 0 (0%) 0 (0%) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Starting 22h kubelet, 192.168.0.143 Starting kubelet. Normal NodeHasSufficientMemory 22h (x2 over 22h) kubelet, 192.168.0.143 Node 192.168.0.143 status is now: NodeHasSufficientMemory Normal NodeHasNoDiskPressure 22h (x2 over 22h) kubelet, 192.168.0.143 Node 192.168.0.143 status is now: NodeHasNoDiskPressure Normal NodeAllocatableEnforced 22h kubelet, 192.168.0.143 Updated Node Allocatable limit across pods Normal NodeHasSufficientPID 22h (x2 over 22h) kubelet, 192.168.0.143 Node 192.168.0.143 status is now: NodeHasSufficientPID Warning Rebooted 22h kubelet, 192.168.0.143 Node 192.168.0.143 has been rebooted, boot id: 47626a75-0307-4985-a01b-bae9473b5ee1 Normal Starting 64m kubelet, 192.168.0.143 Starting kubelet. Warning Rebooted 64m kubelet, 192.168.0.143 Node 192.168.0.143 has been rebooted, boot id: e96c7a46-055f-4fb3-a36b-d040b5d28ded Normal NodeAllocatableEnforced 64m kubelet, 192.168.0.143 Updated Node Allocatable limit across pods Normal NodeHasSufficientMemory 64m kubelet, 192.168.0.143 Node 192.168.0.143 status is now: NodeHasSufficientMemory Normal NodeHasSufficientPID 64m kubelet, 192.168.0.143 Node 192.168.0.143 status is now: NodeHasSufficientPID Normal NodeHasNoDiskPressure 64m kubelet, 192.168.0.143 Node 192.168.0.143 status is now: NodeHasNoDiskPressure Normal Starting 18m kubelet, 192.168.0.143 Starting kubelet. Normal NodeHasSufficientMemory 18m (x2 over 18m) kubelet, 192.168.0.143 Node 192.168.0.143 status is now: NodeHasSufficientMemory Normal NodeHasNoDiskPressure 18m (x2 over 18m) kubelet, 192.168.0.143 Node 192.168.0.143 status is now: NodeHasNoDiskPressure Normal NodeHasSufficientPID 18m (x2 over 18m) kubelet, 192.168.0.143 Node 192.168.0.143 status is now: NodeHasSufficientPID Normal NodeAllocatableEnforced 18m kubelet, 192.168.0.143 Updated Node Allocatable limit across pods Warning Rebooted 18m kubelet, 192.168.0.143 Node 192.168.0.143 has been rebooted, boot id: 729e4b1a-51d3-4753-b1ec-8e510692140a

    上面展示了Node的如下关键信息:

    Node的基本信息:名称、标签、创建时间等;Node的当前运行状态:Node启动后会运行一系列的自检工作,在一切正常时设置Node为Ready状态,该状态表示Node处于健康状态,Master将可以在其上调度新的任务了(如启动Pod);Node的主机地址与主机名;Node上的资源数量:描述Node可用的系统资源,包括CPU、内存数量、最大可调度Pod数量等。主机信息当前运行的Pod列表概要信息;已分配的资源使用概要信息,如资源申请的最低、最大允许使用量占系统总量的百分比;Node相关的Event信息。

    2.3 Pod

    Pod是k8s的最重要也是最基本的概念,它是kubernetes集群中运行部署应用或服务的最小单元,可以支持多容器。它的设计理念是支持多个容器在一个Pod中共享网络地址和文件系统,可以通过进程间通信和文件共享这些简单高效的方式组合完成服务。

    如图是Pod的组成示意图,我们看到每个Pod都有一个特殊的被称为“根容器”的Pause容器。Pause容器对应的镜像属于kubernetes平台的一部分,除了Pause容器,每个Pod还包含一个或多个紧密相关的用户业务容器

    为什么k8s会设计出一个全新的Pod的概念并且Pod有这样特殊的组成结构?

    原因1:一组容器作为一个单元情况下,难以对“整体”简单进行判断及有效地进行行动。

    当一个容器死亡时,此时算整体死亡吗?还是算个体死亡?是N/M的死亡率么?引入业务无关并且不易死亡的Pause容器作为Pod的根容器,以它的状态代表整个容器组的状态,简单、巧妙解决这个难题。

    原因2:Pod里面,多个业务容器之间如何解决彼此的通信和文件共享问题?

    Pod里面多个容器共享Pause容器的IP,共享Pause容器挂接的Volume,这样既简化了密切关联的业务容器之间通信问题,也解决了彼此之间的文件共享问题。

    k8s为每个Pod都分配了唯一的IP地址,称之为Pod IP。一个Pod里面的多个容器共享Pod IP地址。k8s要求底层网络支持集群内任意两个Pod之间的TCP/IP直接通信,通常采用虚拟二层网络技术来实现。牢记一点:在kubernetes里,一个Pod里的容器与另外主机上的Pod容器能够直接通信。

    Pod的两种类型:普通的Pod、静态Pod(static Pod)

    静态Pod并不存放在etcd存储内,而是存放在某个具体的Node上的一个具体文件中,并且只在此Node上启动运行。普通Pod一旦被创建,就会被放入到etcd存储中,随后会被kubernetes进程实例化成一组相关的Docker容器并启动起来。

    在默认情况下,当Pod里某个容器停止时,kubernetes会自动检测到这个问题并且重新启动这个Pod(重启Pod里的所有容器),如果Pod所在的Node宕机,则会将这个Node上的所有Pod重新调度到其他Node节点上。Pod、容器与Node的关系如下:

    kubernetes里的所有资源对象都可采用yaml或JSON格式的文件来定义描述:

    apiVersion: v1 kind: Pod metadata: name: myweb labels: name: myweb spec: containers: - name: myweb image: kubeguide/tomcat-app:v1 ports: - containerPort: 8080 evn: - name: MYSQL_SERVER_HOST value: 'mysql' - name: MYSQL_SERVER_HOST value: '3306'

     解释一下上边各个属性含义:

    kind:为Pod表明这是一个Pod的定义

    metadata:

    name:Pod的名字

    labels:资源对象的标签,这里声明myweb拥有一个name=myweb的标签

    spec:声明容器组的定义规则

    定义了容器的名称、对应镜像名称,该容器注入了环境变量(env关键字),并且在8080端口(containerPort,容器的端口号)上启动容器进程。

    Pod的IP+容器端口(containerPort)组成了一个新的概念-------Endpoint,它表示此 Pod里的一个服务进程的对外通信地址。一个Pod也存在多个Endpoint的情况,当我们把Tomcat定义为一个Pod的时候,可以对外暴露管理端口与服务端口这两个Endpoint。

    2.4 Label(标签)

    Label是k8s系统的另外一个核心概念。一个Label是一个key=value的键值对,其中key与value由用户自己指定。Label通常在资源对象定义时确定,也可以在对象创建后动态添加或删除。

    我们可通过给指定的资源对象绑定一个或多个不同的Label来实现多维度的资源分组管理功能,便于灵活、方便地进行资源分配、调度、配置、部署等管理工作。

    一些常用的Label实例如下:

    版本标签:“release”:"stable",“release”:"canary"....环境标签:“environment”:"dev",“environment”:"qa",“environment”:"production",架构标签:"tier":"frontend","tier":"backend","tier":"middleware"分区标签:"position":"customerA","position":"customerB".....质量管控标签:"track":"daily","track":"weekly"

    Label相当于我们熟悉的“标签”,给某个资源对象定义一个Label,就相当于给它打了一个标签,随后可通过Label Selector(标签选择器)查询和筛选拥有某些Label的资源对象,k8s通过这种方式实现了类似SQL的简单又通用的对象查询机制。

    Label Selector可以类比为SQL语句的where查询条件,如name=redis-slave这个Label Selector作用于Pod时,可以类比为select * from pod where pod's name  ='redis-slave'这样的语句。当前有两种Label Selector的表达式:【1】基于等式;【2】基于集合。

    前者采用“等式类”的表达式匹配标签。具体栗子:

    name=redis-slave:匹配所有具有标签name=redis-slave的资源对象;env!=production:匹配所有不具有env!=production的资源对象

    后者使用集合操作的表达式匹配标签,举个栗子:

    name in (redis-master,redis-slave):匹配所有具有标签name=redis-master或者name=redis-slave的资源对象;name not in (php-frontend):匹配所有不具有标签name=php-frontented的资源对象;

    可以通过多个Label Selector表达式的组合实现复杂的条件选择,多个表达式之间用“,”进行分隔即可,几个条件之间是“AND”的关系,即同时满足多个条件,栗子:

    name=redis-slave,env!=productionname not in (php-frontend),env!=production

    Label Selector在kubernetes中的重要使用场景如下几处:

    kube-controller进程通过资源对象RC上定义的Label Selector来筛选要监控的Pod副本的数量,从而实现Pod副本的数量始终符合预期设定的全自动控制流程。kube-proxy进程通过Service的Label Selector来选择对应的Pod,自动建立起每个Service到对应Pod的请求转发路由表,从而实现Service的智能负载均衡机制。通过对某些Node定义特定的Label,并且在Pod定义文件中使用NodeSelector这种标签调度策略,kube-scheduler进程可以实现Pod“定向调度”的特性。

    假设为Pod定义了3个Label:release、env、role,不同的Pod定义了不同的Label值,如下图所示,如果我们设置了“role=frontend”的Label Selector,则会选取到Node1和Node2上的Pod。

    而设置“rolease=beta”的Label Selector,则会选取到Node2和Node3上的Pod。

    小结:使用Label可以给对象创建多组标签,Label和Label Selector共同构成了kubernetes系统中最核心的应用模型,使得被管理对象能够被精细地分组管理,同时实现了整个集群的高可用性。

    2.5 Replication Controller(副本控制器,RC)

    RC是kubernetes集群中最早的保证Pod高可用的API对象,通过监控运行中的Pod来保证集群中运行指定数目的Pod副本。它其实定义了一个期望的场景,即声明某种Pod的副本数量在任意时刻都符合某个预期值,所以RC的定义包括如下几个部分:

    Pod期望的副本数量(replicas);用于筛选目标Pod的Label Selector;当Pod的副本数量小于预期数量的时候,用于创建新Pod的Pod模板(template);当Pod的副本多于预期数量时,RC就会杀死多余的Pod副本。

    一个完整的RC定义的例子,即确保用于tier=frontend标签的这个Pod在整个kubernetes集群中始终只有一个副本:

    apiVersion: v1 kind: ReplicationController metadata: name: frontend spec: replicas: 1 #预期Pod节点副本数量 selector: #标签选择器 tier: frontend template: metadata: labels: app: app-demo tier: frontend spec: containers: - name: tomcat-demo image: tomcat imagePullPolicy: IfNotPresent evn: - name: GET_HOSTS_FROM value: dns ports: - containerPort: 80  我们定义一个RC并提交到kubernetes集群中后,Master节点上的Controller Manager组件就得到通知,定期巡检系统中存活的目标Pod,并确保目标Pod实例的数量刚好等于此RC的期望数量,如果有过多的Pod副本在运行,系统就会停掉一下Pod,否则系统就会再自动创建一些Pod。通过RC,kubernetes实现了用户应用集群的高可用性,并且大大减少了系统管理员的手工运维工作。

    我们以3个node节点的集群为例,说明kubernetes如何通过RC来实现Pod副本数量自动控制的机制。加入我们的RC里定义redis-slave这个Pod需要保持3个副本,系统将可能在其中的两个Node上创建Pod。下图将描述在两个Node上创建redis-slave Pod的情形。

    加入Node2上的Pod2意外终止,根据RC定义的replicas数量2,kubernetes将会自动创建并启动一个新的Pod,以保证整个集群中始终有两个redis-slave Pod在运行。

    如下图所示,系统可能选择Node1或者Node3来创建一个新的Pod:

    此外,在运行时,我们可以通过修改RC的副本数量,来实现Pod的动态缩放(Scaling)功能。

    这可以通过执行kubectl scale命令来一键完成:

    # kubectl scale rc redis-slave --replicas=3

    Scaling的执行结果如下图所示:

    注意:删除RC并不会影响通过该RC已创建好的Pod。为了删除所有Pod,可以设置replicas的值为0,然后更新该RC。另外,kubectl提供了stop和delete命令来一次性删除RC和RC控制的全部Pod。

    RC实现kubernetes应用升级:

    传统升级方式:通过Build一个新的Docker镜像,并用新的镜像版本替代旧版本达到升级目标。

    平滑升级方式:当前系统中10个对应的旧版本的Pod,可以让旧版本的Pod每次停止一个,同时创建一个新版本的Pod,在整个升级过程中,此消彼长,而运行的Pod数量始终是10个,当所有的Pod都已是新版本时,升级过程完成。通过RC的机制,kubernetes很容易就实现了高级实用的特性,即“滚动升级(Rolling Update)”

    在kubernetes 1.2版本后,RC升级为一个新的概念--------Replica Set,即下一代RC。

    它与当前RC的区别:Replica Set支持基于集合的Label Selector(Set-based selector),而RC只支持基于等式的Label Selector(equality-based selector)。

    RC的一些特性与作用:

    通过定义一个RC实现Pod的创建过程及副本数量的自动控制;RC里包含完整的Pod定义模板;RC通过Label Selector机制实现对Pod副本的自动控制;通过改变RC中的Pod副本数量,可以实现Pod的扩容或缩容功能;通过改变RC中Pod模板中的镜像模板,可以实现Pod的滚动升级功能。

    2.6 Service(服务)

    2.6.1 概念

    kubernetes中的每个service就是我们常提起的微服务架构中的一个“微服务”,先前说的Pod、RC等资源对象就是为kubernetes service做“嫁衣”的。如图显示了Pod、RC与service的逻辑关系:

    上图,kubernetes的service定义了一个服务的服务入口地址,前端应用(Pod)通过这个入口地址访问其背后的一组由Pod副本组成的集群实例,Service与其后端Pod副本集群之间则是通过Label Selector来实现“无缝对接”。而RC的作用实际上就是保证Service的服务能力和质量始终处于预期的标准。

    Service不是共用一个负载均衡器的IP地址,而是每个Service分配了一个全局唯一的虚拟IP地址,即Cluster IP,这样每个服务就变成了具备唯一IP地址的“通信节点”,服务调用就变成了最基础的TCP网络通信问题。

    我们知道Pod的Endpoint地址会随着Pod的销毁和重新创建而发生改变,因为新Pod的IP地址与之前旧Pod的不同。而Service一旦创建,kubernetes就会自动为它分配一个可用的Cluster IP,而在Service的整个生命周期内,它的Cluster IP不会发生改变。关于地址改变问题:只要用Service的name与Cluster IP地址做一个DNS域名映射即可完美解决。关于Endpoint列表,我们可以通过#kubectl get endpoints来查看

    2.6.2 kubernetes的服务发现机制

    任何分布式系统都会涉及“服务发现”这个基础问题,kubernetes采用了直观朴素的思路去解决这个问题。

    每个kubernetes中的Service都有一个唯一的Cluster IP以及唯一的名字,而名字是开发者自己定义的,部署的时候也没必要改变,所有完全可以固定在配置中。接下来的问题就是如何通过Service的名字找到对应的Cluster IP?

    最早的时候kubernetes采用了Linux环境变量的方式解决这个问题,即每个Service生成一些对应的LInux环境变量(ENV),并在每个Pod的容器启动时,自动注入这些环境变量。

    kubernetes通过Add-On增值包的方式引入了DNS系统,把服务名作为DNS域名,程序就可以直接使用服务名来建立通信连接了,目前kubernetes的大部分应用都已经采用了DNS这些新兴的服务发现机制。

    2.6.3 外部系统访问Service的问题

    kubernetes中存在“三种IP”,分别如下:

    Node IP:Node节点的IP地址Pod IP:Pod的IP地址Cluster IP:Service的IP地址

    首先,Node IP是kubernetes集群中每个节点的物理网卡的IP地址,真实存在的物理网络,所有属于这个网络的服务器之间都能通过这个网络直接通信,不管它们中是否有部分节点不属于这个kubernetes集群。这也表明了kubernetes集群之外的节点访问kubernetes集群之内的某个节点或者TCP/IP服务的时候,必须要通过NodeIP进行通信。

    其次,Pod IP是每个Pod的IP地址,它是Docker Engine根据docker()网桥的IP地址段进行分配的,常为虚拟的二层网络。kubernetes要求位于不同Node上的Pod能够彼此直接通信,所有kubernetes里一个Pod里的容器访问另外一个Pod里的容器,就是通过Pod IP所在的虚拟二层网络进行通信的,而真实的TCP/IP流量则是通过Node IP的物理网卡流出的。

    最后,关于Service的Cluster IP,它也是一个虚拟的IP,但是更像是一个“伪造”的IP网络,原因如下:

    Cluster IP仅仅作用于kubernetes Service这个对象,并由kubernetes管理和分配IP地址(来源于Cluster IP地址池)Cluster IP无法被ping,应为没有一个“实体网络对象”来响应Cluster IP只能结合Service Port组成一个具体的通信端口,单独的Cluster IP不具备TCP/IP通信的基础,并且它们属于kubernetes集群这样一个封闭的空间,集群之外的节点如果要访问这个通信端口,则需要做一些额外的工作在kubernetes集群之内,Node IP网、Pod IP网与Cluster IP网之间的通信,采用kubernetes的特殊路由规则。

    由此可知,Service的Cluster IP属于kubernetes集群内部的地址,无法在集群外部直接使用这个地址。比如web端的服务模块,我们可采用 NodePort来解决,在其Service文件中定义nodeport端口,我们在浏览器里服务http://<nodeport IP>:nodeport/

    NodePort的实现方式是在kubernetes集群里的每个Node上为需要外部访问的Service开启一个对应的TCP监听端口,外部系统只需任意一个Node的IP地址+r具体的NodePort端口号即可访问此服务。在任意Node上运行netstat命令,可看大所有NodePort端口被监听:#netstat -tlp | grep 8080

    当然,NodePort并没有完全解决外部访问Service的所有问题,比如负载均衡问题。

    2.7 Namespace(命名空间)

    namespace用于实现多租户的资源隔离。它通过将集群内部的资源对象“分配”到不同namespace中,形成逻辑上分组的不同项目、小组或用户组,便于不同的分组在共享使用整个集群的资源的同时还能被分别管理。

    kubernetes集群在启动后,会创建一个名为“default”的Namespace,通过kubectl可以查看到:#kubectl get namespaces

    如果不特别指明Namespace,则用户创建的Pod、RC、Service都将被系统创建到这个默认的名为default的Namespace中。Namespace的定义很简单,如下所示yaml定义了名为development的Namespace。

    apiVersion: v1

    kind: Namespace

    metadata:

      name: development

    2.8 Annotation(注解)

    Annotation与Label类似,也是以key-value键值对的形式进行定义。不同的是Label具有严格的命名规则,它定义的时kubernetes对象的元数据(Metadata),并且勇于Label Selector,而Annotation则是用户任意定义的“附加”信息,以便于外部工具进行查找,而kubernetes的模块自身会通过Annotation的方式标记资源对象的一些特殊信息。

    通常来说,用Annotation来记录的信息如下:

    build信息、release信息、Docker镜像信息等,例如时间戳、release id号、PR号、镜像hash值、docker registry地址等日志库、监控库、分析库等资源库的地址信息程序调试工具信息团队的联系信息

    3、 Kubernetes工作流程

    【1】创建一个包含应用程序的Develpment的yml文件,然后通过kubectl客户端工具发送给ApiServer;【2】ApiServer接收到客户端的请求并将资源内容存储到数据库etcd中【3】Controller组件(包含scheduler、replication、endpoint)监控资源变化并作出反应【4】ReplicaSet检查数据库变化,创建期望数量的Pod实例【5】Scheduler再次检查数据变化,发现尚未被分配到具体执行节点(Node)的Pod,然后根据一组相关规则将Pod分配到可以运行它们的节点(Node)上,并更新数据库,记录Pod分配情况。【6】kubelet监控数据库变化,管理后续Pod的生命周期,发现被分配到它所在的Node节点上运行的那些Pod。如果找到新的Pod,则会在该节点上运行这个新的Pod,也就是告诉Doeck Engine运行这个Pod【7】kuberproxy运行在集群各个主机上,管理网络通信,如服务发现、负载均衡。例如当有数据发送到主机时,将其路由到正确的pod或容器。对于从主机上发出的数据,它可以基于请求地址发现远程服务器,并将数据正确路由,在某些情况下会使用轮训调度算法(Round-robin)将请求发送到集群中的多个实例。
    最新回复(0)