pod应用实战2

一、探针-Pod健康检查

1.1 探针介绍

1.1.1 什么是探针

探针是用来检测容器或容器内的服务是否存活的一种机制。

1.1.2 为什么要用探针

探针可以周期性检测服务状态,自动完成服务上下线或者容器重启,保障服务的可用性和稳定性。

1.1.3 三种探针

startupProbe:用于启动场景的检测,通常应用场景是应用启动时间不可控的情况。

  • 该探针检测通过之后才会运行后面的探针
  • 一旦该探针通过则不会重复执行,后续重复执行的是liveness和readiness探针

启动之后的两种检测探针:

  • livenessProbe:周期性检测,检查失败就会重启Pod
  • readinessProbe:周期性检测,检查失败就会把Pod从对应的Service端点列表中下线

livenessProbe与startupProbe的区别:

  • startupProbe用于探测容器启动,给容器足够的启动时间防止误杀死
  • livenessProbe用于探测容器存活,监控内存泄漏、线程死锁、端口假死等运行时问题

1.1.4 探针的三种检测方式

  • exec:执行一段命令,成功与否的判定标准不是命令输出内容,而是命令执行的退出状态码(0为成功,非0为失败)
  • httpGet:发送HTTP GET请求,如果响应状态码大于等于200且小于400,则认为容器健康
  • tcpSocket:与目标端口建立TCP连接,建立成功则代表检测通过

1.2 livenessProbe案例

1.2.1 exec方式

通过执行一条命令,探测服务是否可以正常对外提供服务。

apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec
spec:
  containers:
    - name: liveness
      image: busybox
      args:
        - /bin/sh
        - -c
        - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
      livenessProbe:
        exec:
          command:
            - cat
            - /tmp/healthy
        initialDelaySeconds: 5
        periodSeconds: 5
        failureThreshold: 3

参数说明:

  • initialDelaySeconds:第一次执行探针前等待的秒数
  • periodSeconds:kubelet每隔多少秒执行一次探针检测
  • failureThreshold:连续失败多少次才判定为失败

部署5秒后Pod正常running,再过约30秒后文件被删除,连续3次检测失败后Pod重启。可用kubectl describe pod liveness-exec查看重启事件。

1.2.2 httpGet方式

通过访问某个URL路径来探测当前Pod是否可以正常对外提供服务。状态码在200到399之间认定为成功,其他状态码视为失败。

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: pod
  name: pod
spec:
  containers:
  - image: nginx:1.18
    name: web
    livenessProbe:
      httpGet:
        port: 80
        path: /index.html1
      initialDelaySeconds: 5
      periodSeconds: 5
      failureThreshold: 1
  dnsPolicy: ClusterFirst
  restartPolicy: Always

1.2.3 tcpSocket方式

通过连接某个端口的方式,探测服务是否可以正常对外提供服务。

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: pod
  name: pod
spec:
  containers:
  - image: nginx:1.18
    name: web
    livenessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5
      failureThreshold: 3
      successThreshold: 1
  dnsPolicy: ClusterFirst
  restartPolicy: Always

1.3 readinessProbe案例

如果readinessProbe检测失败,Pod无法进入Ready状态,显示0/1。如果该Pod关联了Service,Service会将该Pod从Endpoint列表中剔除,不再将流量转发给该Pod。

readinessProbe的配置方式与livenessProbe完全相同,同样支持exec、httpGet、tcpSocket三种方式,区别仅在于失败后的行为:liveness失败会重启容器,readiness失败仅将Pod从Service下线。

1.4 startupProbe案例

如果一个应用启动时间需要120秒,不推荐直接把initialDelaySeconds设置为120秒,而是设置periodSeconds为12秒,failureThreshold设置为10,总等待时长同样可以达到120秒,但每12秒检测一次,应用一旦启动成功就能立即进入后续探针检测,避免不必要的等待。
引入startupProbe专门应对启动时间不固定的场景。

startupProbe:
  httpGet:
    path: /test
    port: 80
  failureThreshold: 13
  initialDelaySeconds: 10
  periodSeconds: 10
  successThreshold: 1

livenessProbe:
  httpGet:
    path: /test
    port: 80
  failureThreshold: 1
  initialDelaySeconds: 10
  periodSeconds: 10

设计原则:

  • startupProbe应对启动时间不固定,失败阈值可以设大一些,给足启动时间
  • livenessProbe启动之后的检测要短平快,及时检测到问题、及时重启才合理

