微智科技网
您的当前位置:首页Kubernetes中的List-Watch调度约束机制详解与容器生命周期

Kubernetes中的List-Watch调度约束机制详解与容器生命周期

来源:微智科技网

引言

        在Kubernetes(K8s)这个庞大的分布式系统中,资源的实时更新和响应对于维持集群的稳定性和高效性至关重要。而List-Watch机制正是Kubernetes实现这一目标的核心手段。本文将详细介绍Kubernetes中的List-Watch机制,与容器的生命周期。包括其工作原理、应用场景以及性能优化等方面

一、List-Watch机制概述

1.1 基本概念        

        List-Watch是Kubernetes API Server提供的一种资源监控机制。它允许客户端通过API Server获取资源对象的列表(List),并通过建立长连接(Watch)来实时监控资源对象的变化。当资源对象发生创建、更新或删除等操作时,API Server会向订阅了相关资源的客户端发送事件通知,实现资源的实时同步和响应

1.2 工作机制

        List-Watch机制的工作原理可以简单概括为以下两个步骤

1.2.1 list操作

        客户端向Kubernetes API Server发送List请求,指定要获取的资源类型和筛选条件。API Server根据请求返回符合条件的资源对象列表。客户端可以根据这个列表来初始化自己的状态或进行其他操作。

1.2.2 Watch操作

        客户端在获取到资源对象列表后,可以继续向API Server发送Watch请求,建立与API Server的长连接。API Server会持续监控指定资源的变化,并将变化事件以流的形式发送给客户端。客户端可以解析这些事件通知,并触发相应的处理逻辑。

1.3 数据流向

1.3.1 按模块划分

        初始化阶段:Kubernetes的各种组件(如Controller Manager、Scheduler、kubelet等)在启动时,会与APIServer建立连接,并初始化List-Watch机制。

        List操作:组件向APIServer发送List请求,获取当前集群中指定资源类型的所有资源对象列表。例如,Controller Manager可能会请求获取所有Pod的列表。APIServer处理List请求,查询etcd存储系统,并将结果返回给组件。

        Watch操作:组件向APIServer发送Watch请求,建立一个长连接,用于监听指定资源类型的变化。APIServer处理Watch请求,并在内部与etcd建立Watch连接,以监听etcd中对应资源的变化。

        事件触发:当etcd中的资源发生变化(如Pod的创建、更新或删除)时,etcd会发送一个事件通知给APIServer。APIServer接收到事件通知后,会将事件封装成HTTP响应,并通过之前建立的长连接发送给对应的组件。

        组件处理:组件接收到APIServer发送的事件通知后,会解析通知中的信息,并根据事件的类型(如ADD、UPDATE、DELETE)执行相应的操作。例如,如果Controller Manager接收到Pod被创建的事件,它可能会触发相应的控制器逻辑,如ReplicaSet控制器会根据Pod的创建来调整副本集的状态。

        数据同步:通过List-Watch机制,Kubernetes的各个组件能够实时感知集群中资源的变化,并据此进行相应的操作,从而保持数据的同步和一致性。

1.3.2 按整体总结

1)这里有三个 List-Watch,分别是 Controller Manager(运行在 Master),Scheduler(运行在 Master),kubelet(运行在 Node)。 它们在进程已启动就会监听(Watch)APIServer 发出来的事件

2)用户通过 kubectl 或其他 API 客户端提交请求给 APIServer 来建立一个 Pod 对象副本。

3)APIServer将Pod对象的元数据信息存入ETCD当中,待存储完毕后,APIServer会将确认信息返回给客户端,同时ETCD会将创建Pod副本的事件发送给APIServer

4)由于Controller-Manager 一直在监听(Watch,通过https的43端口)APIServer 中的事件。此时 APIServer 接受到了Create(创建Pod副本)事件,又会发送给Controller Manager

5)Controller Manager 在接到 Create 事件以后,调用其中的 Replication Controller 来保证 Node 上面需要创建的副本数量。一旦副本数量少于 RC 中定义的数量,RC 会自动创建副本。总之它是保证副本数量的 Controller(PS:扩容缩容的担当)

6)在Controller-Manager创建Pod副本以后,APIServer会在ETCD中记录这个Pod的详细信息。例如Pod的副本数,Container的内容是什么

7)同样的ETCD会将创建Pod的信息通过事件发送给APIServer

8)由于Scheduler在监听(Watch)APIServer,APIServer会将Create事件发送到Scheduler,Scheduler接收到事件后,会根据预选与优选策略,为该事件选择合适的node节点,

