kubernetes云原生k8s标签选择器使用详解
Posted 小码农叔叔
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kubernetes云原生k8s标签选择器使用详解相关的知识,希望对你有一定的参考价值。
目录
一、标签选择器来源
对于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
:是负责管理运行容器的软件,比如dockerPod
:是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的流程是如何的?
客户端提交Pod的配置信息(可以是yaml文件定义好的信息)到
kube-apiserver
;Apiserver
收到指令后,通知给controller-manager创建一个资源对象;Controller-manager
通过api-server将pod的配置信息存储到ETCD数据中心中;Kube-scheduler
检测到pod信息会开始调度预选,会先过滤掉不符合Pod资源配置要求的节点,然后开始调度调优,主要是挑选出更适合运行pod的节点,然后将pod的资源配置单发送到node节点上的kubelet组件上。Kubelet
根据scheduler发来的资源配置单运行pod,运行成功后,将pod的运行信息返回给scheduler,scheduler将返回的pod运行状况的信息存储到etcd数据中心。
17、删除一个Pod的流程是如何的?
Kube-apiserver
会接受到用户的删除指令,默认有30秒时间等待优雅退出,超过30秒会被标记为死亡状态,此时Pod的状态Terminating
,kubelet看到pod标记为Terminating就开始了关闭Pod的工作;
关闭流程如下:
pod从service的endpoint列表中被移除;
如果该pod定义了一个停止前的钩子,其会在pod内部被调用,停止钩子一般定义了如何优雅的结束进程;
进程被发送TERM信号(kill -14)
当超过优雅退出的时间后,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云原生k8s资源管理命令与Namespace使用详解