1.5 探针总结

探针类型 作用阶段 失败后行为 执行频率
startupProbe 容器启动阶段 重启容器 启动成功后不再执行
livenessProbe 容器运行全程 重启容器 周期性持续执行
readinessProbe 容器运行全程 从Service下线 周期性持续执行

探针通用参数:

  • initialDelaySeconds:首次探测前延迟时间
  • periodSeconds:探测周期,默认10秒
  • timeoutSeconds:探测超时时间,默认1秒
  • successThreshold:从失败转为成功需要连续成功的次数,默认1次
  • failureThreshold:从成功转为失败需要连续失败的次数,默认3次

1.6 Pod Readiness Gates

在三种常规探针检测方式之外,Kubernetes支持自定义就绪条件,即Pod Readiness Gates。
默认情况下,Pod的就绪状态由内置的条件决定(如各容器就绪)。Readiness Gates允许在Pod的就绪条件中添加自定义条件,只有当所有自定义条件和默认条件都为True时,Pod才被认为是就绪的。

使用场景:

  • 需要等待外部依赖就绪(如数据库连接、配置加载完成)
  • 需要与外部负载均衡器或服务网格联动
  • 需要自定义的业务就绪判定逻辑

配置方式:在Pod spec的readinessGates字段中指定自定义条件的conditionType,后续通过Pod Status API更新该条件的状态。这属于Kubernetes定制化开发范畴,日常运维中使用较少。

二、资源申请与限制

2.1 介绍

2.1.1 requests与limits的区别

resources:
  requests:
    cpu: 1
    memory: 1Gi
  limits:
    cpu: 2
    memory: 2Gi
  • requests:调度期间预选阶段的重要参考指标,并不会实际占住资源,实际使用时有可能用超也有可能不足
  • limits:底层会修改目标节点的cgroup参数,做实际的资源硬限制

2.1.2 资源范围

资源配置满足关系:requests <= limits <= 节点可用资源

2.1.3 可压缩与不可压缩资源

  • 可压缩资源:例如CPU,达到limits上限之后只会限频,不会杀掉Pod
  • 不可压缩资源:例如内存、磁盘,达到limits上限之后Pod会被终止,例如内存超过限制则触发Kubernetes级别的OOM Kill

2.1.4 申请资源的单位

CPU单位:

  • 100m中的小写m代表千分之一颗CPU,即100m = 0.1核
  • 1 = 1颗CPU核心 = 1000m

内存单位:

  • Mi:基于1024进制,1Mi = 1024 * 1024字节
  • M:基于1000进制,1M = 1000 * 1000字节
  • 示例:3Mi = 3 * 1024 * 1024字节,3M = 3 * 1000 * 1000字节

2.1.5 具体的资源指标

  resources:
	  requests:
		cpu: "500m"                          # 请求 0.5 核 CPU
		memory: "256Mi"                      # 请求 256 MiB 内存
		
		ephemeral-storage: "1Gi"             # 请求 1 GiB 临时存储,非持久化数据,临时存储,设置在limits下才生效。
		nvidia.com/gpu: "1"                  # 请求 1 个 GPU                         
		hugepages-2Mi: "64Mi"                # 请求 64 MiB 大页内存,容器可以使用大页内存
		example.com/special-resource: "2"    # 请求 2 个自定义扩展资源
											 # 允许你为节点上安装的特殊硬件或软件资源
											 #(例如特殊硬盘)定义自定义资源类型。
											 #你可以在容器中指定这些资源的请求和限制
	  limits:
		cpu: "1"                             # 限制最多使用 1 核 CPU
		memory: "512Mi"                      # 限制最多使用 512 MiB 内存---》触发OOM
		ephemeral-storage: "2Gi"             # 限制最多使用 2 GiB 临时存储
		
		nvidia.com/gpu: "1"                  # 限制最多使用 1 个 GPU
		
		hugepages-2Mi: "128Mi"               # 限制最多使用 128 MiB 大页内存
		example.com/special-resource: "4"    # 限制最多使用 4 个自定义扩展资源

各项说明:

  • cpu:CPU核心数请求与限制
  • memory:内存请求与限制,超限触发OOM
  • ephemeral-storage:临时存储,非持久化数据,设置在limits下才生效
  • nvidia.com/gpu:GPU资源请求与限制
  • hugepages-2Mi:大页内存,容器可以使用大页内存提升性能
  • example.com/special-resource:自定义扩展资源,允许为节点上安装的特殊硬件或软件资源定义自定义资源类型

