介绍
Field Notes 的图库已完成一部分。某一组从源服务收到临时 HTTP 503,而其他组已完成。你将保留这些失败证据,运行一个允许少量重试的新 Job,并在不重新写入已有正确 JPEG 的情况下交付完整集合。
这台独立 VM 包含自己的二十张源照片、共享存储、网站、失败的 Job 和部分输出。你不需要之前 VM 中的文件。请先完成分批构建图库,或熟悉其中的 Indexed Job、YAML 复制/编辑、Pod 检查和下载流程。40 分钟的时长是作者估计。
使用 Workspace 执行命令,使用 Gallery 访问网站。保留提供的文件、源图和参考图片、处理器、计划、服务、PVC、原始 first-try Job,以及它的 Pod 和日志。
恢复失败的照片分组
在这一步中,你将先把不完整的图库与原生失败索引对应起来,再选择恢复策略。
打开 Gallery,选择 Open the gallery,确认显示 14 of 20 images available。第一、第三和第四组已完成;分组 1 中的六张照片缺失。在页面导航中打开 Reference,查看提供的正常示例,再切换到 Workspace。
终端的起始目录为 /home/labex/project/photo-gallery。使用 pwd 确认;如有必要,使用 cd /home/labex/project/photo-gallery 返回。读取分组映射和员工需求说明:
cat inputs/groups.txt
cat inputs/brief.txt
共有四个从零编号的分组。索引 1 包含 photo-07 到 photo-12。检查保留的尝试:
kubectl describe job first-try -n photo-workshop
查找 Completion Mode: Indexed、Completed Indexes: 0,2,3、Pods Statuses 中的一个失败 Pod,以及 Events 下的 FailedIndexes 警告。已完成的索引和下方的 Pod 表格共同指出缺失的分组。在提供的源文件中读取其策略:
cat starter/first-try.yaml
backoffLimitPerIndex: 0 表示某个索引失败后不允许创建替代 Pod。backoffLimit: 6 是单独的全局失败预算,不会覆盖每索引允许次数为零的设置。activeDeadlineSeconds: 180 是活动存续时间上限。即使多个索引成功,Job 仍保持失败状态。
列出该 Job 的实际 Pod 及其索引标签:
kubectl get pods -n photo-workshop -l batch.kubernetes.io/job-name=first-try -L batch.kubernetes.io/job-completion-index
读取它们的全部日志:
kubectl logs -n photo-workshop job/first-try --all-pods=true --prefix=true
索引 1 的 Pod 报告 Source returned HTTP 503 后退出;其他组报告已完成的照片。HTTP 503 表示源服务已响应,但暂时不可用。这与 Pod 缺失、连接失败或 JPEG 无法读取不同。
从表格中复制索引 1 的完整 Pod 名称到以下命令,用它替换 POD_NAME,不要原样输入这个占位符:
kubectl describe pod POD_NAME -n photo-workshop
其已终止容器显示 Exit Code: 42。这是提供的 worker 对源服务 HTTP 错误的刻意响应,并非通用的 Kubernetes HTTP 错误码。在这个场景中,每个新 Job 的索引 1 在第一次请求时都会实际收到一次 503。随后同一索引的替代 Pod 可以成功读取源图。这是受控的临时故障练习,并不表示所有生产环境中的 503 都能安全重试。
保留失败的 Job、它的 Pod 和日志,以及已有的十四张正确 JPEG。处理器只在需要时写入 JPEG;对于内容已经匹配的图片,会保留其字节及文件元数据。每 Pod 的回执和图片索引记录可以更新,以标识新的成功尝试。
为每个索引设置有限重试
现在创建一个新 Job,允许每个索引重试一次。不要尝试将已经失败的 Job 变成一次新的运行。
在 Workspace 中,位于 /home/labex/project/photo-gallery 时,复制提供的恢复草稿:
cp starter/recovery-job.yaml gallery-job.yaml
与上一实验一样,cp 会保留源文件。如果找不到源文件,请用 pwd 确认位置,返回工作区,再使用准确路径重复复制。读取草稿:
cat gallery-job.yaml
它已请求全部四个索引,并行度为 2,但草稿名称是 gallery-draft,且不允许每索引重试。使用 sed -i 替换复制文件中的各个字面值;单引号防止 shell 解释替换表达式:
sed -i 's/name: gallery-draft/name: gallery-retry/' gallery-job.yaml
sed -i 's/backoffLimitPerIndex: 0/backoffLimitPerIndex: 1/' gallery-job.yaml
再次读取文件:
cat gallery-job.yaml
确认其中包含 name: gallery-retry、completions: 4、parallelism: 2 和 backoffLimitPerIndex: 1。保留 backoffLimit: 6、activeDeadlineSeconds: 180 以及所有提供的处理器、挂载、身份和资源设置。本任务接受每索引重试一次或两次,但少量、有限的重试已足够。移除截止时限或允许无限重试会掩盖持续存在的问题。
新 Job 拥有新的 Kubernetes 身份。它可能处理之前已经成功的分组;提供的 worker 会处理这种重复执行,而不重新写入已匹配的 JPEG。不要从 Job 成功就推断处理恰好发生一次。保留原先失败的 Job,也能让此次恢复的原因继续可见。如果编辑未匹配,请在应用前重新复制并修正草稿。如果已创建了不合适的最终 Job,请保留其证据,在保存的文件中准备另一个新名称,不要修改不可变的 Pod 模板或删除 first-try。
应用保存的新 Job:
kubectl apply -n photo-workshop -f gallery-job.yaml
等待它成功完成:
kubectl wait -n photo-workshop --for=condition=Complete job/gallery-retry --timeout=180s
检查它的索引和策略:
kubectl describe job gallery-retry -n photo-workshop
预期看到 Completed Indexes: 0-3。前面的 wait 命令已确认原生 Complete 条件成立。列出实际的 Pod:
kubectl get pods -n photo-workshop -l batch.kubernetes.io/job-name=gallery-retry -L batch.kubernetes.io/job-completion-index
索引 1 现在有一个失败 Pod,以及同一索引对应的另一个已完成的替代 Pod。失败 Pod 是这个受控测试的预期证据。读取它们的输出:
kubectl logs -n photo-workshop job/gallery-retry --all-pods=true --prefix=true
你应看到真实的 HTTP 503,以及随后替代 Pod 的成功处理。其他组对于已经匹配的 JPEG 会报告 Kept。如果等待超时,请检查新 Job 和 Pod 日志;不要清除旧失败、重置 setup 或盲目提高重试上限。请求的并行度是期望的并发设置,并非替换期间绝对的进程数量保证。
交付恢复后的照片集合
在这一步中,你将证明重试生成了完整可用的图库,并保存当前下载文件。
切换到 Gallery,在页面导航中选择 Gallery,然后刷新。确认显示 20 of 20 images available。打开恢复组中的第一张照片 Black-and-white blossoms(photo-07),并与它自己的源图比较。选择 Download thumbnail,然后选择 Back to gallery。再打开较短的最后一组中的 Blue and yellow flowers(photo-20)。

