kubernetes云原生k8s标签选择器使用详解

Posted 小码农叔叔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kubernetes云原生k8s标签选择器使用详解相关的知识,希望对你有一定的参考价值。

目录

一、标签选择器来源

二、什么是标签选择器

2.1 标签选择器概述

2.2 标签选择器概述属性

三、标签使用场景

四、标签选择器特点

4.1 基本特点

4.2 核心标签选择器

4.3 补充说明

五、标签选择器常用操作命令

5.1 前置准备

5.2 常用操作命令

5.2.1 查看namespace下的标签

5.2.2 查看 deploy控制器标签

5.2.3 查看node节点标签

5.2.4 给Pod资源打标签

5.2.5 给Pod资源更新标签

5.2.6 使用标签选择器筛选

5.2.7 删除标签

六、标签选择器案例演示

6.1 查看当前k8s集群的节点信息

6.2 给工作节点打上标签

6.3 创建一个yaml文件,使用上面创建的标签选择器

七、写在结尾


一、标签选择器来源

对于k8s中pod来讲,使用pod控制器创建的pod发生故障后,重建后的pod的ip地址和名称是变化的,为了解决pod访问问题,我们可以创建service,通过访问service的ip地址就可以正常访问到pod,那么问题来了,service是怎样去关联pod的呢?

我们知道在k8s中如果使用pod控制创建的pod,pod发生故障后,对应pod会被对应的控制器重启或重建,一个pod重建以后,对应的ip地址和名称都会发生变化,所以靠ip地址和名称关联pod是不行的,那靠什么关联pod呢?

在k8s上是使用的标签和标签选择器的机制实现资源和资源间相互关联的

二、什么是标签选择器

2.1 标签选择器概述

K8S提供了一种机制来为资源进行分类,那就是Label(标签),同一类资源会拥有相同的标签,具体形式是key-value的标记对,可以在创建资源的时候设置,也可以在后期添加和修改;

1、可以附加到各种资源对象上,如Node,Pod,Service,RC等,一个资源拥有多个标签,可以实现不同维度的管理;

2、给某个资源对象定义一个Label,就相当于给它打了一个标签,可以通过Label Selector(标签选择器)查询和筛选拥有某些Label的资源对象,K8S通过这种方式实现了类似SQL的对象查询机制;

2.2 标签选择器概述属性

每个资源都存在多维度属性,比如下面这些标签:

  • 版本标签:"release" : "stable" , "release" : "canary"...
  • 环境标签:"environment" : "dev" , "environment" : "production";
  • 架构标签:"tier" : "frontend" , "tier" : "backend" , "tier" : "middleware";
  • 分区标签:"partition" : "customerA" , "partition" : "customerB"...

不同的场景可以选择具有合适属性功能的标签进行使用

三、标签使用场景

  • 未使用标签的时候,集群中pod比较多的情况下,分散难以管理,如果需要部署不同版本的应用到不同的环境中,操作起来比较麻烦;
  • 如果给不同的pod打上标签之后,就可以进行集中式管理,方便运维;

四、标签选择器特点

4.1 基本特点

  • 是Kubernetes核心的分组机制,通过label selector客户端/用户能够识别一组有共同特征或属性的资源对象;
  • 对应的资源打上标签后,可以使用标签选择器过滤指定的标签;

4.2 核心标签选择器

matchLabels

用于定义一组Label , 基于等值关系(等于、不等于) ,类似于SQL语句中的=或!=

matchExpressions

基于集合关系(属于、不属于、存在) ,类似于SQL语句中的in或 not in;

4.3 补充说明

如果同时设置了matchLabels和matchExpressions,则两组条件为 AND关系,即需要同时满足所有条件才能完成Selector的筛选。

五、标签选择器常用操作命令

5.1 前置准备

在上一篇,通过下面这种方式导出了一个nginx.yaml,然后通过yaml创建了一个pod

kubectl create deployment test-nginx3 --image=nginx:1.23.0 --namespace default -o yaml --dry-run=client > ./nginx.yaml