9)Scheduler 调度完毕以后会更新Pod的信息,此时的信息更加丰富了。除了知道Pod的副本数量,副本内容。还知道部署到哪个Node上面了。并将上面的Pod信息更新至API Server,

10) APIServer更新至ETCD中,保存起来

11)ETCD将更新成功的事件发送给 APIServer,APIServer 也开始反映此 Pod 对象的调度结果

12)kubelet是在Node上面运行的进程,它也通过List-Watch的方式监听(Watch,通过https的43端口)APIServer发送的Pod更新的事件。kubelet会尝试在当前节点上调用Docker启动容器,并将Pod以及容器的结果状态回送至APIServer,同时kubelet会负责Pod的整个生命周期

13)最后,APIServer将Pod状态信息存入ETCD中。在ETCD确认写入操作成功完成后,APIServer将确认信息发送至相关的kubelet,事件将通过它被接受

注释:kubelet持续监控Pod状态,当kubectl发送删除、扩容、缩容等指令时,会将以上流程重复一遍,而后根据最新的情况,在node节点中调整部署资源

二、pod生命周期

Pod的生命周期从创建开始,经历一系列阶段直至最终终止或被删除。

2.1 生命周期

2.1.1 创建

        用户通过创建一个新的Pod对象来请求Kubernetes调度器为Pod分配资源。

        Kubernetes系统会赋予Pod一个唯一的ID(UID)

2.1.2 调度

        Pod被提交到集群后,调度器根据节点资源可用性和Pod的资源需求、亲和性/反亲和性规则等选择合适的节点,并将Pod绑定到该节点上。

2.1.3 初始化容器启动

        若Pod定义中包含初始化容器(init containers),这些容器会在主容器启动前按顺序执行,用于设置运行主容器所需的条件或环境。

        每个Init容器都必须在下一个Init容器启动之前成功完成。

        如果Pod的Init容器失败,并且Pod的重启策略(restartPolicy)值为“Always”,则kubelet会不断地重启该Init容器直到该容器成功为止。但如果Pod的重启策略值为“Never”,则Kubernetes不会重新启动Pod。

2.1.4 镜像拉取

        主容器对应的镜像如果没有在节点上,则kubelet负责从注册表中拉取镜像。

2.1.5 容器创建与运行

        kubelet根据Pod Spec创建并启动主容器。

        容器状态会经历从Pending(等待中)到Running(运行中)的变化。

2.1.6 健康检查与就绪检测

        在容器运行期间,kubelet可以配置并执行健康检查(liveness probes)和就绪检查(readiness probes)以确保容器正常工作。

        Liveness Probe用于判断容器是否存活,若失败则可能重启容器。

         Readiness Probe用于决定容器是否准备好接收流量,只有当容器处于ready状态时,Service才会将其添加到服务端点列表中。

2.1.7 重启策略

        根据Pod的重启策略(Always、OnFailure或Never),kubelet会决定在容器退出时应采取何种行动

2.1.8.清理

当Pod被删除或者由于某种原因需要终止时,kubelet会按照预定义的优雅关闭策略通知容器停止服务,并等待一段时间让容器完成任何必要的清理操作。

清理完成后,kubelet会真正删除Pod及其相关的容器实例和其他资源。

2.1.9.终止

Pod完全从节点上移除。

此外,Pod生命周期中还包括容器启动后钩子(post-start hook)和停止前钩子(pre-stop hook),这些钩子允许在容器启动后和停止前执行特定的操作。

2.2 生命周期状态

Pod的生命周期状态主要包括

1.Pending
Pod已经被Kubernetes系统接受,但是有一个或多个容器镜像尚未创建。

如果Pod一直处于等待中,可能是由于资源不足、调度问题或其他原因导致。

2.Running
Pod已经被调度至某节点,所有容器都已经被kubelet创建完成,且至少有一个容器处于启动、重启或运行过程中。

3.Succeeded
Pod中的所有容器都已成功完成并退出。

通常适用于一次性或批处理作业。

4.Failed
Pod中的一个或多个容器由于某种原因失败。

这可能是由于容器的退出代码非零、初始化容器失败、依赖资源不可用等原因导致。

5.Unknown
由于某种原因,Pod的状态无法确定。

这可能是由于与API服务器的通信问题或其他异常情况导致。

三、scheduler的调度策略

3.1 简介

Scheduler 是 kubernetes 的调度器,主要的任务是把定义的 pod 分配到集群的节点上。其主要考虑的问题如下:

①公平:如何保证每个节点都能被分配资源

②资源高效利用:集群所有资源最大化被使用

