Fix forgejo-backup large dump copy with chunked kubectl cp
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Split in-pod dumps over 50MiB into 16MiB parts with retry to avoid
websocket EOF and connection resets on ~700MiB archives.
This commit is contained in:
tegwick 2026-07-08 00:11:08 +02:00
parent e36694648a
commit a71369d71c

View file

@ -74,10 +74,43 @@ ok "forgejo-db" "${FORGEJO_DB_NAMESPACE}/${FORGEJO_DB_POD}"
# 1. Application dump (repos, packages, attachments, LFS, avatars)
ok "forgejo dump" "running in pod…"
DUMP_REMOTE="/tmp/forgejo-backup-${TS}.zip"
# Single exec: dump then stream stdout (avoids kubectl cp / multi-exec websocket drops)
kubectl exec -n "${FORGEJO_NAMESPACE}" "${PROD_POD}" -c gitea -- \
sh -c "forgejo dump -f '${DUMP_REMOTE}' && cat '${DUMP_REMOTE}' && rm -f '${DUMP_REMOTE}'" \
> "${DUMP_PLAIN}"
forgejo dump -f "${DUMP_REMOTE}"
# Large dumps (~700M) fail via stdout stream or single kubectl cp — use chunks.
dump_size="$(kubectl exec -n "${FORGEJO_NAMESPACE}" "${PROD_POD}" -c gitea -- \
stat -c%s "${DUMP_REMOTE}" 2>/dev/null || echo 0)"
copy_from_pod() {
local remote_path="$1" local_path="$2" attempt
for attempt in 1 2 3; do
if kubectl cp -n "${FORGEJO_NAMESPACE}" -c gitea \
"${FORGEJO_NAMESPACE}/${PROD_POD}:${remote_path}" "${local_path}" 2>/dev/null; then
return 0
fi
sleep $((attempt * 3))
done
return 1
}
if [[ "${dump_size}" -lt 52428800 ]]; then
copy_from_pod "${DUMP_REMOTE}" "${DUMP_PLAIN}" || exit 1
else
ok "forgejo dump" "chunked copy (${dump_size} bytes)…"
chunk_dir="$(mktemp -d)"
parts="$(kubectl exec -n "${FORGEJO_NAMESPACE}" "${PROD_POD}" -c gitea -- \
sh -c "split -b 16m '${DUMP_REMOTE}' /tmp/forgejo-backup-part- && ls /tmp/forgejo-backup-part-*")"
for part in ${parts}; do
base="$(basename "${part}")"
copy_from_pod "${part}" "${chunk_dir}/${base}" || { bad "forgejo dump" "chunk copy failed: ${base}"; exit 1; }
done
cat "${chunk_dir}"/forgejo-backup-part-* > "${DUMP_PLAIN}"
rm -rf "${chunk_dir}"
kubectl exec -n "${FORGEJO_NAMESPACE}" "${PROD_POD}" -c gitea -- \
rm -f /tmp/forgejo-backup-part-* "${DUMP_REMOTE}" || true
fi
if [[ ! -f "${DUMP_PLAIN}" || ! -s "${DUMP_PLAIN}" ]]; then
bad "forgejo dump" "failed to copy dump from pod"
exit 1
fi
ok "forgejo dump" "$(du -h "${DUMP_PLAIN}" | awk '{print $1}') $(basename "${DUMP_PLAIN}")"
# 2. PostgreSQL logical dump (plain SQL to stdout; CNPG root FS is read-only)