默认情况下查看pod时不会列出任何标签

5.2 常用操作命令

5.2.1 查看namespace下的标签

kubectl get pod -n default --show-labels

这里显示的标签名称,正是导出的nginx.yaml中的下面这里的配置

5.2.2 查看 deploy控制器标签

kubectl get deploy -n default --show-labels

5.2.3 查看node节点标签

kubectl get node --show-labels

5.2.4 给Pod资源打标签

kubectl label pod pod名称 -n default 标签名称

再次查看标签时:kubectl get pod -n default --show-labels  ,可以看到上述打的标签就有了

5.2.5 给Pod资源更新标签

kubectl label pod pod名称 -n default version=2.0 --overwrite

比如在上面那个pod,已经打上了version=1.0,现在将其标签更新为2.0;

5.2.6 使用标签选择器筛选

kubectl get pod -l "标签名称" -n default --show-labels

比如这里我们筛选一下上面给nginx这个pod打的version=2.0这个标签;

5.2.7 删除标签

kubectl label pod pod名称 -n default version-

删除上面这个version=2.0的标签

六、标签选择器案例演示

在上文谈到,使用标签选择器可以很方便的对pod进行管理,举例来说,k8s集群中有很多个工作(node)节点,运维人员在明确了各工作节点的配置前提下,希望在开启某个pod的时候,这个pod被调度到特定的节点上,而不是使用k8s默认的调度策略,这时候就可以先通过给工作节点打标签,然后在启动pod的时候,使用标签选择器选择这个标签即可达到这个目的;

针对上面这个需求,通过实操演示下;

6.1 查看当前k8s集群的节点信息

目前一个master节点,和一个工作节点

6.2 给工作节点打上标签

kubectl label node izbp1hgw1v5d5y7bpvejtwz env=node1

6.3 创建一个yaml文件,使用上面创建的标签选择器

apiVersion: v1
kind: Pod
metadata:
  name: test-nginx-label
spec:
  containers:
  - name: nginx
    image: nginx:1.23.0
    imagePullPolicy: IfNotPresent
  nodeSelector:
    env: node1

执行之后,可以看到就成功创建了一个pod,并且使用的是自己创建的这个标签选择器;

七、写在结尾

标签的思想最早在docker容器中比较常见,尤其是在生产环境下,当docker容器的数量非常庞大的时候,为了更好的管理不同环境不同版本下的docker容器时,方便运维更好更快捷的找到对应的docker容器,标签这一概念就显得很实用了,k8s中使用标签的思想也源于此,在日常开发中,也可以适当的考虑将标签这一设计思想进行运用。

云原生一文细数kubernetes常见20道问题

  • 1、K8S是什么?

  • 2、容器和主机部署应用的区别是什么?

  • 3、K8S架构的组成是什么?

  • 4、kubenetes针对pod资源对象的健康监测机制

  • 5、如何控制滚动更新过程?

  • 6、镜像下载策略是什么?

  • 7、image的状态有哪些?

  • 8、pod的重启策略是什么?

  • 9、K8S中部署应用版本回滚的命令

  • 10、标签和标签选择器的作用是什么?

  • 11、常用的标签分类有哪些?

  • 12、查看标签的方式?

  • 13、添加、修改觉删除标签的命令

  • 14、DaemonSet资源对象的特性

  • 15、Pod的生命周期有哪些状态?

  • 16、创建一个Pod的流程是如何的?

  • 17、删除一个Pod的流程是如何的?

  • 18、K8S的service是什么?

  • 19、K8S如何进服务注册?

  • 20、K8S数据持久化的方式有哪些?

1、K8S是什么?

Kubenetes是一个针对容器应用,进行自动部署,弹性伸缩和管理的开源系统。主要功能是生产环境中的容器编排。

关于K8S网上有很多介绍,大家可以根据自己的理解讲出来。

2、容器和主机部署应用的区别是什么?

容器的中心思想就是秒级启动;一次封装、到处运行;

