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