资源调度
Label & Selector
在Kubernetes中,Label是键值对形式的元数据,可以附加到各种资源对象上,比如Pod、Service、Deployment等。这些Label可以用来对资源对象进行分类、组织和标记,从而方便管理和操作。
Label Selector则是一种查询语法,用于根据Label的键值对来选择匹配的资源对象。它可以在各种场景下使用,比如查找特定类型的Pod、服务发现、负载均衡等。通过Label Selector,可以方便地根据需要选择和操作资源对象,实现灵活的资源管理和控制。
命令
# 创建临时label,永久修改可以通过edit
kubectl label po <po> app=hello -n <ns>
# 获取label
kubectl label po--show-labels
# 根据标签去匹配pod
kubectl get po -l type=app
kubectl get po -l 'version in (1.1.0, 1.0.0)'
kubectl get po -l version!=1.1.0,type=app
# 使用逻辑运算符 OR:
kubectl get pods -l 'key1=value1' -o 'key2=value2'
基本操作
Label Selector 通常由以下几种表达式组成:
- 等式(Equality): 使用等式操作符(=)来匹配指定键值对的标签。例如,app=nginx 表示选择具有标签 app,其值为 nginx 的资源对象。
- 集合匹配(Set-based Matching): 使用集合操作符(in、notin、exists、does not exist)来匹配指定标签的值。例如,environment in (production, staging) 表示选择具有标签 environment,其值为 production 或 staging 的资源对象。
- 按键过滤(Key Filtering): 使用键过滤操作符(!=、!)来匹配指定键的资源对象。例如,app!=nginx 表示选择具有标签 app,但其值不为 nginx 的资源对象。
- 逻辑运算(Logical Operators): 使用逻辑操作符(AND、OR、NOT)来组合多个标签选择器。例如,app=nginx, environment=production 表示选择具有标签 app 值为 nginx 且具有标签 environment 值为 production 的资源对象。
以下是一些使用 Label Selector 的示例:
- 选择具有标签 app=nginx 的 Pod:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
- 选择具有标签 environment 值为 production 或 staging 的 Service:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
environment:
in: [production, staging]
- 选择具有标签 tier 值为 backend 但没有标签 app 的 Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-deployment
spec:
selector:
matchLabels:
tier: backend
matchExpressions:
- {key: app, operator: DoesNotExist}
Deployment
在 Kubernetes 中,Deployment、ReplicaSet(简称 RS)和 Pod 之间存在一种关系,它们通常是这样关联的:
- Deployment:Deployment 是一个高级别的资源对象,用于管理应用程序的部署和更新。它负责定义所需的 Pod 模板和副本数目,并控制 RS 的创建、更新和删除过程。
- ReplicaSet:ReplicaSet 是一个控制器对象,用于确保指定数量的 Pod 副本在集群中运行。Deployment 通常会创建一个或多个 ReplicaSet,并使用 ReplicaSet 来管理 Pod 的生命周期。当 Deployment 进行滚动更新或扩缩容时,它会通过创建新的 ReplicaSet、逐步删除旧的 ReplicaSet 来实现更新和调整副本数目。
- Pod:Pod 是 Kubernetes 中最小的部署单元,它可以包含一个或多个容器,并共享相同的网络命名空间、存储卷和 IP 地址。ReplicaSet 负责创建和管理一组相同配置的 Pod 副本,确保它们按照预期的副本数目运行在集群中。
简单来说,Deployment 使用 ReplicaSet 来管理 Pod 的副本数目和生命周期。当需要更新应用程序时,Deployment 会创建一个新的 ReplicaSet,并逐步替换旧的 ReplicaSet 中的 Pod。这种方式可以实现应用程序的滚动更新,并保证在更新过程中不会中断服务。
创建
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment # 部署的名称
spec:
replicas: 3 # 副本数
hostNetwork: true # 是否使用主机网络
selector:
matchLabels:
app: nginx # 选择器,用于选择部署的 Pod
strategy:
type: RollingUpdate # 滚动更新策略类型
rollingUpdate:
maxSurge: 1 # 最大超出副本数
maxUnavailable: 1 # 最大不可用副本数
template: # Pod 模板
metadata:
labels:
app: nginx # Pod 的标签
spec:
containers:
- name: nginx
image: nginx:latest # 使用的镜像
ports:
- containerPort: 80 # 容器监听端口
resources:
limits:
cpu: "1"
memory: "1Gi"
storage: "1Gi"
network: "1Mbps"
gpu: "1"
requests:
cpu: "0.5"
memory: "512Mi"
storage: "512Mi"
network: "512Kbps"
gpu: "0.5"
revisionHistoryLimit: 5 # 保留的历史版本数量
滚动更新
滚动更新是 Kubernetes 中一种更新 Deployment 的策略,它允许你在不中断服务的情况下逐步更新应用程序的实例。滚动更新的步骤如下:
- Kubernetes 更新 Deployment 的 Pod 模板:通过修改 Deployment 中的 Pod 模板,例如更改容器的镜像版本或配置。
- Kubernetes 创建新的 ReplicaSet:一旦 Deployment 的 Pod 模板被更新,Kubernetes 将创建一个新的 ReplicaSet,该 ReplicaSet 包含根据新 Pod 模板创建的 Pod。
- Kubernetes 逐步调整实例数:Kubernetes 会逐步增加新 ReplicaSet 中 Pod 的数量,同时减少旧 ReplicaSet 中 Pod 的数量,以确保整个应用程序的实例数保持稳定。这确保了在更新期间服务的稳定性。
- Kubernetes 删除旧的 ReplicaSet:一旦新 ReplicaSet 中的 Pod 数量达到预期数量,并且旧 ReplicaSet 中的 Pod 数量减少到零,Kubernetes 将删除旧 ReplicaSet。
查看滚动更新信息
kubectl rollout status deploy nginx-deployment
回滚
要回滚 Kubernetes 中的 Deployment,你可以使用以下命令:
kubectl rollout undo deployment <deployment-name>
这会将指定 Deployment 的当前版本回滚到之前的版本。Kubernetes 会自动处理回滚,并且在回滚完成后,新的 Pod 会逐步替换掉旧的 Pod,直到回滚完成。
你也可以使用 --to-revision 标志来指定要回滚到的特定版本,例如:
kubectl rollout undo deployment <deployment-name> --to-revision=<revision>
这将指定 Deployment 回滚到指定的修订版本号。
回滚完成后,你可以使用以下命令查看回滚历史:
kubectl rollout history deployment <deployment-name>
扩容和缩容
- 扩容: 使用以下命令将 Deployment 扩容到指定的副本数量:
kubectl scale deployment <deployment-name> --replicas=<desired-replicas>
其中,<deployment-name>
是要扩容的 Deployment 的名称,<desired-replicas>
是要设置的目标副本数量。
- 缩容: 使用以下命令将 Deployment 缩容到指定的副本数量:
kubectl scale deployment <deployment-name> --replicas=<desired-replicas>
同样地,<deployment-name>
是要缩容的 Deployment 的名称,<desired-replicas>
是要设置的目标副本数量。
暂停与恢复
kubectl rollout pause deployment <deployment-name>
kubectl rollout resume deployment <deployment-name>
StatefulSet
StatefulSet 是 Kubernetes 中用于管理有状态应用程序的控制器。与 Deployment 不同,StatefulSet 给每个 Pod 分配一个稳定的标识符(通常是序号),并确保每个 Pod 的网络标识符、存储和其他属性在 Pod 重启和迁移时保持不变。
StatefulSet 主要用于运行需要持久化存储或唯一网络标识符的应用程序,如数据库(例如 MySQL、PostgreSQL)、分布式消息队列(例如 Kafka)或其他需要唯一标识符的应用程序。
StatefulSet 与 Deployment 相似,但有几个关键区别:
- Pod 的名称:StatefulSet 控制的 Pod 的名称包含了一个有序的索引,例如 pod-name-0、pod-name-1 等。
- 稳定标识符:StatefulSet 为每个 Pod 提供一个唯一的稳定标识符,如 hostname。
- 网络标识符:StatefulSet 为每个 Pod 提供一个唯一的网络标识符,可用于服务发现和 DNS 查询。
- 持久化标识符:StatefulSet 支持动态卷配置,可以确保每个 Pod 在重启和迁移时都能够保留相同的持久化存储。
StatefulSet 在需要管理有状态应用程序的场景下非常有用,它确保了应用程序的稳定性和可靠性,并提供了对有状态应用程序的良好支持。
定义
apiVersion: apps/v1 # 使用的 Kubernetes API 版本
kind: StatefulSet # 定义的 Kubernetes 资源类型
metadata:
name: example-statefulset # StatefulSet 的名称
spec:
replicas: 3 # 副本数量
serviceName: "example-service" # 关联的服务名称
selector: # 选择器,用于匹配 Pod
matchLabels: # 匹配的标签
app: example # app 标签的值为 example
template: # Pod 模板
metadata:
labels:
app: example # Pod 的标签
spec: # Pod 的规格
containers: # 容器列表
- name: nginx # 容器名称
image: nginx:1.7.9 # 容器使用的镜像
ports: # 容器暴露的端口
- containerPort: 80 # 端口号为 80
name: web # 端口名称为 web
volumeMounts: # 挂载的卷
- name: www # 卷的名称
mountPath: /usr/share/nginx/html/ # 挂载路径
volumeClaimTemplates: # 卷声明模板
- metadata:
name: www # 卷声明的名称
annotations: # 注释
volume.alpha.kubernetes.io/storage-class: anything # 存储类注释
spec: # 卷声明的规格
accessModes: ["ReadWriteOnce"] # 访问模式
resources: # 资源请求
requests:
storage: 1Gi # 存储容量
扩容缩容与滚动更新
会按顺序更新
更新image需要通过patch命令
发布与删除
灰度发布:
- 通过逐步更新 StatefulSet 中的 Pod 实例来实现灰度发布。您可以先更新一部分 Pod,然后观察它们的行为,如果没有问题,则继续更新其他 Pod。
- 您可以使用 StatefulSet 的 updateStrategy 字段来控制 Pod 的更新策略,例如 OnDelete 策略会等待所有 Pod 删除后再更新,而 RollingUpdate 策略会逐步更新 Pod。
金丝雀发布:
- 类似于灰度发布,您可以先更新一小部分 Pod 实例,然后观察它们的行为和性能。如果一切正常,可以逐步增加更新的 Pod 实例数量。
- 使用 StatefulSet 的 updateStrategy 字段,结合适当的标签选择器和选择条件,可以实现金丝雀发布。通过逐步更新匹配特定标签的 Pod 实例,您可以控制新版本的逐步部署。
Partition 属性:Partition 属性是 StatefulSet 对象的一个字段,它确定了更新时受影响的 Pod 子集。当您将 partition 属性设置为一个非零值时,StatefulSet 将只更新具有比该值小的索引的 Pod。这允许您以分批的方式更新 Pod,从而实现灰度发布。
灰度发布策略:通过逐步增加 partition 的值,您可以控制更新的 Pod 数量。例如,将 partition 设置为 1 将更新索引小于 1 的 Pod,将 partition 设置为 2 将更新索引小于 2 的 Pod,依此类推。逐步增加 partition 可以逐步扩大更新范围,实现灰度发布。
全部更新:如果您希望更新全部的 Pod,可以将 partition 属性设置为 0,这将影响所有 Pod 并触发它们的滚动更新。
onDelete
onDelete 策略类型:onDelete 策略有两种类型:
- Delete:表示在删除 StatefulSet 对象时,Pod 将被删除,并且 StatefulSet 控制器不会自动创建替代的 Pod。这意味着一旦删除了 StatefulSet,相关的 Pod 将被永久删除。
- Orphan:表示在删除 StatefulSet 对象时,Pod 将被“放逐”而不是立即删除。被放逐的 Pod 不再受 StatefulSet 控制,但它们仍然存在于集群中。这允许您手动处理这些 Pod,例如将它们重新分配到其他控制器。
级联删除与非级联删除
StatefulSet 的级联删除与非级联删除与一般资源的概念类似,但是有一些特定的注意事项:
- 级联删除:
- 在删除 StatefulSet 时,默认情况下会执行级联删除,这意味着与 StatefulSet 相关的所有 Pod 和持久卷声明 (PVC) 也会被删除。
- 该操作将删除 StatefulSet 的所有实例,以及它们对应的网络标识符、持久化存储和其他相关资源。
- 级联删除适用于在删除 StatefulSet 时希望清理所有相关资源的场景。
- 非级联删除:
- 非级联删除将仅删除 StatefulSet 本身,而不会影响与其相关的 Pod 和 PVC。
- 这意味着 StatefulSet 的 Pod 将继续运行,并且与它们的网络标识符和持久化存储保持连接,即使 StatefulSet 自身已被删除。
- 非级联删除通常用于确保 StatefulSet 的实例持续运行,即使 StatefulSet 资源本身不再存在。
在 Kubernetes 中,您可以通过在删除资源时设置 --cascade=false 选项来执行非级联删除,例如:
kubectl delete statefulset <statefulset-name> --cascade=false
主要命令
- 创建 StatefulSet:
kubectl create -f <statefulset-definition.yaml>
- 查看 StatefulSet:
kubectl get sts
- 查看详细信息:
kubectl describe sts <statefulset-name>
- 更新 StatefulSet:
kubectl apply -f <updated-statefulset-definition.yaml>
- 删除 StatefulSet:
kubectl delete sts <statefulset-name>
- 扩容或缩容:
kubectl scale sts <statefulset-name> --replicas=<new-replica-count>
- 滚动更新:
kubectl rollout status sts <statefulset-name>
- 回滚到先前的版本:
kubectl rollout undo sts <statefulset-name>
DaemonSet
- 每个节点一个 Pod:
- DaemonSet 会在集群中的每个节点上创建一个 Pod 的副本,确保每个节点都运行指定的应用程序或服务。
- 当有新的节点加入集群时,DaemonSet 会自动在新节点上创建 Pod,以确保集群中每个节点的运行环境都是一致的。
- 滚动更新:
- 类似于其他控制器,DaemonSet 支持滚动更新功能,可以在更新 DaemonSet 时逐步替换现有的 Pod 实例,以避免影响集群的稳定性。
- 节点调度:
- DaemonSet 可以根据节点的标签选择器来确定在哪些节点上运行 Pod 实例。
- 通过节点选择器,可以灵活地控制 DaemonSet 在哪些节点上运行 Pod,从而满足不同节点的资源需求或特定的部署策略。
- 应用场景:
- DaemonSet 适用于需要在每个节点上运行的服务或应用程序,例如日志收集代理、监控代理、网络代理等。
- 它还常用于在整个集群中部署辅助工具,如存储卷插件、容器网络插件等。
- 自动调整:
- 通过 Kubernetes 的自动调度和自愈机制,DaemonSet 可以确保在节点故障或不可用时自动重新调度 Pod 实例,以保证系统的高可用性和稳定性。
日志收集
Fluentd
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
namespace: kube-system
spec:
selector:
matchLabels:
app: fluentd
template:
metadata:
labels:
app: fluentd
spec:
serviceAccount: fluentd
containers:
- name: fluentd
image: agilestacks/fluentd-elasticsearch:v1.3.0
volumeMounts:
- name: containers
mountPath: /var/lib/docker/containers
- name: varlog
mountPath: /varlog
volumes:
- hostPath:
path: /var/lib/docker/containers
name: containers
- hostPath:
path: /var/log
name: varlog
指定部署节点
在 DaemonSet 中指定节点部署有几种方法:
- nodeSelector: 使用 nodeSelector 字段可以指定一个或多个节点标签,以确保 DaemonSet 的 Pod 仅部署到具有匹配标签的节点上。
spec:
template:
spec:
nodeSelector:
disk: ssd
- affinity/anti-affinity: 使用 affinity 字段可以根据节点的亲和性或反亲和性进行部署。亲和性可确保一组 Pod 在同一节点上部署,而反亲和性则确保一组 Pod 在不同的节点上部署。
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disk
operator: In
values:
- ssd
- nodeSelectorTerms: 在 nodeAffinity 字段中,nodeSelectorTerms 允许您指定多个节点选择器条件。这样可以更灵活地控制 DaemonSet 的 Pod 部署。
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disk
operator: In
values:
- ssd
- matchExpressions:
- key: gpu
operator: Exists
更新策略
推荐使用OnDelete
HPA
metrics
top本身不可用,需要安装这个命令才可以使用
在使用 Horizontal Pod Autoscaler (HPA) 之前,您需要确保您的 Kubernetes 集群中已经配置了支持 HPA 所需的度量指标(metrics)。常见的度量指标包括 CPU 利用率和内存利用率。
HPA 支持以下两种类型的度量指标:
- Resource Metrics:资源度量指标是关于 Pod 的资源使用情况,例如 CPU 利用率和内存利用率。这些度量指标由 Kubernetes 监控系统(如 metrics-server)提供。
- Custom Metrics:自定义度量指标是您可以根据自己的需求定义的度量指标,例如队列长度、请求速率等。这些度量指标由您自己的监控系统提供,并且需要安装和配置相应的监控适配器,例如 Prometheus 适配器。
wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml -O metrics-server-components.yaml
sed -i "s/k8s.gcr.ioVmetrics-server/registry.cn-hangzhou.aliyuncs.comVgoogle_containers/g' metrics-server-components.yaml
# 去除HTTPS 配置
在containers里面添加
# - --kubelet-insecure-tls
使用
Horizontal Pod Autoscaler(HPA)是 Kubernetes 中的一种资源,用于根据 CPU 使用率或自定义指标自动调整 Pod 的副本数量,以适应应用程序的负载变化。以下是一个简单的 HPA 的 YAML 示例:
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: my-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-deployment
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization: 50
这个 HPA 的 YAML 文件描述了一个 HorizontalPodAutoscaler 资源,它会自动调整名为 my-deployment 的 Deployment 中 Pod 的副本数量。
- scaleTargetRef: 指定了要自动扩展的 Deployment 的引用。
- minReplicas 和 maxReplicas: 指定了 Pod 副本数量的最小值和最大值。
- metrics: 指定了用于自动扩展的指标。
- type: Resource: 表示使用资源指标(例如 CPU 使用率)进行自动扩展。
- resource.name: cpu: 指定了使用 CPU 使用率作为自动扩展的指标。
- resource.targetAverageUtilization: 50: 指定了目标平均 CPU 利用率为 50%,当 CPU 利用率超过此阈值时,HPA 将增加 Pod 的副本数量。
这个示例中的 HPA 会监视名为 my-deployment 的 Deployment 中 Pod 的 CPU 使用率,并在 CPU 使用率超过 50% 时增加 Pod 的副本数量,最多不超过 10 个,最少不少于 1 个。
kubectl autoscale deployment <deployment-name> --cpu-percent=80 --min=1 --max=10
Job
Job 负责确保 Pod 成功运行完成(成功退出代码 0),适合一次性任务,比如数据库初始化、日志分析等。 与Deployment 不同的是,Job 不会自动重启 Pod,当 Pod 退出时,Job 会自动删除 Pod。 Deployment 维护长期运行的服务(不断重启),而 Job 只负责运行一次并成功退出的任务。
- 一次性任务:数据库迁移、批处理脚本
- 异步任务:用户上传处理、模型训练
- 定期运行:结合 CronJob 使用
- 大规模并发任务(MapReduce 类似)
使用
apiVersion: batch/v1
kind: Job
metadata:
name: example-job
spec:
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
控制 Job 行为的参数
参数 | 说明 |
---|---|
completions | 完成任务所需的 Pod 次数(默认 1) |
parallelism | 同时运行的 Pod 数量(默认 1) |
backoffLimit | 失败重试次数(默认 6) |
activeDeadlineSeconds | 最长运行时间 |
ttlSecondsAfterFinished | Job 完成后保留多久再清理资源(支持自动清理) |
Job 类型
类型 | 场景 | 特点 |
---|---|---|
普通 Job | 一次性执行任务 | 最常见 |
Parallel Job | 多任务并行执行 | 使用 completions 和 parallelism 控制 |
Indexed Job | 有编号的任务 | 使用 completionMode: Indexed ,用于任务分片 |
CronJob | 定时任务 | 类似 Linux 的 cron,生成 Job |
Job 的状态和排错
状态字段 | 含义 |
---|---|
status.succeeded | 成功完成的 Pod 数量 |
status.failed | 失败的 Pod 次数 |
kubectl describe job | 查看 Job 控制器行为 |
kubectl logs pod-name | 查看 Pod 输出 |
最佳实践
- 设置 ttlSecondsAfterFinished,自动清理资源
- 合理设置 backoffLimit 和 activeDeadlineSeconds
- 使用 Resource Limit,避免批处理任务消耗过多资源
- 对大规模并发任务使用 Indexed Job 做任务分片处理
- Job 中不要使用 restartPolicy: Always
CronJob
CronJob 会在指定时间创建一个或多个 Job。 每次调度都会生成一个新的 Job 实例(Job controller 来管理)。 适合做定时清理、定时备份、周期性同步、定时上报等任务。
- 日志归档:定时清理旧日志文件
- 数据备份:每天/每周备份数据库、对象存储
- 数据同步:定时从外部源拉取/推送数据
- 模型训练调度:每晚训练模型、更新指标
- 健康检测:定时调用内外部服务健康检查并上报
使用
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello-cron
spec:
schedule: "*/5 * * * *" # 每5分钟执行一次
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes CronJob!
restartPolicy: OnFailure
字段 | 说明 |
---|---|
schedule | 定时规则(Cron 表达式) |
jobTemplate | Job 模板,与普通 Job 一样 |
startingDeadlineSeconds | 最大延迟时间,超出则不执行 |
concurrencyPolicy | Allow 允许多个并发执行(默认); Forbid 禁止并发,前一个未完成则跳过当前调度; Replace 杀掉上一个未完成的 Job,执行新的 ; |
successfulJobsHistoryLimit | 成功 Job 保留数量(默认 3) |
failedJobsHistoryLimit | 失败 Job 保留数量(默认 1) |
suspend | 设置为 true 可暂停调度 |
最佳实践
- 避免执行时间太短的任务(调度开销大)
- Job 的运行时间不应超过 schedule 间隔
- 设置好 concurrencyPolicy 避免重复执行
- 使用 ttlSecondsAfterFinished 清理 Job
- 为任务配置资源限制和失败重试
- 保留 successfulJobsHistoryLimit 和 failedJobsHistoryLimit 以便追踪日志
InitC
在 Kubernetes 中,Init 容器是在主业务容器(app container)启动之前运行的容器,用于执行一些预处理或准备任务。 它们和普通容器一样定义镜像、命令、挂载等,但只能 顺序运行,所有 Init 容器完成后,主容器才会启动。
作用
- 依赖检查:等待数据库、缓存服务等就绪
- 文件准备:拷贝配置文件或初始化数据
- 权限设定:设置挂载目录的权限
- 等待条件满足:使用 nslookup、curl 等工具等待某服务可用
使用
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
initContainers:
- name: init-myservice
image: busybox
command: ['sh', '-c', 'until nslookup myservice; do echo waiting; sleep 2; done;']
containers:
- name: main-app
image: busybox
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
- initContainer 依次执行。
- 每个 initContainer 必须 成功(退出码 0),下一个才能运行。
- 所有 init 容器执行完成后,Pod 中的主容器(containers)开始启动。
污点和容忍(Taints and Tolerations)
概念
- 污点(Taint):施加在节点上的标记,用于“驱逐”不满足条件的 Pod,使得这些 Pod 不能调度到该节点上。
- 容忍(Toleration):Pod 对污点的“容忍”声明,表示该 Pod 可以被调度到带有相应污点的节点上。
作用
- 通过污点和容忍机制,Kubernetes 实现节点对 Pod 调度的过滤与控制。
- 防止某些 Pod 被调度到不适合的节点。
- 实现节点隔离、资源预留、专用节点等场景。
机制说明
节点可以有多个污点,每个污点包含
key=value:effect
,其中 effect 有三种类型:NoSchedule
:不允许 Pod 调度到此节点,除非 Pod 有对应容忍。PreferNoSchedule
:尽量避免调度,但不强制。NoExecute
:驱逐节点上不容忍该污点的 Pod,并且后续不允许调度。
Pod 通过添加容忍,声明可以容忍特定的污点。
示例
给节点打污点:
kubectl taint nodes node1 key=value:NoSchedule
Pod 添加容忍:
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
亲和力(Affinity)
概念
亲和力用于定义 Pod 在节点上的调度偏好和约束,主要有两种:
- 节点亲和力(Node Affinity):指定 Pod 需要调度到符合特定标签的节点。
- Pod 亲和力/反亲和力(Pod Affinity/AntiAffinity):指定 Pod 与其他 Pod 的共存或避让规则。
作用
- 实现更灵活的调度策略。
- 优化资源利用、提高可用性。
- 实现 Pod 之间的协同或隔离。
节点亲和力
- 类似污点/容忍,但更细粒度。
- 支持“必须(requiredDuringSchedulingIgnoredDuringExecution)”和“优选(preferredDuringSchedulingIgnoredDuringExecution)”两种规则。
示例:调度到带有 disktype=ssd
标签的节点
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
Pod 亲和力与反亲和力
- Pod 亲和力:要求新 Pod 与已有 Pod 在同一节点或同一区域。
- Pod 反亲和力:要求新 Pod 不和某些 Pod 在同一节点或同一区域。
示例:Pod 反亲和力,避免和标签为 app=web
的 Pod 在同一节点
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
topologyKey: "kubernetes.io/hostname"