这是主机部署应用无法达到的效果,但同时也更应该注重容器的数据持久化问题。另外,容器部署可以将各个服务进行隔离,互不影响,这也是容器的另一个核心概念。

3、K8S架构的组成是什么?


主节点主要用于暴露API,调度部署和节点的管理;

计算节点运行一个容器运行环境,一般是docker环境(类似docker环境的还有rkt),同时运行一个K8s的代理(kubelet)用于和master通信。

计算节点也会运行一些额外的组件,像记录日志,节点监控,服务发现等等。计算节点是k8s集群中真正工作的节点

Master节点:

  • Kubectl:客户端命令行工具,作为整个K8s集群的操作入口;

  • Api Server:在K8s架构中承担的是“桥梁”的角色,作为资源操作的唯一入口,它提供了认证、授权、访问控制、API注册和发现等机制。

    客户端与k8s群集及K8s内部组件的通信,都要通过Api Server这个组件;

  • Controller-manager:负责维护群集的状态,比如故障检测、自动扩展、滚动更新等;

  • Scheduler:负责资源的调度,按照预定的调度策略将pod调度到相应的node节点上;

  • Etcd:担任数据中心的角色,保存了整个群集的状态;

Node节点:

  • Kubelet:负责维护容器的生命周期,同时也负责Volume和网络的管理,一般运行在所有的节点,是Node节点的代理,当Scheduler确定某个node上运行pod之后,会将pod的具体信息(image,volume)等发送给该节点的kubelet,kubelet根据这些信息创建和运行容器,并向master返回运行状态。(自动修复功能:如果某个节点中的容器宕机,它会尝试重启该容器,若重启无效,则会将该pod杀死,然后重新创建一个容器);

  • Kube-proxy:Service在逻辑上代表了后端的多个pod。负责为Service提供cluster内部的服务发现和负载均衡(外界通过Service访问pod提供的服务时,Service接收到的请求后就是通过kube-proxy来转发到pod上的);

  • container-runtime:是负责管理运行容器的软件,比如docker

  • Pod:是k8s集群里面最小的单位。每个pod里边可以运行一个或多个container(容器),如果一个pod中有两个container,那么container的USR(用户)、MNT(挂载点)、PID(进程号)是相互隔离的,UTS(主机名和域名)、IPC(消息队列)、NET(网络栈)是相互共享的。

4、kubenetes针对pod资源对象的健康监测机制

K8s中对于pod资源对象的健康状态检测,提供了三类probe(探针)来执行对pod的健康监测:

1)livenessProbe探针

可以根据用户自定义规则来判定pod是否健康,如果livenessProbe探针探测到容器不健康,则kubelet会根据其重启策略来决定是否重启,初始探测状态为健康状态直到探测失败。如果一个容器不包含livenessProbe探针,则kubelet会认为容器的livenessProbe探针的返回值永远成功。

2)ReadinessProbe探针

同样是可以根据用户自定义规则来判断pod是否健康,如果探测失败,控制器会将此pod从对应service的endpoint列表中移除,从此不再将任何请求调度到此Pod上,直到下次探测成功。初始探测为失败状态,直到探测成功后,将pod加入到service的endpoint列表中。

3)startupProbe探针

启动检查机制,应用一些启动缓慢的业务,避免业务长时间启动而被上面两类探针kill掉,这个问题也可以换另一种方式解决,就是定义上面两类探针机制时,初始化时间定义的长一些即可。

探针检查支持以下参数设置:

  • initialDelaySeconds:初始第一次探测间隔,用于应用启动的时间,防止应用还没启动而健康检查失败

  • periodSeconds:检查间隔,多久执行probe检查,默认为10s;

  • timeoutSeconds:检查超时时长,探测应用timeout后为失败;

  • successThreshold:成功探测阈值,表示探测多少次为健康正常,默认探测1次。

探针支持分探测方案:

1)通过执行命令的方式来检查服务是否正常,比如使用cat命令查看pod中的某个重要配置文件是否存在,若存在,则表示pod健康。反之异常。

Exec探测方式的yaml文件语法如下:

