选择合适的工作负载资源

KubernetesBeginner
立即练习

介绍

在 CKAD 考试任务中,通常要求你在编写清单(manifest)之前选择正确的 Kubernetes 工作负载资源。Pod 是最小的可运行单元;Deployment 用于保持长期运行的应用程序副本可用;Job 用于运行任务直到完成;而 CronJob 则用于存储定时任务的 Job 模板。

在本实验中,你将通过观察资源的行为而非死记硬背定义来对比这些资源。你将看到:独立的 Pod 在删除后不会自动恢复,Deployment 会重新创建其 Pod,Job 会在执行完成后记录成功状态,而 CronJob 则会存储用于周期性任务的调度信息。

准备工作负载对比命名空间

在此步骤中,你将准备一个干净的命名空间,用于对比各种工作负载资源。

从 /home/labex/project 开始。在对比工作负载行为时,你将在此目录中创建小型清单文件。

mkdir -p /home/labex/project
cd /home/labex/project

检查 Kubernetes API 服务器是否可达。如果虚拟机刚启动且节点尚未就绪,请等待几秒钟后再运行该命令。

kubectl get nodes --request-timeout=5s

预期输出包含:

NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35...

工作负载会创建 Pod,因此请等待集群网络 Pod 就绪。

kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s

预期输出:

pod/calico-node-... condition met

创建一个名为 ckad-prep-workloads 的命名空间:

kubectl create namespace ckad-prep-workloads

将此命名空间设置为当前上下文的命名空间:

kubectl config set-context --current --namespace=ckad-prep-workloads

确认当前命名空间:

kubectl config view --minify --output 'jsonpath={..namespace}'; echo

预期输出:

ckad-prep-workloads

对比 Pod 与 Deployment

在此步骤中,你将通过删除 Pod 和 Deployment 来对比独立 Pod 与 Deployment,并观察 Kubernetes 的后续操作。

当你需要一个直接管理的运行时单元来执行极小的任务或进行检查时,独立的 Pod 非常有用。而对于长期运行的应用程序,Deployment 则更为合适,因为 Deployment 拥有 ReplicaSet,而 ReplicaSet 会确保所需数量的 Pod 始终处于运行状态。

创建一个独立 Pod 的清单。容器会进入睡眠状态,以便 Pod 保持运行足够长的时间供你观察。terminationGracePeriodSeconds: 0 字段可以确保你在稍后删除 Pod 时实验能快速完成。

cat > standalone-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: standalone-task
  labels:
    app: standalone-task
    workload.labex.io/intent: direct-pod
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: sleeper
    image: busybox:1.36
    command: ["/bin/sh", "-c", "sleep 3600"]
EOF

创建一个 Deployment 清单。此 Deployment 要求 Kubernetes 保持一个 managed-worker Pod 运行,其 Pod 模板使用了相同的快速终止设置。

cat > managed-deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: managed-worker
  labels:
    workload.labex.io/intent: long-running
spec:
  replicas: 1
  selector:
    matchLabels:
      app: managed-worker
  template:
    metadata:
      labels:
        app: managed-worker
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: sleeper
        image: busybox:1.36
        command: ["/bin/sh", "-c", "sleep 3600"]
EOF

应用这两个清单:

kubectl apply -f standalone-pod.yaml
kubectl apply -f managed-deployment.yaml

预期输出:

pod/standalone-task created
deployment.apps/managed-worker created

等待两个工作负载就绪:

kubectl wait --for=condition=Ready pod/standalone-task --timeout=120s
kubectl wait --for=condition=Available deployment/managed-worker --timeout=120s

预期输出:

pod/standalone-task condition met
deployment.apps/managed-worker condition met

获取当前的 Deployment Pod 名称,然后删除独立 Pod 和由 Deployment 管理的 Pod:

managed_pod="$(kubectl get pods -l app=managed-worker -o 'jsonpath={.items[0].metadata.name}')"
kubectl delete pod standalone-task "$managed_pod"

预期输出包含:

pod "standalone-task" deleted
pod "managed-worker-..." deleted

等待 Deployment 再次变为可用状态:

kubectl wait --for=condition=Available deployment/managed-worker --timeout=120s

