PodMigrationJob

Koordinator定义了一个基于 CRD 的 Pod 迁移 API,称为 PodMigrationJob,通过此 API,重调度器(descheduler)或其他自动故障恢复组件可以更安全地将 Pod 驱逐或删除。

介绍

迁移 Pods 是许多组件(如descheduler)依赖的重要能力,可用于优化调度或帮助解决工作负载运行时质量问题。我们认为,Pod 迁移是一个复杂的过程,涉及诸如审计(auditing)、资源分配和应用程序启动等步骤,并与应用程序升级、伸缩等场景以及集群管理员的资源操作和维护操作混合在一起。因此,如何管理此过程的稳定性风险,以确保应用程序不会因为 Pod 迁移而失败,是必须解决的关键的问题。

基于 PodMigrationJob CRD 的最终状态导向迁移能力,我们可以跟踪迁移过程中每个过程的状态,感知应用程序升级和扩展等场景,以确保工作负载的稳定性。

设置

前置条件

  • Kubernetes >= 1.18
  • Koordinator >= 0.6

Installation

请确保Koordinator组件已正确安装在您的集群中。如果未安装,请参考安装.

Configurations

PodMigrationJob 已默认启用。您可以在koord-descheduler配置中无需任何修改即可使用它。

使用 PodMigrationJob

快速开始

  1. 使用下面的YAML文件创建一个名为pod-demo的Deployment
1. apiVersion: apps/v1
2. kind: Deployment
3. metadata:
4. name: pod-demo
5. namespace: default
6. spec:
7. progressDeadlineSeconds: 600
8. replicas: 1
9. revisionHistoryLimit: 10
10. selector:
11. matchLabels:
12. app: pod-demo
13. strategy:
14. rollingUpdate:
15. maxSurge: 25%
16. maxUnavailable: 25%
17. type: RollingUpdate
18. template:
19. metadata:
20. creationTimestamp: null
21. labels:
22. app: pod-demo
23. name: stress
24. spec:
25. containers:
26. - args:
27. - -c
28. - "1"
29. command:
30. - stress
31. image: polinux/stress
32. imagePullPolicy: Always
33. name: stress
34. resources:
35. limits:
36. cpu: "2"
37. memory: 4Gi
38. requests:
39. cpu: 200m
40. memory: 400Mi
41. restartPolicy: Always
42. schedulerName: koord-scheduler
1. $ kubectl create -f pod-demo.yaml
2. deployment.apps/pod-demo created
  1. 检查Pod pod-demo-0 的调度结果
1. $ kubectl get pod -o wide
2. NAME                        READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
3. pod-demo-5f9b977566-c7lvk   1/1     Running   0          41s   10.17.0.9     node-0   <none>           <none>

pod-demo-5f9b977566-c7lvk 被调度在节点 node-0上

  1. 使用下面的YAML文件创建一个 PodMigrationJob 来迁移 pod-demo-0
1. apiVersion: scheduling.koordinator.sh/v1alpha1
2. kind: PodMigrationJob
3. metadata:
4. name: migrationjob-demo
5. spec:
6. paused: false
7. ttl: 5m
8. mode: ReservationFirst
9. podRef:
10. namespace: default
11. name: pod-demo-5f9b977566-c7lvk
12. status:
13. phase: Pending
1. $ kubectl create -f migrationjob-demo.yaml
2. podmigrationjob.scheduling.koordinator.sh/migrationjob-demo created
  1. 查看迁移状态
1. $ kubectl get podmigrationjob migrationjob-demo
2. NAME                PHASE     STATUS     AGE   NODE     RESERVATION                            PODNAMESPACE   POD                         NEWPOD                      TTL
3. migrationjob-demo   Succeed   Complete   37s   node-1   d56659ab-ba16-47a2-821d-22d6ba49258e   default        pod-demo-5f9b977566-c7lvk   pod-demo-5f9b977566-nxjdf   5m0s

从上述结果可以观察到:

  • PHASE 为 Succeed, STATUS 为 Complete, 表明迁移成功;
  • NODE node-1 表示迁移后新Pod所调度的节点;
  • RESERVATION d56659ab-ba16-47a2-821d-22d6ba49258e 是在迁移期间创建的 Reservation。PodMigrationJob Controller 将在开始驱逐 Pod 之前尝试为 Reservation 创建预留资源。在成功预留资源后,将启动驱逐操作,这可以确保新 Pod 必须被驱逐,因为已有资源可用;
  • PODNAMESPACE default 表示待迁移 Pod 所在的命名空间;
  • POD pod-demo-5f9b977566-c7lvk 表示待迁移的 Pod;
  • NEWPOD pod-demo-5f9b977566-nxjdf 表示迁移后新创建的 Pod;
  • TTL 表示当前作业的 TTL 周期。

  • 查看迁移事件

