OpenShift OKD 资源限制与调度实战指南
·
OpenShift OKD 资源限制与调度实战指南
目标:掌握资源调度 —— 设置 CPU/内存限制 & 使用 NodeSelector
一、前置准备
1.1 环境检查
# 确认已登录 OKD 集群
oc whoami
oc cluster-info
# 查看集群节点状态
oc get nodes
# 查看节点详细信息(包括标签)
oc get nodes --show-labels
1.2 创建实验项目
# 创建独立的实验命名空间
oc new-project resource-demo
# 确认当前项目
oc project
二、设置 CPU / 内存限制
资源限制分为两个层次:
- Pod 级别:直接在容器 spec 中设置
resources - 命名空间级别:通过
LimitRange设置默认值,通过ResourceQuota设置总配额
2.1 Pod 级别资源限制
核心概念
| 字段 | 作用 |
|---|---|
requests |
调度器用于选择节点的最低保证资源 |
limits |
容器可使用的资源上限,超出将被限流(CPU)或 OOM Kill(内存) |
创建带资源限制的 Pod
# resource-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: resource-demo-pod
namespace: resource-demo
spec:
containers:
- name: demo-container
image: nginx:latest
resources:
requests:
cpu: "250m" # 0.25 核(millicores)
memory: "128Mi" # 128 MiB
limits:
cpu: "500m" # 0.5 核
memory: "256Mi" # 256 MiB
# 部署 Pod
oc apply -f resource-pod.yaml
# 验证资源配置
oc describe pod resource-demo-pod | grep -A 10 "Limits\|Requests"
创建带资源限制的 Deployment
# resource-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: resource-demo-deploy
namespace: resource-demo
spec:
replicas: 2
selector:
matchLabels:
app: resource-demo
template:
metadata:
labels:
app: resource-demo
spec:
containers:
- name: app-container
image: nginx:latest
resources:
requests:
cpu: "100m"
memory: "64Mi"
limits:
cpu: "300m"
memory: "128Mi"
oc apply -f resource-deployment.yaml
oc get pods -n resource-demo
oc describe pod -l app=resource-demo -n resource-demo
2.2 命名空间级别:LimitRange(默认限制)
LimitRange 为没有显式声明资源的容器自动注入默认值。
# limitrange.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: demo-limitrange
namespace: resource-demo
spec:
limits:
# ---- Container 级别限制 ----
- type: Container
default: # 默认 limits(未声明时使用)
cpu: "500m"
memory: "256Mi"
defaultRequest: # 默认 requests(未声明时使用)
cpu: "100m"
memory: "64Mi"
max: # 单个容器最大值
cpu: "2"
memory: "1Gi"
min: # 单个容器最小值
cpu: "50m"
memory: "32Mi"
# ---- Pod 级别限制 ----
- type: Pod
max:
cpu: "4"
memory: "2Gi"
# 应用 LimitRange
oc apply -f limitrange.yaml
# 查看生效的 LimitRange
oc describe limitrange demo-limitrange -n resource-demo
# 测试:创建一个不带资源声明的 Pod,观察是否自动注入
oc run test-auto --image=nginx --restart=Never -n resource-demo
oc describe pod test-auto -n resource-demo | grep -A 6 "Limits\|Requests"
2.3 命名空间级别:ResourceQuota(总配额)
ResourceQuota 限制整个命名空间的资源总量。
# resourcequota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: demo-quota
namespace: resource-demo
spec:
hard:
# 计算资源配额
requests.cpu: "2" # 所有容器 requests.cpu 总和
requests.memory: "2Gi"
limits.cpu: "4" # 所有容器 limits.cpu 总和
limits.memory: "4Gi"
# 对象数量配额
pods: "10" # 最多 10 个 Pod
services: "5"
persistentvolumeclaims: "5"
# 应用配额
oc apply -f resourcequota.yaml
# 查看当前配额使用情况
oc describe resourcequota demo-quota -n resource-demo
# 实时监控配额
oc get resourcequota demo-quota -n resource-demo -o yaml
2.4 验证资源限制效果
# 尝试创建超出 limits 的 Pod(预期失败)
cat <<EOF | oc apply -f -
apiVersion: v1
kind: Pod
metadata:
name: over-limit-pod
namespace: resource-demo
spec:
containers:
- name: big-container
image: nginx
resources:
limits:
cpu: "10" # 超过 LimitRange 的 max.cpu: 2
memory: "10Gi"
EOF
# 查看拒绝原因
oc describe pod over-limit-pod -n resource-demo
三、使用 NodeSelector 调度
NodeSelector 通过节点标签将 Pod 固定调度到满足条件的节点。
3.1 查看节点标签
# 查看所有节点及标签
oc get nodes --show-labels
# 以可读格式查看单个节点标签
oc describe node <node-name> | grep -A 20 "Labels:"
# 查看节点内置标签(常用)
oc get nodes -o custom-columns=\
NAME:.metadata.name,\
ROLE:.metadata.labels."node-role\.kubernetes\.io/worker",\
OS:.metadata.labels."kubernetes\.io/os",\
ARCH:.metadata.labels."kubernetes\.io/arch"
3.2 为节点添加自定义标签
# 语法:oc label node <node-name> <key>=<value>
oc label node worker-node-1 environment=production
oc label node worker-node-2 environment=staging
oc label node worker-node-1 disk=ssd
# 验证标签已添加
oc get node worker-node-1 --show-labels
# 删除标签(键后加 - 号)
# oc label node worker-node-1 disk-
3.3 在 Pod 中使用 NodeSelector
# nodeselector-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: prod-pod
namespace: resource-demo
spec:
nodeSelector:
environment: production # 只调度到有此标签的节点
kubernetes.io/os: linux # 可叠加多个标签(AND 逻辑)
containers:
- name: app
image: nginx:latest
resources:
requests:
cpu: "100m"
memory: "64Mi"
limits:
cpu: "200m"
memory: "128Mi"
oc apply -f nodeselector-pod.yaml
# 查看 Pod 被调度到哪个节点
oc get pod prod-pod -n resource-demo -o wide
# 确认节点选择器生效
oc describe pod prod-pod -n resource-demo | grep -A 3 "Node-Selectors"
3.4 在 Deployment 中使用 NodeSelector
# nodeselector-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: prod-deployment
namespace: resource-demo
spec:
replicas: 3
selector:
matchLabels:
app: prod-app
template:
metadata:
labels:
app: prod-app
spec:
nodeSelector:
environment: production # 所有副本都调度到 production 节点
containers:
- name: app
image: nginx:latest
resources:
requests:
cpu: "100m"
memory: "64Mi"
limits:
cpu: "300m"
memory: "256Mi"
oc apply -f nodeselector-deployment.yaml
# 查看所有副本分布
oc get pods -l app=prod-app -n resource-demo -o wide
# 查看调度事件
oc get events -n resource-demo --sort-by='.lastTimestamp'
3.5 验证调度失败场景
# 设置一个不存在的标签(预期 Pod 进入 Pending 状态)
cat <<EOF | oc apply -f -
apiVersion: v1
kind: Pod
metadata:
name: unschedulable-pod
namespace: resource-demo
spec:
nodeSelector:
environment: nonexistent # 没有节点有此标签
containers:
- name: app
image: nginx
EOF
# 观察 Pod 状态(应为 Pending)
oc get pod unschedulable-pod -n resource-demo
# 查看调度失败原因
oc describe pod unschedulable-pod -n resource-demo | grep -A 5 "Events:"
四、综合实践:资源限制 + NodeSelector
将两个特性结合,部署一个完整的生产级应用:
# combined-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: full-demo
namespace: resource-demo
labels:
app: full-demo
spec:
replicas: 2
selector:
matchLabels:
app: full-demo
template:
metadata:
labels:
app: full-demo
tier: backend
spec:
# ---- NodeSelector ----
nodeSelector:
environment: production
kubernetes.io/os: linux
# ---- 容器定义 ----
containers:
- name: backend
image: nginx:latest
ports:
- containerPort: 80
# ---- 资源限制 ----
resources:
requests:
cpu: "200m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
# ---- 健康检查 ----
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 15
periodSeconds: 20
oc apply -f combined-demo.yaml
# 全面验证
echo "=== Pod 状态 ==="
oc get pods -l app=full-demo -n resource-demo -o wide
echo "=== 资源使用 ==="
oc top pods -n resource-demo
echo "=== 节点选择器 ==="
oc describe pods -l app=full-demo -n resource-demo | grep -E "Node:|Node-Selectors:|Limits:|Requests:"
echo "=== 配额使用 ==="
oc describe resourcequota demo-quota -n resource-demo
五、常用诊断命令速查
# === 资源查看 ===
oc describe pod <pod-name> # Pod 详情(含资源、事件)
oc top nodes # 节点资源使用率
oc top pods -n resource-demo # Pod 资源使用率
oc get resourcequota -n resource-demo # 查看配额
oc get limitrange -n resource-demo # 查看限制范围
# === 节点标签管理 ===
oc get nodes --show-labels # 查看所有节点标签
oc label node <node> key=value # 添加标签
oc label node <node> key- # 删除标签
oc get nodes -l key=value # 按标签筛选节点
# === 调度诊断 ===
oc get events -n resource-demo --sort-by='.lastTimestamp' # 查看事件
oc describe pod <pending-pod> # 查看 Pending 原因
# === 清理实验环境 ===
oc delete project resource-demo
六、关键概念总结
| 概念 | 作用域 | 说明 |
|---|---|---|
resources.requests |
容器 | 调度依据,保证最低资源 |
resources.limits |
容器 | 资源使用上限 |
LimitRange |
命名空间 | 设置默认值与单体上下限 |
ResourceQuota |
命名空间 | 限制整个命名空间的总资源量 |
nodeSelector |
Pod/Deployment | 按标签指定调度节点 |
💡 最佳实践:始终为生产环境的容器设置
requests和limits,并通过LimitRange为命名空间设置兜底默认值,防止未声明资源的 Pod 无限制地消耗集群资源。
更多推荐


所有评论(0)