预期输出:

deployment.apps/managed-worker condition met

列出 Pod。你会发现独立 Pod 已经消失,而一个新的 managed-worker Pod 已经生成。

kubectl get pods

预期输出包含 managed-worker Pod,但不包含 standalone-task:

NAME                              READY   STATUS    RESTARTS   AGE
managed-worker-...                1/1     Running   0          ...

为任务完成选择 Job

在此步骤中,你将为那些需要成功完成而非永久运行的任务选择 Job。

当期望状态是「保持此应用程序运行」时,Deployment 是合适的选择。而当期望状态是「运行此任务直到完成」时,Job 是更好的选择。这就是为什么数据迁移、批处理和一次性维护命令通常对应 Job 的原因。

创建一个名为 schema-migration 的 Job:

kubectl create job schema-migration --image=busybox:1.36 -- /bin/sh -c 'echo migration-start; echo migration-complete'

预期输出:

job.batch/schema-migration created

等待 Job 达到 Complete 状态:

kubectl wait --for=condition=Complete job/schema-migration --timeout=120s

预期输出:

job.batch/schema-migration condition met

检查 Job 摘要。COMPLETIONS 应显示 1/1,这意味着任务已成功运行一次。

kubectl get job schema-migration

预期输出包含:

NAME               STATUS     COMPLETIONS   DURATION   AGE
schema-migration   Complete   1/1           ...        ...

查看 Job 日志:

kubectl logs job/schema-migration

预期输出:

migration-start
migration-complete

为周期性任务选择 CronJob

在此步骤中,你将为需要按计划运行的任务选择 CronJob。

CronJob 是一个定时 Job 模板。当任务需要重复执行而非仅完成一次时,它是正确的选择。为了使本实验具有确定性,你将以挂起(suspended)状态创建 CronJob。这样你可以在不等待时间边界的情况下检查调度和模板。

创建 cleanup-cronjob.yaml:

cat > cleanup-cronjob.yaml <<'EOF'
apiVersion: batch/v1
kind: CronJob
metadata:
  name: cleanup-schedule
  labels:
    workload.labex.io/intent: recurring-task
spec:
  schedule: "*/5 * * * *"
  suspend: true
  successfulJobsHistoryLimit: 1
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: cleanup
            image: busybox:1.36
            command:
            - /bin/sh
            - -c
            - 'echo cleanup-ready'
EOF

应用清单:

kubectl apply -f cleanup-cronjob.yaml

预期输出:

cronjob.batch/cleanup-schedule created

检查 CronJob 摘要。SUSPEND 为 True,因为本实验使用 CronJob 定义来学习资源选择,而无需等待定时任务触发。

kubectl get cronjob cleanup-schedule

预期输出包含:

NAME               SCHEDULE      TIMEZONE   SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cleanup-schedule   */5 * * * *   <none>     True      0        <none>          ...

直接从对象中读取调度和模板镜像:

kubectl get cronjob cleanup-schedule -o 'jsonpath={.spec.schedule}{" "}{.spec.suspend}{" "}{.spec.jobTemplate.spec.template.spec.containers[0].image}{"\n"}'

预期输出:

*/5 * * * * true busybox:1.36

列出你在本实验中创建的工作负载资源。此视图将资源类型与预期行为联系起来:Deployment 用于长期运行的副本,Job 用于任务完成,CronJob 用于周期性任务。

kubectl get deployment,job,cronjob

预期输出包含:

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/managed-worker   1/1     1            1           ...

NAME                         STATUS     COMPLETIONS   DURATION   AGE
job.batch/schema-migration   Complete   1/1           ...        ...

NAME                               SCHEDULE      TIMEZONE   SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/cleanup-schedule     */5 * * * *   <none>     True      0        <none>          ...

总结

你通过行为对比了 Kubernetes 的工作负载资源。独立的 Pod 在删除后不会恢复,Deployment 会重新创建其 Pod 以保持副本可用,Job 会运行任务直到成功完成,而 CronJob 则存储了周期性任务的 Job 模板。这些观察结果有助于你在编写 CKAD 风格的清单之前选择正确的资源。