恢复后的集合现已包含原先缺失的六张照片,以及较短的最后一组。页面仍链接到未改变的参考示例和获许可的源图。
返回图库,使用 Download source index CSV 和 Download gallery ZIP。选择 Reference,确认提供的示例保持完整,再选择 Credits 检查来源署名。网站仅展示 worker 实际输出的可读文件,不会使用源照片集合补齐缺失图片。
切换到 Workspace,位于 /home/labex/project/photo-gallery。使用第一个实验教过的相同选项,保存当前的真实交付文件:
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
检查 CSV 表头和前几行:
head -n 3 gallery-index.csv
不解压归档,安全地列出其内容:
python3 -m zipfile -l gallery.zip
其中包含 index.csv 和二十张实际 JPEG,包括恢复组以及 photos/photo-20.jpg。源图与缩略图哈希将每张照片关联到它自己的结果;仅凭文件名还不够。
最后确认两次尝试都仍可查看:
kubectl get jobs -n photo-workshop
原始 first-try 处于失败状态,新 gallery-retry 已完成。这就是预期的最终状态。保留保存的清单、下载文件、成功和失败的 Pod、原先的十四张 JPEG、源图和参考示例,使它们继续可用。如果下载失败或不完整,请修正工作负载或服务后重新下载;不要手动修补收到的文件。
总结
你诊断了 Indexed Job 的部分失败,保留了其原生证据,并使用允许每索引有限重试的新 Job 完成了真实的照片集合。由源图生成的文件、原先成功的 JPEG、运行中的图库、保存的清单和交付文件现已一致。



