#!/usr/bin/env bash # # JbTecWiz Support Centre -- generated fix script # # Fault : ImagePullBackOff, ErrImagePull and registry rate limits # Fix : Supply credentials the node can actually use # Source: https://jbtecwiz.com/support/lnx-ctr-imagepull # # Run as : Root shell # Expect : 30 minutes # Risk : medium # Reversible : yes # # WHEN THIS IS THE RIGHT FIX # unauthorized, or authentication required. # # HOW TO UNDO IT # Delete and recreate the secret with the previous credentials. # # Walks the fix one step at a time and asks before each. Steps with no # command are yours to do -- it prints those and waits. DRYRUN=1 prints # without executing; UNATTENDED=1 does not ask. # # -------------------------------------------------------------------- # NO WARRANTY - USE AT YOUR OWN RISK # # This script is provided by JbTecWiz as-is and with no warranty of any # kind, express or implied. You run it entirely at your own risk. # # JbTecWiz accepts no liability for any loss or damage arising from its # use, including but not limited to data loss, downtime, or configuration # changes that turn out to be wrong for your system. # # You are responsible for reading this script before running it, for # satisfying yourself that it suits the machine in front of you, and for # having a working backup first. Some steps cannot be undone. # -------------------------------------------------------------------- set -uo pipefail DRYRUN="${DRYRUN:-0}" UNATTENDED="${UNATTENDED:-0}" failed=0 # - THIS SCRIPT WILL NOT RUN UNTIL YOU EDIT IT - cat >&2 <<'EOF' This script needs editing before it can run. Replace each of these with a real value: example.com (a placeholder domain) Then delete this block near the top of the script. EOF exit 2 if [ "$(id -u)" -ne 0 ]; then echo " This fix is documented as needing root. Re-run with sudo." >&2 exit 3 fi rule() { printf "\n%s\n" "$(printf '-%.0s' $(seq 1 70))"; if [ $# -gt 0 ]; then echo "$1"; fi; } prose() { echo "$1" | fold -s -w 74 | sed "s/^/ /"; } # Returns 0 when the caller should run the command, 1 when it should not. # A manual step always returns 1 -- there is nothing for the caller to run. step() { # step [command lines...] local n="$1" dotext="$2" why="$3" mode="$4"; shift 4 rule " Step $n of 5" prose "$dotext" if [ -n "$why" ]; then echo; prose "$why"; fi if [ "$mode" = "manual" ]; then echo; echo " -> Do this yourself, then press Enter to carry on." if [ "$UNATTENDED" = "0" ] && [ "$DRYRUN" = "0" ]; then read -r _; fi return 1 fi echo; printf " %s\n" "$@"; echo if [ "$DRYRUN" = "1" ]; then echo " (dry run -- not executed)"; return 1; fi if [ "$UNATTENDED" = "0" ]; then read -r -p " Run this step? [Y]es / [S]kip / [Q]uit " a case "$a" in [Qq]*) echo " Stopped at your request."; exit 0 ;; [Ss]*) echo " Skipped."; return 1 ;; esac fi return 0 } rule echo " ImagePullBackOff, ErrImagePull and registry rate limits" echo " Supply credentials the node can actually use" echo echo " Risk: medium Reversible 30 minutes" echo prose 'No warranty. Use at your own risk - JbTecWiz accepts no liability. Read it before you run it, and have a backup.' rule echo if [ "$UNATTENDED" = "0" ] && [ "$DRYRUN" = "0" ]; then read -r -p " Ready? [y/N] " go case "$go" in [Yy]*) ;; *) echo " Nothing was changed."; exit 0;; esac fi if step 1 'Check the secret exists in the same namespace as the pod. An imagePullSecret in a different namespace is invisible.' 'Secrets are namespaced and image pull secrets are not shared. This is the most common cause of credentials that are definitely correct and definitely not working.' cmd 'kubectl get secrets -n myns' 'kubectl get pod mypod -n myns -o jsonpath='\''{.spec.imagePullSecrets}'\'''; then kubectl get secrets -n myns kubectl get pod mypod -n myns -o jsonpath='{.spec.imagePullSecrets}' if [ $? -ne 0 ]; then failed=$((failed+1)) echo " Step 1 failed. The rest of the fix may depend on it." >&2 fi fi if step 2 'Check the secret'\''s contents decode to the right registry host.' '' cmd 'kubectl get secret regcred -n myns -o jsonpath='\''{.data.\.dockerconfigjson}'\'' | base64 -d'; then kubectl get secret regcred -n myns -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d if [ $? -ne 0 ]; then failed=$((failed+1)) echo " Step 2 failed. The rest of the fix may depend on it." >&2 fi fi step 3 'The registry server must match exactly what the image reference uses, including whether it has a port.' '' manual || true if step 4 'Test the credentials directly from a node.' '' cmd 'sudo crictl pull registry.example.com/myapp:1.2.3' 'docker login registry.example.com'; then sudo crictl pull registry.example.com/myapp:1.2.3 docker login registry.example.com if [ $? -ne 0 ]; then failed=$((failed+1)) echo " Step 4 failed. The rest of the fix may depend on it." >&2 fi fi step 5 'Rotate the token if it has expired -- most registry tokens are short-lived by design.' '' manual || true rule " Confirm it worked" prose 'The image pulls and the pod reaches Running.' if [ "$DRYRUN" = "0" ]; then kubectl get pod mypod -n myns -w fi rule if [ "$failed" -gt 0 ]; then echo " Finished with $failed failed step(s)." echo " Read the full write-up at https://jbtecwiz.com/support/lnx-ctr-imagepull" else echo " Finished." fi echo prose 'To undo: Delete and recreate the secret with the previous credentials.' rule