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