github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/deploy/dev/docker/deploy_docker.sh (about)

     1  #!/bin/bash
     2  
     3  set -e
     4  
     5  DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
     6  name=$(basename "$0")
     7  
     8  usage() {
     9      echo "Usage: $name [-c=NUM] [-d=NUM] [-f=LIST] [-g] [-h] [-l] [-m] [-p=NUM] [-s] [-t=NUM] [-qs=AWS_DIR (Optional)]"
    10      echo "  -c=NUM or --cluster=NUM                 : where NUM is the number of clusters"
    11      echo "  -d=NUM or --directories=NUM             : where NUM is the number of local cache directories"
    12      echo "  -f=LIST or --filesystems=LIST           : where LIST is a comma separated list of filesystems"
    13      echo "  -h or --help                            : show usage"
    14      echo "  -l or --last                            : redeploy using the arguments from the last ais docker deployment"
    15      echo "  -m or --multi                           : use multiple networks"
    16      echo "  -p=NUM or --proxy=NUM                   : where NUM is the number of proxies"
    17      echo "  -s or --single                          : use a single network"
    18      echo "  -t=NUM or --target=NUM                  : where NUM is the number of targets"
    19      echo "  -qs=AWS_DIR or --quickstart=AWS_DIR     : deploys a quickstart version of AIS with one proxy, one targe and one local file system"
    20      echo "  -nocloud                                : to deploy AIS without any 3rd party backend provider"
    21      echo "  -grafana                                : starts Graphite and Grafana containers"
    22      echo "  -nodiskio=BOOL                          : run Dry-Run mode with disk IO is disabled (default = false)"
    23      echo "  -dryobjsize=SIZE                        : size of an object when a source is a 'fake' one."
    24      echo "                                            'g' or 'G' - GiB, 'm' or 'M' - MiB, 'k' or 'K' - KiB. Default value is '8m'"
    25      echo "Note:"
    26      echo "   -if the -f or --filesystems flag is used, the -d or --directories flag is disabled and vice-versa"
    27      echo "   -if the -a or --aws flag is used, the -g or --gcp flag is disabled and vice-versa"
    28      echo "   -if both -f and -d or -a and -g are provided, the flag that is provided last will take precedence"
    29      echo "   -if the -s or --single and -m  or --multi flag are used, then multiple networks will take precedence"
    30      echo
    31      exit 1;
    32  }
    33  
    34  is_number() {
    35      if ! [[ "$1" =~ ^[0-9]+$ ]] ; then
    36        echo "Error: '$1' is not a number"; exit 1
    37      fi
    38  }
    39  
    40  is_size() {
    41      if [ -z "$1" ]; then
    42        DRYOBJSIZE="8m"
    43      elif ! [[ "$1" =~ ^[0-9]+[g|G|m|M|k|K]$ ]] ; then
    44        echo "Error: '$1' is not a valid size"; exit 1
    45      fi
    46  }
    47  
    48  save_env() {
    49      echo "Public network: ${PUB_SUBNET}"
    50      echo "Internal control network: ${INT_CONTROL_SUBNET}"
    51      echo "Internal data network: ${INT_DATA_SUBNET}"
    52      export PUB_SUBNET=${PUB_SUBNET}
    53      export INT_CONTROL_SUBNET=${INT_CONTROL_SUBNET}
    54      export INT_DATA_SUBNET=${INT_DATA_SUBNET}
    55  
    56      echo "" > ${TMP_ENV}
    57      echo "QUICK=${QUICK}" >> ${TMP_ENV}
    58      echo "TARGET_CNT=${TARGET_CNT:-1000}" >> ${TMP_ENV}
    59      echo "AIS_BACKEND_PROVIDERS=${AIS_BACKEND_PROVIDERS-}" >> ${TMP_ENV}
    60      echo "TEST_FSPATH_COUNT=${TEST_FSPATH_COUNT}" >> ${TMP_ENV}
    61      echo "AIS_FS_PATHS=${AIS_FS_PATHS}" >> ${TMP_ENV}
    62  
    63      echo "NODISKIO=${NODISKIO-false}" >> ${TMP_ENV}
    64      echo "DRYOBJSIZE=${DRYOBJSIZE-8m}" >> ${TMP_ENV}
    65  
    66      echo "GRAPHITE_PORT=${GRAPHITE_PORT}" >> ${TMP_ENV}
    67      echo "GRAPHITE_SERVER=${GRAPHITE_SERVER}" >> ${TMP_ENV}
    68  
    69      echo "PUB_SUBNET=${PUB_SUBNET}" >> ${TMP_ENV}
    70      echo "INT_CONTROL_SUBNET=${INT_CONTROL_SUBNET}" >> ${TMP_ENV}
    71      echo "INT_DATA_SUBNET=${INT_DATA_SUBNET}" >> ${TMP_ENV}
    72      echo "HOSTNAME_LIST=${HOSTNAME_LIST}" >> ${TMP_ENV}
    73      echo "HOSTNAME_LIST_INTRA_CONTROL=${HOSTNAME_LIST_INTRA_CONTROL}" >> ${TMP_ENV}
    74      echo "HOSTNAME_LIST_INTRA_DATA=${HOSTNAME_LIST_INTRA_DATA}" >> ${TMP_ENV}
    75  }
    76  
    77  save_setup() {
    78      echo "" > ${SETUP_FILE}
    79      echo "Saving setup"
    80      echo "CLUSTER_CNT=$CLUSTER_CNT" >> ${SETUP_FILE}
    81      echo "PROXY_CNT=$PROXY_CNT" >> ${SETUP_FILE}
    82      echo "TARGET_CNT=$TARGET_CNT" >> ${SETUP_FILE}
    83      echo "NETWORK=${NETWORK}" >> ${SETUP_FILE}
    84  
    85      echo "AIS_BACKEND_PROVIDERS=$AIS_BACKEND_PROVIDERS" >> ${SETUP_FILE}
    86  
    87      echo "DRYRUN"=$DRYRUN >> ${SETUP_FILE}
    88      echo "NODISKIO"=$NODISKIO >> ${SETUP_FILE}
    89      echo "DRYOBJSIZE"=$DRYOBJSIZE >> ${SETUP_FILE}
    90  
    91      echo "FS_LIST=$FS_LIST" >> ${SETUP_FILE}
    92      echo "TEST_FSPATH_COUNT=${TEST_FSPATH_COUNT}" >> ${SETUP_FILE}
    93      echo "AIS_FS_PATHS=$AIS_FS_PATHS" >> ${SETUP_FILE}
    94  
    95      echo "PRIMARY_HOST_IP=${PRIMARY_HOST_IP}" >> ${SETUP_FILE}
    96      echo "NEXT_TIER_HOST_IP=${NEXT_TIER_HOST_IP}" >> ${SETUP_FILE}
    97  
    98      echo "PORT=$PORT" >> ${SETUP_FILE}
    99      echo "PORT_INTRA_CONTROL=$PORT_INTRA_CONTROL" >> ${SETUP_FILE}
   100      echo "PORT_INTRA_DATA=$PORT_INTRA_DATA" >> ${SETUP_FILE}
   101      echo "Finished saving setup"
   102  }
   103  
   104  get_setup() {
   105      if [ -f $"${SETUP_FILE}" ]; then
   106          source ${SETUP_FILE}
   107      else
   108          echo "No setup configuration found for your last docker deployment. Exiting..."
   109          exit 1
   110      fi
   111  }
   112  
   113  deploy_mode() {
   114      if $NODISKIO; then
   115          echo "Deployed in no disk IO mode with ${DRYOBJSIZE} fake object size."
   116      else
   117          echo "Deployed in normal mode."
   118      fi
   119  }
   120  
   121  deploy_quickstart() {
   122      cp $DIR/../local/aisnode_config.sh aisnode_config.sh
   123      cp $DIR/../../conf/limits.conf limits.conf
   124  
   125      QS_AWSDIR=${1:-'~/.aws/'}
   126      QS_AWSDIR="${QS_AWSDIR/#\~/$HOME}"
   127      if docker ps | grep ais-quickstart > /dev/null 2>&1; then
   128          echo "Terminating old instance of quickstart cluster ..."
   129          ./stop_docker.sh -qs
   130      fi
   131      echo "Building Docker image ..."
   132      docker build -q -t ais-quickstart --build-arg GOBASE=/go --build-arg QUICK=quick .
   133      if [ ! -d "$QS_AWSDIR" ]; then
   134          echo "AWS credentials not found (tests may not work!) ..."
   135          docker run -di  --entrypoint=/bin/bash ais-quickstart:latest
   136      else
   137          echo "AWS credentials found (${QS_AWSDIR}), continuing ..."
   138          docker run -di --entrypoint=/bin/bash -v ${QS_AWSDIR}credentials:/root/.aws/credentials -v ${QS_AWSDIR}config:/root/.aws/config ais-quickstart:latest
   139      fi
   140  
   141      echo "SSH into container ..."
   142      container_id=$(docker ps | grep ais-quickstart | awk '{ print $1 }')
   143      docker exec -it $container_id /bin/bash -c "echo 'Hello from AIS!'; /bin/bash;"
   144  
   145      rm -rf aisnode_config.sh
   146      rm -rf limits.conf
   147  }
   148  
   149  
   150  if ! [ -x "$(command -v docker-compose)" ]; then
   151    echo 'Error: docker-compose is not installed.' >&2
   152    exit 1
   153  fi
   154  
   155  AIS_BACKEND_PROVIDERS=""
   156  CLUSTER_CNT=0
   157  PROXY_CNT=0
   158  TARGET_CNT=0
   159  FS_LIST=""
   160  TEST_FSPATH_COUNT=1
   161  NETWORK=""
   162  AWS_ENV=""
   163  
   164  mkdir -p /tmp/docker_ais
   165  LOCAL_AWS="/tmp/docker_ais/aws.env"
   166  SETUP_FILE="/tmp/docker_ais/deploy.env"
   167  TMP_ENV="/tmp/docker_ais/tmp.env"
   168  touch ${TMP_ENV}
   169  
   170  GRAFANA=false
   171  
   172  # Indicate which dry-run mode the cluster is running on
   173  DRYRUN=0
   174  NODISKIO=false
   175  DRYOBJSIZE="8m"
   176  
   177  source ../utils.sh
   178  
   179  for i in "$@"
   180  do
   181  case $i in
   182      -c=*|--cluster=*)
   183          CLUSTER_CNT="${i#*=}"
   184          is_number $CLUSTER_CNT
   185          NETWORK="multi"
   186          shift # past argument=value
   187          ;;
   188  
   189      -d=*|--directories=*)
   190          TEST_FSPATH_COUNT="${i#*=}"
   191          is_number $TEST_FSPATH_COUNT
   192          FS_LIST=""
   193          shift # past argument=value
   194          ;;
   195  
   196      -f=*|--filesystems=*)
   197          FS_LIST="${i#*=}"
   198          TEST_FSPATH_COUNT=0
   199          shift # past argument=value
   200          ;;
   201  
   202      -h|--help)
   203          usage
   204          shift # past argument
   205          ;;
   206  
   207      -l|--last)
   208          get_setup
   209          break
   210          shift # past argument
   211          ;;
   212  
   213      -m|--multi)
   214          NETWORK="multi"
   215          shift # past argument
   216          ;;
   217  
   218      -p=*|--proxy=*)
   219          PROXY_CNT="${i#*=}"
   220          is_number $PROXY_CNT
   221          shift # past argument=value
   222          ;;
   223  
   224      -qs=*|--quickstart=*|-qs|--quickstart)
   225          deploy_quickstart "${i#*=}"
   226          exit 1
   227          ;;
   228  
   229      -s|--single)
   230          if [ "${NETWORK}" != "multi" ]; then
   231              NETWORK="single"
   232          fi
   233          shift # past argument=value
   234          ;;
   235  
   236      -t=*|--target=*)
   237          TARGET_CNT="${i#*=}"
   238          is_number $TARGET_CNT
   239          shift # past argument=value
   240          ;;
   241  
   242      -grafana)
   243          GRAFANA=true
   244          shift # past argument
   245          ;;
   246  
   247      -nodiskio=*|--nodiskio=*)
   248          export NODISKIO="${i#*=}"
   249          if $NODISKIO; then
   250              DRYRUN=1
   251          fi
   252          shift # past argument=value
   253          ;;
   254  
   255      -dryobjsize=*|--dryobjsize=*)
   256          DRYOBJSIZE="${i#*=}"
   257          is_size $DRYOBJSIZE
   258          shift # past argument=value
   259          ;;
   260  
   261      *)
   262          usage
   263          ;;
   264  esac
   265  done
   266  
   267  
   268  if [ $DRYRUN -ne 0 ]; then
   269      echo "Configure Dry Run object size (default is '8m' - 8 megabytes):"
   270      echo "Note: 'g' or 'G' - GiB, 'm' or 'M' - MiB, 'k' or 'K' - KiB"
   271      echo "No input will result in using the default size"
   272      read DRYOBJSIZE
   273      is_size $DRYOBJSIZE
   274  fi
   275  
   276  parse_backend_providers
   277  
   278  touch $LOCAL_AWS
   279  echo "Configured backend providers: '${AIS_BACKEND_PROVIDERS}'"
   280  if [[ "${AIS_BACKEND_PROVIDERS}" == *aws* ]]; then
   281      echo "Enter the location of your AWS configuration and credentials files:"
   282      echo "Note: No input will result in using the default aws dir (~/.aws/)"
   283      read AWS_ENV
   284  
   285      if [[ -z ${aws_env} ]]; then
   286          AWS_ENV="${HOME}/.aws/"
   287      fi
   288  
   289      AWS_ENV="${AWS_ENV/#\~/$HOME}"
   290      temp_file="${AWS_ENV}/credentials"
   291      has_reg=0
   292      if [[ -f ${temp_file} ]]; then
   293          cp ${temp_file} ${LOCAL_AWS}
   294          has_reg=$(cat ${temp_file} | grep -c "region")
   295      else
   296          echo "No AWS credentials file found in specified directory. Exiting..."
   297          exit 1
   298      fi
   299  
   300      if [[ $has_reg -eq 0 ]]; then
   301          temp_file="${AWS_ENV}/config"
   302          if [[ -f ${temp_file} ]] && [[ $(cat ${temp_file} | grep -c "region") -gt 0 ]]; then
   303              grep region ${temp_file} >> ${LOCAL_AWS}
   304          else
   305              echo "No region config field found in aws directory. Exiting..."
   306              exit 1
   307          fi
   308      fi
   309  
   310      sed -i 's/\[default\]//g' ${LOCAL_AWS}
   311      sed -i 's/ = /=/g' ${LOCAL_AWS}
   312      sed -i 's/aws_access_key_id/AWS_ACCESS_KEY_ID/g' ${LOCAL_AWS}
   313      sed -i 's/aws_secret_access_key/AWS_SECRET_ACCESS_KEY/g' ${LOCAL_AWS}
   314      sed -i 's/region/AWS_REGION/g' ${LOCAL_AWS}
   315  fi
   316  
   317  if [ "$CLUSTER_CNT" -eq 0 ]; then
   318      echo Enter number of AIStore clusters:
   319      read CLUSTER_CNT
   320      is_number $CLUSTER_CNT
   321      if [ "$CLUSTER_CNT" -gt 1 ]; then
   322          NETWORK="multi"
   323      fi
   324  fi
   325  
   326  if [[ -z "${NETWORK// }" ]]; then
   327      echo "Enter 's' for single network configuration or 'm' for multi-network configuration:"
   328      read network_config
   329      if [ "$network_config" = "s" ]; then
   330          NETWORK="single"
   331      elif [ $network_config = 'm' ] ; then
   332          NETWORK="multi"
   333      else
   334          echo Valid network configuration was not supplied.
   335          usage
   336      fi
   337  fi
   338  
   339  if [ "$TARGET_CNT" -eq 0 ]; then
   340      echo Enter number of target servers:
   341      read TARGET_CNT
   342      is_number $TARGET_CNT
   343  fi
   344  
   345  if [ "$PROXY_CNT" -eq 0 ]; then
   346      echo Enter number of proxy servers:
   347      read PROXY_CNT
   348      is_number $PROXY_CNT
   349      if [ $PROXY_CNT -lt 1 ] ; then
   350        echo "Error: $PROXY_CNT is less than 1"; exit 1
   351      fi
   352  fi
   353  
   354  AIS_FS_PATHS=""
   355  if [ "$FS_LIST" = "" ] && [ "$TEST_FSPATH_COUNT" -eq 0 ]; then
   356      echo Select
   357      echo  1: Local cache directories
   358      echo  2: Filesystems
   359      echo "Enter your cache choice (1 or 2):"
   360      read cachesource
   361      is_number $cachesource
   362      if [ $cachesource -eq 1 ]; then
   363         echo Enter number of local cache directories:
   364         read TEST_FSPATH_COUNT
   365         is_number $TEST_FSPATH_COUNT
   366      elif [ $cachesource -eq 2 ]; then
   367         echo Enter filesystem info in comma separated format ex: /tmp/ais1,/tmp/ais:
   368         read FS_LIST
   369      else
   370          echo "Not a valid entry. Exiting..."
   371          exit 1
   372      fi
   373  fi
   374  
   375  if [ "$FS_LIST" != "" ] && [ "$TEST_FSPATH_COUNT" -eq 0 ]; then
   376      AIS_FS_PATHS=""
   377      IFS=',' read -r -a array <<< "$FS_LIST"
   378      for element in "${array[@]}"
   379      do
   380          AIS_FS_PATHS="$AIS_FS_PATHS,\"$element\" : {} "
   381      done
   382      AIS_FS_PATHS=${AIS_FS_PATHS#","}
   383  fi
   384  
   385  composer_file="${DIR}/docker-compose.singlenet.yml"
   386  if [ "${NETWORK}" = "multi" ]; then
   387      composer_file="${DIR}/docker-compose.singlenet.yml -f ${DIR}/docker-compose.multinet.yml"
   388  fi
   389  
   390  cp $DIR/../local/aisnode_config.sh aisnode_config.sh
   391  cp $DIR/../../conf/limits.conf limits.conf
   392  
   393  docker network create docker_default || true
   394  if [ "$GRAFANA" == true ]; then
   395      GRAPHITE_PORT=2003
   396      GRAPHITE_SERVER="graphite"
   397      docker-compose -f ${composer_file} up --build -d graphite
   398      docker-compose -f ${composer_file} up --build -d grafana
   399  else
   400      GRAPHITE_PORT=2003
   401      GRAPHITE_SERVER="localhost"
   402  fi
   403  
   404  PORT_INTRA_CONTROL=9080
   405  PORT_INTRA_DATA=10080
   406  export PORT=51080
   407  export AIS_NO_DISK_IO=${NODISKIO}
   408  export AIS_BACKEND_PROVIDERS=${AIS_BACKEND_PROVIDERS}
   409  # Setting the IP addresses for the containers
   410  echo "Network type: ${NETWORK}"
   411  for ((i=0; i<${CLUSTER_CNT}; i++)); do
   412      PUB_NET="172.5$((0 + (i * 3))).0"
   413      PUB_SUBNET="${PUB_NET}.0/24"
   414      INT_CONTROL_NET="172.5$((1 + (i * 3))).0"
   415      INT_CONTROL_SUBNET="${INT_CONTROL_NET}.0/24"
   416      INT_DATA_NET="172.5$((2 + (i * 3))).0"
   417      INT_DATA_SUBNET="${INT_DATA_NET}.0/24"
   418  
   419      if [ $i -eq 0 ]; then
   420          PRIMARY_HOST_IP="${PUB_NET}.2"
   421      fi
   422      if [ $i -eq 1 ]; then
   423          NEXT_TIER_HOST_IP="${PUB_NET}.2"
   424      fi
   425  
   426      HOSTNAME_LIST=""
   427      HOSTNAME_LIST_INTRA_CONTROL=""
   428      HOSTNAME_LIST_INTRA_DATA=""
   429  
   430      mkdir -p /tmp/ais/${i}
   431      # UID is used to ensure that volumes' folders have the same permissions as
   432      # the user who starts the script. Otherwise they would have `root` permission.
   433      export UID # (see docker compose files)
   434      export CLUSTER=${i}
   435  
   436      for j in $(seq 2 $(((TARGET_CNT + PROXY_CNT + 1) * CLUSTER_CNT))); do
   437          HOSTNAME_LIST="${HOSTNAME_LIST}${PUB_NET}.$j,"
   438      done
   439      if [ "$HOSTNAME_LIST" != "" ]; then
   440          HOSTNAME_LIST=${HOSTNAME_LIST/%?/} # remove last ","
   441      fi
   442  
   443      if [ "${NETWORK}" = "multi" ]; then
   444          # HOSTNAME_LIST_INTRA
   445          for j in $(seq 2 $(((TARGET_CNT + PROXY_CNT + 1) * CLUSTER_CNT))); do
   446              HOSTNAME_LIST_INTRA_CONTROL="${HOSTNAME_LIST_INTRA_CONTROL}${INT_CONTROL_NET}.$j,"
   447          done
   448          HOSTNAME_LIST_INTRA_CONTROL=${HOSTNAME_LIST_INTRA_CONTROL/%?/} # remove last ","
   449  
   450          # HOSTNAME_LIST_INTRA_DATA
   451          for j in $(seq 2 $(((TARGET_CNT + PROXY_CNT + 1) * CLUSTER_CNT))); do
   452              HOSTNAME_LIST_INTRA_DATA="${HOSTNAME_LIST_INTRA_DATA}${INT_DATA_NET}.$j,"
   453          done
   454          HOSTNAME_LIST_INTRA_DATA=${HOSTNAME_LIST_INTRA_DATA/%?/} # remove last ","
   455      fi
   456  
   457      save_env
   458  
   459      echo Stopping running clusters...
   460      docker-compose -p ais${i} -f ${composer_file} down
   461  
   462      echo Building Image..
   463      docker-compose -p ais${i} -f ${composer_file} build
   464  
   465      echo Starting Primary Proxy
   466      docker-compose -p ais${i} -f ${composer_file} up -d proxy
   467      sleep 2 # give primary proxy some room to breathe
   468      echo Starting cluster ..
   469      PRIMARY_IP=$(docker inspect -f "{{ .NetworkSettings.Networks.ais${i}_public.IPAddress }}" ais${i}_proxy_1)
   470      PRIMARY_IP=${PRIMARY_IP} docker-compose -p ais${i} -f ${composer_file} up -d --scale proxy=${PROXY_CNT} --scale target=$TARGET_CNT --scale grafana=0 --scale graphite=0 --no-recreate
   471  done
   472  
   473  sleep 5
   474  # Records all environment variables into ${SETUP_FILE}
   475  save_setup
   476  
   477  if [ "$CLUSTER_CNT" -gt 1 ] && [ "${NETWORK}" = "multi" ]; then
   478      echo Connecting clusters together...
   479      for container_name in $(docker ps --format "{{.Names}}"); do
   480          container_id=$(docker ps -aqf "name=${container_name}")
   481          for ((i=0; i<${CLUSTER_CNT}; i++)); do
   482              if [[ $container_name != ais${i}_* ]]; then
   483                  echo Connecting $container_name to $ais${i}_public
   484                  docker network connect ais${i}_public $container_id
   485                  if [[ $container_name == *"_target_"* ]]; then
   486                      echo Connecting $container_name to $ais${i}_internal_data
   487                      docker network connect ais${i}_internal_data $container_id
   488                  fi
   489              fi
   490          done
   491      done
   492  fi
   493  
   494  if [ "$GRAFANA" == true ]; then
   495      # Set up Graphite datasource
   496      curl -d '{"name":"Graphite","type":"graphite","url":"http://graphite:80","access":"proxy","basicAuth":false,"isDefault":true}' -H "Content-Type: application/json" -X POST http://admin:admin@localhost:3000/api/datasources > /dev/null 2>&1
   497  fi
   498  
   499  # Consider moving these to a folder instead of deleting - for future reference
   500  rm aisnode_config.sh
   501  rm limits.conf
   502  docker ps
   503  
   504  # Install the CLI
   505  cd $DIR/../../../ && make cli
   506  
   507  deploy_mode
   508  
   509  for ((i=0; i<${CLUSTER_CNT}; i++)); do
   510      PRIMARY_IP=$(docker inspect -f "{{ .NetworkSettings.Networks.ais${i}_public.IPAddress }}" ais${i}_proxy_1)
   511      echo "Cluster${i} deployed! use 'AIS_ENDPOINT=\"http://${PRIMARY_IP}:${PORT}\" ais show cluster' to view cluster info"
   512  done
   513  
   514  echo done