You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

221 lines
7.3 KiB

  1. #!/bin/bash
  2. OPTION=$1
  3. CURRENT_DIR=$(cd $(dirname $0); pwd)
  4. TEMP_DIR="${CURRENT_DIR}/temp"
  5. IMAGE_TAR_FILE="${CURRENT_DIR}/container-images.tar.gz"
  6. IMAGE_DIR="${CURRENT_DIR}/container-images"
  7. IMAGE_LIST="${IMAGE_DIR}/container-images.txt"
  8. RETRY_COUNT=5
  9. function create_container_image_tar() {
  10. set -e
  11. if [ -z "${IMAGES_FROM_FILE}" ]; then
  12. echo "Getting images from current \"$(kubectl config current-context)\""
  13. IMAGES=$(mktemp --suffix=-images)
  14. trap 'rm -f "${IMAGES}"' EXIT
  15. kubectl describe cronjobs,jobs,pods --all-namespaces | grep " Image:" | awk '{print $2}' | sort | uniq > "${IMAGES}"
  16. # NOTE: etcd and pause cannot be seen as pods.
  17. # The pause image is used for --pod-infra-container-image option of kubelet.
  18. kubectl cluster-info dump | grep -E "quay.io/coreos/etcd:|registry.k8s.io/pause:" | sed s@\"@@g >> "${IMAGES}"
  19. else
  20. echo "Getting images from file \"${IMAGES_FROM_FILE}\""
  21. if [ ! -f "${IMAGES_FROM_FILE}" ]; then
  22. echo "${IMAGES_FROM_FILE} is not a file"
  23. exit 1
  24. fi
  25. IMAGES=$(realpath $IMAGES_FROM_FILE)
  26. fi
  27. rm -f ${IMAGE_TAR_FILE}
  28. rm -rf ${IMAGE_DIR}
  29. mkdir ${IMAGE_DIR}
  30. cd ${IMAGE_DIR}
  31. sudo ${runtime} pull registry:latest
  32. sudo ${runtime} save -o registry-latest.tar registry:latest
  33. while read -r image
  34. do
  35. FILE_NAME="$(echo ${image} | sed s@"/"@"-"@g | sed s/":"/"-"/g | sed -E 's/\@.*//g')".tar
  36. set +e
  37. for step in $(seq 1 ${RETRY_COUNT})
  38. do
  39. sudo ${runtime} pull ${image}
  40. if [ $? -eq 0 ]; then
  41. break
  42. fi
  43. echo "Failed to pull ${image} at step ${step}"
  44. if [ ${step} -eq ${RETRY_COUNT} ]; then
  45. exit 1
  46. fi
  47. done
  48. set -e
  49. sudo ${runtime} save -o ${FILE_NAME} ${image}
  50. # NOTE: Here removes the following repo parts from each image
  51. # so that these parts will be replaced with Kubespray.
  52. # - kube_image_repo: "registry.k8s.io"
  53. # - gcr_image_repo: "gcr.io"
  54. # - ghcr_image_repo: "ghcr.io"
  55. # - docker_image_repo: "docker.io"
  56. # - quay_image_repo: "quay.io"
  57. FIRST_PART=$(echo ${image} | awk -F"/" '{print $1}')
  58. if [ "${FIRST_PART}" = "registry.k8s.io" ] ||
  59. [ "${FIRST_PART}" = "gcr.io" ] ||
  60. [ "${FIRST_PART}" = "ghcr.io" ] ||
  61. [ "${FIRST_PART}" = "docker.io" ] ||
  62. [ "${FIRST_PART}" = "quay.io" ] ||
  63. [ "${FIRST_PART}" = "${PRIVATE_REGISTRY}" ]; then
  64. image=$(echo ${image} | sed s@"${FIRST_PART}/"@@ | sed -E 's/\@.*/\n/g')
  65. fi
  66. echo "${FILE_NAME} ${image}" >> ${IMAGE_LIST}
  67. done < "${IMAGES}"
  68. cd ..
  69. sudo chown ${USER} ${IMAGE_DIR}/*
  70. tar -zcvf ${IMAGE_TAR_FILE} ./container-images
  71. rm -rf ${IMAGE_DIR}
  72. echo ""
  73. echo "${IMAGE_TAR_FILE} is created to contain your container images."
  74. echo "Please keep this file and bring it to your offline environment."
  75. }
  76. function register_container_images() {
  77. create_registry=false
  78. REGISTRY_PORT=${REGISTRY_PORT:-"5000"}
  79. if [ -z "${DESTINATION_REGISTRY}" ]; then
  80. echo "DESTINATION_REGISTRY not set, will create local registry"
  81. create_registry=true
  82. DESTINATION_REGISTRY="$(hostname):${REGISTRY_PORT}"
  83. fi
  84. echo "Images will be pushed to ${DESTINATION_REGISTRY}"
  85. if [ ! -f ${IMAGE_TAR_FILE} ]; then
  86. echo "${IMAGE_TAR_FILE} should exist."
  87. exit 1
  88. fi
  89. if [ ! -d ${TEMP_DIR} ]; then
  90. mkdir ${TEMP_DIR}
  91. fi
  92. # To avoid "http: server gave http response to https client" error.
  93. if [ -d /etc/docker/ ]; then
  94. set -e
  95. # Ubuntu18.04, RHEL7/CentOS7
  96. cp ${CURRENT_DIR}/docker-daemon.json ${TEMP_DIR}/docker-daemon.json
  97. sed -i s@"HOSTNAME"@"$(hostname)"@ ${TEMP_DIR}/docker-daemon.json
  98. sudo cp ${TEMP_DIR}/docker-daemon.json /etc/docker/daemon.json
  99. elif [ -d /etc/containers/ ]; then
  100. set -e
  101. # RHEL8/CentOS8
  102. cp ${CURRENT_DIR}/registries.conf ${TEMP_DIR}/registries.conf
  103. sed -i s@"HOSTNAME"@"$(hostname)"@ ${TEMP_DIR}/registries.conf
  104. sudo cp ${TEMP_DIR}/registries.conf /etc/containers/registries.conf
  105. else
  106. echo "runtime package(docker-ce, podman, nerctl, etc.) should be installed"
  107. exit 1
  108. fi
  109. tar -zxvf ${IMAGE_TAR_FILE}
  110. if [ "${create_registry}" ]; then
  111. sudo ${runtime} load -i ${IMAGE_DIR}/registry-latest.tar
  112. set +e
  113. sudo ${runtime} container inspect registry >/dev/null 2>&1
  114. if [ $? -ne 0 ]; then
  115. sudo ${runtime} run --restart=always -d -p "${REGISTRY_PORT}":"${REGISTRY_PORT}" --name registry registry:latest
  116. fi
  117. set -e
  118. fi
  119. while read -r line; do
  120. file_name=$(echo ${line} | awk '{print $1}')
  121. raw_image=$(echo ${line} | awk '{print $2}')
  122. new_image="${DESTINATION_REGISTRY}/${raw_image}"
  123. load_image=$(sudo ${runtime} load -i ${IMAGE_DIR}/${file_name} | head -n1)
  124. org_image=$(echo "${load_image}" | awk '{print $3}')
  125. # special case for tags containing the digest when using docker or podman as the container runtime
  126. if [ "${org_image}" == "ID:" ]; then
  127. org_image=$(echo "${load_image}" | awk '{print $4}')
  128. fi
  129. image_id=$(sudo ${runtime} image inspect ${org_image} | grep "\"Id\":" | awk -F: '{print $3}'| sed s/'\",'//)
  130. if [ -z "${file_name}" ]; then
  131. echo "Failed to get file_name for line ${line}"
  132. exit 1
  133. fi
  134. if [ -z "${raw_image}" ]; then
  135. echo "Failed to get raw_image for line ${line}"
  136. exit 1
  137. fi
  138. if [ -z "${org_image}" ]; then
  139. echo "Failed to get org_image for line ${line}"
  140. exit 1
  141. fi
  142. if [ -z "${image_id}" ]; then
  143. echo "Failed to get image_id for file ${file_name}"
  144. exit 1
  145. fi
  146. sudo ${runtime} load -i ${IMAGE_DIR}/${file_name}
  147. sudo ${runtime} tag ${image_id} ${new_image}
  148. sudo ${runtime} push ${new_image}
  149. done <<< "$(cat ${IMAGE_LIST})"
  150. echo "Succeeded to register container images to local registry."
  151. echo "Please specify \"${DESTINATION_REGISTRY}\" for the following options in your inventry:"
  152. echo "- kube_image_repo"
  153. echo "- gcr_image_repo"
  154. echo "- docker_image_repo"
  155. echo "- quay_image_repo"
  156. }
  157. # get runtime command
  158. if command -v nerdctl 1>/dev/null 2>&1; then
  159. runtime="nerdctl"
  160. elif command -v podman 1>/dev/null 2>&1; then
  161. runtime="podman"
  162. elif command -v docker 1>/dev/null 2>&1; then
  163. runtime="docker"
  164. else
  165. echo "No supported container runtime found"
  166. exit 1
  167. fi
  168. if [ "${OPTION}" == "create" ]; then
  169. create_container_image_tar
  170. elif [ "${OPTION}" == "register" ]; then
  171. register_container_images
  172. else
  173. echo "This script has two features:"
  174. echo "(1) Get container images from an environment which is deployed online, or set IMAGES_FROM_FILE"
  175. echo " environment variable to get images from a file (e.g. temp/images.list after running the"
  176. echo " ./generate_list.sh script)."
  177. echo "(2) Deploy local container registry and register the container images to the registry."
  178. echo ""
  179. echo "Step(1) should be done online site as a preparation, then we bring"
  180. echo "the gotten images to the target offline environment. if images are from"
  181. echo "a private registry, you need to set PRIVATE_REGISTRY environment variable."
  182. echo "Then we will run step(2) for registering the images to local registry, or to an existing"
  183. echo "registry set by the DESTINATION_REGISTRY environment variable. By default, the local registry"
  184. echo "will run on port 5000. This can be changed with the REGISTRY_PORT environment variable"
  185. echo ""
  186. echo "${IMAGE_TAR_FILE} is created to contain your container images."
  187. echo "Please keep this file and bring it to your offline environment."
  188. echo ""
  189. echo "Step(1) can be operated with:"
  190. echo " $ ./manage-offline-container-images.sh create"
  191. echo ""
  192. echo "Step(2) can be operated with:"
  193. echo " $ ./manage-offline-container-images.sh register"
  194. echo ""
  195. echo "Please specify 'create' or 'register'."
  196. echo ""
  197. exit 1
  198. fi