@@ -387,6 +387,37 @@ pub fn kopia_cache_pvc_size(snapshot_size: &Quantity) -> Quantity {
387387 chosen. into ( )
388388}
389389
390+ /// MB to leave free on the cache PVC for kopia's metadata cache, its
391+ /// rolling CLI logs, and slop. Subtracted from the PVC capacity to
392+ /// derive the content-cache hard cap.
393+ pub const KOPIA_CACHE_RESERVE_MB : u64 = 2048 ;
394+ /// Hardcoded metadata-cache cap. Kopia's metadata cache is small
395+ /// (indices and manifest data) so a fixed allocation is fine.
396+ pub const KOPIA_METADATA_CACHE_MB : u64 = 512 ;
397+ /// Floor for the content-cache cap in MB, so degenerate-small PVCs
398+ /// still get a useful cache.
399+ pub const KOPIA_CONTENT_CACHE_FLOOR_MB : u64 = 1024 ;
400+
401+ /// Compute the content-cache cap (MB) passed to `kopia repository
402+ /// connect --content-cache-size-mb`. Sized to the cache PVC minus a
403+ /// fixed reserve for metadata cache + logs + slop.
404+ ///
405+ /// Without a cap kopia's content cache grows unbounded and eventually
406+ /// fills the PVC, after which kopia can't even write its config and
407+ /// every restore Job pod exits in 1–2 minutes. The cap turns that into
408+ /// kopia's own LRU eviction, which is what we want.
409+ pub fn kopia_content_cache_mb ( snapshot_size : & Quantity ) -> u64 {
410+ let pvc_size = kopia_cache_pvc_size ( snapshot_size) ;
411+ let pvc_bytes = ParsedQuantity :: try_from ( pvc_size)
412+ . ok ( )
413+ . and_then ( |q| q. to_bytes_f64 ( ) )
414+ . unwrap_or ( 0.0 ) ;
415+ let pvc_mb = ( pvc_bytes / 1024.0 / 1024.0 ) as u64 ;
416+ pvc_mb
417+ . saturating_sub ( KOPIA_CACHE_RESERVE_MB )
418+ . max ( KOPIA_CONTENT_CACHE_FLOOR_MB )
419+ }
420+
390421pub fn build_kopia_cache_pvc (
391422 replica : & PostgresPhysicalReplica ,
392423 snapshot_size : & Quantity ,
@@ -446,17 +477,29 @@ if [ "$KOPIA_DISABLE_TLS" = "true" ]; then
446477 ENDPOINT_ARGS="$ENDPOINT_ARGS --disable-tls --disable-tls-verification"
447478fi
448479
480+ # Global kopia flags applied to every invocation: rotate CLI logs so
481+ # they don't fill the cache PVC. Cap at 20 most-recent files and
482+ # 24 hours, plenty for debugging a current restore without growing
483+ # without bound.
484+ KOPIA_GLOBAL_FLAGS="--log-dir-max-files=20 --log-dir-max-age=24h"
485+
449486echo "Connecting to kopia repository..."
450- kopia repository connect s3 \
487+ # --content-cache-size-mb / --metadata-cache-size-mb are persisted to
488+ # the local config on connect, so subsequent operations inherit the
489+ # bound. Without them kopia's content cache grows unbounded and
490+ # eventually fills the cache PVC (observed across multiple replicas).
491+ kopia $KOPIA_GLOBAL_FLAGS repository connect s3 \
451492 --bucket="$KOPIA_BUCKET" \
452493 --region="$KOPIA_REGION" \
453494 --access-key="$AWS_ACCESS_KEY_ID" \
454495 --secret-access-key="$AWS_SECRET_ACCESS_KEY" \
455496 --password="$KOPIA_PASSWORD" \
497+ --content-cache-size-mb="$KOPIA_CONTENT_CACHE_MB" \
498+ --metadata-cache-size-mb="$KOPIA_METADATA_CACHE_MB" \
456499 $ENDPOINT_ARGS
457500
458501echo "Starting restore..."
459- kopia snapshot restore "$SNAPSHOT_ID" /pgdata/postgres
502+ kopia $KOPIA_GLOBAL_FLAGS snapshot restore "$SNAPSHOT_ID" /pgdata/postgres
460503
461504echo "Restore complete"
462505ls -la /pgdata/
@@ -544,11 +587,26 @@ echo -n "$VERSION" > /dev/termination-log
544587 args: Some ( vec![ restore_script. to_string( ) ] ) ,
545588 env: Some (
546589 [
547- vec![ EnvVar {
548- name: "SNAPSHOT_ID" . to_string( ) ,
549- value: Some ( restore. spec. snapshot. clone( ) ) ,
550- ..Default :: default ( )
551- } ] ,
590+ vec![
591+ EnvVar {
592+ name: "SNAPSHOT_ID" . to_string( ) ,
593+ value: Some ( restore. spec. snapshot. clone( ) ) ,
594+ ..Default :: default ( )
595+ } ,
596+ EnvVar {
597+ name: "KOPIA_CONTENT_CACHE_MB" . to_string( ) ,
598+ value: Some (
599+ kopia_content_cache_mb( & restore. spec. snapshot_size)
600+ . to_string( ) ,
601+ ) ,
602+ ..Default :: default ( )
603+ } ,
604+ EnvVar {
605+ name: "KOPIA_METADATA_CACHE_MB" . to_string( ) ,
606+ value: Some ( KOPIA_METADATA_CACHE_MB . to_string( ) ) ,
607+ ..Default :: default ( )
608+ } ,
609+ ] ,
552610 kopia_writable_env( ) ,
553611 vec![
554612 env_from_secret( "KOPIA_BUCKET" , kopia_secret, "bucket" ) ,
0 commit comments