diff --git a/docker/cleanup.sh b/docker/cleanup.sh index 58154c8fc2..3915401885 100755 --- a/docker/cleanup.sh +++ b/docker/cleanup.sh @@ -3,36 +3,37 @@ # Cleanup script for the Firefly app. # # Usage: cleanup.sh [--once] [--dry-run] [--help] -# (default) run forever: every CLEANUP_INTERVAL sweep the targeted work areas, then sleep. +# (default) run forever: every CLEANUP_INTERVAL sweep both work areas, then sleep. # Sweeps append to /firefly/logs/cleanup//cleanup..log, one file # per day, keeping 7 days. -# --once make one sweep, log it to stdout and exit; for an external scheduler such as -# a Kubernetes CronJob. Exits 1 when the sweep cannot run. +# --once make one sweep, log it to stdout and exit. # --dry-run log what would be removed, remove nothing. # # An app has two work areas, each a dir named after the app: # workarea /firefly/workarea/ this container's own files # shared workarea /firefly/shared-workarea/ files shared by all replicas # where is the simple name of the application; see CLEANUP_APP_NAME. -# Each targeted work area gets two passes per sweep, workarea first: +# Each work area gets two passes per sweep, workarea first: # # age pass Each entry has a maximum age; files not *modified* within it are removed. # size pass Only when the work area's MAX is set. When usage is at or above it, ages # are ignored and the oldest files are removed until usage is down to # 90% of MAX. # +# Replicas sharing a work area take turns, using two files in its app dir: +# .cleanup.lock/ held during a sweep; others skip it. Broken when not refreshed +# for 2 x CLEANUP_INTERVAL (at least 30m). +# .cleanup.last the last sweep; one within CLEANUP_INTERVAL means skip. +# --dry-run uses neither. +# # ------------------------------------------------------------------------------------ # Environment variables (all optional) # # Name Default Description # --------------------- ------- --------------------------------------------------- -# CLEANUP_INTERVAL 1h how often a sweep runs; ignored with --once -# CLEANUP_TARGETS all work areas to sweep: all, workarea, shared or none. -# Use workarea in app containers when one other -# process (e.g. a CronJob) sweeps the shared workarea. +# CLEANUP_INTERVAL 1h how often a sweep runs # CLEANUP_APP_NAME auto the app, i.e. the work area dir name. Unset uses the -# first dir under /firefly/workarea; required when -# CLEANUP_TARGETS=shared. +# first dir under /firefly/workarea. # # age pass -- maximum age per group of entries # CLEANUP_AGE_WORKAREA 1h workarea: temp_files, perm_files, visualize/* @@ -65,6 +66,12 @@ readonly RM=/bin/rm readonly LOG_ROOT=/firefly/logs/cleanup # outside the dirs being cleaned readonly LOG_KEEP=7 # days of logs kept per app readonly CLEAN_TO_PCT=90 # the size pass cleans down to this % of MAX +readonly LOCK_NAME=.cleanup.lock # in each app dir; see "Several pods" above +readonly LAST_NAME=.cleanup.last +readonly SLACK_SECONDS=60 # a sweep this much early is still due +readonly REFRESH_EVERY=1000 # the size pass refreshes its lock per this many files +HOST="${HOSTNAME:-$(hostname 2>/dev/null || echo unknown)}" +readonly HOST warn() { # -- reports a problem and carries on echo "Cleanup: WARNING: $*" >&2 @@ -102,6 +109,7 @@ readonly ONCE DRY_RUN ${FIND} /dev/null -maxdepth 0 -printf '' 2>/dev/null || require "GNU findutils (find -printf)" printf '' | sort -z >/dev/null 2>&1 || require "GNU coreutils (sort -z)" date -d @0 >/dev/null 2>&1 || require "GNU coreutils (date -d)" +stat -c %Y / >/dev/null 2>&1 || require "GNU coreutils (stat -c)" # ------------------------------------------------------------------------------------ # Work area definitions. Entries are "||" @@ -218,20 +226,6 @@ describe_max() { esac } -# targets_setting -- prints " ", the last two true or false -targets_setting() { - local value="${CLEANUP_TARGETS:-all}" - case "${value,,}" in - all) echo "all true true" ;; - workarea) echo "workarea true false" ;; - shared) echo "shared false true" ;; - none) echo "none false false" ;; - *) - warn "CLEANUP_TARGETS='${value}' must be all, workarea, shared or none; using all" - echo "all true true" ;; - esac -} - # ------------------------------------------------------------------------------------ # Path helpers # ------------------------------------------------------------------------------------ @@ -239,30 +233,21 @@ targets_setting() { # CLEANUP_APP_NAME: Unset, it falls back to the first dir under the workarea (sorted, so the choice is # stable across sweeps). That is right for the usual one-app container; set # CLEANUP_APP_NAME when there are multiple apps under the workarea and you want to sweep a specific one. -# Set, it must name a dir under the workarea when the workarea is a target, or the sweep is -# skipped with an error: a wrong name would otherwise clean nothing, quietly. With only the -# shared-workarea targeted a missing dir is not an error, since the app creates it on first use. +# Set, it must name a dir in at least one work area, or the sweep is skipped with an error: a +# wrong name would otherwise clean nothing, quietly. A work area without the dir is skipped. # The shared-workarea is not searched: it may hold other data (e.g. redis), so a guess could be wrong. -# Returns 1 on an error, 2 when there is nothing to clean yet. +# Returns 1 on an error. resolve_app_name() { local name="${CLEANUP_APP_NAME:-}" dirs=() if [[ -n "${name}" ]]; then - if [[ "${DO_WORKAREA}" == true && ! -d "${WORKAREA_DIR}/${name}" ]]; then - error "CLEANUP_APP_NAME='${name}': ${WORKAREA_DIR}/${name} is not a dir;" \ - "skipping this sweep" + if [[ ! -d "${WORKAREA_DIR}/${name}" && ! -d "${SHARED_WORKAREA_DIR}/${name}" ]]; then + error "CLEANUP_APP_NAME='${name}': not a dir under ${WORKAREA_DIR} or" \ + "${SHARED_WORKAREA_DIR}; skipping this sweep" return 1 fi - if [[ "${DO_WORKAREA}" != true && ! -d "${SHARED_WORKAREA_DIR}/${name}" ]]; then - echo "Cleanup: ${SHARED_WORKAREA_DIR}/${name} does not exist yet; nothing to clean" >&2 - return 2 - fi echo "${name}" return 0 fi - if [[ "${DO_WORKAREA}" != true ]]; then - warn "CLEANUP_APP_NAME must be set when the workarea is not a target; skipping this sweep" - return 1 - fi readarray -t dirs < <(${FIND} "${WORKAREA_DIR}" -mindepth 1 -maxdepth 1 -type d \ ! -name cleanup_logs -printf '%f\n' 2>/dev/null | sort) ((${#dirs[@]})) || { @@ -306,6 +291,7 @@ clean_by_age() { ${FIND} "${path}" -type f -mmin "+${minutes}" -print -delete prune_empty_dirs "${path}" fi + refresh_lock done } @@ -365,6 +351,7 @@ clean_by_size() { [[ "${DRY_RUN}" == true ]] || ${RM} -f -- "${path}" || continue freed_kb=$((freed_kb + kb)) removed=$((removed + 1)) + ((removed % REFRESH_EVERY)) || refresh_lock done < <(${FIND} "${paths[@]}" -type f -printf '%T@\t%k\t%p\0' | sort -z -t$'\t' -k1,1n) echo @@ -374,6 +361,92 @@ clean_by_size() { return 0 } +# ------------------------------------------------------------------------------------ +# Taking turns with other pods sweeping the same work area +# ------------------------------------------------------------------------------------ + +HELD_LOCK="" # the lock this process holds, removed on exit + +# mtime_of -- seconds since the epoch, by the clock of the filesystem holding it +mtime_of() { + stat -c %Y -- "$1" 2>/dev/null +} + +# fs_now -- the time now by 's filesystem: a file made there carries its clock +fs_now() { + local probe="$1/.cleanup.clock.${HOST}.$$" now + : > "${probe}" 2>/dev/null || return 1 + now=$(mtime_of "${probe}") + ${RM} -f -- "${probe}" + [[ -n "${now}" ]] && echo "${now}" +} + +# owner_of -- the pod named in a lock's owner or a last-ran file +owner_of() { + local line + read -r line < "$1" 2>/dev/null && echo "${line}" || echo "unknown" +} + +# take_lock -- 0 when the lock is ours, 1 when another pod holds it +take_lock() { + local lock="$1/${LOCK_NAME}" now taken age stale + if ! mkdir "${lock}" 2>/dev/null; then + # held: break it only when its holder has stopped refreshing it + now=$(fs_now "$1") && taken=$(mtime_of "${lock}") || return 1 + age=$((now - taken)) + ((age >= LOCK_TTL_SECONDS)) || return 1 + # renaming is atomic, so of several pods breaking it at once only one succeeds + stale="${lock}.stale.${HOST}.$$" + mv -T -- "${lock}" "${stale}" 2>/dev/null && + warn "broke a lock held $((age / 60)) min by $(owner_of "${stale}/owner")" && + ${RM} -rf -- "${stale}" + mkdir "${lock}" 2>/dev/null || return 1 + fi + HELD_LOCK="${lock}" + echo "${HOST} pid $$ since $(date '+%F %T %Z')" > "${lock}/owner" +} + +# refresh_lock -- shows the lock is still in use, so a long sweep is not taken for a dead one +refresh_lock() { + [[ -n "${HELD_LOCK}" ]] && touch -c -- "${HELD_LOCK}" 2>/dev/null + return 0 +} + +release_lock() { + [[ -n "${HELD_LOCK}" ]] && ${RM} -rf -- "${HELD_LOCK}" + HELD_LOCK="" +} +trap release_lock EXIT +trap 'exit 143' TERM +trap 'exit 130' INT + +# claim_area -- 0 to sweep it, 1 to leave it to another pod for now +claim_area() { + local app_dir="$1" now last + if [[ ! -w "${app_dir}" ]]; then + warn "cannot write ${app_dir}; sweeping without a lock" + return 0 + fi + if ! take_lock "${app_dir}"; then + echo "locked by $(owner_of "${app_dir}/${LOCK_NAME}/owner"); skipping" + return 1 + fi + # the lock was just made, so its time is the filesystem's now + now=$(mtime_of "${HELD_LOCK}") + last=$(mtime_of "${app_dir}/${LAST_NAME}") + if [[ -n "${now}" && -n "${last}" ]] && ((now - last < INTERVAL_SECONDS - SLACK_SECONDS)); then + echo "swept $(((now - last) / 60)) min ago by $(owner_of "${app_dir}/${LAST_NAME}"); skipping" + release_lock + return 1 + fi +} + +# done_area -- records the sweep and lets the next pod in +done_area() { + echo "${HOST} $(date '+%F %T %Z')" > "$1/${LAST_NAME}" 2>/dev/null + release_lock +} + # ------------------------------------------------------------------------------------ # Sweep # ------------------------------------------------------------------------------------ @@ -386,14 +459,19 @@ sweep_dir() { echo echo "----- ${label}: ${app_dir}" [[ -d "${app_dir}" ]] || { echo "does not exist, skipping"; return; } + if [[ "${DRY_RUN}" != true ]]; then + claim_area "${app_dir}" || return + fi clean_by_age "${app_dir}" "$@" - [[ "${max}" == off ]] && return - for spec in "$@"; do - IFS='|' read -r entry _ _ <<< "${spec}" - [[ -d "${app_dir}/${entry}" ]] && paths+=("${app_dir}/${entry}") - done - clean_by_size "${app_dir}" "${max}" "${paths[@]}" + if [[ "${max}" != off ]]; then + for spec in "$@"; do + IFS='|' read -r entry _ _ <<< "${spec}" + [[ -d "${app_dir}/${entry}" ]] && paths+=("${app_dir}/${entry}") + done + clean_by_size "${app_dir}" "${max}" "${paths[@]}" + fi + [[ "${DRY_RUN}" == true ]] || done_area "${app_dir}" } # Does the work of one sweep, writing to stdout. The workarea goes first so its @@ -404,13 +482,9 @@ sweep_body() { echo "===== cleanup start -- app '${app}' -- $(date) =====" [[ "${DRY_RUN}" == true ]] && echo "DRY RUN -- nothing will be removed" - if [[ "${DO_WORKAREA}" == true ]]; then - sweep_dir "workarea" "${WORKAREA_DIR}" "${app}" "${WORKAREA_MAX}" "${WORKAREA_ENTRIES[@]}" - fi - if [[ "${DO_SHARED}" == true ]]; then - sweep_dir "shared-workarea" "${SHARED_WORKAREA_DIR}" "${app}" "${SHARED_MAX}" \ - "${SHARED_WORKAREA_ENTRIES[@]}" - fi + sweep_dir "workarea" "${WORKAREA_DIR}" "${app}" "${WORKAREA_MAX}" "${WORKAREA_ENTRIES[@]}" + sweep_dir "shared-workarea" "${SHARED_WORKAREA_DIR}" "${app}" "${SHARED_MAX}" \ + "${SHARED_WORKAREA_ENTRIES[@]}" echo echo "===== cleanup done -- $(date) =====" @@ -449,53 +523,37 @@ if ! [[ "${INTERVAL}" =~ ^[0-9]+[mhd]$ ]]; then INTERVAL="${DEFAULT_INTERVAL}" fi readonly INTERVAL +readonly INTERVAL_SECONDS=$(($(to_minutes "${INTERVAL}") * 60)) +# a lock unrefreshed this long is abandoned: 2 intervals, at least 30 minutes +readonly LOCK_TTL_SECONDS=$((INTERVAL_SECONDS * 2 > 1800 ? INTERVAL_SECONDS * 2 : 1800)) -read -r TARGETS DO_WORKAREA DO_SHARED <<< "$(targets_setting)" -readonly TARGETS DO_WORKAREA DO_SHARED -if [[ "${DO_WORKAREA}" == true ]]; then - age_settings "${WORKAREA_ENTRIES[@]}" - readonly WORKAREA_MAX=$(max_setting CLEANUP_WORKAREA_MAX) -fi -if [[ "${DO_SHARED}" == true ]]; then - age_settings "${SHARED_WORKAREA_ENTRIES[@]}" - readonly SHARED_MAX=$(max_setting CLEANUP_SHARED_MAX) -fi +age_settings "${WORKAREA_ENTRIES[@]}" "${SHARED_WORKAREA_ENTRIES[@]}" +readonly WORKAREA_MAX=$(max_setting CLEANUP_WORKAREA_MAX) +readonly SHARED_MAX=$(max_setting CLEANUP_SHARED_MAX) if [[ "${ONCE}" == true ]]; then mode="once"; else mode="every ${INTERVAL}"; fi [[ "${DRY_RUN}" == true ]] && mode+=", dry run" echo "Cleanup: started with:" printf 'Cleanup: %s\n' \ "mode=${mode}" \ - "CLEANUP_TARGETS=${TARGETS}" \ - "CLEANUP_APP_NAME=${CLEANUP_APP_NAME:-auto}" -if [[ "${DO_WORKAREA}" == true ]]; then - describe_ages "${WORKAREA_ENTRIES[@]}" - printf 'Cleanup: %s\n' "CLEANUP_WORKAREA_MAX=$(describe_max "${WORKAREA_MAX}")" -fi -if [[ "${DO_SHARED}" == true ]]; then - describe_ages "${SHARED_WORKAREA_ENTRIES[@]}" - printf 'Cleanup: %s\n' "CLEANUP_SHARED_MAX=$(describe_max "${SHARED_MAX}")" -fi - -if [[ "${DO_WORKAREA}" != true && "${DO_SHARED}" != true ]]; then - echo "Cleanup: no targets; nothing to do" - exit 0 -fi + "CLEANUP_APP_NAME=${CLEANUP_APP_NAME:-auto}" \ + "CLEANUP_INTERVAL=${INTERVAL}" +describe_ages "${WORKAREA_ENTRIES[@]}" +printf 'Cleanup: %s\n' "CLEANUP_WORKAREA_MAX=$(describe_max "${WORKAREA_MAX}")" +describe_ages "${SHARED_WORKAREA_ENTRIES[@]}" +printf 'Cleanup: %s\n' "CLEANUP_SHARED_MAX=$(describe_max "${SHARED_MAX}")" if [[ "${ONCE}" == true ]]; then - app=$(resolve_app_name) - case $? in - 0) sweep_body "${app}" ;; - 2) ;; # nothing to clean yet - *) exit 1 ;; - esac + app=$(resolve_app_name) || exit 1 + sweep_body "${app}" exit 0 fi -sleep 30 # give the app time to create its work area before the first sweep +# "sleep & wait" so a TERM stops the script at once, instead of waiting for the sleep to end. +sleep 30 & wait $! # give the app time to create its work area before the first sweep while true; do # re-resolve every sweep: the app dir may not exist yet at container start if app=$(resolve_app_name); then sweep_to_log "${app}"; fi - sleep "${INTERVAL}" + sleep "${INTERVAL}" & wait $! done diff --git a/helm/README.md b/helm/README.md index 430673bec1..1d93696038 100644 --- a/helm/README.md +++ b/helm/README.md @@ -156,40 +156,15 @@ Automatically deployed when `replicaCount > 1`. Consult `Reference Values` for c ### Cleanup Each pod runs `cleanup.sh`, which removes expired files from its work areas. Cleanup settings are `CLEANUP_*` environment variables set through `env`; see the header of [cleanup.sh](https://github.com/Caltech-IPAC/firefly/blob/dev/docker/cleanup.sh) for all of them. -#### Multi-replica with this chart -The pods share `sharedWorkDir`, so a CronJob (`-cleanup`, on `cleanup.schedule`) cleans it once, and each pod cleans only its own `workDir`. - -The chart sets `CLEANUP_TARGETS` in the pods and the CronJob, and `CLEANUP_APP_NAME` (from `cleanup.appName`) in the CronJob, and fails to render if `env` sets either one. The pods find their app dir themselves. Other settings in `env` reach both, and each side ignores the ones it does not use. For example, to sweep the shared work area every 6 hours and cap the app's dir there at 50Gi: +For example, to sweep every 6 hours and cap the app's dir in the shared work area at 50Gi: ```yaml -cleanup: - schedule: "0 */6 * * *" - env: + - name: CLEANUP_INTERVAL + value: "6h" - name: CLEANUP_SHARED_MAX value: "50Gi" ``` -#### Multi-replica without this chart -When several Firefly containers share `/firefly/shared-workarea`, only one process should sweep the shared work area. -Split the work in two: - -**Each Firefly container** cleans only its own work area: -```bash -CLEANUP_TARGETS=workarea # required: leave the shared work area to the scheduled job -``` - -**One scheduled job** (e.g. Kubernetes CronJob) runs the same image with the shared volume mounted at `/firefly/shared-workarea` -and the command `/usr/local/tomcat/cleanup.sh --once`, which makes one sweep, logs it to stdout and exits: - -```bash -CLEANUP_TARGETS=shared # required -CLEANUP_APP_NAME=firefly # required: the job has no work area to find the app dir from -CLEANUP_SHARED_MAX=50Gi # optional: cap the shared work area -``` -Run the job about as often as you would set `CLEANUP_INTERVAL`. `CLEANUP_APP_NAME` is the app's directory under the work areas: `firefly` for the stock image, or the name of your app if it is built on the Firefly image. - -For a Kubernetes example, see this chart's [cleanup-cronjob.yaml](https://github.com/Caltech-IPAC/firefly/blob/dev/helm/templates/cleanup-cronjob.yaml). - ## Reference ## Values @@ -207,9 +182,6 @@ For a Kubernetes example, see this chart's [cleanup-cronjob.yaml](https://github | autoscaling.scaleUpWindow | int | `60` | Stabilization window in seconds before scaling up. | | autoscaling.targetCpuUsage | int | `80` | Target average CPU utilization (%) across pods to trigger scale up. Set to empty to disable. | | autoscaling.targetMemoryUsage | int | `100` | Target average memory utilization (%) across pods to trigger scale up. Set to empty to disable. | -| cleanup.appName | string | `"firefly"` | App dir name under the shared work area, passed to the cleanup CronJob as CLEANUP_APP_NAME. The pods find their app dir themselves. Override only for an app built on the Firefly image. | -| cleanup.resources | object | `{"limits":{"memory":"256Mi"},"requests":{"cpu":"50m","memory":"64Mi"}}` | CronJob resource requests and limits. | -| cleanup.schedule | string | `"0 * * * *"` | Schedule of the CronJob that cleans the shared work area. The CronJob is created in multi-replica mode only; each pod then cleans just its own work area. Cleanup settings (CLEANUP_*) go in `env` and apply to both. | | env | list | `[]` | Additional environment variables. | | extraLabels | object | `{}` | Additional labels added to all resources (e.g. owner: jenkins). | | image.pullPolicy | string | `"IfNotPresent"` | Image pull policy. | diff --git a/helm/README.md.gotmpl b/helm/README.md.gotmpl index 31d8415463..29979c84f0 100644 --- a/helm/README.md.gotmpl +++ b/helm/README.md.gotmpl @@ -158,40 +158,15 @@ Automatically deployed when `replicaCount > 1`. Consult `Reference Values` for c ### Cleanup Each pod runs `cleanup.sh`, which removes expired files from its work areas. Cleanup settings are `CLEANUP_*` environment variables set through `env`; see the header of [cleanup.sh](https://github.com/Caltech-IPAC/firefly/blob/dev/docker/cleanup.sh) for all of them. -#### Multi-replica with this chart -The pods share `sharedWorkDir`, so a CronJob (`-cleanup`, on `cleanup.schedule`) cleans it once, and each pod cleans only its own `workDir`. - -The chart sets `CLEANUP_TARGETS` in the pods and the CronJob, and `CLEANUP_APP_NAME` (from `cleanup.appName`) in the CronJob, and fails to render if `env` sets either one. The pods find their app dir themselves. Other settings in `env` reach both, and each side ignores the ones it does not use. For example, to sweep the shared work area every 6 hours and cap the app's dir there at 50Gi: +For example, to sweep every 6 hours and cap the app's dir in the shared work area at 50Gi: ```yaml -cleanup: - schedule: "0 */6 * * *" - env: + - name: CLEANUP_INTERVAL + value: "6h" - name: CLEANUP_SHARED_MAX value: "50Gi" ``` -#### Multi-replica without this chart -When several Firefly containers share `/firefly/shared-workarea`, only one process should sweep the shared work area. -Split the work in two: - -**Each Firefly container** cleans only its own work area: -```bash -CLEANUP_TARGETS=workarea # required: leave the shared work area to the scheduled job -``` - -**One scheduled job** (e.g. Kubernetes CronJob) runs the same image with the shared volume mounted at `/firefly/shared-workarea` -and the command `/usr/local/tomcat/cleanup.sh --once`, which makes one sweep, logs it to stdout and exits: - -```bash -CLEANUP_TARGETS=shared # required -CLEANUP_APP_NAME=firefly # required: the job has no work area to find the app dir from -CLEANUP_SHARED_MAX=50Gi # optional: cap the shared work area -``` -Run the job about as often as you would set `CLEANUP_INTERVAL`. `CLEANUP_APP_NAME` is the app's directory under the work areas: `firefly` for the stock image, or the name of your app if it is built on the Firefly image. - -For a Kubernetes example, see this chart's [cleanup-cronjob.yaml](https://github.com/Caltech-IPAC/firefly/blob/dev/helm/templates/cleanup-cronjob.yaml). - ## Reference {{ template "chart.valuesSection" . }} \ No newline at end of file diff --git a/helm/templates/_helpers.tpl b/helm/templates/_helpers.tpl index 3b0b07421c..7981b1d3ce 100644 --- a/helm/templates/_helpers.tpl +++ b/helm/templates/_helpers.tpl @@ -36,11 +36,4 @@ Validates chart values. Call this from deployment.yaml to catch misconfiguration {{- if and (include "firefly.multiReplica" .) (not .Values.persistence.sharedWorkDir.pvc) (not .Values.persistence.sharedWorkDir.existingClaim) }} {{- fail "persistence.sharedWorkDir must be configured (pvc or existingClaim) in multi-replica mode (replicaCount > 1 or autoscaling.enabled). Use ReadWriteMany accessMode." }} {{- end }} -{{- if include "firefly.multiReplica" . }} -{{- range .Values.env }} -{{- if has .name (list "CLEANUP_TARGETS" "CLEANUP_APP_NAME") }} -{{- fail (printf "env: %s is set by the chart in multi-replica mode (pods sweep the workarea, the cleanup CronJob sweeps the shared work area); use cleanup.appName for the app dir" .name) }} -{{- end }} -{{- end }} -{{- end }} {{- end }} diff --git a/helm/templates/cleanup-cronjob.yaml b/helm/templates/cleanup-cronjob.yaml deleted file mode 100644 index 5657524b6f..0000000000 --- a/helm/templates/cleanup-cronjob.yaml +++ /dev/null @@ -1,61 +0,0 @@ -{{- if include "firefly.multiReplica" . }} -{{/* -In multi-replica mode the pods share sharedWorkDir, so one CronJob cleans it instead of -every pod. The pods clean only their own work area (CLEANUP_TARGETS=workarea). -*/}} -apiVersion: batch/v1 -kind: CronJob -metadata: - name: {{ include "firefly.fullname" . }}-cleanup - labels: - {{- include "firefly.labels" . | nindent 4 }} - app.kubernetes.io/component: cleanup -spec: - schedule: {{ .Values.cleanup.schedule | quote }} - concurrencyPolicy: Forbid - startingDeadlineSeconds: 600 - successfulJobsHistoryLimit: 1 - failedJobsHistoryLimit: 3 - jobTemplate: - spec: - backoffLimit: 0 - ttlSecondsAfterFinished: 86400 - template: - metadata: - labels: - # not firefly.selectorLabels: these pods must not receive Service traffic - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/component: cleanup - spec: - restartPolicy: Never - {{- if .Values.serviceAccount.create }} - serviceAccountName: {{ .Values.serviceAccount.name | default (include "firefly.fullname" .) }} - {{- end }} - {{- with .Values.securityContext }} - securityContext: - {{- toYaml . | nindent 12 }} - {{- end }} - containers: - - name: cleanup - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - command: ["/usr/local/tomcat/cleanup.sh", "--once"] - env: - - name: CLEANUP_TARGETS - value: shared - - name: CLEANUP_APP_NAME - value: {{ .Values.cleanup.appName | quote }} - {{- with .Values.env }} - {{- toYaml . | nindent 16 }} - {{- end }} - resources: - {{- toYaml .Values.cleanup.resources | nindent 16 }} - volumeMounts: - - name: shared-work-dir - mountPath: /firefly/shared-workarea - volumes: - # firefly.validate guarantees a sharedWorkDir PVC in multi-replica mode - - name: shared-work-dir - persistentVolumeClaim: - claimName: {{ .Values.persistence.sharedWorkDir.existingClaim | default (printf "%s-shared-work" (include "firefly.fullname" .)) }} -{{- end }} diff --git a/helm/templates/deployment.yaml b/helm/templates/deployment.yaml index 32c7f9dec4..319354735a 100644 --- a/helm/templates/deployment.yaml +++ b/helm/templates/deployment.yaml @@ -51,11 +51,6 @@ spec: - name: PROPS_redis__host value: {{ include "firefly.redisName" . }} {{- end }} - {{- if include "firefly.multiReplica" . }} - # the shared work area is cleaned by the cleanup CronJob - - name: CLEANUP_TARGETS - value: workarea - {{- end }} {{- with .Values.env }} {{- toYaml . | nindent 12 }} {{- end }} diff --git a/helm/values.yaml b/helm/values.yaml index b7351e1a9b..069057c9c2 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -97,23 +97,6 @@ redis: # -- Redis persistence. Falls back to sharedWorkDir PVC if configured, otherwise emptyDir. persistence: {} -cleanup: - # -- App dir name under the shared work area, passed to the cleanup CronJob as - # CLEANUP_APP_NAME. The pods find their app dir themselves. Override only for an app - # built on the Firefly image. - appName: firefly - # -- Schedule of the CronJob that cleans the shared work area. The CronJob is created - # in multi-replica mode only; each pod then cleans just its own work area. - # Cleanup settings (CLEANUP_*) go in `env` and apply to both. - schedule: "0 * * * *" - # -- CronJob resource requests and limits. - resources: - requests: - cpu: 50m - memory: 64Mi - limits: - memory: 256Mi - autoscaling: # -- Enable horizontal pod autoscaling. When enabled, Redis is automatically deployed # and session affinity annotations are injected into the ingress.