spec:  
  containers:  
  - name: liveness  
    image: k8s.gcr.io/busybox  
    args:  
    - /bin/sh  
    - -c  
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600  
    livenessProbe:         #选择livenessProbe的探测机制  
      exec:                      #执行以下命令  
        command:  
        - cat  
        - /tmp/healthy  
      initialDelaySeconds: 5          #在容器运行五秒后开始探测  
      periodSeconds: 5               #每次探测的时间间隔为5秒

在上面的配置文件中,探测机制为在容器运行5秒后,每隔五秒探测一次,如果cat命令返回的值为“0”,则表示健康,如果为非0,则表示异常。

2)Httpget:通过发送http/htps请求检查服务是否正常,返回的状态码为200-399则表示容器健康(注http get类似于命令curl -I)。

Httpget探测方式的yaml文件语法如下:

spec:  
  containers:  
  - name: liveness  
    image: k8s.gcr.io/liveness  
    livenessProbe:              #采用livenessProbe机制探测  
      httpGet:                  #采用httpget的方式  
    scheme:HTTP         #指定协议,也支持https  
        path: /healthz          #检测是否可以访问到网页根目录下的healthz网页文件  
        port: 8080              #监听端口是8080  
      initialDelaySeconds: 3     #容器运行3秒后开始探测  
      periodSeconds: 3                #探测频率为3秒

上述配置文件中,探测方式为项容器发送HTTP GET请求,请求的是8080端口下的healthz文件,返回任何大于或等于200且小于400的状态码表示成功。任何其他代码表示异常。

3)tcpSocket:通过容器的IP和Port执行TCP检查,如果能够建立TCP连接,则表明容器健康,这种方式与HTTPget的探测机制有些类似,tcpsocket健康检查适用于TCP业务。

tcpSocket探测方式的yaml文件语法如下:

spec:  
  containers:  
  - name: goproxy  
    image: k8s.gcr.io/goproxy:0.1  
    ports:  
- containerPort: 8080  
#这里两种探测机制都用上了,都是为了和容器的8080端口建立TCP连接  
    readinessProbe:  
      tcpSocket:  
        port: 8080  
      initialDelaySeconds: 5  
      periodSeconds: 10  
    livenessProbe:  
      tcpSocket:  
        port: 8080  
      initialDelaySeconds: 15  
      periodSeconds: 20

在上述的yaml配置文件中,两类探针都使用了,在容器启动5秒后,kubelet将发送第一个readinessProbe探针,这将连接容器的8080端口,如果探测成功,则该pod为健康,十秒后,kubelet将进行第二次连接。

除了readinessProbe探针外,在容器启动15秒后,kubelet将发送第一个livenessProbe探针,仍然尝试连接容器的8080端口,如果连接失败,则重启容器。

探针探测的结果有以下三种可能:

  • Success:Container通过了检查;

  • Failure:Container没有通过检查;

  • Unknown:没有执行检查,因此不采取任何措施(通常是我们没有定义探针检测,默认为成功)。

5、如何控制滚动更新过程?

可以通过下面的命令查看到更新时可以控制的参数:

kubectl explain deploy.spec.strategy.rollingUpdate
  • 1

  • maxSurge:此参数控制滚动更新过程,副本总数超过预期pod数量的上限。可以是百分比,也可以是具体的值。默认为1。

    上述参数的作用就是在更新过程中,值若为3,那么怎样,先运行三个pod,用于替换旧的pod,以此类推

  • maxUnavailable:此参数控制滚动更新过程中,不可用的Pod的数量。

    这个值和上面的值没有任何关系,举个例子:我有十个pod,但是在更新的过程中,我允许这十个pod中最多有三个不可用,那么就将这个参数的值设置为3,在更新的过程中,只要不可用的pod数量小于或等于3,那么更新过程就不会停止

6、镜像下载策略是什么?

可通过命令“kubectl explain pod.spec.containers”来查看imagePullPolicy这行的解释。

