好的,各位观众,各位Geek,欢迎来到今天的K8s资源限制与Pod驱逐策略脱口秀!我是你们的老朋友,今天就让我们一起扒一扒K8s集群里那些“吃得多干得少”的Pod,以及如何优雅地把它们请出家门。
先别急着打瞌睡,我知道一听到“资源限制”、“驱逐策略”这些词,大家可能觉得枯燥。但相信我,这比你想象的有趣多了!你想想,你的K8s集群就像一个大House,里面住着各种各样的Pod,有的勤勤恳恳,有的好吃懒做。作为房东,你肯定希望资源分配公平合理,对不对?
今天我们就来聊聊,如何当好这个“房东”,让你的K8s House井然有序,高效运转。
一、资源限制:给Pod戴上“紧箍咒”
首先,我们要给Pod们戴上“紧箍咒”,也就是资源限制。这就像给孩子们零花钱一样,你得告诉他们,这个月能花多少,不能超支。
在K8s里,我们主要限制两种资源:CPU和内存。
- CPU: 可以理解为Pod的“算力”,决定了Pod处理任务的速度。
- 内存: 可以理解为Pod的“记忆力”,决定了Pod能存储多少数据。
K8s通过resources
字段来设置Pod的资源限制,这个字段下面有两个子字段:
requests
: 资源请求,Pod启动时向K8s声明自己需要的资源量。这就像你跟房东说:“我需要一间卧室,一个厨房。”limits
: 资源限制,Pod能使用的最大资源量。这就像房东说:“卧室和厨房你可以用,但不能把客厅也占了!”
让我们看一个例子:
apiVersion: v1
kind: Pod
metadata:
name: resource-demo
spec:
containers:
- name: main
image: busybox:latest
command: ["/bin/sh", "-c", "while true; do sleep 1; done"]
resources:
requests:
cpu: "100m" # 100 millicores,相当于0.1个CPU核心
memory: "128Mi" # 128 MB
limits:
cpu: "500m" # 500 millicores,相当于0.5个CPU核心
memory: "256Mi" # 256 MB
这个Pod的含义是:
- 启动时,它会告诉K8s:“我需要0.1个CPU核心和128MB内存。”
- 但它最多可以使用0.5个CPU核心和256MB内存。
为什么要设置requests和limits?
- Requests: 确保Pod能够获得足够的资源来启动和运行。K8s调度器会根据Pod的requests来选择合适的节点。如果节点上的可用资源不足以满足Pod的requests,Pod将无法被调度。
- Limits: 防止Pod过度占用资源,影响其他Pod的运行。如果Pod尝试使用的资源超过了limits,K8s会采取相应的措施,例如限制CPU使用率或杀死Pod。
资源单位:
- CPU: 可以用整数表示CPU核心数,也可以用带有"m"后缀的字符串表示millicores(千分之一个CPU核心)。例如,
1
表示1个CPU核心,100m
表示0.1个CPU核心。 - 内存: 可以用整数表示字节数,也可以用带有单位的字符串表示。例如,
128974848
和128Mi
都表示128MB。常见的单位有:- E, P, T, G, M, K (例如:5E, 4P, 3T, 2G, 1M, 5K)
- Ei, Pi, Ti, Gi, Mi, Ki (例如:5Ei, 4Pi, 3Ti, 2Gi, 1Mi, 5Ki)
资源QoS等级:
K8s根据Pod的资源请求和限制,将Pod分为三种QoS等级:
- Guaranteed: 最高优先级。Pod的所有容器都设置了相同的requests和limits,并且CPU和内存都有设置。这类Pod通常用于关键应用,例如数据库。
- Burstable: 中等优先级。Pod的至少一个容器设置了requests,但requests不等于limits,或者只有CPU或内存设置了requests和limits。这类Pod通常用于不太重要的应用,例如Web服务器。
- BestEffort: 最低优先级。Pod的所有容器都没有设置requests和limits。这类Pod通常用于对资源需求不高的应用,例如后台任务。
表格总结:
QoS等级 | CPU Requests | CPU Limits | Memory Requests | Memory Limits | 优先级 | 适用场景 |
---|---|---|---|---|---|---|
Guaranteed | 等于 | 等于 | 等于 | 等于 | 高 | 核心服务 |
Burstable | 已设置 | 可选 | 已设置 | 可选 | 中 | 普通应用 |
BestEffort | 未设置 | 未设置 | 未设置 | 未设置 | 低 | 资源需求不高的任务 |
二、Pod驱逐策略:清理门户,腾笼换鸟
现在我们已经给Pod们戴上了“紧箍咒”,但总有一些Pod不听话,要么过度占用资源,要么节点本身资源不足。这时候,我们就需要祭出我们的“杀手锏”——Pod驱逐策略。
Pod驱逐是指K8s主动终止Pod的运行,并将Pod重新调度到其他节点上。这就像房东把不听话的租客赶走,然后找新的租客一样。
为什么要驱逐Pod?
- 节点资源不足: 当节点上的CPU、内存、磁盘空间等资源不足时,K8s会驱逐一些Pod,以释放资源,保证节点的稳定运行。
- 节点维护: 当需要对节点进行维护时,例如升级内核、更换硬件等,K8s会驱逐节点上的所有Pod,以便安全地进行维护操作。
- 节点故障: 当节点发生故障时,例如硬件故障、网络故障等,K8s会自动驱逐节点上的所有Pod,并将它们重新调度到其他健康的节点上。
Pod驱逐的触发条件:
K8s通过kubelet
组件来监控节点的资源使用情况,当节点的资源使用超过一定的阈值时,就会触发Pod驱逐。这些阈值是可以配置的,常见的阈值有:
memory.available
: 可用内存低于某个值。nodefs.available
: 节点文件系统可用空间低于某个值。nodefs.inodesFree
: 节点文件系统可用inode数量低于某个值。imagefs.available
: 镜像文件系统可用空间低于某个值。imagefs.inodesFree
: 镜像文件系统可用inode数量低于某个值。pid.available
: 可用PID数量低于某个值。disk pressure
: 磁盘压力过高。memory pressure
: 内存压力过高。
Pod驱逐的优先级:
当需要驱逐Pod时,K8s会按照一定的优先级来选择要驱逐的Pod。优先级从低到高依次为:
- BestEffort Pods: 首先驱逐QoS等级为BestEffort的Pod。这类Pod没有设置资源请求和限制,因此被认为是最不重要的。
- Burstable Pods: 其次驱逐QoS等级为Burstable的Pod。这类Pod设置了资源请求,但没有达到Guaranteed级别,因此被认为优先级低于Guaranteed Pod。
- Guaranteed Pods: 最后驱逐QoS等级为Guaranteed的Pod。这类Pod设置了资源请求和限制,并且CPU和内存都有设置,因此被认为是最重要的。
在同一QoS等级的Pod中,K8s会优先驱逐资源使用率最高的Pod。
如何控制Pod驱逐?
虽然K8s会自动进行Pod驱逐,但我们也可以通过一些手段来控制Pod驱逐的行为。
- PodDisruptionBudget (PDB): PDB允许你指定在自愿中断(例如节点维护)期间,一个Deployment、StatefulSet或ReplicationController中至少需要保持运行的Pod数量。这可以防止关键应用在维护期间完全停止服务。
- Taints and Tolerations: Taints用于标记节点,Tolerations用于标记Pod。只有具有与节点Taint匹配的Toleration的Pod才能被调度到该节点上。通过使用Taints和Tolerations,你可以控制哪些Pod可以运行在哪些节点上,从而影响Pod驱逐的行为。
- 优先级类 (PriorityClass): 优先级类允许你为Pod分配优先级,优先级高的Pod在资源竞争时更有可能被保留,而优先级低的Pod更容易被驱逐。
PDB示例:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: my-pdb
spec:
minAvailable: 2 # 至少保持2个Pod可用
selector:
matchLabels:
app: my-app
这个PDB的含义是:
- 它保护所有带有
app: my-app
标签的Pod。 - 在自愿中断期间,至少需要保持2个这样的Pod可用。
Taints and Tolerations示例:
# 为节点添加Taint
kubectl taint nodes node1 key=value:NoSchedule
# 为Pod添加Toleration
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: main
image: busybox:latest
command: ["/bin/sh", "-c", "while true; do sleep 1; done"]
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
这个例子中,我们为节点node1
添加了一个Taint,表示只有具有相应Toleration的Pod才能被调度到该节点上。然后,我们为Podmy-pod
添加了一个Toleration,使其能够被调度到node1
上。
优先级类示例:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for high-priority pods only."
---
apiVersion: v1
kind: Pod
metadata:
name: my-high-priority-pod
spec:
containers:
- name: main
image: busybox:latest
command: ["/bin/sh", "-c", "while true; do sleep 1; done"]
priorityClassName: high-priority
这个例子中,我们定义了一个名为high-priority
的优先级类,并将其值设置为1000000
。然后,我们将Podmy-high-priority-pod
的priorityClassName
设置为high-priority
,使其具有高优先级。
三、总结:K8s资源管理,任重道远
好了,今天的K8s资源限制与Pod驱逐策略脱口秀就到这里了。希望通过今天的讲解,大家对K8s的资源管理有了更深入的理解。
总而言之,K8s资源管理是一个复杂但重要的课题。我们需要根据应用的特点和集群的资源状况,合理地设置资源限制,并灵活地运用Pod驱逐策略,才能保证K8s集群的稳定运行和高效利用。
记住,K8s集群就像一个生态系统,我们需要像爱护环境一样,爱护我们的K8s集群,才能让它健康成长,为我们提供源源不断的动力。
最后,送给大家一句忠告:
资源限制要合理,Pod驱逐要优雅,K8s集群才能长长久久!
感谢大家的收听,我们下期再见! 👋