Введение
У Field Notes есть двадцать садовых фотографий с лицензией на использование. Нужна небольшая галерея, которую сотрудники смогут скачать. Сначала вы обработаете одну группу, затем запустите все четыре группы с помощью Job в Kubernetes. В последней группе только две фотографии; ей всё равно нужен собственный успешно завершённый индекс.
Вы уже должны понимать, что такое Pod, Deployment, Service и метки, читать простой YAML и ориентироваться в базовых путях терминала. Job, индексы завершения, используемый общий том и команды редактирования объясняются ниже. Кластер, образ обработчика, оригинальные фотографии, сайт и хранилище подготовлены. Писать Python, собирать образ или иметь облачную учётную запись не требуется.
Используйте Workspace для команд и Gallery для сайта. Оба входа используют одну учебную VM. Оставьте без изменений предоставленные файлы в starter/ и inputs/, исходные фотографии, эталон, обработчик, сервисы и хранилище. Продолжительность в 45 минут — авторская оценка, включающая чтение и обычные ошибки.
Сначала обработайте одну группу
На этом шаге вы сравните обычный готовый пример с его источником, а затем обработаете отдельный образец с помощью Job с одним индексом.
Откройте Gallery. На главной странице большая фотография помечена Source collection · licensed garden photographs: это входные данные, а не выполненная вами работа. Выберите See the reference. Thumbnail — предоставленный JPEG размером 320 × 220; Licensed source copy сохраняет исходные пропорции. Кадрирование объясняет различие краёв. Выберите Gallery в навигации страницы. Вначале там показано 0 of 20 images available.
Переключитесь на Workspace. Этот терминал запускается в /home/labex/project/photo-gallery. pwd выводит текущий рабочий каталог:
pwd
Если вы перешли в другое место, вернитесь командой cd /home/labex/project/photo-gallery. Все относительные имена файлов ниже отсчитываются от этого каталога. Файлы сохраняются в этой VM, но другая работа начинается с собственными независимыми файлами и ресурсами кластера.
Deployment поддерживает работу сервиса. Job, напротив, запускает Pod до завершения конечного объёма работы. Предоставленный worker обрабатывает одну группу фотографий и завершает работу. В Indexed Job Kubernetes присваивает каждому требуемому завершению номер, начиная с нуля. Worker читает своё штатное значение JOB_COMPLETION_INDEX и выбирает соответствующую группу. Вы настраиваете Job, а не пишете worker.
Прочитайте предоставленный манифест образца. cat показывает файл, не меняя его:
cat starter/sample-job.yaml
Его важные поля — completionMode: Indexed, completions: 1 и parallelism: 1. Они запрашивают только индекс 0 с одним желаемым одновременно работающим worker. restartPolicy: Never означает, что завершившийся с ошибкой контейнер остаётся в таком состоянии в своём Pod; необходимость другого Pod определяет политика Job. backoffLimit: 0 означает отсутствие повторных попыток в этом упражнении с исправным источником, а activeDeadlineSeconds: 180 ограничивает активное время жизни Job. Остальные поля подключают подготовленный образ, план входных данных и выходной том; оставьте их без изменений.
PersistentVolumeClaim, или PVC, запрашивает постоянное хранилище. Подготовленный PVC gallery-output сохраняет файлы после завершения worker. Здесь его том ReadWriteOnce могут подключать несколько Pod на одном узле. Это не обещает совместную запись с нескольких узлов. Образец записывается в отдельный каталог sample, поэтому он не может незаметно заполнить итоговую галерею.
Примените образец. apply -f читает указанный YAML-файл; -n выбирает пространство имён, объединяющее ресурсы Kubernetes этого проекта:
kubectl apply -n photo-workshop -f starter/sample-job.yaml
Дождитесь штатного условия Complete у Job. --timeout=180s ограничивает ожидание этой команды; он не меняет срок выполнения Job:
kubectl wait -n photo-workshop --for=condition=Complete job/gallery-sample --timeout=180s
Ожидаемое окончание: job.batch/gallery-sample condition met. Сам по себе тайм-аут не доказывает сбой: прежде чем решать, что менять, изучите Job и его логи командами из шага 3. Не запускайте подготовку повторно и не удаляйте предоставленные ресурсы.
Переключитесь на Gallery, выберите Sample и убедитесь, что показано 6 of 6 images available. Откройте Windmill garden, сравните миниатюру и источник и выберите Back to sample. Выберите Gallery в навигации страницы: итоговая коллекция всё ещё пуста. Это различие не позволяет принять успешную тренировочную обработку за полную поставку.
Спланируйте каждый индекс завершения
На этом шаге вы перенесёте группировку входных данных в сохранённый манифест Job. Пока никакая итоговая обработка не запускается.
Переключитесь на Workspace, начиная с /home/labex/project/photo-gallery. Прочитайте полное распределение входных данных:
cat inputs/groups.txt
Здесь четыре строки: от Index 0 до Index 3. Первые три содержат по шесть фотографий; индекс 3 содержит photo-19 и photo-20. completions считает группы, а не фотографии: для этой поставки нужны 4 успешно завершённых индекса, а не 20 и не 3.
Прочитайте задание сотрудников:
cat inputs/brief.txt
Оно разрешает запрошенный параллелизм от 1 до 2. Мы запросим 2, чтобы две группы могли продвигаться одновременно. Kubernetes может запускать меньше Pod при нехватке ресурсов; запрошенный параллелизм не задаёт абсолютный предел общего числа процессов при повторных попытках или завершении. В проекте используется один небольшой подготовленный узел, а не распределённая платформа обработки.
Скопируйте подготовленный шаблон итогового Job в свой редактируемый файл. cp копирует файл; источник в starter/ остаётся нетронутым:
cp starter/gallery-job.yaml gallery-job.yaml
Если cp сообщает No such file or directory, проверьте pwd, вернитесь в указанный выше каталог и повторите копирование с точным именем файла. Не создавайте пустой файл вместо шаблона.
Измените два буквальных значения полей в скопированном файле с помощью sed. -i редактирует этот файл на месте. Каждое выражение имеет вид s/old/new/: заменить старый текст новым. Одинарные кавычки заставляют оболочку передать выражение буквально. В предоставленном шаблоне каждое из этих точных полей встречается один раз:
sed -i 's/completions: 1/completions: 4/' gallery-job.yaml
sed -i 's/parallelism: 1/parallelism: 2/' gallery-job.yaml
Прочитайте сохранённый результат перед применением:
cat gallery-job.yaml
Проверьте metadata.name: gallery-batch, completionMode: Indexed, completions: 4 и parallelism: 2. Сохраните подготовленные образ обработчика, команду, окружение, подключения томов, настройки ресурсов, политику без повторных попыток и срок в 180 секунд. Допустимы эквивалентное форматирование YAML и другое новое имя итогового Job; сохранённый файл должен описывать именно тот Job, который вы запускаете.
Замена с опечаткой может завершиться успешно, ничего не найдя, поэтому важно прочитать результат. Если вы ещё не применили файл, для исправления снова скопируйте исходный шаблон и повторите два изменения. После применения Job избегайте повторного копирования с конфликтующим именем: шаблоны задач Job обычно неизменяемы, поэтому для другой попытки подготовьте новое имя Job.
Запустите полную пакетную обработку
На этом шаге вы примените сохранённый Job и свяжете его штатные свидетельства завершения с настоящими Pod обработчика.
В Workspace, в /home/labex/project/photo-gallery, примените сохранённый файл:
kubectl apply -n photo-workshop -f gallery-job.yaml
Дождитесь всех требуемых индексов:
kubectl wait -n photo-workshop --for=condition=Complete job/gallery-batch --timeout=180s
Прочитайте штатную сводку Job:
kubectl get job gallery-batch -n photo-workshop
Завершённый Job должен показывать 4/4 завершений. describe добавляет подробности и события:
kubectl describe job gallery-batch -n photo-workshop
Найдите Completion Mode: Indexed и Completed Indexes: 0-3. Диапазон включает оба конца, то есть охватывает все четыре группы, включая короткую последнюю. Одни лишь свидетельства завершения не доказывают правильность содержимого изображений; дальше вы осмотрите и скачаете их.
Выведите только Pod, принадлежащие этому Job. -l выбирает по метке. -L добавляет столбец с другой меткой, здесь — индексом завершения:
kubectl get pods -n photo-workshop -l batch.kubernetes.io/job-name=gallery-batch -L batch.kubernetes.io/job-completion-index
Ожидаются завершённые Pod для индексов 0, 1, 2 и 3. Completed в этой таблице соответствует успешной фазе Pod. Прочитайте настоящий вывод их worker. --all-pods=true включает Pod этого Job, а --prefix=true указывает, какой Pod вывел каждую строку:
kubectl logs -n photo-workshop job/gallery-batch --all-pods=true --prefix=true
Каждый worker называет назначенные ему фотографии и сообщает о результатах 320 x 220. Индекс 3 должен обработать две фотографии. Эти логи помогают понять произошедшее; также проверяются настоящие файлы, их связи с источниками и успешно завершённые Pod, принадлежащие Job.
Если ожидание завершилось по тайм-ауту, используйте describe и те же команды Pod/логов, чтобы отличить незавершённую обработку от сбоя. Неизвестное имя Job обычно означает, что файл не применён или имя отличается: прочитайте gallery-job.yaml и используйте фактическое имя. Не удаляйте завершённые Pod или образец. Следующая пошаговая работа учит восстановлению после намеренного временного сбоя источника.
Передайте настоящие изображения
На этом шаге вы осмотрите полный сайт и сохраните оба пригодных к использованию файла поставки.
Переключитесь на Gallery, выберите Gallery в навигации страницы и обновите её. Убедитесь, что показано 20 of 20 images available. Откройте Blue and yellow flowers (photo-20) из короткой последней группы. Сравните миниатюру с её собственным источником; это не должна быть повторная копия другого цветка. Выберите Download thumbnail, затем Back to gallery.

