k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/cluster/gce/gci/flexvolume_node_setup.sh (about) 1 #!/usr/bin/env bash 2 3 # Copyright 2017 The Kubernetes Authors. 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 # Sets up FlexVolume drivers on GCE COS instances using mounting utilities packaged in a Google 18 # Container Registry image. 19 # The user-provided FlexVolume driver(s) must be under /flexvolume of the image filesystem. 20 # For example, the driver k8s/nfs must be located at /flexvolume/k8s~nfs/nfs . 21 # 22 # This script should be used on a clean instance, with no FlexVolume installed. 23 # Should not be run on instances with an existing full or partial installation. 24 # Upon failure, the script will clean up the partial installation automatically. 25 # 26 # Must be executed under /home/kubernetes/bin with sudo. 27 # Warning: kubelet will be restarted upon successful execution. 28 29 set -o errexit 30 set -o nounset 31 set -o pipefail 32 33 MOUNTER_IMAGE=${1:-} 34 MOUNTER_PATH=/home/kubernetes/flexvolume_mounter 35 VOLUME_PLUGIN_DIR=/home/kubernetes/flexvolume 36 37 usage() { 38 echo "usage: $0 imagename[:tag]" 39 echo " imagename Name of a Container Registry image. By default the latest image is used." 40 echo " :tag Container Registry image tag." 41 exit 1 42 } 43 44 if [ -z "${MOUNTER_IMAGE}" ]; then 45 echo "ERROR: No Container Registry mounter image is specified." 46 echo 47 usage 48 fi 49 50 # Unmounts a mount point lazily. If a mount point does not exist, continue silently, 51 # and without error. 52 umount_silent() { 53 umount -l "$1" &> /dev/null || /bin/true 54 } 55 56 # Waits for kubelet to restart for 1 minute. 57 kubelet_wait() { 58 timeout=60 59 healthz_port=10248 60 until [[ $timeout -eq 0 ]]; do 61 printf "." 62 if [[ $( curl -s http://localhost:${healthz_port}/healthz ) == "ok" ]]; then 63 return 0 64 fi 65 sleep 1 66 timeout=$(( timeout-1 )) 67 done 68 69 # Timed out waiting for kubelet to become healthy. 70 return 1 71 } 72 73 flex_clean() { 74 echo 75 echo "An error has occurred. Cleaning up..." 76 echo 77 78 umount_silent ${VOLUME_PLUGIN_DIR} 79 rm -rf ${VOLUME_PLUGIN_DIR} 80 umount_silent ${MOUNTER_PATH}/var/lib/kubelet 81 umount_silent ${MOUNTER_PATH} 82 rm -rf ${MOUNTER_PATH} 83 84 if [[ -n ${IMAGE_URL:-} ]]; then 85 docker rmi -f "${IMAGE_URL}" &> /dev/null || /bin/true 86 fi 87 if [[ -n ${MOUNTER_DEFAULT_NAME:-} ]]; then 88 docker rm -f "${MOUNTER_DEFAULT_NAME}" &> /dev/null || /bin/true 89 fi 90 } 91 92 trap flex_clean ERR 93 94 # Generates a bash script that wraps all calls to the actual driver inside mount utilities 95 # in the chroot environment. Kubelet sees this script as the FlexVolume driver. 96 generate_chroot_wrapper() { 97 if [ ! -d ${MOUNTER_PATH}/flexvolume ]; then 98 echo "Failed to set up FlexVolume driver: cannot find directory '/flexvolume' in the mount utility image." 99 exit 1 100 fi 101 102 for driver_dir in "${MOUNTER_PATH}/flexvolume"/*; do 103 if [ -d "$driver_dir" ]; then 104 105 filecount=$(cd "$driver_dir"; find . -mindepth 1 -maxdepth 1 -print0 | xargs -0 -n1 basename | wc -l) 106 if [ "$filecount" -gt 1 ]; then 107 echo "ERROR: Expected 1 file in the FlexVolume directory but found $filecount." 108 exit 1 109 fi 110 111 driver_file=$(cd "$driver_dir"; find . -mindepth 1 -maxdepth 1 -print0 | xargs -0 -n1 basename | head -n 1) 112 113 # driver_path points to the actual driver inside the mount utility image, 114 # relative to image root. 115 # wrapper_path is the wrapper script location, which is known to kubelet. 116 driver_path=flexvolume/$( basename "$driver_dir" )/${driver_file} 117 wrapper_dir=${VOLUME_PLUGIN_DIR}/$( basename "$driver_dir" ) 118 wrapper_path=${wrapper_dir}/${driver_file} 119 120 mkdir -p "$wrapper_dir" 121 cat >"$wrapper_path" <<EOF 122 #!/usr/bin/env bash 123 chroot ${MOUNTER_PATH} ${driver_path} "\$@" 124 EOF 125 126 chmod 755 "$wrapper_path" 127 echo "FlexVolume driver installed at ${wrapper_path}" 128 fi 129 done 130 } 131 132 echo 133 echo "Importing mount utility image from Container Registry..." 134 echo 135 136 METADATA=http://metadata.google.internal/computeMetadata/v1 137 SVC_ACCT_ENDPOINT=$METADATA/instance/service-accounts/default 138 ACCESS_TOKEN=$(curl -s -H 'Metadata-Flavor: Google' $SVC_ACCT_ENDPOINT/token | cut -d'"' -f 4) 139 PROJECT_ID=$(curl -s -H 'Metadata-Flavor: Google' $METADATA/project/project-id) 140 IMAGE_URL=gcr.io/${PROJECT_ID}/${MOUNTER_IMAGE} 141 MOUNTER_DEFAULT_NAME=flexvolume_mounter 142 sudo -u "${SUDO_USER}" docker login -u _token -p "$ACCESS_TOKEN" https://gcr.io > /dev/null 143 sudo -u "${SUDO_USER}" docker run --name=${MOUNTER_DEFAULT_NAME} "${IMAGE_URL}" 144 docker export ${MOUNTER_DEFAULT_NAME} > /tmp/${MOUNTER_DEFAULT_NAME}.tar 145 docker rm ${MOUNTER_DEFAULT_NAME} > /dev/null 146 docker rmi "${IMAGE_URL}" > /dev/null 147 148 echo 149 echo "Loading mount utilities onto this instance..." 150 echo 151 152 mkdir -p ${MOUNTER_PATH} 153 tar xf /tmp/${MOUNTER_DEFAULT_NAME}.tar -C ${MOUNTER_PATH} 154 155 # Bind the kubelet directory to one under flexvolume_mounter 156 mkdir -p ${MOUNTER_PATH}/var/lib/kubelet 157 mount --rbind /var/lib/kubelet/ ${MOUNTER_PATH}/var/lib/kubelet 158 mount --make-rshared ${MOUNTER_PATH}/var/lib/kubelet 159 160 # Remount the flexvolume_mounter environment with /dev enabled. 161 mount --bind ${MOUNTER_PATH} ${MOUNTER_PATH} 162 mount -o remount,dev,exec ${MOUNTER_PATH} 163 164 echo 165 echo "Setting up FlexVolume driver..." 166 echo 167 168 mkdir -p ${VOLUME_PLUGIN_DIR} 169 mount --bind ${VOLUME_PLUGIN_DIR} ${VOLUME_PLUGIN_DIR} 170 mount -o remount,exec ${VOLUME_PLUGIN_DIR} 171 generate_chroot_wrapper 172 173 echo 174 echo "Restarting Kubelet..." 175 echo 176 177 systemctl restart kubelet.service 178 if kubelet_wait; then 179 echo 180 echo "FlexVolume is ready." 181 else 182 echo "ERROR: Timed out after 1 minute waiting for kubelet restart." 183 fi