Portable Images & Offline Installs...

Portable Images & Offline Installs...

One question I always get asked is how do we do offline installs. Imagine a situation where your business blocks certain websites and you cannot download an application container images to your local laptop for pushing to an air gapped repository. If your k8s cluster is fully air gapped, it cannot do the pulling itself, nor can you provide it with the images to the local repository...because you're blocked from doing so.

In this instance you need to pull them from outside the security perimeter, but that prohibits pushing to the local repository too. What you need is a portable image export.

Kasten uses images hosted on a variety of locations:

  1. docker.io/grafana
  2. docker.io/jimmidyson
  3. gcr.io/kasten-images
  4. ghcr.io/kanisterio
  5. quay.io/prometheus
  6. registry.access.redhat.com/ubi9

The manual process of pulling via docker & exporting is very time consuming, so me being me...I scripted it:

#!/bin/bash
echo "Enter version you want to export (format 5.0.5): "
read VERSION < /dev/tty
# Define the target directory for individual zip files
EXPORT_DIR="image_exports"

# Create the export directory if it doesn't exist
mkdir -p "$EXPORT_DIR"
docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock gcr.io/kasten-images/k10offline:$VERSION pull images
# List images that contain the version number in their repository name
IMAGES=$(docker images | grep "$VERSION" | awk '{print $1":"$2}')

# Loop through the list of images, export each as a separate zip file, and collect the filenames
zip_files=()
for image in ${IMAGES[@]}; do
    image_name=$(echo "$image" | cut -d'/' -f3-)
    zip_file="${EXPORT_DIR}/${image_name//:/_}.zip"
    docker save -o "$zip_file" "$image"
    zip_files+=("$zip_file")
done

# Create a single rolled-up zip file containing all individual zip files
final_zip="kasten_images_$VERSION.zip"
zip -j "$final_zip" "${zip_files[@]}"

# Clean up individual zip files
rm -rf "$EXPORT_DIR"

echo "Images exported as individual zip files and rolled up into '$final_zip'"
echo "Cleaning up images in local docker repository....."
for image in ${IMAGES[@]}; do
    docker rmi -f "$image"

This is docker specific and will pull all the images down for whatever release you input, export them as individual zip files and lastly roll them up as a single portable zip. I have also created a version for podman if you're using a RedHat distro, as podman doesn't run via a socket, the commands are slightly different. Both of these will still require you to manually pull the offline HELM chart for install which can be done with:

helm repo update && helm fetch kasten/k10 --version=<k10-version>

Once you have the zip file onsite, just expand it and then load each zip with a docker import command (or podman import). You can then run the install from the local HELM tgz file, referencing your local image repository:

helm install k10 k10-6.0.11.tgz --namespace kasten-io --set global.airgapped.repository=repo.local.com

You should then be up and running with K10 in your offline environment. That wasn't so bad now, was it?

The podman version is as follows:

#!/bin/bash
echo "Enter version you want to export (format 5.0.5): "
read VERSION < /dev/tty
# Define the target directory for individual zip files
EXPORT_DIR="image_exports"

# Create the export directory if it doesn't exist
mkdir -p "$EXPORT_DIR"
export PODMAN_SYSTEMD_CGROUP=true
podman pull gcr.io/kasten-images/k10offline:$VERSION
IMAGES=$(podman run --rm -it gcr.io/kasten-images/k10offline:$VERSION list-images | tr -d '\r')
for i in $IMAGES
do
    podman pull $i
done

# Loop through the list of images, export each as a separate zip file, and collect the filenames
zip_files=()
for image in ${IMAGES[@]}; do
    image_name=$(echo "$image" | cut -d'/' -f3-)
    zip_file="${EXPORT_DIR}/${image_name//:/_}.zip"
    podman save -o "$zip_file" "$image"
    zip_files+=("$zip_file")
done

# Create a single rolled-up zip file containing all individual zip files
final_zip="kasten_images_$VERSION.zip"
zip -j "$final_zip" "${zip_files[@]}"

# Clean up individual zip files
rm -rf "$EXPORT_DIR"

echo "Images exported as individual zip files and rolled up into '$final_zip'"
echo "Cleaning up images in local docker repository....."
for image in ${IMAGES[@]}; do
    podman rmi -f "$image"
done