Итоговая галерея содержит двадцать различных подготовленных фотографий, включая два изображения короткой последней группы. Действия скачивания находятся под коллекцией.
В разделе Take the collection with you выберите Download source index CSV и Download gallery ZIP. CSV связывает каждый результат с хешем источника, хешем миниатюры, автором и страницей источника. ZIP содержит index.csv и настоящие JPEG в photos/. Страница сообщает о фактически доступных файлах; она не создаёт заново недостающую работу из оригиналов. Можно скачать и неполную коллекцию, поэтому перед передачей проверьте полноту результата.
Выберите Reference в навигации страницы и убедитесь, что исходный предоставленный пример по-прежнему работает. Выберите Credits, чтобы увидеть авторов и ссылки на источники в Wikimedia Commons. Фотографии — материалы с лицензией CC0, а не снимки, сделанные LabEx.
Переключитесь на Workspace, в /home/labex/project/photo-gallery. Сохраните здесь те же настоящие выгрузки. curl запрашивает URL; --fail возвращает ошибку при сбое HTTP, --silent --show-error скрывает индикатор загрузки, сохраняя ошибки, а -o задаёт имя выходного файла. Порт 8091 ведёт к подготовленному Service галереи из этой VM:
curl --fail --silent --show-error http://127.0.0.1:8091/download/index.csv -o gallery-index.csv
curl --fail --silent --show-error http://127.0.0.1:8091/download/gallery.zip -o gallery.zip
Загрузки в браузере сохраняет браузер; эти две команды сохраняют копии, требуемые в рабочем каталоге VM. Если запрос не удался, осмотрите сайт и повторите запрос после устранения проблемы. Не редактируйте полученный индекс, чтобы скрыть недостающие изображения.
Выведите заголовок и первые две строки данных. head -n 3 читает первые три строки:
head -n 3 gallery-index.csv
Заголовок начинается с id,title,source_file,thumbnail,width,height. Каждая строка связывает одну фотографию с её собственным photos/photo-NN.jpg, размерами 320,220 и фактическими сведениями об источнике.
Выведите содержимое архива без распаковки. python3 -m zipfile запускает стандартную утилиту Python для ZIP; -l выводит список элементов:
python3 -m zipfile -l gallery.zip
Найдите index.csv и пути всех двадцати JPEG, включая photos/photo-20.jpg. Одни имена или количества не доказывают правильность изображений, поэтому функциональные проверки также декодируют настоящие JPEG и сравнивают каждый с результатом обработки его собственного источника. Сохраните доступными gallery-job.yaml, обе выгрузки, образец, завершённые Pod, исходные файлы, эталон и подготовленные сервисы.
Резюме
Вы подготовили настоящую фотогалерею с помощью Indexed Job. Вы распределили фотографии по индексам завершения, ограничили запрошенный параллелизм, проверили штатные свидетельства Pod и Job и передали настоящие изображения с индексом источников. Образец и эталон остались отделены от итоговой работы.