K8s的镜像下载策略有三种:Always、Never、IFNotPresent

  • Always:镜像标签为latest时,总是从指定的仓库中获取镜像;

  • Never:禁止从仓库中下载镜像,也就是说只能使用本地镜像;

  • IfNotPresent:仅当本地没有对应镜像时,才从目标仓库中下载。

默认的镜像下载策略是:当镜像标签是latest时,默认策略是Always;当镜像标签是自定义时(也就是标签不是latest),那么默认策略是IfNotPresent

7、image的状态有哪些?

  • Running:Pod所需的容器已经被成功调度到某个节点,且已经成功运行,

  • Pending:APIserver创建了pod资源对象,并且已经存入etcd中,但它尚未被调度完成或者仍然处于仓库中下载镜像的过程

  • Unknown:APIserver无法正常获取到pod对象的状态,通常是其无法与所在工作节点的kubelet通信所致。

8、pod的重启策略是什么?

可以通过命令“kubectl explain pod.spec”查看pod的重启策略。(restartPolicy字段)

  • Always:但凡pod对象终止就重启,此为默认策略。

  • OnFailure:仅在pod对象出现错误时才重启

9、K8S中部署应用版本回滚的命令

#运行yaml文件,并记录版本信息;
kubectl apply -f httpd2-deploy1.yaml  --record    
 
#查看该deployment的历史版本  
kubectl rollout history deployment httpd-devploy1    

#执行回滚操作,指定回滚到版本1 
kubectl rollout undo deployment httpd-devploy1 --to-revision=1

10、标签和标签选择器的作用是什么?

标签:是当相同类型的资源对象越来越多的时候,为了更好的管理,可以按照标签将其分为一个组,为的是提升资源对象的管理效率。

标签选择器:就是标签的查询过滤条件。目前API支持两种标签选择器:

  • 基于等值关系的,如:=、==、!=(注:==也是等于的意思,yaml文件中的matchLabels字段);

  • 基于集合的,如:in、notin、exists(yaml文件中的matchExpressions字段);

11、常用的标签分类有哪些?

标签分类是可以自定义的,但是为了能使他人可以达到一目了然的效果,一般会使用以下一些分类:

  • 版本类标签(release):stable(稳定版)、canary(金丝雀版本,可以将其称之为测试版中的测试版)、beta(测试版);

  • 环境类标签(environment):dev(开发)、qa(测试)、production(生产)、op(运维);

  • 应用类(app):ui、as、pc、sc;

  • 架构类(tier):frontend(前端)、backend(后端)、cache(缓存);

  • 分区标签(partition):customerA(客户A)、customerB(客户B);

  • 品控级别(Track):daily(每天)、weekly(每周)

12、查看标签的方式?

kubectl get pod --show-labels    #查看pod,并且显示标签内容 

kubectl get pod -L env,tier      #显示资源对象标签的值  

kubectl get pod -l env,tier      #只显示符合键值资源对象的pod,而“-L”是显示所有的pod

13、添加、修改觉删除标签的命令

#对pod标签的操作  
kubectl label pod label-pod abc=123     #给名为label-pod的pod添加标签  
kubectl label pod label-pod abc=456 --overwrite      #修改名为label-pod的标签  
kubectl label pod label-pod abc-             #删除名为label-pod的标签  
kubectl get pod --show-labels  

#对node节点的标签操作     
kubectl label nodes node01 disk=ssd      #给节点node01添加disk标签  
kubectl label nodes node01 disk=sss –overwrite    #修改节点node01的标签  
kubectl label nodes node01 disk-         #删除节点node01的disk标签

14、DaemonSet资源对象的特性

DaemonSet这种资源对象会在每个k8s集群中的节点上运行,并且每个节点只能运行一个pod,这是它和deployment资源对象的最大也是唯一的区别。

15、Pod的生命周期有哪些状态?

  • Pending:表示pod已经被同意创建,正在等待kube-scheduler选择合适的节点创建,或者正在准备镜像;

  • Running:表示pod中所有的容器已经被创建,并且至少有一个容器正在运行或者是正在启动或者是正在重启;

  • Succeeded:表示所有容器已经成功终止,并且不会再启动;

  • Failed:表示pod中所有容器都是非0(不正常)状态退出;

  • Unknown:表示无法读取Pod状态,通常是kube-controller-manager无法与Pod通信。