2.1.6 initContainers与多容器调度机制

当Pod包含多个init容器和多个业务容器时,Kubernetes的调度预选步骤如下:

  1. 找出initContainers中多个容器对资源需求requests最大的那一个,得到值x
  2. 求出Containers下多个业务容器对资源需求requests的总和,得到值y
  3. Kubernetes会取x与y中较大的那一个作为预选阶段的筛选依据,确保Pod被调度到某个节点后,无论是initContainer还是业务容器都有足够的剩余资源可以正常启动

2.1.7 服务质量等级QoS

当某个节点的资源不足时,Kubernetes会对该节点上的Pod进行驱逐,Pod状态变为evicted。驱逐时会按照Pod的QoS质量等级进行驱逐,质量等级越低的越优先被驱逐。
按照优先级从高到低排列:

Guaranteed:完全可靠的等级。Pod中的所有容器对所有资源类型(CPU与内存)都定义了limits与requests,且二者值相等、且大于0。
Burstable:不稳定等级。一个Pod既不是Guaranteed级也不是BestEffort级,就是Burstable级。一句话概括:设置了requests或limits,但存在不一致的情况。
BestEffort:尽最大努力等级。Pod中的所有容器都未定义资源配置,requests与limits都未定义。

2.2 实践

2.2.1 资源申请/限制与cgroup

Kubernetes资源限制底层基于cgroup实现,涉及的核心参数:

  • cpu.cfs_period_us:CPU调度周期
  • cpu.cfs_quota_us:每个周期内可使用的CPU时间配额
  • cpu.shares:CPU相对权重,仅在CPU资源用满时才会发生作用

limits修改的是cfs_period和cfs_quota两个参数,实现硬限制;requests修改的是shares参数,实现相对权重调度。

2.2.2 containerd配置Nvidia Container Runtime

如果使用containerd作为容器引擎,并且希望为其安装NVIDIA Container Runtime,同时配置runc为默认运行时,步骤如下:
第一步:安装NVIDIA Container Runtime
在每个GPU节点上安装NVIDIA Container Toolkit:

# 设置容器运行时的安装源
distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
  && curl -s -L https://nvidia.github.io/nvidia-container-toolkit/gpgkey | sudo apt-key add - \
  && curl -s -L https://nvidia.github.io/nvidia-container-toolkit/$distribution/nvidia-container-toolkit.list | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

# 更新包列表并安装 NVIDIA Container Toolkit
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit

# 重启 containerd 服务以应用更改
sudo systemctl restart containerd

第二步:配置containerd以使用NVIDIA Container Runtime
编辑containerd配置文件/etc/containerd/config.toml。如果文件不存在,先生成默认配置:

sudo containerd config default | sudo tee /etc/containerd/config.toml

修改config.toml,添加NVIDIA运行时配置:

