diff options
author | Chris Evich <cevich@redhat.com> | 2019-06-14 13:28:47 -0400 |
---|---|---|
committer | Chris Evich <cevich@redhat.com> | 2019-07-15 15:26:26 -0400 |
commit | e8564dc44f54b15dc34c9cce17d5e302c618d58e (patch) | |
tree | 05b247ce7c977eed3b1b5ba2dc085ad1ac40fa58 /contrib/imgprune | |
parent | 547cb4e55e9262b7127706d07291f0e45ccf4f42 (diff) | |
download | podman-e8564dc44f54b15dc34c9cce17d5e302c618d58e.tar.gz podman-e8564dc44f54b15dc34c9cce17d5e302c618d58e.tar.bz2 podman-e8564dc44f54b15dc34c9cce17d5e302c618d58e.zip |
Cirrus: Print images that should be pruned
Over time unless they're removed, the project could grow quite a large
collection of VM images. While generally cheap (less than a penny each,
per month), these will become a significant cost item if not kept
in-check.
Add a specialized container for handling image-pruning, but limit
it to only finding and printing (not actually deleting) images.
Also update the image-building workflow so that base-images used to
compose cache-images are also labeled with metadata.
N/B: As an additional safeguard, the service account which
executes the new container in production *DOES NOT*
have access to delete images. This can be enabled
by adding the GCE IAM role: CustomComputeImagePrune
Signed-off-by: Chris Evich <cevich@redhat.com>
Diffstat (limited to 'contrib/imgprune')
-rw-r--r-- | contrib/imgprune/Dockerfile | 7 | ||||
-rw-r--r-- | contrib/imgprune/README.md | 11 | ||||
-rwxr-xr-x | contrib/imgprune/entrypoint.sh | 67 |
3 files changed, 85 insertions, 0 deletions
diff --git a/contrib/imgprune/Dockerfile b/contrib/imgprune/Dockerfile new file mode 100644 index 000000000..26329e828 --- /dev/null +++ b/contrib/imgprune/Dockerfile @@ -0,0 +1,7 @@ +FROM libpod/imgts:latest + +RUN yum -y update && \ + yum clean all + +COPY /contrib/imgprune/entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod 755 /usr/local/bin/entrypoint.sh diff --git a/contrib/imgprune/README.md b/contrib/imgprune/README.md new file mode 100644 index 000000000..48abc2028 --- /dev/null +++ b/contrib/imgprune/README.md @@ -0,0 +1,11 @@ +![PODMAN logo](../../logo/podman-logo-source.svg) + +A container image for maintaining the collection of +VM images used by CI/CD on this project and several others. +Acts upon metadata maintained by the imgts container. + +Example build (from repository root): + +```bash +sudo podman build -t $IMAGE_NAME -f contrib/imgprune/Dockerfile . +``` diff --git a/contrib/imgprune/entrypoint.sh b/contrib/imgprune/entrypoint.sh new file mode 100755 index 000000000..a4b77523b --- /dev/null +++ b/contrib/imgprune/entrypoint.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +set -e + +source /usr/local/bin/lib_entrypoint.sh + +req_env_var GCPJSON GCPNAME GCPPROJECT IMGNAMES + +gcloud_init + +# For safety's sake + limit nr background processes +PRUNE_LIMIT=10 +THEFUTURE=$(date --date='+1 hour' +%s) +TOO_OLD='90 days ago' +THRESHOLD=$(date --date="$TOO_OLD" +%s) +# Format Ref: https://cloud.google.com/sdk/gcloud/reference/topic/formats +FORMAT='value[quote](name,selfLink,creationTimestamp,labels)' +PROJRE="/v1/projects/$GCPPROJECT/global/" +BASE_IMAGE_RE='cloud-base' +RECENTLY=$(date --date='30 days ago' --iso-8601=date) +EXCLUDE="$IMGNAMES $IMAGE_BUILDER_CACHE_IMAGE_NAME" # whitespace separated values +# Filter Ref: https://cloud.google.com/sdk/gcloud/reference/topic/filters +FILTER="selfLink~$PROJRE AND creationTimestamp<$RECENTLY AND NOT name=($EXCLUDE)" +TODELETE=$(mktemp -p '' todelete.XXXXXX) + +echo "Searching images for pruning candidates older than $TOO_OLD ($THRESHOLD):" +$GCLOUD compute images list --format="$FORMAT" --filter="$FILTER" | \ + while read name selfLink creationTimestamp labels + do + created_ymd=$(date --date=$creationTimestamp --iso-8601=date) + last_used=$(egrep --only-matching --max-count=1 'last-used=[[:digit:]]+' <<< $labels || true) + markmsgpfx="Marking $name (created $created_ymd) for deletion" + if [[ -z "$last_used" ]] + then # image pre-dates addition of tracking labels + echo "$markmsgpfx: Missing 'last-used' metadata, labels: '$labels'" + echo "$name" >> $TODELETE + continue + fi + + last_used_timestamp=$(date --date=@$(cut -d= -f2 <<< $last_used || true) +%s || true) + last_used_ymd=$(date --date=@$last_used_timestamp --iso-8601=date) + if [[ -z "$last_used_timestamp" ]] || [[ "$last_used_timestamp" -ge "$THEFUTURE" ]] + then + echo "$markmsgpfx: Missing or invalid last-used timestamp: '$last_used_timestamp'" + echo "$name" >> $TODELETE + continue + fi + + if [[ "$last_used_timestamp" -le "$THRESHOLD" ]] + then + echo "$markmsgpfx: Used over $TOO_OLD on $last_used_ymd" + echo "$name" >> $TODELETE + continue + fi + + echo "NOT $markmsgpfx: last used on $last_used_ymd)" + done + +echo "Pruning up to $PRUNE_LIMIT images that were marked for deletion:" +for image_name in $(tail -$PRUNE_LIMIT $TODELETE | sort --random-sort) +do + # This can take quite some time (minutes), run in parallel disconnected from terminal + echo "TODO: Would have: $GCLOUD compute images delete $image_name &" + sleep "$[1+RANDOM/1000]s" & # Simlate background operation +done + +wait || true # Nothing to delete: No background jobs |