③效率:调度的性能要好,能够尽快地对大批量的 pod 完成调度工作

④灵活:允许用户根据自己的需求控制调度的逻辑

Sheduler 是作为单独的程序运行的,启动之后会一直监听 APIServer,获取 spec.nodeName 为空的 pod,对每个 pod 都会创建一个 binding,表明该 pod 应该放到哪个节点上。

调度分为几个部分:首先是过滤掉不满足条件的节点,这个过程称为预算策略(predicate);然后对通过的节点按照优先级排序,这个是优选策略(priorities);最后从中选择优先级最高的节点。如果中间任何一步骤有错误,就直接返回错误。

3.2 scheduler预选策略的算法

①PodFitsResources:节点上剩余的资源是否大于 pod 请求的资源nodeName,检查节点名称是否和 NodeName 匹配。

②PodFitsHost:如果 pod 指定了 NodeName,检查节点名称是否和 NodeName 匹配。

③PodFitsHostPorts:节点上已经使用的 port 是否和 pod 申请的 port 冲突。

④PodSelectorMatches:过滤掉和 pod 指定的 label 不匹配的节点。 

⑤NoDiskConflict:已经 mount 的 volume 和 pod 指定的 volume 不冲突,除非它们都是只读。

如果在 predicate 过程中没有合适的节点,pod 会一直在 pending 状态,不断重试调度,直到有节点满足条件。 经过这个步骤,如果有多个节点满足条件,就继续 priorities 过程:按照优先级大小对节点排序。

3.3 scheduler的优选策略的算法

①LeastRequestedPriority:通过计算CPU和Memory的使用率来决定权重,使用率越低权重越高。也就是说,这个优先级指标倾向于资源使用比例更低的节点。

②BalancedResourceAllocation:节点上 CPU 和 Memory 使用率越接近,权重越高。这个一般和上面的一起使用,不单独使用。比如 node01 的 CPU 和 Memory 使用率 20:60,node02 的 CPU 和 Memory 使用率 50:50,虽然 node01 的总使用率比 node02 低,但 node02 的 CPU 和 Memory 使用率更接近,从而调度时会优选 node02。

③ImageLocalityPriority:倾向于已经有要使用镜像的节点,镜像总大小值越大,权重越高。

四、k8s中的标签管理及nodeSelector和nodeName的调度方式

4.1 指定调度节点

        pod.spec.nodeName 将 Pod 直接调度到指定的 Node 节点上,会跳过 Scheduler 的调度策略,该匹配规则是强制匹配

pod.spec.nodeSelector:通过 kubernetes 的 label-selector 机制选择节点,由调度器调度策略匹配 label,然后调度 Pod 到目标节点,该匹配规则属于强制约束

4.2 获取标签帮助

kubectl label --help
Usage:
  kubectl label [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version] [options]

4.3 需要获取node上的Name的名称

kubectl get node
 
AME     STATUS   ROLES    AGE   VERSION
master   Ready    master   30h   v1.20.11
node01   Ready    <none>   30h   v1.20.11
node02   Ready    <none>   30h   v1.20.11

4.4 给对应的node设置标签分别为cph=a cph=b

kubectl label nodes node01 cph=a
 
kubectl label nodes node02 cph=b

4.5 查看标签

kubectl get nodes --show-labels

4.6 修改成nodeSelector调度方式

vim myapp1.yaml
apiVersion: apps/v1
kind: Deployment  
metadata:
  name: myapp1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp1
  template:
    metadata:
      labels:
        app: myapp1
    spec:
      nodeSelector:
        rmh: a
      containers:
      - name: myapp1
        image: soscscs/myapp:v1
        ports:
        - containerPort: 80
 
 
kubectl apply -f myapp1.yaml 
 
kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
myapp1-58cff4d75-52xm5   1/1     Running   0          24s   10.244.1.29   node01   <none>           <none>
myapp1-58cff4d75-f747q   1/1     Running   0          24s   10.244.1.27   node01   <none>           <none>
myapp1-58cff4d75-kn8gk   1/1     Running   0          24s   10.244.1.28   node01   <none>           <none>

4.7 查看详细事件

kubectl describe pod myapp1-58794f76cb-626xv 
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  96s   default-scheduler  Successfully assigned default/myapp1-58794f76cb-626xv to node01
  Normal  Pulled     94s   kubelet            Container image "soscscs/myapp:v1" already present on machine
  Normal  Created    94s   kubelet            Created container myapp1
  Normal  Started    94s   kubelet            Started container myapp1
//修改一个 label 的值,需要加上 --overwrite 参数
kubectl label nodes node02 kgc=a --overwrite
 
