github.com/felipejfc/helm@v2.1.2+incompatible/scripts/local-cluster.sh (about)

     1  #!/usr/bin/env bash
     2  
     3  # Copyright 2016 The Kubernetes Authors All rights reserved.
     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  # Bash 'Strict Mode'
    18  # http://redsymbol.net/articles/unofficial-bash-strict-mode
    19  set -euo pipefail
    20  IFS=$'\n\t'
    21  
    22  HELM_ROOT="${BASH_SOURCE[0]%/*}/.."
    23  cd "$HELM_ROOT"
    24  
    25  # Globals ----------------------------------------------------------------------
    26  
    27  KUBE_VERSION=${KUBE_VERSION:-}
    28  KUBE_PORT=${KUBE_PORT:-8080}
    29  KUBE_CONTEXT=${KUBE_CONTEXT:-docker}
    30  KUBECTL=${KUBECTL:-kubectl}
    31  ENABLE_CLUSTER_DNS=${KUBE_ENABLE_CLUSTER_DNS:-true}
    32  LOG_LEVEL=${LOG_LEVEL:-2}
    33  
    34  # Helper Functions -------------------------------------------------------------
    35  
    36  # Display error message and exit
    37  error_exit() {
    38    echo "error: ${1:-"unknown error"}" 1>&2
    39    exit 1
    40  }
    41  
    42  # Checks if a command exists.  Returns 1 or 0
    43  command_exists() {
    44    hash "${1}" 2>/dev/null
    45  }
    46  
    47  # fetch url using wget or curl and print to stdout
    48  fetch_url() {
    49    local url="$1"
    50    if command_exists wget; then
    51      curl -sSL "$url"
    52    elif command_exists curl; then
    53      wget -qO- "$url"
    54    else
    55      error_exit "Couldn't find curl or wget.  Bailing out."
    56    fi
    57  }
    58  
    59  # Program Functions ------------------------------------------------------------
    60  
    61  # Check host platform and docker host
    62  verify_prereqs() {
    63    echo "Verifying Prerequisites...."
    64  
    65    case "$(uname -s)" in
    66      Darwin)
    67        host_os=darwin
    68        ;;
    69      Linux)
    70        host_os=linux
    71        ;;
    72      *)
    73        error_exit "Unsupported host OS.  Must be Linux or Mac OS X."
    74        ;;
    75    esac
    76  
    77    case "$(uname -m)" in
    78      x86_64*)
    79        host_arch=amd64
    80        ;;
    81      i?86_64*)
    82        host_arch=amd64
    83        ;;
    84      amd64*)
    85        host_arch=amd64
    86        ;;
    87      arm*)
    88        host_arch=arm
    89        ;;
    90      i?86*)
    91        host_arch=x86
    92        ;;
    93      s390x*)
    94        host_arch=s390x
    95        ;;
    96      ppc64le*)
    97        host_arch=ppc64le
    98        ;;
    99      *)
   100        error_exit "Unsupported host arch. Must be x86_64, 386, arm, s390x or ppc64le."
   101        ;;
   102    esac
   103  
   104  
   105    command_exists docker || error_exit "You need docker"
   106  
   107    if ! docker info >/dev/null 2>&1 ; then
   108      error_exit "Can't connect to 'docker' daemon."
   109    fi
   110  
   111    if docker inspect kubelet >/dev/null 2>&1 ; then
   112      error_exit "Kubernetes is already running"
   113    fi
   114  
   115    $KUBECTL version --client >/dev/null || download_kubectl
   116  }
   117  
   118  # Get the latest stable release tag
   119  get_latest_version_number() {
   120    local channel="stable"
   121    if [[ -n "${ALPHA:-}" ]]; then
   122      channel="latest"
   123    fi
   124    local latest_url="https://storage.googleapis.com/kubernetes-release/release/${channel}.txt"
   125    fetch_url "$latest_url"
   126  }
   127  
   128  # Detect ip address od docker host
   129  detect_docker_host_ip() {
   130    if [[ -n "${DOCKER_HOST:-}" ]]; then
   131      awk -F'[/:]' '{print $4}' <<< "$DOCKER_HOST"
   132    else
   133      ifconfig docker0 \
   134        | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' \
   135        | grep -Eo '([0-9]*\.){3}[0-9]*' >/dev/null 2>&1 || :
   136    fi
   137  }
   138  
   139  # Set KUBE_MASTER_IP from docker host ip.  Defaults to localhost
   140  set_master_ip() {
   141    local docker_ip
   142  
   143    if [[ -z "${KUBE_MASTER_IP:-}" ]]; then
   144      docker_ip=$(detect_docker_host_ip)
   145      if [[ -n "${docker_ip}" ]]; then
   146        KUBE_MASTER_IP="${docker_ip}"
   147      else
   148        KUBE_MASTER_IP=localhost
   149      fi
   150    fi
   151  }
   152  
   153  # Start dockerized kubelet
   154  start_kubernetes() {
   155    echo "Starting kubelet"
   156  
   157    # Enable dns
   158    if [[ "${ENABLE_CLUSTER_DNS}" = true ]]; then
   159      dns_args="--cluster-dns=10.0.0.10 --cluster-domain=cluster.local"
   160    else
   161      # DNS server for real world hostnames.
   162      dns_args="--cluster-dns=8.8.8.8"
   163    fi
   164  
   165    local start_time=$(date +%s)
   166  
   167    docker run \
   168      --name=kubelet \
   169      --volume=/:/rootfs:ro \
   170      --volume=/sys:/sys:ro \
   171      --volume=/var/lib/docker/:/var/lib/docker:rw \
   172      --volume=/var/lib/kubelet/:/var/lib/kubelet:rw,rslave \
   173      --volume=/var/run:/var/run:rw \
   174      --net=host \
   175      --pid=host \
   176      --privileged=true \
   177      -d \
   178      gcr.io/google_containers/hyperkube-amd64:${KUBE_VERSION} \
   179        /hyperkube kubelet \
   180          --containerized \
   181          --hostname-override="127.0.0.1" \
   182          --api-servers=http://localhost:${KUBE_PORT} \
   183          --config=/etc/kubernetes/manifests \
   184          --allow-privileged=true \
   185          ${dns_args} \
   186          --v=${LOG_LEVEL} >/dev/null
   187  
   188    until $KUBECTL cluster-info &> /dev/null; do
   189      sleep 1
   190    done
   191  
   192    if [[ $KUBE_VERSION == "1.2"* ]]; then
   193      create_kube_system_namespace
   194      create_kube_dns
   195    fi
   196  
   197    # We expect to have at least 3 running pods - etcd, master and kube-proxy.
   198    local attempt=1
   199    while (($(KUBECTL get pods --all-namespaces --no-headers 2>/dev/null | grep -c "Running") < 3)); do
   200      echo -n "."
   201      sleep $(( attempt++ ))
   202    done
   203    echo
   204  
   205    echo "Started master components in $(($(date +%s) - start_time)) seconds."
   206  }
   207  
   208  # Open kubernetes master api port.
   209  setup_firewall() {
   210    [[ -n "${DOCKER_MACHINE_NAME:-}" ]] || return
   211  
   212    echo "Adding iptables hackery for docker-machine..."
   213  
   214    local machine_ip
   215    machine_ip=$(docker-machine ip "$DOCKER_MACHINE_NAME")
   216    local iptables_rule="PREROUTING -p tcp -d ${machine_ip} --dport ${KUBE_PORT} -j DNAT --to-destination 127.0.0.1:${KUBE_PORT}"
   217  
   218    if ! docker-machine ssh "${DOCKER_MACHINE_NAME}" "sudo /usr/local/sbin/iptables -t nat -C ${iptables_rule}" &> /dev/null; then
   219      docker-machine ssh "${DOCKER_MACHINE_NAME}" "sudo /usr/local/sbin/iptables -t nat -I ${iptables_rule}"
   220    fi
   221  }
   222  
   223  # Create kube-system namespace in kubernetes
   224  create_kube_system_namespace() {
   225    $KUBECTL create namespace kube-system >/dev/null
   226  }
   227  
   228  # Activate skydns in kubernetes and wait for pods to be ready.
   229  create_kube_dns() {
   230    [[ "${ENABLE_CLUSTER_DNS}" = true ]] || return
   231  
   232    local start_time=$(date +%s)
   233  
   234    echo "Setting up cluster dns..."
   235  
   236    $KUBECTL create -f ./scripts/cluster/skydns.yaml >/dev/null
   237  
   238    echo "Waiting for cluster DNS to become available..."
   239  
   240    local attempt=1
   241    until $KUBECTL get pods --no-headers --namespace kube-system --selector=k8s-app=kube-dns 2>/dev/null | grep "Running" &>/dev/null; do
   242      echo -n "."
   243      sleep $(( attempt++ ))
   244    done
   245    echo
   246    echo "Started DNS in $(($(date +%s) - start_time)) seconds."
   247  }
   248  
   249  # Generate kubeconfig data for the created cluster.
   250  generate_kubeconfig() {
   251    local cluster_args=(
   252        "--server=http://${KUBE_MASTER_IP}:${KUBE_PORT}"
   253        "--insecure-skip-tls-verify=true"
   254    )
   255  
   256    $KUBECTL config set-cluster "${KUBE_CONTEXT}" "${cluster_args[@]}" >/dev/null
   257    $KUBECTL config set-context "${KUBE_CONTEXT}" --cluster="${KUBE_CONTEXT}" >/dev/null
   258    $KUBECTL config use-context "${KUBE_CONTEXT}" >/dev/null
   259  
   260    echo "Wrote config for kubeconfig using context: '${KUBE_CONTEXT}'"
   261  }
   262  
   263  # Download kubectl
   264  download_kubectl() {
   265    echo "Downloading kubectl binary..."
   266  
   267    local output="/usr/local/bin/kubectl"
   268  
   269    kubectl_url="https://storage.googleapis.com/kubernetes-release/release/${KUBE_VERSION}/bin/${host_os}/${host_arch}/kubectl"
   270    fetch_url "${kubectl_url}" > "${output}"
   271    chmod a+x "${output}"
   272  
   273    KUBECTL="${output}"
   274  }
   275  
   276  # Clean volumes that are left by kubelet
   277  #
   278  # https://github.com/kubernetes/kubernetes/issues/23197
   279  # code stolen from https://github.com/huggsboson/docker-compose-kubernetes/blob/SwitchToSharedMount/kube-up.sh
   280  clean_volumes() {
   281    if [[ -n "${DOCKER_MACHINE_NAME}" ]]; then
   282      docker-machine ssh "${DOCKER_MACHINE_NAME}" "mount | grep -o 'on /var/lib/kubelet.* type' | cut -c 4- | rev | cut -c 6- | rev | sort -r | xargs --no-run-if-empty sudo umount"
   283      docker-machine ssh "${DOCKER_MACHINE_NAME}" "sudo rm -Rf /var/lib/kubelet"
   284      docker-machine ssh "${DOCKER_MACHINE_NAME}" "sudo mkdir -p /var/lib/kubelet"
   285      docker-machine ssh "${DOCKER_MACHINE_NAME}" "sudo mount --bind /var/lib/kubelet /var/lib/kubelet"
   286      docker-machine ssh "${DOCKER_MACHINE_NAME}" "sudo mount --make-shared /var/lib/kubelet"
   287    else
   288      mount | grep -o 'on /var/lib/kubelet.* type' | cut -c 4- | rev | cut -c 6- | rev | sort -r | xargs --no-run-if-empty sudo umount
   289      sudo rm -Rf /var/lib/kubelet
   290      sudo mkdir -p /var/lib/kubelet
   291      sudo mount --bind /var/lib/kubelet /var/lib/kubelet
   292      sudo mount --make-shared /var/lib/kubelet
   293    fi
   294  }
   295  
   296  # Helper function to properly remove containers
   297  delete_container() {
   298    local container=("$@")
   299    docker stop "${container[@]}" &>/dev/null || :
   300    docker wait "${container[@]}" &>/dev/null || :
   301    docker rm --force --volumes "${container[@]}" &>/dev/null || :
   302  }
   303  
   304  # Delete master components and resources in kubernetes.
   305  kube_down() {
   306    echo "Deleting all resources in kubernetes..."
   307    $KUBECTL delete replicationcontrollers,services,pods,secrets --all >/dev/null 2>&1 || :
   308    $KUBECTL delete replicationcontrollers,services,pods,secrets --all --namespace=kube-system >/dev/null 2>&1 || :
   309    $KUBECTL delete namespace kube-system >/dev/null 2>&1 || :
   310  
   311    echo "Stopping kubelet..."
   312    delete_container kubelet
   313  
   314    echo "Stopping remaining kubernetes containers..."
   315    local kube_containers=($(docker ps -aqf "name=k8s_"))
   316    if [[ "${#kube_containers[@]}" -gt 0 ]]; then
   317      delete_container "${kube_containers[@]}"
   318    fi
   319  }
   320  
   321  # Start a kubernetes cluster in docker.
   322  kube_up() {
   323    verify_prereqs
   324  
   325    set_master_ip
   326    clean_volumes
   327    setup_firewall
   328  
   329    generate_kubeconfig
   330    start_kubernetes
   331  
   332    $KUBECTL cluster-info
   333  }
   334  
   335  KUBE_VERSION=${KUBE_VERSION:-$(get_latest_version_number)}
   336  
   337  # Main -------------------------------------------------------------------------
   338  
   339  main() {
   340    case "$1" in
   341      up|start)
   342        kube_up
   343        ;;
   344      down|stop)
   345        kube_down
   346        ;;
   347      restart)
   348        kube_down
   349        kube_up
   350        ;;
   351      *)
   352        echo "Usage: $0 {up|down|restart}"
   353        ;;
   354    esac
   355  }
   356  
   357  main "${@:-}"
   358