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的调度预选步骤如下:
- 找出initContainers中多个容器对资源需求requests最大的那一个,得到值x
- 求出Containers下多个业务容器对资源需求requests的总和,得到值y
- 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,相当于一种系统级服务。
特点总结:
- 静态Pod由kubelet进行管理,静态Pod的创建请求不会发给Master节点的API Server,也不会被Deployment或DaemonSet等控制器关联
- 静态Pod由所在节点上的kubelet进程自己监控,kubelet无法对其进行健康检测,但Pod崩溃时kubelet会重启该静态Pod
- 静态Pod始终与某个Node节点的kubelet绑定,即始终运行在同一个节点,不会被调度到其他节点
- 静态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会立即重新创建。
正确的删除方式:
- 登录到静态Pod所在的节点
- 进入staticPodPath对应的目录(通常是/etc/kubernetes/manifests)
- 删除对应的yaml文件
- 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)是在资源上添加的键值对标识,用来对资源进行区分和选择。
标签的作用:
- 建立资源之间的关联关系,例如Service通过标签选择器关联后端Pod
- 筛选和查询资源,按维度过滤资源列表
标签的特点:
- 形式: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调度到满足条件的节点上。
使用步骤:
- 先给目标节点打上对应的标签
- 在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

浙公网安备 33010602011771号