//删除一个 label,只需在命令行最后指定 label 的 key 名并与一个减号相连即可:
kubectl label nodes node02 kgc-
 
//指定标签查询 node 节点
kubectl get node -l kgc

五、亲和性

https://kubernetes.io/zh/docs/concepts/scheduling-eviction/assign-pod-node/

5.1 简介:

        关于亲和性的调度方式,可以分为三大类:node的亲和性,pod的亲和性,pod的反亲和性。它们都能起到控制pod分配到node的调度的结果的作用

5.2 查看亲和性的种类

#查看亲和性的种类
kubectl explain pod.spec.affinity

5.3 node的亲和性

node的亲和一共分为两种调度策略:软策略(preferredDuringSchedulingIgnoredDuringExecution和硬策略(requiredDuringSchedulingIgnoredDuringExecution)

#查看你node亲和性的调度策略
kubectl explain pod.spec.affinity.nodeAffinity

5.3.1 node亲和性硬策略的设置测试

#硬策略的设置方式
kubectl explain pod.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms
 
#硬策略的标签设置方式
kubectl explain pod.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchExpressions

5.3.2 运算关系

3.21In:label 的值在某个列表中  pending   
3.22NotIn:label 的值不在某个列表中
3.23Gt:label 的值大于某个值
3.24Lt:label 的值小于某个值
3.25Exists:某个 label 存在
3.26DoesNotExist:某个 label 不存在

5.4 进行硬策略设置的实验

实验前先在node01node02添加标签test=a test=b的标签

kubectl get nodes --show-labels
NAME     STATUS   ROLES    AGE   VERSION   LABELS
master   Ready    master   11d   v1.20.11   beta.kubernetes.io/arch=amd,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd,kubernetes.io/hostname=master,kubernetes.io/os=linux,node-role.kubernetes.io/master=
node01   Ready    <none>   11d   v1.20.11   beta.kubernetes.io/arch=amd,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd,kubernetes.io/hostname=node01,kubernetes.io/os=linux
node02   Ready    <none>   11d   v1.20.11   beta.kubernetes.io/arch=amd,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd,kubernetes.io/hostname=node02,kubernetes.io/os=linux
 
//requiredDuringSchedulingIgnoredDuringExecution:硬策略
mkdir /opt/affinity
cd /opt/affinity
 
vim pod1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname    #指定node的标签
            operator: NotIn     #设置Pod安装到kubernetes.io/hostname的标签值不在values列表中的node上
            values:
            - node02
            
 
kubectl apply -f pod1.yaml
 
kubectl get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
affinity   1/1     Running   0          13s   10.244.1.30   node01   <none>           <none>
 
kubectl delete pod --all && kubectl apply -f pod1.yaml && kubectl get pods -o wide
 
#如果硬策略不满足条件,Pod 状态一直会处于 Pending 状态。

如果硬策略不满足条件,Pod 状态一直会处于 Pending 状态。

5.5 进行软策略设置实验

如果把硬策略和软策略合在一起使用,则要先满足硬策略之后才会满足软策略

//preferredDuringSchedulingIgnoredDuringExecution:软策略
vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1   #如果有多个软策略选项的话,权重越大,优先级越高
        preference:
          matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - node03
 
 
kubectl apply -f pod2.yaml
 
kubectl get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
affinity   1/1     Running   0          5s    10.244.2.35   node02   <none>           <none>
 
//把values:的值改成node01,则会优先在node01上创建Pod
kubectl delete pod --all && kubectl apply -f pod2.yaml && kubectl get pods -o wide
 
//如果把硬策略和软策略合在一起使用,则要先满足硬策略之后才会满足软策略
//示例:
apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:   #先满足硬策略,排除有kubernetes.io/hostname=node02标签的节点
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: NotIn
            values:
            - node02
      preferredDuringSchedulingIgnoredDuringExecution:  #再满足软策略,优先选择有kgc=a标签的节点
      - weight: 1
        preference:
          matchExpressions:
          - key: lbj
            operator: In
            values:
            - a

5.6 pod亲和性和反亲和性

调度策略            匹配标签    操作符                                        拓扑域支持        调度目标
nodeAffinity        主机        In, NotIn, Exists,DoesNotExist, Gt, Lt        否                指定主机
podAffinity            Pod            In, NotIn, Exists,DoesNotExist            是                Pod与指定Pod同一拓扑域
podAntiAffinity        Pod            In, NotIn, Exists,DoesNotExist            是                Pod与指定Pod不在同一拓扑域
 
 
kubectl label nodes node01 rmh=a
kubectl label nodes node02 rmh=a
 
//创建一个标签为 app=myapp01 的 Pod
vim pod3.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp01
  labels:
    app: myapp01
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
    
 
kubectl apply -f pod3.yaml
 
kubectl get pods --show-labels -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES   LABELS
myapp01   1/1     Running   0          37s   10.244.2.3   node01   <none>           <none>            app=myapp01
 
//使用 Pod 亲和性调度,创建多个 Pod 资源
vim pod4.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp02
  labels:
    app: myapp02
spec:
  containers:
  - name: myapp02
    image: soscscs/myapp:v1
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - myapp01
        topologyKey: rmh
 
 
#仅当节点和至少一个已运行且有键为“app”且值为“myapp01”的标签 的 Pod 处于同一拓扑域时,才可以将该 Pod 调度到节点上。 (更确切的说,如果节点 N 具有带有键 kgc 和某个值 V 的标签,则 Pod 有资格在节点 N 上运行,以便集群中至少有一个具有键 kgc 和值为 V 的节点正在运行具有键“app”和值 “myapp01”的标签的 pod。)
#topologyKey 是节点标签的键。如果两个节点使用此键标记并且具有相同的标签值,则调度器会将这两个节点视为处于同一拓扑域中。 调度器试图在每个拓扑域中放置数量均衡的 Pod。
#如果 kgc 对应的值不一样就是不同的拓扑域。比如 Pod1 在 kgc=a 的 Node 上,Pod2 在 lbj=b 的 Node 上,Pod3 在 lbj=a 的 Node 上,则 Pod2 和 Pod1、Pod3 不在同一个拓扑域,而Pod1 和 Pod3在同一个拓扑域。
 
kubectl apply -f pod4.yaml
 
kubectl get pods --show-labels -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES   LABELS
myapp01   1/1     Running   0          15m   10.244.1.3   node01   <none>           <none>            app=myapp01
myapp02   1/1     Running   0          8s    10.244.1.4   node01   <none>           <none>            app=myapp02
myapp03   1/1     Running   0          52s   10.244.2.53  node02   <none>           <none>            app=myapp03
myapp04   1/1     Running   0          44s   10.244.1.51  node01   <none>           <none>            app=myapp03
myapp05   1/1     Running   0          38s   10.244.2.54  node02   <none>           <none>            app=myapp03
myapp06   1/1     Running   0          30s   10.244.1.52  node01   <none>           <none>            app=myapp03
myapp07   1/1     Running   0          24s   10.244.2.55  node02   <none>           <none>            app=myapp03
 

5.7  使用pod反亲和性调度

5.7.1 官方示例1

 vim pod5.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp10
  labels:
    app: myapp10
spec:
  containers:
  - name: myapp10
    image: soscscs/myapp:v1
  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - myapp01
          topologyKey: kubernetes.io/hostname

如果节点处于 Pod 所在的同一拓扑域且具有键“app”和值“myapp01”的标签, 则该 pod 不应将其调度到该节点上。 (如果 topologyKey 为 kubernetes.io/hostname,则意味着当节点和具有键 “app”和值“myapp01”的 Pod 处于相同的拓扑域,Pod 不能被调度到该节点上。

7.2官方示例2

vim pod6.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp20
  labels:
    app: myapp20
spec:
  containers:
  - name: myapp20
    image: soscscs/myapp:v1
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - myapp01
        topologyKey: rmh
        
//由于指定 Pod 所在的 node01 节点上具有带有键 kgc 和标签值 a 的标签,node02 也有这个kgc=a的标签,所以 node01 和 node02 是在一个拓扑域中,反亲和要求新 Pod 与指定 Pod 不在同一拓扑域,所以新 Pod 没有可用的 node 节点,即为 Pending 状态。
kubectl get pod --show-labels -owide
NAME          READY   STATUS    RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES   LABELS
myapp01       1/1     Running   0          43s     10.244.1.68   node01   <none>           <none>            app=myapp01
myapp20       0/1     Pending   0          4s      <none>        <none>   <none>           <none>            app=myapp03
 
kubectl label nodes node02 kgc=b --overwrite
 
kubectl get pod --show-labels -o wide
NAME          READY   STATUS    RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES   LABELS
myapp01       1/1     Running   0          7m40s   10.244.1.68   node01   <none>           <none>            app=myapp01
myapp21       1/1     Running   0          7m1s    10.244.2.65   node02   <none>           <none>            app=myapp03

因篇幅问题不能全部显示,请点此查看更多更全内容