github.com/kubernetes-incubator/kube-aws@v0.16.4/contrib/cluster-backup/restore.sh (about) 1 #!/bin/bash 2 set -ue 3 4 err() { 5 (>&2 echo "${1} Exiting.") 6 exit 1 7 } 8 9 main_help() { 10 cat >&2 <<EOF 11 Usage: BUCKET_URI [ NAMESPACE1 NAMESPACE2 ... ] 12 13 Arguments: 14 BUCKET_URI The S3 uri of the timestamped backup bucket. Example: 's3://bucket-name/cf/cluster-name/clusterBackup/2017-04-07_09-03-11' 15 [ NAMESPACE1 NAMESPACE2 ... ] (Optional) Namespaces to create. Example: 'alpha beta' 16 17 Description: 18 Import Kubernetes resources to a cluster from a previous clusterBackup in S3. 19 All namespaces (and associated resources) are restored by default with the exception of namespaces: 'kube-system' and 'default'. 20 To whitelist namespaces, include the desired namespace names as additional arguments after the BUCKET_URI argument. 21 22 Please monitor the restoration process to ensure the Kubernetes resources restored correctly. 23 24 Assumptions: 25 - 'kubectl' installed locally 26 - 'aws' installed locally 27 - 'jq' installed locally 28 - 'kubeconfig' configured correctly 29 - 'jq' configured correctly 30 - cluster is reachable 31 32 EOF 33 34 exit 0 35 } 36 37 defaultCreate () { kubectl create -f ${1} || : ;} 38 39 createResource() { 40 RESOURCE="${1}" 41 NAMESPACE="" 42 FILEPATH="${TEMP_DIR}/${RESOURCE}.json" 43 if [[ ! -z ${2:-} ]] ; then 44 NAMESPACE="${2}" 45 FILEPATH="${TEMP_DIR}/${NAMESPACE}/${RESOURCE}.json" 46 fi 47 if [[ -s "${FILEPATH}" ]] ; then 48 createFunc=${RESOURCE}Create 49 type -t $createFunc >/dev/null || createFunc=defaultCreate 50 $createFunc "${FILEPATH}" "${NAMESPACE}" 51 fi 52 } 53 54 doesResourceExist() { 55 TYPE="${1}" 56 NAME="${2}" 57 if kubectl get ${TYPE} ${NAME} >&/dev/null ; then 58 return 1 59 fi 60 return 0 61 } 62 63 preFlightChecks() { 64 [[ "${1}" != "--help" ]] || main_help 65 which kubectl >/dev/null || err "'kubectl' not found." 66 which aws >/dev/null || err "'aws' not found." 67 which jq >/dev/null || err "'jq' not found." 68 [[ "${1}" == s3://* ]] || err "Invalid S3 bucket URL syntax - expecting \"s3://*\"." 69 aws s3 ls ${1} >/dev/null || err "Cannot not validate the S3 bucket \"${1}\"." 70 kubectl get nodes >/dev/null || err "Cannot establish kubectl connection." 71 } 72 73 ## Custom functions - For resources that require more than just 'kubectl create' 74 persistentvolumeclaimsCreate() { # PersistentVolumeClaims should be status=Bound before creating resources that may use them 75 FILEPATH="${1}"; 76 NAMESPACE="${2}"; 77 kubectl create -f ${FILEPATH} || : 78 79 # Validate bound status 80 SUCCESS=0 81 for i in {1..5} ; do 82 BOUND=1 83 kubectl get pvc -o json -n ${NAMESPACE} | jq -r '.items[].status.phase' \ 84 | grep -qv Bound || { SUCCESS=1; break; } 85 sleep 1 86 done 87 if [ "${SUCCESS}" != 1 ] ; then 88 echo "WARNING: PersistentVolumeClaims failed to achieve 'status=Bound': '$(kubectl describe pvc -n ${NAMESPACE})'" 89 fi 90 } 91 92 main() { 93 # Define the resources to restore in order. 94 RESTORATION_ORDER=( storageclasses persistentvolumes ) # clusterrolebindings clusterroles 95 RESTORATION_ORDER_NS=( persistentvolumeclaims configmaps endpoints ingresses jobs limitranges networkpolicies 96 podsecuritypolicies podtemplates resourcequotas secrets serviceaccounts services thirdpartyresources 97 horizontalpodautoscalers pods replicasets replicationcontrollers daemonsets deployments statefulsets 98 poddisruptionbudgets roles rolebindings) 99 100 preFlightChecks "${@}" 101 AWS_BUCKET="${1}"; shift 102 103 echo "Downloading S3 bucket..." 104 aws s3 sync ${AWS_BUCKET} ${TEMP_DIR} >/dev/null || err "Could not retrieve the backup bucket from aws!" 105 106 if [ ! -f ${TEMP_DIR}/namespaces.json ]; then 107 err "Could not find a namespaces.json file - are you sure a valid back-up bucket exists?" 108 fi 109 110 # Compile a list of namespaces to create/populate 111 echo "Evaluating namespaces..." 112 NAMESPACE_WHITELIST="${@:-}" 113 NAMESPACES="" 114 if [ -z ${NAMESPACE_WHITELIST} ]; then 115 for ns in $(jq -r '.items[].metadata.name' < ${TEMP_DIR}/namespaces.json); do 116 if [[ ${ns} != "kube-system" && ${ns} != "default" ]] ; then 117 doesResourceExist "namespace" "${ns}" || err "Namespace '${ns}' already exists in the cluster!" 118 NAMESPACES="${NAMESPACES} ${ns}" 119 fi 120 done 121 else 122 echo "Limiting Namespaces to '${NAMESPACE_WHITELIST}'..." 123 for nswl in ${NAMESPACE_WHITELIST}; do 124 for ns in $(jq -r '.items[].metadata.name' < ${TEMP_DIR}/namespaces.json); do 125 if [ "${ns}" == "${nswl}" ] ; then 126 doesResourceExist "namespace" "${ns}" || echo "Namespace '${ns}' already exists in the cluster! Restoration will still proceed..." 127 NAMESPACES="${NAMESPACES} ${ns}" 128 break 129 fi 130 done 131 done 132 fi 133 134 echo "Restoring resources that are not within a Namespace..." 135 # Create the Kubernetes resources that reside outside of namespaces 136 for r in ${RESTORATION_ORDER[@]}; do 137 createResource "${r}" 138 done 139 140 # Iterate through namespaces and create the Kubernetes resources that reside inside of namespaces 141 for ns in ${NAMESPACES}; do 142 if [ -e "${TEMP_DIR}/${ns}" ] && [ -d "${TEMP_DIR}/${ns}" ]; then 143 echo "Restoring resources for '${ns}' Namespace..." 144 kubectl create -f <(echo $(cat ${TEMP_DIR}/namespaces.json | jq -r --arg NS "$ns" '.items[] | select(.metadata.name == ($NS))')) 145 for r in ${RESTORATION_ORDER_NS[@]}; do 146 createResource "${r}" "${ns}" 147 done 148 else 149 echo "Could not find a backup directory for namespace '${ns}'" 150 fi 151 done 152 153 echo "Restoration finished." 154 } 155 156 157 ### START ### 158 159 TEMP_DIR=$(mktemp -d) 160 trap "rm -f -r ${TEMP_DIR}" EXIT 161 162 main "${@:-}" 163