16、创建一个Pod的流程是如何的?

  1. 客户端提交Pod的配置信息(可以是yaml文件定义好的信息)到kube-apiserver

  2. Apiserver收到指令后,通知给controller-manager创建一个资源对象;

  3. Controller-manager通过api-server将pod的配置信息存储到ETCD数据中心中;

  4. Kube-scheduler检测到pod信息会开始调度预选,会先过滤掉不符合Pod资源配置要求的节点,然后开始调度调优,主要是挑选出更适合运行pod的节点,然后将pod的资源配置单发送到node节点上的kubelet组件上。

  5. Kubelet根据scheduler发来的资源配置单运行pod,运行成功后,将pod的运行信息返回给scheduler,scheduler将返回的pod运行状况的信息存储到etcd数据中心。

17、删除一个Pod的流程是如何的?

Kube-apiserver会接受到用户的删除指令,默认有30秒时间等待优雅退出,超过30秒会被标记为死亡状态,此时Pod的状态Terminating,kubelet看到pod标记为Terminating就开始了关闭Pod的工作;

关闭流程如下:

  1. pod从service的endpoint列表中被移除;

  2. 如果该pod定义了一个停止前的钩子,其会在pod内部被调用,停止钩子一般定义了如何优雅的结束进程;

  3. 进程被发送TERM信号(kill -14)

  4. 当超过优雅退出的时间后,Pod中的所有进程都会被发送SIGKILL信号(kill -9)。

18、K8S的service是什么?

Pod每次重启或者重新部署,其IP地址都会产生变化,这使得pod间通信和pod与外部通信变得困难,这时候,就需要Service为pod提供一个固定的入口。

Service的Endpoint列表通常绑定了一组相同配置的pod,通过负载均衡的方式把外界请求分配到多个pod上。

19、K8S如何进服务注册?

Pod启动后会加载当前环境所有Service信息,以便不同Pod根据Service名进行通信。

20、K8S数据持久化的方式有哪些?

emptyDir:是最基础的Volume类型,用于存储临时数据的简单空目录。如果Pod设置了emptyDir类型Volume,Pod被分配到Node上时候,会创建emptyDir,只要Pod运行在Node上,emptyDir都会存在(容器挂掉不会导致emptyDir丢失数据),但是如果Pod从Node上被删除(Pod被删除,或者Pod发生迁移),emptyDir也会被删除,并且永久丢失。

Hostpath:将宿主机上已存在的目录或文件挂载到容器内部。类似于docker中的bind mount挂载方式。这种数据持久化方式,运用场景不多,因为它增加了pod与节点之间的耦合。


PersistentVolume (持久卷, 简称 PV) 和 Persistent VolumeClaim(持久卷声明,简称 PVC)

使得K8s集群具备了存储的逻辑抽象能力,使得在配置Pod的逻辑里可以忽略对实际后台存储技术的配置,而把这项配置的工作交给PV的配置者,即集群的管理者。

存储的PV和PVC的这种关系,跟计算的Node和Pod的关系是非常类似的;PV和Node是资源的提供者,根据集群的基础设施变化而变化,由K8s集群管理员配置;而PVC和Pod是资源的使用者,根据业务服务的需求变化而变化,由K8s集群的使用者即服务的管理员来配置。

以上是关于kubernetes云原生k8s标签选择器使用详解的主要内容,如果未能解决你的问题,请参考以下文章

云原生一文细数kubernetes常见20道问题

云原生一文细数kubernetes常见20道问题

kubernetes云原生k8s资源管理命令与Namespace使用详解

#云原生征文#深入Kubernetes(k8s)概念

云原生Kubernetes系列第五篇kubeadm v1.20 部署K8S 集群架构(人生这道选择题,总会有遗憾)

#云原生征文#深入了解Kubernetes(k8s)Service