[plugins]
[plugins."io.containerd.grpc.v1.cri"]
  [plugins."io.containerd.grpc.v1.cri".containerd]
    default_runtime_name = "runc"
    [plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
      [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
        runtime_type = "io.containerd.runc.v2"
      [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia]
        runtime_type = "io.containerd.runc.v2"
        [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia.options]
          BinaryName = "/usr/bin/nvidia-container-runtime"

配置说明:

  • default_runtime_name = "runc":设置runc为默认运行时
  • runtime_type = "io.containerd.runc.v2":指定使用runc作为容器运行时
  • BinaryName = "/usr/bin/nvidia-container-runtime":指定NVIDIA Container Runtime的路径

第三步:重启containerd

sudo systemctl restart containerd

第四步:验证配置

sudo ctr run --rm --gpus 1 docker.io/nvidia/cuda:11.0-base nvidia-smi

该命令输出GPU信息则表明容器可以正确访问GPU。

总结:配置完成后,默认情况下Pod会使用runc,但如果在Pod中请求GPU资源,containerd会自动使用NVIDIA Container Runtime来运行这些Pod。大厂中常用vGPU虚拟化技术来进一步优化GPU资源分配。

2.2.3 大页内存

大页内存HugePages是为了提高TLB(Translation Lookaside Buffer,转译后备缓冲器)的命中效率而设计的。传统内存页大小为4KB,大页通常为2MB或1GB,可以显著减少页表条目数量,降低TLB miss开销,提升内存访问性能。

在Kubernetes中使用大页内存:

  • 节点需要预先配置好大页内存(通过内核参数启动时预留)
  • Pod的resources中通过hugepages-2Mi或hugepages-1Gi指定大页内存的请求和限制
  • 大页内存必须以limits的形式设置,通常requests与limits值相等
  • 容器内需要挂载对应的hugetlb文件系统才能使用大页

大页内存常用于数据库、高性能计算等对内存访问延迟敏感的场景。

2.2.4 多容器场景的预选机制

多个init容器与业务容器并存时的资源预选逻辑:
init阶段:init容器先于业务容器串行启动,运行一个、关闭一个,启动完成后会释放掉资源。因此调度时只需要考虑占用资源最大的那个init容器。
业务容器启动阶段:业务容器是并行持续运行的,需要的资源是所有业务容器资源需求的总和。
预选公式:max( max(init containers requests), sum(work containers requests) )

即取init容器中最大资源需求和所有业务容器资源需求总和两者中的较大值,作为节点调度的资源判定依据。


三、静态Pod

3.1 什么是静态Pod

静态Pod指的是由kubelet直接管理的Pod,相当于一种系统级服务。
特点总结:

  1. 静态Pod由kubelet进行管理,静态Pod的创建请求不会发给Master节点的API Server,也不会被Deployment或DaemonSet等控制器关联
  2. 静态Pod由所在节点上的kubelet进程自己监控,kubelet无法对其进行健康检测,但Pod崩溃时kubelet会重启该静态Pod
  3. 静态Pod始终与某个Node节点的kubelet绑定,即始终运行在同一个节点,不会被调度到其他节点
  4. 静态Pod的状态可以通过API Server查看到,但无法通过API彻底删除,删掉后会自动被kubelet重新拉起,除非删除节点上的yaml文件

补充说明:kubelet会为静态Pod在API Server上创建一个镜像Pod(Mirror Pod),用于展示静态Pod的状态,但实际管理权仍在kubelet手中。

3.2 创建静态Pod的方式

3.2.1 配置文件方式

查看kubelet配置中的静态Pod路径:

cat /var/lib/kubelet/config.yaml
# 找到如下配置项
staticPodPath: /etc/kubernetes/manifests

将Pod的yaml文件放入该目录,kubelet会自动检测并创建静态Pod。Kubernetes集群的控制平面组件(kube-apiserver、kube-controller-manager、kube-scheduler、etcd)通常就是以静态Pod方式运行的。

3.2.2 HTTP方式

除了本地配置文件目录,kubelet还支持通过HTTP URL的方式加载静态Pod清单。
配置方式:在kubelet启动参数中设置--manifest-url参数,指定一个HTTP地址,kubelet会定期从该URL下载Pod清单并创建静态Pod。

# kubelet启动参数示例
--manifest-url=http://config-server/static-pods/

这种方式适用于集中管理多节点静态Pod配置的场景,使用频率相对较低。

3.2.3 删除静态Pod

通过kubectl delete pod命令无法真正删除静态Pod,删除后kubelet会立即重新创建。
正确的删除方式:

  1. 登录到静态Pod所在的节点
  2. 进入staticPodPath对应的目录(通常是/etc/kubernetes/manifests)
  3. 删除对应的yaml文件
  4. kubelet检测到文件被移除后,会自动停止并删除该静态Pod

如果是通过HTTP方式创建的静态Pod,则需要从HTTP源移除对应的清单文件。


四、Downward API

4.1 介绍

基于Downward API机制可以把容器所在Pod的一些状态信息(Pod名字、Pod IP、调度节点、Pod标签、注解等)注入到容器中。在容器内体现的形式可以是环境变量,也可以是挂载到某个目录下的文件。

注意事项:Downward API能够获取到的信息,一定是Pod里的容器进程启动之前就能够确定下来的信息。如果想要获取Pod容器运行后才会出现的信息(比如容器进程的PID),就不能使用Downward API,而应该考虑在Pod里定义一个sidecar容器来获取。

Downward API的两种注入方式:

  • 环境变量方式:将Pod或Container信息设置为容器内的环境变量
  • Volume挂载方式:将Pod或Container的信息以文件形式挂载到容器内部

4.2 环境变量方式

通过fieldRef获取Pod元数据信息:

apiVersion: v1
kind: Pod
metadata:
  name: env-pod
spec:
  containers:
  - name: env-pod
    image: registry.cn-shanghai.aliyuncs.com/egon-k8s-test/busybox:v1.0
    command: ["/bin/sh", "-c"]
    args:
    - while true;do
      echo -en "\n";
      env;
      echo "===============";
      sleep 300;
      done;
    env:
    - name: NODE_NAME
      valueFrom:
        fieldRef:
          fieldPath: spec.nodeName
    - name: POD_NAME
      valueFrom:
        fieldRef:
          fieldPath: metadata.name
    - name: POD_NAMESPACE
      valueFrom:
        fieldRef:
          fieldPath: metadata.namespace
    - name: POD_IP
      valueFrom:
        fieldRef:
          fieldPath: status.podIP

通过resourceFieldRef获取容器资源信息:

apiVersion: v1
kind: Pod
metadata:
  name: dapi-envars-resourcefieldref
spec:
  containers:
    - name: test-container
      image: registry.cn-shanghai.aliyuncs.com/egon-k8s-test/busybox:v1.0
      command: [ "sh", "-c"]
      args:
      - while true; do
          echo -en '\n';
          printenv MY_CPU_REQUEST MY_CPU_LIMIT;
          printenv MY_MEM_REQUEST MY_MEM_LIMIT;
          sleep 10;
        done;
      resources:
        requests:
          memory: "32Mi"
          cpu: "1"
        limits:
          memory: "64Mi"
          cpu: "2"
      env:
        - name: MY_CPU_REQUEST
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: requests.cpu
        - name: MY_CPU_LIMIT
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: limits.cpu
        - name: MY_MEM_REQUEST
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: requests.memory
        - name: MY_MEM_LIMIT
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: limits.memory
  restartPolicy: Never

4.3 Volume挂载方式

将Pod元数据以文件形式挂载到容器内:

apiVersion: v1
kind: Pod
metadata:
  name: volume-pod
  labels:
    k8s-app: test-volume
    node-env: test
  annotations:
    user: egon
    gender: male
    build: test
spec:
  volumes:
  - name: podinfo
    downwardAPI:
      items:
      - path: labels
        fieldRef:
          fieldPath: metadata.labels
      - path: annotations
        fieldRef:
          fieldPath: metadata.annotations
  containers:
  - name: volume-pod
    image: busybox
    args:
    - sleep
    - "3600"
    volumeMounts:
    - name: podinfo
      mountPath: /etc/podinfo

容器启动后,可以在/etc/podinfo目录下看到labels和annotations两个文件,内容分别为Pod的标签和注解信息。Volume方式的优势是标签和注解更新后,容器内的文件内容也会同步更新,而环境变量方式则不会动态更新。

4.4 Downward API支持的字段

4.4.1 fieldRef支持的字段

metadata层级:

  • metadata.name:Pod名称
  • metadata.namespace:Pod所在命名空间
  • metadata.uid:Pod的UID
  • metadata.labels:Pod的所有标签(仅volume方式可用完整集合,环境变量方式需指定单个key)
  • metadata.annotations:Pod的所有注解(仅volume方式可用完整集合)

spec层级:

  • spec.nodeName:Pod调度到的节点名称
  • spec.serviceAccountName:Pod使用的服务账号名称
  • spec.hostIP:节点的IP地址

status层级:

  • status.podIP:Pod的IP地址
  • status.hostIP:节点的IP地址

4.4.2 resourceFieldRef支持的字段

  • requests.cpu:容器的CPU请求值
  • requests.memory:容器的内存请求值
  • requests.ephemeral-storage:容器的临时存储请求值
  • limits.cpu:容器的CPU限制值
  • limits.memory:容器的内存限制值
  • limits.ephemeral-storage:容器的临时存储限制值

resourceFieldRef可以通过containerName指定容器,支持获取其他容器的资源配置(但必须在同一个Pod内)。


五、名称空间

5.1 名称空间介绍

Namespace(名称空间)是Kubernetes中实现资源隔离的重要机制,用于将集群内部的资源划分为多个逻辑隔离的组。不同名称空间中的资源名称可以重复,同一名称空间内同类资源名称必须唯一。

常见用途:

  • 按环境隔离:开发环境、测试环境、生产环境
  • 按团队或项目隔离:不同团队使用不同的名称空间
  • 按业务线隔离:不同业务线资源独立管理
  • 配合ResourceQuota和LimitRange实现资源配额管理
  • 配合RBAC实现权限控制

Kubernetes默认名称空间:

  • default:默认名称空间,未指定namespace的资源都放在这里
  • kube-system:系统组件所在的名称空间,如kube-proxy、CoreDNS等
  • kube-public:公开可读的名称空间,所有用户都可以读取
  • kube-node-lease:节点租约相关的名称空间,用于节点心跳检测

5.2 常用操作

创建名称空间:

kubectl create namespace test
# 简写
kubectl create ns test

查看名称空间列表:

kubectl get namespace
kubectl get ns

YAML清单中指定名称空间,在metadata.namespace字段指定,不指定默认是default:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  namespace: test
spec:
  ...

查看指定名称空间下的资源:

kubectl -n test get pods
kubectl -n test get svc

查看所有名称空间的资源:

kubectl get pods --all-namespaces
kubectl get pods -A

删除名称空间:

kubectl delete ns test

注意:删除名称空间时,会删除掉该名称空间内的所有资源。如果资源比较多,删除ns的过程会比较慢,因为需要级联清理所有关联资源。生产环境慎用删除名称空间操作。

名称空间无法嵌套,一个资源只能属于一个名称空间。并非所有Kubernetes资源都在名称空间中,例如Node、PersistentVolume、StorageClass等属于集群级资源,不属于任何名称空间。


六、标签

6.1 介绍

标签(Label)是在资源上添加的键值对标识,用来对资源进行区分和选择。
标签的作用:

  1. 建立资源之间的关联关系,例如Service通过标签选择器关联后端Pod
  2. 筛选和查询资源,按维度过滤资源列表

标签的特点:

  • 形式:key: value键值对形式
  • 作用对象:Node、Pod、Service、Deployment等几乎所有资源
  • 数量:一个对象可以定义任意数量的标签,同一个标签可以添加到多个对象上
  • 定义时间:可以在定义资源时设置,也可以在资源创建后动态添加修改
  • 用途:多维度分组,便于资源分配、调度、配置、部署等管理工作

6.2 常见标签

Kubernetes推荐的常用标签约定:

  • app.kubernetes.io/name:应用名称
  • app.kubernetes.io/instance:应用实例标识
  • app.kubernetes.io/version:应用版本
  • app.kubernetes.io/component:应用组件类型(如frontend、backend、database)
  • app.kubernetes.io/part-of:所属的上层应用
  • app.kubernetes.io/managed-by:管理工具(如helm、kubectl)
  • environment/env:环境标识(如prod、test、dev)
  • tier:层级(如frontend、backend、cache)
  • release:发布版本
  • track:发布轨道(如stable、canary)

节点常用标签:

  • kubernetes.io/hostname:节点主机名
  • beta.kubernetes.io/os:节点操作系统
  • beta.kubernetes.io/arch:节点架构
  • node-role.kubernetes.io/master:主节点角色标签
  • node.kubernetes.io/instance-type:云服务器实例类型
  • topology.kubernetes.io/zone:可用区
  • topology.kubernetes.io/region:地域

6.3 标签的使用场景

  • Service和Deployment的关联:Service通过selector匹配Pod的标签,实现服务发现和负载均衡
  • Deployment滚动更新:通过标签选择器管理对应的Pod副本
  • 节点亲和性与Pod调度:通过节点标签控制Pod调度到哪些节点
  • 资源筛选与批量操作:按标签过滤资源,批量执行删除、查看等操作
  • 网络策略:通过标签选择器定义网络访问规则
  • 资源监控与计费:按标签维度进行监控分组和成本核算

6.4 查看标签

# 查看Pod标签
kubectl get pod --show-labels
# 查看节点标签
kubectl get node --show-labels
# 查看Service标签
kubectl get svc --show-labels
# 查看Deployment标签
kubectl get deployment --show-labels

按标签筛选:

# 筛选带有x=y标签的Pod
kubectl get pods -l x=y
# 筛选带有标签x的Pod(不管值是什么)
kubectl get pods -l x
# 同时带有mm标签和nn标签的Pod
kubectl get pods -l mm,nn
# 多条件组合筛选,逗号表示AND关系
kubectl get pods -l app=nginx,env=test

标签选择器的高级用法:

# 不等于筛选
kubectl get pods -l env!=prod
# 集合筛选:值在集合内
kubectl get pods -l 'env in (dev, test)'
# 集合筛选:值不在集合内
kubectl get pods -l 'env notin (prod)'
# 存在性筛选:不存在某个标签
kubectl get pods -l '!env'

6.5 添加标签

方式一:在YAML清单中设置

metadata:
  labels:
    app: myapp
    env: test

方式二:通过kubectl label命令动态添加

# 给节点打标签
kubectl label node xxx x=y
# 给Pod打标签
kubectl label pod xxx x=y
# 给Deployment打标签
kubectl label deployment xxx x=y

覆盖已有的标签值:

kubectl label pods xxx x=1111111 --overwrite

6.6 删除标签

方式一:编辑YAML文件删除对应标签后重新apply
方式二:通过kubectl label命令删除,在标签key后面加减号

kubectl label pods web-test-7ccc7b6b86-hwr2g x-

6.7 节点标签选择器nodeSelector

nodeSelector是最简单的节点选择方式,通过标签匹配将Pod调度到满足条件的节点上。
使用步骤:

  1. 先给目标节点打上对应的标签
  2. 在Pod的spec中配置nodeSelector字段,指定需要匹配的标签键值对

示例:

# 第一步:给节点打标签
kubectl label nodes node01 disktype=ssd
# 第二步:Pod配置nodeSelector
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd

配置后,该Pod只会被调度到带有disktype=ssd标签的节点上。如果没有满足条件的节点,Pod会处于Pending状态。

nodeSelector是基础的节点选择方式,更复杂的调度需求可以使用节点亲和性nodeAffinity、Pod亲和性podAffinity、污点与容忍Taint/Toleration等机制。


七、通过PID找到对应Pod

7.1 方法步骤

在某个节点上,发现某个PID进程异常,想找到它属于哪个Pod,可以按以下步骤操作:
第一步:顺着这个PID往上寻找它的父进程

[root@node01 ~]# ps -elf | grep 3342 | grep -v grep
4 S root        3342    3184  0  80   0 -   304 do_wai 12:13 ?        00:00:00 /bin/sh -c while true;do echo 111 >> /tmp/run.log;sleep 1;done
0 S root        9338    3342  0  80   0 -   301 hrtime 12:23 ?        00:00:00 sleep 1

第二步:继续查找父进程PID对应的进程,找到containerd-shim进程

[root@node01 ~]# ps -elf | grep 3184 | grep -v grep
0 S root        3184       1  0  80   0 - 309050 futex_ 12:13 ?       00:00:00 /usr/bin/containerd-shim-runc-v2 -namespace k8s.io -id dac0137a48b0467c5767d70cd219cc0682488f067f3703b1f6ef11ad6c8220fa -address /run/containerd/containerd.sock
4 S 65535       3215    3184  0  80   0 -   241 ia32_s 12:13 ?        00:00:00 /pause
4 S root        3342    3184  0  80   0 -   304 do_wai 12:13 ?        00:00:00 /bin/sh -c while true;do echo 111 >> /tmp/run.log;sleep 1;done

从containerd-shim进程的参数中可以提取出容器ID:dac0137a48b0467c5767d70cd219cc0682488f067f3703b1f6ef11ad6c8220fa

第三步:使用crictl ps命令根据容器ID找到对应的Pod信息

[root@node01 ~]# crictl ps
CONTAINER      IMAGE          CREATED         STATE    NAME        ATTEMPT   POD ID         POD
0dd721dd6cf1d  a229b61a74acb  11 minutes ago  Running  nginx-test  0         dac0137a48b04  mynginx-d9dfc55bf-pbpn6

从输出中可以看到POD ID和Pod名称,从而定位到该PID属于哪个Pod。

7.2 其他快速方法

方法二:通过cgroup路径查找

# 查看进程的cgroup信息
cat /proc/3342/cgroup
# 输出中会包含kubepods和podID相关路径,从中提取Pod UID

方法三:使用crictl inspect

# 根据容器ID直接查看详细信息
crictl inspect dac0137a48b0467c5767d70cd219cc0682488f067f3703b1f6ef11ad6c8220fa | grep pod

方法四:在集群全局查找

# 已知Pod名称后,查找所在节点和命名空间
kubectl get pods -A -o wide | grep mynginx-d9dfc55bf-pbpn6
posted @ 2026-07-09 15:23  cuckooyang  阅读(29)  评论(0)    收藏  举报