Введение
При выполнении задач CKAD от вас часто требуется выбрать подходящий ресурс рабочей нагрузки Kubernetes еще до написания манифеста. Pod — это наименьшая единица запуска, Deployment поддерживает доступность реплик долгоживущих приложений, Job выполняет работу до завершения, а CronJob хранит шаблон для периодического запуска заданий.
В этой лабораторной работе вы сравните эти ресурсы на основе их наблюдаемого поведения, а не простого заучивания определений. Вы увидите, что отдельный Pod не восстанавливается после удаления, Deployment воссоздает свой Pod, Job завершается и фиксирует успех, а CronJob хранит расписание для повторяющихся задач.
Подготовка пространства имен для сравнения рабочих нагрузок
На этом этапе вы подготовите чистое пространство имен (namespace) для сравнения ресурсов рабочих нагрузок.
Начните работу в директории /home/labex/project. Вы будете создавать небольшие манифесты в этой директории по мере сравнения поведения ресурсов.
mkdir -p /home/labex/project
cd /home/labex/project
Убедитесь, что API-сервер Kubernetes доступен. Если виртуальная машина только что запустилась и узел еще не готов, подождите несколько секунд и повторите команду.
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, удалив оба и наблюдая за тем, как Kubernetes отреагирует на это.
Отдельный Pod полезен, когда вам нужна одна напрямую управляемая единица выполнения для очень простой задачи или проверки. Deployment лучше подходит для долгоживущих приложений, так как он управляет 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 поддерживать один работающий Pod managed-worker, а его шаблон 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
Получите имя Pod-а, созданного Deployment-ом, а затем удалите отдельный Pod и Pod, принадлежащий Deployment-у:
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 должен исчезнуть, в то время как новый Pod managed-worker должен появиться.
kubectl get pods
Ожидаемый вывод включает Pod managed-worker, но не standalone-task:
NAME READY STATUS RESTARTS AGE
managed-worker-... 1/1 Running 0 ...
Выбор Job для выполнения задачи
На этом этапе вы выберете Job для работы, которая должна успешно завершиться, а не работать бесконечно.
Deployment хорошо подходит, когда желаемое состояние — «поддерживать приложение запущенным». Job лучше подходит, когда желаемое состояние — «выполнить задачу до завершения». Именно поэтому миграции, пакетная обработка данных и разовые команды обслуживания обычно реализуются через Jobs.
Создайте Job с именем schema-migration:
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. Это правильный выбор, когда задача должна повторяться, а не просто выполниться один раз. Чтобы сделать эту лабораторную работу детерминированной, вы создадите 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 сохранил шаблон для периодического запуска. Эти наблюдения помогут вам выбрать правильный ресурс перед написанием манифеста в стиле CKAD.