PodMigrationJob Controller 将在迁移过程的重要步骤中创建事件,以帮助用户诊断迁移问题

1. $ kubectl describe podmigrationjob migrationjob-demo
2. ...
3. Events:
4. Type    Reason                Age    From               Message
5. ----    ------                ----   ----               -------
6. Normal  ReservationCreated    8m33s  koord-descheduler  Successfully create Reservation "d56659ab-ba16-47a2-821d-22d6ba49258e"
7. Normal  ReservationScheduled  8m33s  koord-descheduler  Assigned Reservation "d56659ab-ba16-47a2-821d-22d6ba49258e" to node "node-1"
8. Normal  Evicting              8m33s  koord-descheduler  Try to evict Pod "default/pod-demo-5f9b977566-c7lvk"
9. Normal  EvictComplete         8m     koord-descheduler  Pod "default/pod-demo-5f9b977566-c7lvk" has been evicted
10. Normal  Complete              8m     koord-descheduler  Bind Pod "default/pod-demo-5f9b977566-nxjdf" in Reservation "d56659ab-ba16-47a2-821d-22d6ba49258e"

高级配置

最新的API可以查看pod_migration_job_types.go.

示例: 手动确认是否允许迁移

驱逐或迁移操作会带来稳定性风险,因此希望在启动迁移操作之前手动检查和确认没有错误,然后再启动迁移。

因此,在创建 PodMigrationJob 时,将 spec.paused 设置为 true,手动确认允许执行后再将 spec.paused 设置为 false。如果拒绝执行,则可以更新 status.phase=Failed 立即终止PodMigrationJob 的执行,或者等待 PodMigrationJob 自动过期。

1. apiVersion: scheduling.koordinator.sh/v1alpha1
2. kind: PodMigrationJob
3. metadata:
4. name: migrationjob-demo
5. spec:
6. # paused indicates whether the PodMigrationJob should to work or not.
7. paused: true
8. # ttl controls the PodMigrationJob timeout duration.
9. ttl: 5m
10. mode: ReservationFirst
11. podRef:
12. namespace: default
13. name: pod-demo-5f9b977566-c7lvk
14. status:
15. phase: Pending

示例: 只想驱逐 Pods, 无需预留资源

PodMigrationJob 提供两种迁移模式:

  • EvictDirectly 直接驱逐 Pod,无需预留资源,
  • ReservationFirst 先预留资源,以确保在开始驱逐之前可以分配资源。

如果你只想驱逐 Pod,只需将 spec.mode 设置为 EvictDirectly。

1. apiVersion: scheduling.koordinator.sh/v1alpha1
2. kind: PodMigrationJob
3. metadata:
4. name: migrationjob-demo
5. spec:
6. paused: false
7. ttl: 5m
8. mode: EvictDirectly
9. podRef:
10. namespace: default
11. name: pod-demo-5f9b977566-c7lvk
12. status:
13. phase: Pending

示例: 在迁移中使用预留资源

在某些情况下,首先预留资源,然后在成功后创建一个 PodMigrationJob,以重复使用 PodMigrationJob Controller 提供的仲裁机制(在v0.7中实现)以确保工作负载的稳定性。

1. apiVersion: scheduling.koordinator.sh/v1alpha1
2. kind: PodMigrationJob
3. metadata:
4. name: migrationjob-demo
5. spec:
6. paused: false
7. ttl: 5m
8. mode: ReservationFirst
9. podRef:
10. namespace: default
11. name: pod-demo-5f9b977566-c7lvk
12. reservationOptions:
13. # the reservation-0 created before creating PodMigrationJob
14. reservationRef:
15. name: reservation-0
16. status:
17. phase: Pending

示例: 优雅驱逐 Pods

PodMigrationJob 支持 Pod 的优雅驱逐。

1. apiVersion: scheduling.koordinator.sh/v1alpha1
2. kind: PodMigrationJob
3. metadata:
4. name: migrationjob-demo
5. spec:
6. paused: true
7. ttl: 5m
8. mode: ReservationFirst
9. podRef:
10. namespace: default
11. name: pod-demo-5f9b977566-c7lvk
12. deleteOptions:
13. # The duration in seconds before the object should be deleted. Value must be non-negative integer.
14. # The value zero indicates delete immediately. If this value is nil, the default grace period for the
15. # specified type will be used.
16. # Defaults to a per object value if not specified. zero means delete immediately.
17. gracePeriodSeconds: 60
18. status:
19. phase: Pending

已知问题