2014-07-14 17:50:04 +00:00
|
|
|
#!/bin/bash
|
|
|
|
|
2017-04-25 23:03:27 +00:00
|
|
|
# Copyright 2017 The Kubernetes Authors.
|
2014-07-14 17:50:04 +00:00
|
|
|
#
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
# You may obtain a copy of the License at
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
# limitations under the License.
|
|
|
|
|
|
|
|
# A library of helper functions and constant for the local config.
|
|
|
|
|
|
|
|
# Use the config file specified in $KUBE_CONFIG_FILE, or default to
|
|
|
|
# config-default.sh.
|
2014-10-03 21:58:49 +00:00
|
|
|
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
|
|
|
source "${KUBE_ROOT}/cluster/gce/${KUBE_CONFIG_FILE-"config-default.sh"}"
|
2015-03-06 22:49:25 +00:00
|
|
|
source "${KUBE_ROOT}/cluster/common.sh"
|
2017-03-11 06:18:38 +00:00
|
|
|
source "${KUBE_ROOT}/hack/lib/util.sh"
|
2014-07-14 17:50:04 +00:00
|
|
|
|
2017-04-18 18:47:23 +00:00
|
|
|
if [[ "${NODE_OS_DISTRIBUTION}" == "debian" || "${NODE_OS_DISTRIBUTION}" == "container-linux" || "${NODE_OS_DISTRIBUTION}" == "trusty" || "${NODE_OS_DISTRIBUTION}" == "gci" || "${NODE_OS_DISTRIBUTION}" == "ubuntu" ]]; then
|
2016-06-23 18:22:04 +00:00
|
|
|
source "${KUBE_ROOT}/cluster/gce/${NODE_OS_DISTRIBUTION}/node-helper.sh"
|
2016-05-19 20:24:03 +00:00
|
|
|
else
|
2016-06-23 18:22:04 +00:00
|
|
|
echo "Cannot operate on cluster using node os distro: ${NODE_OS_DISTRIBUTION}" >&2
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2017-04-18 18:47:23 +00:00
|
|
|
if [[ "${MASTER_OS_DISTRIBUTION}" == "container-linux" || "${MASTER_OS_DISTRIBUTION}" == "trusty" || "${MASTER_OS_DISTRIBUTION}" == "gci" || "${MASTER_OS_DISTRIBUTION}" == "ubuntu" ]]; then
|
2016-06-23 18:22:04 +00:00
|
|
|
source "${KUBE_ROOT}/cluster/gce/${MASTER_OS_DISTRIBUTION}/master-helper.sh"
|
|
|
|
else
|
|
|
|
echo "Cannot operate on cluster using master os distro: ${MASTER_OS_DISTRIBUTION}" >&2
|
2016-05-19 20:24:03 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2016-06-23 18:22:04 +00:00
|
|
|
if [[ "${MASTER_OS_DISTRIBUTION}" == "gci" ]]; then
|
2017-05-20 12:23:39 +00:00
|
|
|
DEFAULT_GCI_PROJECT=google-containers
|
|
|
|
if [[ "${GCI_VERSION}" == "cos"* ]]; then
|
|
|
|
DEFAULT_GCI_PROJECT=cos-cloud
|
|
|
|
fi
|
|
|
|
MASTER_IMAGE_PROJECT=${KUBE_GCE_MASTER_PROJECT:-${DEFAULT_GCI_PROJECT}}
|
|
|
|
# If the master image is not set, we use the latest GCI image.
|
|
|
|
# Otherwise, we respect whatever is set by the user.
|
|
|
|
MASTER_IMAGE=${KUBE_GCE_MASTER_IMAGE:-${GCI_VERSION}}
|
2016-07-18 21:20:45 +00:00
|
|
|
elif [[ "${MASTER_OS_DISTRIBUTION}" == "debian" ]]; then
|
2017-05-20 12:23:39 +00:00
|
|
|
MASTER_IMAGE=${KUBE_GCE_MASTER_IMAGE:-${CVM_VERSION}}
|
|
|
|
MASTER_IMAGE_PROJECT=${KUBE_GCE_MASTER_PROJECT:-google-containers}
|
2016-06-23 18:22:04 +00:00
|
|
|
fi
|
|
|
|
|
2016-09-16 01:42:08 +00:00
|
|
|
# Sets node image based on the specified os distro. Currently this function only
|
2017-04-25 23:03:27 +00:00
|
|
|
# supports gci and debian.
|
2016-09-16 01:42:08 +00:00
|
|
|
function set-node-image() {
|
2017-05-20 12:23:39 +00:00
|
|
|
if [[ "${NODE_OS_DISTRIBUTION}" == "gci" ]]; then
|
|
|
|
DEFAULT_GCI_PROJECT=google-containers
|
|
|
|
if [[ "${GCI_VERSION}" == "cos"* ]]; then
|
|
|
|
DEFAULT_GCI_PROJECT=cos-cloud
|
|
|
|
fi
|
|
|
|
|
|
|
|
# If the node image is not set, we use the latest GCI image.
|
|
|
|
# Otherwise, we respect whatever is set by the user.
|
|
|
|
NODE_IMAGE=${KUBE_GCE_NODE_IMAGE:-${GCI_VERSION}}
|
|
|
|
NODE_IMAGE_PROJECT=${KUBE_GCE_NODE_PROJECT:-${DEFAULT_GCI_PROJECT}}
|
|
|
|
elif [[ "${NODE_OS_DISTRIBUTION}" == "debian" ]]; then
|
|
|
|
NODE_IMAGE=${KUBE_GCE_NODE_IMAGE:-${CVM_VERSION}}
|
|
|
|
NODE_IMAGE_PROJECT=${KUBE_GCE_NODE_PROJECT:-google-containers}
|
|
|
|
fi
|
2016-09-16 01:42:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
set-node-image
|
2015-04-28 08:22:25 +00:00
|
|
|
|
2016-05-17 11:15:49 +00:00
|
|
|
# Verfiy cluster autoscaler configuration.
|
2016-06-07 20:10:17 +00:00
|
|
|
if [[ "${ENABLE_CLUSTER_AUTOSCALER}" == "true" ]]; then
|
2017-06-22 07:59:07 +00:00
|
|
|
if [[ -z $AUTOSCALER_MIN_NODES ]]; then
|
2016-05-17 11:15:49 +00:00
|
|
|
echo "AUTOSCALER_MIN_NODES not set."
|
|
|
|
exit 1
|
|
|
|
fi
|
2017-06-22 07:59:07 +00:00
|
|
|
if [[ -z $AUTOSCALER_MAX_NODES ]]; then
|
2016-05-17 11:15:49 +00:00
|
|
|
echo "AUTOSCALER_MAX_NODES not set."
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
2015-01-28 14:57:10 +00:00
|
|
|
NODE_INSTANCE_PREFIX="${INSTANCE_PREFIX}-minion"
|
2016-07-18 21:20:45 +00:00
|
|
|
NODE_TAGS="${NODE_TAG}"
|
2015-01-28 14:57:10 +00:00
|
|
|
|
2015-04-28 15:02:45 +00:00
|
|
|
ALLOCATE_NODE_CIDRS=true
|
2017-06-14 11:23:41 +00:00
|
|
|
PREEXISTING_NETWORK=false
|
|
|
|
PREEXISTING_NETWORK_MODE=""
|
2015-04-28 15:02:45 +00:00
|
|
|
|
2016-11-04 22:10:24 +00:00
|
|
|
KUBE_PROMPT_FOR_UPDATE=${KUBE_PROMPT_FOR_UPDATE:-"n"}
|
2015-10-07 01:51:27 +00:00
|
|
|
# How long (in seconds) to wait for cluster initialization.
|
|
|
|
KUBE_CLUSTER_INITIALIZATION_TIMEOUT=${KUBE_CLUSTER_INITIALIZATION_TIMEOUT:-300}
|
2015-03-27 20:53:26 +00:00
|
|
|
|
2016-08-02 07:08:05 +00:00
|
|
|
function join_csv() {
|
2015-05-23 04:07:09 +00:00
|
|
|
local IFS=','; echo "$*";
|
|
|
|
}
|
|
|
|
|
2016-06-23 18:22:04 +00:00
|
|
|
# This function returns the first string before the comma
|
2016-08-02 07:08:05 +00:00
|
|
|
function split_csv() {
|
2016-06-23 18:22:04 +00:00
|
|
|
echo "$*" | cut -d',' -f1
|
|
|
|
}
|
|
|
|
|
2014-09-23 22:54:27 +00:00
|
|
|
# Verify prereqs
|
2016-08-02 07:08:05 +00:00
|
|
|
function verify-prereqs() {
|
2014-10-06 20:25:27 +00:00
|
|
|
local cmd
|
2014-11-25 18:32:27 +00:00
|
|
|
for cmd in gcloud gsutil; do
|
2015-03-27 20:46:28 +00:00
|
|
|
if ! which "${cmd}" >/dev/null; then
|
2016-11-04 22:10:24 +00:00
|
|
|
local resp="n"
|
2015-03-31 21:03:18 +00:00
|
|
|
if [[ "${KUBE_PROMPT_FOR_UPDATE}" == "y" ]]; then
|
2015-03-30 17:20:29 +00:00
|
|
|
echo "Can't find ${cmd} in PATH. Do you wish to install the Google Cloud SDK? [Y/n]"
|
|
|
|
read resp
|
|
|
|
fi
|
2015-03-27 20:46:28 +00:00
|
|
|
if [[ "${resp}" != "n" && "${resp}" != "N" ]]; then
|
|
|
|
curl https://sdk.cloud.google.com | bash
|
|
|
|
fi
|
|
|
|
if ! which "${cmd}" >/dev/null; then
|
2015-10-07 18:19:32 +00:00
|
|
|
echo "Can't find ${cmd} in PATH, please fix and retry. The Google Cloud " >&2
|
|
|
|
echo "SDK can be downloaded from https://cloud.google.com/sdk/." >&2
|
2015-03-27 20:46:28 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
2015-04-02 00:23:00 +00:00
|
|
|
fi
|
2014-09-23 22:54:27 +00:00
|
|
|
done
|
2016-11-04 22:10:24 +00:00
|
|
|
update-or-verify-gcloud
|
2014-09-23 22:54:27 +00:00
|
|
|
}
|
|
|
|
|
2014-07-14 17:50:04 +00:00
|
|
|
# Use the gcloud defaults to find the project. If it is already set in the
|
|
|
|
# environment then go with that.
|
2014-09-23 22:54:27 +00:00
|
|
|
#
|
|
|
|
# Vars set:
|
|
|
|
# PROJECT
|
2015-01-15 19:21:42 +00:00
|
|
|
# PROJECT_REPORTED
|
2016-08-02 07:08:05 +00:00
|
|
|
function detect-project() {
|
2014-10-06 20:25:27 +00:00
|
|
|
if [[ -z "${PROJECT-}" ]]; then
|
2016-05-04 21:10:00 +00:00
|
|
|
PROJECT=$(gcloud config list project --format 'value(core.project)')
|
2014-07-14 17:50:04 +00:00
|
|
|
fi
|
|
|
|
|
2014-10-06 20:25:27 +00:00
|
|
|
if [[ -z "${PROJECT-}" ]]; then
|
|
|
|
echo "Could not detect Google Cloud Platform project. Set the default project using " >&2
|
|
|
|
echo "'gcloud config set project <PROJECT>'" >&2
|
2014-07-14 17:50:04 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
2015-01-15 19:21:42 +00:00
|
|
|
if [[ -z "${PROJECT_REPORTED-}" ]]; then
|
|
|
|
echo "Project: ${PROJECT}" >&2
|
|
|
|
echo "Zone: ${ZONE}" >&2
|
|
|
|
PROJECT_REPORTED=true
|
|
|
|
fi
|
2014-07-14 17:50:04 +00:00
|
|
|
}
|
|
|
|
|
2017-06-14 14:49:59 +00:00
|
|
|
# Use gsutil to get the md5 hash for a particular tar
|
|
|
|
function gsutil_get_tar_md5() {
|
|
|
|
# location_tar could be local or in the cloud
|
|
|
|
# local tar_location example ./_output/release-tars/kubernetes-server-linux-amd64.tar.gz
|
|
|
|
# cloud tar_location example gs://kubernetes-staging-PROJECT/kubernetes-devel/kubernetes-server-linux-amd64.tar.gz
|
|
|
|
local -r tar_location=$1
|
|
|
|
#parse the output and return the md5 hash
|
|
|
|
#the sed command at the end removes whitespace
|
|
|
|
local -r tar_md5=$(gsutil hash -h -m ${tar_location} 2>/dev/null | grep "Hash (md5):" | awk -F ':' '{print $2}' | sed 's/^[[:space:]]*//g')
|
|
|
|
echo "${tar_md5}"
|
|
|
|
}
|
|
|
|
|
2016-03-01 00:23:54 +00:00
|
|
|
# Copy a release tar and its accompanying hash.
|
|
|
|
function copy-to-staging() {
|
2015-05-01 17:50:18 +00:00
|
|
|
local -r staging_path=$1
|
|
|
|
local -r gs_url=$2
|
|
|
|
local -r tar=$3
|
|
|
|
local -r hash=$4
|
2017-06-01 18:06:48 +00:00
|
|
|
local -r basename_tar=$(basename ${tar})
|
|
|
|
|
|
|
|
#check whether this tar alread exists and has the same hash
|
|
|
|
#if it matches, then don't bother uploading it again
|
2017-06-13 23:12:21 +00:00
|
|
|
|
|
|
|
#remote_tar_md5 checks the remote location for the existing tarball and its md5
|
|
|
|
#staging_path example gs://kubernetes-staging-PROJECT/kubernetes-devel
|
|
|
|
#basename_tar example kubernetes-server-linux-amd64.tar.gz
|
|
|
|
local -r remote_tar_md5=$(gsutil_get_tar_md5 "${staging_path}/${basename_tar}")
|
|
|
|
if [[ -n ${remote_tar_md5} ]]; then
|
|
|
|
#local_tar_md5 checks the remote location for the existing tarball and its md5 hash
|
|
|
|
#tar example ./_output/release-tars/kubernetes-server-linux-amd64.tar.gz
|
|
|
|
local -r local_tar_md5=$(gsutil_get_tar_md5 "${tar}")
|
|
|
|
if [[ "${remote_tar_md5}" == "${local_tar_md5}" ]]; then
|
|
|
|
echo "+++ ${basename_tar} uploaded earlier, cloud and local file md5 match (md5 = ${local_tar_md5})"
|
2017-06-01 18:06:48 +00:00
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
fi
|
2015-05-01 17:50:18 +00:00
|
|
|
|
2016-03-01 00:23:54 +00:00
|
|
|
echo "${hash}" > "${tar}.sha1"
|
|
|
|
gsutil -m -q -h "Cache-Control:private, max-age=0" cp "${tar}" "${tar}.sha1" "${staging_path}"
|
|
|
|
gsutil -m acl ch -g all:R "${gs_url}" "${gs_url}.sha1" >/dev/null 2>&1
|
2017-06-01 18:06:48 +00:00
|
|
|
echo "+++ ${basename_tar} uploaded (sha1 = ${hash})"
|
2016-03-01 00:23:54 +00:00
|
|
|
}
|
|
|
|
|
2017-06-13 23:12:21 +00:00
|
|
|
|
2016-03-01 00:23:54 +00:00
|
|
|
# Given the cluster zone, return the list of regional GCS release
|
|
|
|
# bucket suffixes for the release in preference order. GCS doesn't
|
|
|
|
# give us an API for this, so we hardcode it.
|
|
|
|
#
|
|
|
|
# Assumed vars:
|
2016-03-05 00:43:08 +00:00
|
|
|
# RELEASE_REGION_FALLBACK
|
|
|
|
# REGIONAL_KUBE_ADDONS
|
2016-03-01 00:23:54 +00:00
|
|
|
# ZONE
|
|
|
|
# Vars set:
|
|
|
|
# PREFERRED_REGION
|
2016-03-05 00:43:08 +00:00
|
|
|
# KUBE_ADDON_REGISTRY
|
2016-03-01 00:23:54 +00:00
|
|
|
function set-preferred-region() {
|
|
|
|
case ${ZONE} in
|
|
|
|
asia-*)
|
|
|
|
PREFERRED_REGION=("asia" "us" "eu")
|
|
|
|
;;
|
|
|
|
europe-*)
|
|
|
|
PREFERRED_REGION=("eu" "us" "asia")
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
PREFERRED_REGION=("us" "eu" "asia")
|
|
|
|
;;
|
|
|
|
esac
|
2016-03-05 00:43:08 +00:00
|
|
|
local -r preferred="${PREFERRED_REGION[0]}"
|
2016-03-01 00:23:54 +00:00
|
|
|
|
|
|
|
if [[ "${RELEASE_REGION_FALLBACK}" != "true" ]]; then
|
2016-03-05 00:43:08 +00:00
|
|
|
PREFERRED_REGION=( "${preferred}" )
|
|
|
|
fi
|
|
|
|
|
|
|
|
# If we're using regional GCR, and we're outside the US, go to the
|
|
|
|
# regional registry. The gcr.io/google_containers registry is
|
|
|
|
# appropriate for US (for now).
|
|
|
|
if [[ "${REGIONAL_KUBE_ADDONS}" == "true" ]] && [[ "${preferred}" != "us" ]]; then
|
|
|
|
KUBE_ADDON_REGISTRY="${preferred}.gcr.io/google_containers"
|
|
|
|
else
|
|
|
|
KUBE_ADDON_REGISTRY="gcr.io/google_containers"
|
2015-05-01 17:50:18 +00:00
|
|
|
fi
|
2016-05-18 17:02:33 +00:00
|
|
|
|
|
|
|
if [[ "${ENABLE_DOCKER_REGISTRY_CACHE:-}" == "true" ]]; then
|
|
|
|
DOCKER_REGISTRY_MIRROR_URL="https://${preferred}-mirror.gcr.io"
|
|
|
|
fi
|
2015-05-01 17:50:18 +00:00
|
|
|
}
|
2014-12-09 23:37:06 +00:00
|
|
|
|
2014-09-23 22:54:27 +00:00
|
|
|
# Take the local tar files and upload them to Google Storage. They will then be
|
|
|
|
# downloaded by the master as part of the start up script for the master.
|
|
|
|
#
|
|
|
|
# Assumed vars:
|
|
|
|
# PROJECT
|
|
|
|
# SERVER_BINARY_TAR
|
|
|
|
# SALT_TAR
|
2015-12-08 22:32:23 +00:00
|
|
|
# KUBE_MANIFESTS_TAR
|
2016-03-01 00:23:54 +00:00
|
|
|
# ZONE
|
2014-09-23 22:54:27 +00:00
|
|
|
# Vars set:
|
|
|
|
# SERVER_BINARY_TAR_URL
|
2015-06-18 18:31:21 +00:00
|
|
|
# SERVER_BINARY_TAR_HASH
|
2014-09-23 22:54:27 +00:00
|
|
|
# SALT_TAR_URL
|
2015-06-18 18:31:21 +00:00
|
|
|
# SALT_TAR_HASH
|
2015-12-08 22:32:23 +00:00
|
|
|
# KUBE_MANIFESTS_TAR_URL
|
|
|
|
# KUBE_MANIFESTS_TAR_HASH
|
2014-09-23 22:54:27 +00:00
|
|
|
function upload-server-tars() {
|
|
|
|
SERVER_BINARY_TAR_URL=
|
2015-06-18 18:31:21 +00:00
|
|
|
SERVER_BINARY_TAR_HASH=
|
2014-09-23 22:54:27 +00:00
|
|
|
SALT_TAR_URL=
|
2015-06-18 18:31:21 +00:00
|
|
|
SALT_TAR_HASH=
|
2015-12-08 22:32:23 +00:00
|
|
|
KUBE_MANIFESTS_TAR_URL=
|
|
|
|
KUBE_MANIFESTS_TAR_HASH=
|
2014-09-23 22:54:27 +00:00
|
|
|
|
|
|
|
local project_hash
|
|
|
|
if which md5 > /dev/null 2>&1; then
|
|
|
|
project_hash=$(md5 -q -s "$PROJECT")
|
|
|
|
else
|
2014-11-12 07:04:01 +00:00
|
|
|
project_hash=$(echo -n "$PROJECT" | md5sum | awk '{ print $1 }')
|
2014-09-23 22:54:27 +00:00
|
|
|
fi
|
2015-05-01 17:50:18 +00:00
|
|
|
|
2015-04-09 04:51:50 +00:00
|
|
|
# This requires 1 million projects before the probability of collision is 50%
|
|
|
|
# that's probably good enough for now :P
|
|
|
|
project_hash=${project_hash:0:10}
|
2014-09-23 22:54:27 +00:00
|
|
|
|
2016-03-01 00:23:54 +00:00
|
|
|
set-preferred-region
|
2014-09-23 22:54:27 +00:00
|
|
|
|
2016-03-01 00:23:54 +00:00
|
|
|
SERVER_BINARY_TAR_HASH=$(sha1sum-file "${SERVER_BINARY_TAR}")
|
|
|
|
SALT_TAR_HASH=$(sha1sum-file "${SALT_TAR}")
|
2016-07-18 21:20:45 +00:00
|
|
|
if [[ -n "${KUBE_MANIFESTS_TAR:-}" ]]; then
|
|
|
|
KUBE_MANIFESTS_TAR_HASH=$(sha1sum-file "${KUBE_MANIFESTS_TAR}")
|
|
|
|
fi
|
2014-09-23 22:54:27 +00:00
|
|
|
|
2016-03-01 00:23:54 +00:00
|
|
|
local server_binary_tar_urls=()
|
|
|
|
local salt_tar_urls=()
|
|
|
|
local kube_manifest_tar_urls=()
|
2014-09-23 22:54:27 +00:00
|
|
|
|
2016-03-01 00:23:54 +00:00
|
|
|
for region in "${PREFERRED_REGION[@]}"; do
|
|
|
|
suffix="-${region}"
|
|
|
|
if [[ "${suffix}" == "-us" ]]; then
|
|
|
|
suffix=""
|
|
|
|
fi
|
|
|
|
local staging_bucket="gs://kubernetes-staging-${project_hash}${suffix}"
|
2015-05-01 17:50:18 +00:00
|
|
|
|
2016-03-01 00:23:54 +00:00
|
|
|
# Ensure the buckets are created
|
2016-10-19 00:32:56 +00:00
|
|
|
if ! gsutil ls "${staging_bucket}" >/dev/null; then
|
2016-03-01 00:23:54 +00:00
|
|
|
echo "Creating ${staging_bucket}"
|
|
|
|
gsutil mb -l "${region}" "${staging_bucket}"
|
|
|
|
fi
|
2014-11-08 00:16:45 +00:00
|
|
|
|
2016-03-01 00:23:54 +00:00
|
|
|
local staging_path="${staging_bucket}/${INSTANCE_PREFIX}-devel"
|
|
|
|
|
|
|
|
echo "+++ Staging server tars to Google Storage: ${staging_path}"
|
|
|
|
local server_binary_gs_url="${staging_path}/${SERVER_BINARY_TAR##*/}"
|
|
|
|
local salt_gs_url="${staging_path}/${SALT_TAR##*/}"
|
|
|
|
copy-to-staging "${staging_path}" "${server_binary_gs_url}" "${SERVER_BINARY_TAR}" "${SERVER_BINARY_TAR_HASH}"
|
|
|
|
copy-to-staging "${staging_path}" "${salt_gs_url}" "${SALT_TAR}" "${SALT_TAR_HASH}"
|
2015-12-02 19:42:23 +00:00
|
|
|
|
2015-12-08 22:32:23 +00:00
|
|
|
# Convert from gs:// URL to an https:// URL
|
2016-03-01 00:23:54 +00:00
|
|
|
server_binary_tar_urls+=("${server_binary_gs_url/gs:\/\//https://storage.googleapis.com/}")
|
|
|
|
salt_tar_urls+=("${salt_gs_url/gs:\/\//https://storage.googleapis.com/}")
|
2016-07-18 21:20:45 +00:00
|
|
|
if [[ -n "${KUBE_MANIFESTS_TAR:-}" ]]; then
|
|
|
|
local kube_manifests_gs_url="${staging_path}/${KUBE_MANIFESTS_TAR##*/}"
|
|
|
|
copy-to-staging "${staging_path}" "${kube_manifests_gs_url}" "${KUBE_MANIFESTS_TAR}" "${KUBE_MANIFESTS_TAR_HASH}"
|
|
|
|
# Convert from gs:// URL to an https:// URL
|
|
|
|
kube_manifests_tar_urls+=("${kube_manifests_gs_url/gs:\/\//https://storage.googleapis.com/}")
|
|
|
|
fi
|
2016-03-01 00:23:54 +00:00
|
|
|
done
|
|
|
|
|
2016-06-23 18:22:04 +00:00
|
|
|
SERVER_BINARY_TAR_URL=$(join_csv "${server_binary_tar_urls[@]}")
|
|
|
|
SALT_TAR_URL=$(join_csv "${salt_tar_urls[@]}")
|
2016-07-18 21:20:45 +00:00
|
|
|
if [[ -n "${KUBE_MANIFESTS_TAR:-}" ]]; then
|
|
|
|
KUBE_MANIFESTS_TAR_URL=$(join_csv "${kube_manifests_tar_urls[@]}")
|
|
|
|
fi
|
2014-09-23 22:54:27 +00:00
|
|
|
}
|
|
|
|
|
2015-01-28 14:57:10 +00:00
|
|
|
# Detect minions created in the minion group
|
2014-09-23 22:54:27 +00:00
|
|
|
#
|
|
|
|
# Assumed vars:
|
2015-01-28 14:57:10 +00:00
|
|
|
# NODE_INSTANCE_PREFIX
|
|
|
|
# Vars set:
|
2015-11-24 03:04:40 +00:00
|
|
|
# NODE_NAMES
|
2015-12-11 08:09:09 +00:00
|
|
|
# INSTANCE_GROUPS
|
2016-08-02 07:08:05 +00:00
|
|
|
function detect-node-names() {
|
2015-01-28 14:57:10 +00:00
|
|
|
detect-project
|
2015-12-11 08:09:09 +00:00
|
|
|
INSTANCE_GROUPS=()
|
2016-04-25 19:10:25 +00:00
|
|
|
INSTANCE_GROUPS+=($(gcloud compute instance-groups managed list \
|
2016-08-01 10:44:13 +00:00
|
|
|
--zones "${ZONE}" --project "${PROJECT}" \
|
2016-04-25 19:10:25 +00:00
|
|
|
--regexp "${NODE_INSTANCE_PREFIX}-.+" \
|
2017-08-28 19:24:24 +00:00
|
|
|
--format='value(name)' || true))
|
2015-12-11 08:09:09 +00:00
|
|
|
NODE_NAMES=()
|
|
|
|
if [[ -n "${INSTANCE_GROUPS[@]:-}" ]]; then
|
|
|
|
for group in "${INSTANCE_GROUPS[@]}"; do
|
|
|
|
NODE_NAMES+=($(gcloud compute instance-groups managed list-instances \
|
|
|
|
"${group}" --zone "${ZONE}" --project "${PROJECT}" \
|
2016-04-25 19:10:25 +00:00
|
|
|
--format='value(instance)'))
|
2015-12-11 08:09:09 +00:00
|
|
|
done
|
|
|
|
fi
|
2017-06-28 17:50:58 +00:00
|
|
|
# Add heapster node name to the list too (if it exists).
|
|
|
|
if [[ -n "${HEAPSTER_MACHINE_TYPE:-}" ]]; then
|
|
|
|
NODE_NAMES+=("${NODE_INSTANCE_PREFIX}-heapster")
|
|
|
|
fi
|
|
|
|
|
2016-04-27 00:41:15 +00:00
|
|
|
echo "INSTANCE_GROUPS=${INSTANCE_GROUPS[*]:-}" >&2
|
|
|
|
echo "NODE_NAMES=${NODE_NAMES[*]:-}" >&2
|
2015-01-28 14:57:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Detect the information about the minions
|
|
|
|
#
|
|
|
|
# Assumed vars:
|
2014-09-23 22:54:27 +00:00
|
|
|
# ZONE
|
|
|
|
# Vars set:
|
2015-11-24 03:04:40 +00:00
|
|
|
# NODE_NAMES
|
2015-11-24 03:00:46 +00:00
|
|
|
# KUBE_NODE_IP_ADDRESSES (array)
|
2016-08-02 07:08:05 +00:00
|
|
|
function detect-nodes() {
|
2014-12-09 23:07:54 +00:00
|
|
|
detect-project
|
2015-11-09 07:33:06 +00:00
|
|
|
detect-node-names
|
2015-11-24 03:00:46 +00:00
|
|
|
KUBE_NODE_IP_ADDRESSES=()
|
2015-11-24 03:04:40 +00:00
|
|
|
for (( i=0; i<${#NODE_NAMES[@]}; i++)); do
|
2015-12-11 08:09:09 +00:00
|
|
|
local node_ip=$(gcloud compute instances describe --project "${PROJECT}" --zone "${ZONE}" \
|
2016-05-04 19:32:13 +00:00
|
|
|
"${NODE_NAMES[$i]}" --format='value(networkInterfaces[0].accessConfigs[0].natIP)')
|
2015-12-11 08:09:09 +00:00
|
|
|
if [[ -z "${node_ip-}" ]] ; then
|
2015-11-24 03:04:40 +00:00
|
|
|
echo "Did not find ${NODE_NAMES[$i]}" >&2
|
2014-09-22 17:25:25 +00:00
|
|
|
else
|
2016-02-29 21:55:03 +00:00
|
|
|
echo "Found ${NODE_NAMES[$i]} at ${node_ip}"
|
|
|
|
KUBE_NODE_IP_ADDRESSES+=("${node_ip}")
|
2014-09-22 17:25:25 +00:00
|
|
|
fi
|
2014-07-14 17:50:04 +00:00
|
|
|
done
|
2015-11-24 03:00:46 +00:00
|
|
|
if [[ -z "${KUBE_NODE_IP_ADDRESSES-}" ]]; then
|
2014-10-06 20:25:27 +00:00
|
|
|
echo "Could not detect Kubernetes minion nodes. Make sure you've launched a cluster with 'kube-up.sh'" >&2
|
2014-07-14 17:50:04 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2014-09-23 22:54:27 +00:00
|
|
|
# Detect the IP for the master
|
|
|
|
#
|
|
|
|
# Assumed vars:
|
|
|
|
# MASTER_NAME
|
|
|
|
# ZONE
|
2016-07-20 15:25:25 +00:00
|
|
|
# REGION
|
2014-09-23 22:54:27 +00:00
|
|
|
# Vars set:
|
|
|
|
# KUBE_MASTER
|
|
|
|
# KUBE_MASTER_IP
|
2016-08-02 07:08:05 +00:00
|
|
|
function detect-master() {
|
2014-12-09 23:07:54 +00:00
|
|
|
detect-project
|
2014-07-14 17:50:04 +00:00
|
|
|
KUBE_MASTER=${MASTER_NAME}
|
2016-08-23 20:18:22 +00:00
|
|
|
echo "Trying to find master named '${MASTER_NAME}'" >&2
|
2014-10-06 20:25:27 +00:00
|
|
|
if [[ -z "${KUBE_MASTER_IP-}" ]]; then
|
2016-08-23 20:18:22 +00:00
|
|
|
local master_address_name="${MASTER_NAME}-ip"
|
|
|
|
echo "Looking for address '${master_address_name}'" >&2
|
|
|
|
KUBE_MASTER_IP=$(gcloud compute addresses describe "${master_address_name}" \
|
2016-07-20 14:37:31 +00:00
|
|
|
--project "${PROJECT}" --region "${REGION}" -q --format='value(address)')
|
2014-07-14 17:50:04 +00:00
|
|
|
fi
|
2014-10-06 20:25:27 +00:00
|
|
|
if [[ -z "${KUBE_MASTER_IP-}" ]]; then
|
|
|
|
echo "Could not detect Kubernetes master node. Make sure you've launched a cluster with 'kube-up.sh'" >&2
|
2014-07-14 17:50:04 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
2016-08-23 20:18:22 +00:00
|
|
|
echo "Using master: $KUBE_MASTER (external IP: $KUBE_MASTER_IP)" >&2
|
2014-07-14 17:50:04 +00:00
|
|
|
}
|
|
|
|
|
2016-03-05 20:50:28 +00:00
|
|
|
# Reads kube-env metadata from master
|
|
|
|
#
|
|
|
|
# Assumed vars:
|
|
|
|
# KUBE_MASTER
|
|
|
|
# PROJECT
|
|
|
|
# ZONE
|
|
|
|
function get-master-env() {
|
|
|
|
# TODO(zmerlynn): Make this more reliable with retries.
|
|
|
|
gcloud compute --project ${PROJECT} ssh --zone ${ZONE} ${KUBE_MASTER} --command \
|
|
|
|
"curl --fail --silent -H 'Metadata-Flavor: Google' \
|
|
|
|
'http://metadata/computeMetadata/v1/instance/attributes/kube-env'" 2>/dev/null
|
2017-02-14 19:02:11 +00:00
|
|
|
gcloud compute --project ${PROJECT} ssh --zone ${ZONE} ${KUBE_MASTER} --command \
|
|
|
|
"curl --fail --silent -H 'Metadata-Flavor: Google' \
|
|
|
|
'http://metadata/computeMetadata/v1/instance/attributes/kube-master-certs'" 2>/dev/null
|
2016-03-05 20:50:28 +00:00
|
|
|
}
|
|
|
|
|
2015-10-07 20:48:28 +00:00
|
|
|
# Robustly try to create a static ip.
|
|
|
|
# $1: The name of the ip to create
|
|
|
|
# $2: The name of the region to create the ip in.
|
2016-08-02 07:08:05 +00:00
|
|
|
function create-static-ip() {
|
2015-10-07 20:48:28 +00:00
|
|
|
detect-project
|
|
|
|
local attempt=0
|
|
|
|
local REGION="$2"
|
|
|
|
while true; do
|
2016-03-03 16:20:12 +00:00
|
|
|
if gcloud compute addresses create "$1" \
|
2015-10-07 20:48:28 +00:00
|
|
|
--project "${PROJECT}" \
|
|
|
|
--region "${REGION}" -q > /dev/null; then
|
2016-09-20 14:51:19 +00:00
|
|
|
# successful operation - wait until it's visible
|
|
|
|
start="$(date +%s)"
|
|
|
|
while true; do
|
|
|
|
now="$(date +%s)"
|
|
|
|
# Timeout set to 15 minutes
|
2017-06-22 07:59:07 +00:00
|
|
|
if [[ $((now - start)) -gt 900 ]]; then
|
2016-09-20 14:51:19 +00:00
|
|
|
echo "Timeout while waiting for master IP visibility"
|
|
|
|
exit 2
|
|
|
|
fi
|
|
|
|
if gcloud compute addresses describe "$1" --project "${PROJECT}" --region "${REGION}" >/dev/null 2>&1; then
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
echo "Master IP not visible yet. Waiting..."
|
|
|
|
sleep 5
|
|
|
|
done
|
2016-03-03 16:20:12 +00:00
|
|
|
break
|
|
|
|
fi
|
|
|
|
|
2016-11-15 17:13:40 +00:00
|
|
|
if gcloud compute addresses describe "$1" \
|
2016-03-03 16:20:12 +00:00
|
|
|
--project "${PROJECT}" \
|
|
|
|
--region "${REGION}" >/dev/null 2>&1; then
|
|
|
|
# it exists - postcondition satisfied
|
2015-10-07 20:48:28 +00:00
|
|
|
break
|
|
|
|
fi
|
2016-03-03 16:20:12 +00:00
|
|
|
|
|
|
|
if (( attempt > 4 )); then
|
|
|
|
echo -e "${color_red}Failed to create static ip $1 ${color_norm}" >&2
|
|
|
|
exit 2
|
|
|
|
fi
|
|
|
|
attempt=$(($attempt+1))
|
|
|
|
echo -e "${color_yellow}Attempt $attempt failed to create static ip $1. Retrying.${color_norm}" >&2
|
|
|
|
sleep $(($attempt * 5))
|
2015-10-07 20:48:28 +00:00
|
|
|
done
|
|
|
|
}
|
|
|
|
|
2014-12-09 23:37:06 +00:00
|
|
|
# Robustly try to create a firewall rule.
|
|
|
|
# $1: The name of firewall rule.
|
|
|
|
# $2: IP ranges.
|
2014-12-16 18:22:29 +00:00
|
|
|
# $3: Target tags for this firewall rule.
|
2016-08-02 07:08:05 +00:00
|
|
|
function create-firewall-rule() {
|
2014-12-09 23:07:54 +00:00
|
|
|
detect-project
|
2014-12-09 23:37:06 +00:00
|
|
|
local attempt=0
|
|
|
|
while true; do
|
|
|
|
if ! gcloud compute firewall-rules create "$1" \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--network "${NETWORK}" \
|
|
|
|
--source-ranges "$2" \
|
2014-12-16 18:22:29 +00:00
|
|
|
--target-tags "$3" \
|
2015-05-23 04:07:09 +00:00
|
|
|
--allow tcp,udp,icmp,esp,ah,sctp; then
|
2015-10-07 20:48:28 +00:00
|
|
|
if (( attempt > 4 )); then
|
|
|
|
echo -e "${color_red}Failed to create firewall rule $1 ${color_norm}" >&2
|
|
|
|
exit 2
|
|
|
|
fi
|
|
|
|
echo -e "${color_yellow}Attempt $(($attempt+1)) failed to create firewall rule $1. Retrying.${color_norm}" >&2
|
|
|
|
attempt=$(($attempt+1))
|
|
|
|
sleep $(($attempt * 5))
|
2014-12-09 23:37:06 +00:00
|
|
|
else
|
2015-01-28 14:57:10 +00:00
|
|
|
break
|
2014-12-09 23:37:06 +00:00
|
|
|
fi
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
2017-02-27 08:31:13 +00:00
|
|
|
# Format the string argument for gcloud network.
|
|
|
|
function make-gcloud-network-argument() {
|
|
|
|
local network="$1"
|
|
|
|
local address="$2" # optional
|
|
|
|
local enable_ip_alias="$3" # optional
|
|
|
|
local alias_subnetwork="$4" # optional
|
|
|
|
local alias_size="$5" # optional
|
|
|
|
|
|
|
|
local ret=""
|
|
|
|
|
|
|
|
if [[ "${enable_ip_alias}" == 'true' ]]; then
|
|
|
|
ret="--network-interface"
|
|
|
|
ret="${ret} network=${network}"
|
|
|
|
# If address is omitted, instance will not receive an external IP.
|
|
|
|
ret="${ret},address=${address:-}"
|
|
|
|
ret="${ret},subnet=${alias_subnetwork}"
|
|
|
|
ret="${ret},aliases=pods-default:${alias_size}"
|
|
|
|
ret="${ret} --no-can-ip-forward"
|
|
|
|
else
|
2017-06-28 12:27:52 +00:00
|
|
|
if [[ ${ENABLE_BIG_CLUSTER_SUBNETS} != "true" || (${PREEXISTING_NETWORK} = "true" && "${PREEXISTING_NETWORK_MODE}" != "custom") ]]; then
|
2017-06-14 11:23:41 +00:00
|
|
|
ret="--network ${network}"
|
|
|
|
else
|
|
|
|
ret="--subnet=${network}"
|
|
|
|
fi
|
2017-02-27 08:31:13 +00:00
|
|
|
ret="${ret} --can-ip-forward"
|
|
|
|
if [[ -n ${address:-} ]]; then
|
|
|
|
ret="${ret} --address ${address}"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo "${ret}"
|
|
|
|
}
|
|
|
|
|
2015-09-28 23:22:13 +00:00
|
|
|
# $1: version (required)
|
2016-08-02 07:08:05 +00:00
|
|
|
function get-template-name-from-version() {
|
2015-09-28 23:22:13 +00:00
|
|
|
# trim template name to pass gce name validation
|
|
|
|
echo "${NODE_INSTANCE_PREFIX}-template-${1}" | cut -c 1-63 | sed 's/[\.\+]/-/g;s/-*$//g'
|
|
|
|
}
|
|
|
|
|
2015-01-28 14:57:10 +00:00
|
|
|
# Robustly try to create an instance template.
|
|
|
|
# $1: The name of the instance template.
|
2014-12-09 23:37:06 +00:00
|
|
|
# $2: The scopes flag.
|
2017-06-28 17:50:58 +00:00
|
|
|
# $3: String of comma-separated metadata entries (must all be from a file).
|
2016-08-02 07:08:05 +00:00
|
|
|
function create-node-template() {
|
2014-12-09 23:07:54 +00:00
|
|
|
detect-project
|
2015-09-28 23:22:13 +00:00
|
|
|
local template_name="$1"
|
2015-05-08 00:41:22 +00:00
|
|
|
|
|
|
|
# First, ensure the template doesn't exist.
|
2015-08-26 17:05:34 +00:00
|
|
|
# TODO(zmerlynn): To make this really robust, we need to parse the output and
|
2015-05-08 00:41:22 +00:00
|
|
|
# add retries. Just relying on a non-zero exit code doesn't
|
|
|
|
# distinguish an ephemeral failed call from a "not-exists".
|
2015-09-28 23:22:13 +00:00
|
|
|
if gcloud compute instance-templates describe "$template_name" --project "${PROJECT}" &>/dev/null; then
|
2015-06-12 03:56:01 +00:00
|
|
|
echo "Instance template ${1} already exists; deleting." >&2
|
2017-05-11 23:51:54 +00:00
|
|
|
if ! gcloud compute instance-templates delete "$template_name" --project "${PROJECT}" --quiet &>/dev/null; then
|
2015-06-12 03:56:01 +00:00
|
|
|
echo -e "${color_yellow}Failed to delete existing instance template${color_norm}" >&2
|
|
|
|
exit 2
|
|
|
|
fi
|
2015-05-08 00:41:22 +00:00
|
|
|
fi
|
|
|
|
|
2017-02-27 08:31:13 +00:00
|
|
|
local gcloud="gcloud"
|
2017-05-10 19:07:02 +00:00
|
|
|
|
|
|
|
local accelerator_args=""
|
|
|
|
# VMs with Accelerators cannot be live migrated.
|
|
|
|
# More details here - https://cloud.google.com/compute/docs/gpus/add-gpus#create-new-gpu-instance
|
|
|
|
if [[ ! -z "${NODE_ACCELERATORS}" ]]; then
|
|
|
|
accelerator_args="--maintenance-policy TERMINATE --restart-on-failure --accelerator ${NODE_ACCELERATORS}"
|
|
|
|
gcloud="gcloud beta"
|
|
|
|
fi
|
|
|
|
|
2017-02-27 08:31:13 +00:00
|
|
|
if [[ "${ENABLE_IP_ALIASES:-}" == 'true' ]]; then
|
2017-05-17 23:26:23 +00:00
|
|
|
gcloud="gcloud beta"
|
2017-02-27 08:31:13 +00:00
|
|
|
fi
|
|
|
|
|
2015-08-07 06:47:10 +00:00
|
|
|
local preemptible_minions=""
|
2015-11-24 03:06:47 +00:00
|
|
|
if [[ "${PREEMPTIBLE_NODE}" == "true" ]]; then
|
2015-08-07 06:47:10 +00:00
|
|
|
preemptible_minions="--preemptible --maintenance-policy TERMINATE"
|
2015-08-08 16:07:12 +00:00
|
|
|
fi
|
2017-02-27 08:31:13 +00:00
|
|
|
|
2017-03-27 19:17:15 +00:00
|
|
|
local local_ssds=""
|
2017-06-22 07:59:07 +00:00
|
|
|
if [[ ! -z ${NODE_LOCAL_SSDS+x} ]]; then
|
2017-07-19 01:43:45 +00:00
|
|
|
# The NODE_LOCAL_SSDS check below fixes issue #49171
|
|
|
|
# Some versions of seq will count down from 1 if "seq 0" is specified
|
|
|
|
if [[ ${NODE_LOCAL_SSDS} -ge 1 ]]; then
|
2017-03-27 19:17:15 +00:00
|
|
|
for i in $(seq ${NODE_LOCAL_SSDS}); do
|
2017-07-19 01:43:45 +00:00
|
|
|
local_ssds="$local_ssds--local-ssd=interface=SCSI "
|
2017-03-27 19:17:15 +00:00
|
|
|
done
|
2017-07-19 01:43:45 +00:00
|
|
|
fi
|
2017-03-27 19:17:15 +00:00
|
|
|
fi
|
2017-02-27 08:31:13 +00:00
|
|
|
|
|
|
|
local network=$(make-gcloud-network-argument \
|
|
|
|
"${NETWORK}" "" \
|
|
|
|
"${ENABLE_IP_ALIASES:-}" \
|
|
|
|
"${IP_ALIAS_SUBNETWORK:-}" \
|
|
|
|
"${IP_ALIAS_SIZE:-}")
|
|
|
|
|
|
|
|
local attempt=1
|
2014-12-09 23:37:06 +00:00
|
|
|
while true; do
|
2015-06-17 07:13:26 +00:00
|
|
|
echo "Attempt ${attempt} to create ${1}" >&2
|
2017-05-10 19:07:02 +00:00
|
|
|
if ! ${gcloud} compute instance-templates create \
|
2017-02-27 08:31:13 +00:00
|
|
|
"$template_name" \
|
2014-12-09 23:37:06 +00:00
|
|
|
--project "${PROJECT}" \
|
2015-11-24 03:05:51 +00:00
|
|
|
--machine-type "${NODE_SIZE}" \
|
2015-11-24 03:02:38 +00:00
|
|
|
--boot-disk-type "${NODE_DISK_TYPE}" \
|
|
|
|
--boot-disk-size "${NODE_DISK_SIZE}" \
|
|
|
|
--image-project="${NODE_IMAGE_PROJECT}" \
|
|
|
|
--image "${NODE_IMAGE}" \
|
2015-11-24 03:06:00 +00:00
|
|
|
--tags "${NODE_TAG}" \
|
2017-04-28 22:57:39 +00:00
|
|
|
${accelerator_args} \
|
2017-03-27 19:17:15 +00:00
|
|
|
${local_ssds} \
|
2017-02-27 08:31:13 +00:00
|
|
|
--region "${REGION}" \
|
|
|
|
${network} \
|
2015-08-08 16:07:12 +00:00
|
|
|
${preemptible_minions} \
|
2014-12-09 23:37:06 +00:00
|
|
|
$2 \
|
2017-06-28 17:50:58 +00:00
|
|
|
--metadata-from-file $3 >&2; then
|
2014-12-09 23:37:06 +00:00
|
|
|
if (( attempt > 5 )); then
|
2015-09-28 23:22:13 +00:00
|
|
|
echo -e "${color_red}Failed to create instance template $template_name ${color_norm}" >&2
|
2014-12-09 23:37:06 +00:00
|
|
|
exit 2
|
|
|
|
fi
|
2015-09-28 23:22:13 +00:00
|
|
|
echo -e "${color_yellow}Attempt ${attempt} failed to create instance template $template_name. Retrying.${color_norm}" >&2
|
2014-12-09 23:37:06 +00:00
|
|
|
attempt=$(($attempt+1))
|
2015-10-23 20:57:13 +00:00
|
|
|
sleep $(($attempt * 5))
|
2016-02-23 00:01:06 +00:00
|
|
|
|
|
|
|
# In case the previous attempt failed with something like a
|
|
|
|
# Backend Error and left the entry laying around, delete it
|
|
|
|
# before we try again.
|
|
|
|
gcloud compute instance-templates delete "$template_name" --project "${PROJECT}" &>/dev/null || true
|
2015-01-28 14:57:10 +00:00
|
|
|
else
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
|
|
|
# Robustly try to add metadata on an instance.
|
2015-08-08 21:29:57 +00:00
|
|
|
# $1: The name of the instance.
|
2015-04-17 17:58:26 +00:00
|
|
|
# $2...$n: The metadata key=value pairs to add.
|
2016-08-02 07:08:05 +00:00
|
|
|
function add-instance-metadata() {
|
2015-04-17 17:58:26 +00:00
|
|
|
local -r instance=$1
|
|
|
|
shift 1
|
|
|
|
local -r kvs=( "$@" )
|
2015-01-28 14:57:10 +00:00
|
|
|
detect-project
|
|
|
|
local attempt=0
|
|
|
|
while true; do
|
2015-04-17 17:58:26 +00:00
|
|
|
if ! gcloud compute instances add-metadata "${instance}" \
|
2015-01-28 14:57:10 +00:00
|
|
|
--project "${PROJECT}" \
|
|
|
|
--zone "${ZONE}" \
|
2015-04-17 17:58:26 +00:00
|
|
|
--metadata "${kvs[@]}"; then
|
2015-01-28 14:57:10 +00:00
|
|
|
if (( attempt > 5 )); then
|
2015-10-07 18:19:32 +00:00
|
|
|
echo -e "${color_red}Failed to add instance metadata in ${instance} ${color_norm}" >&2
|
2015-01-28 14:57:10 +00:00
|
|
|
exit 2
|
|
|
|
fi
|
2015-10-07 18:19:32 +00:00
|
|
|
echo -e "${color_yellow}Attempt $(($attempt+1)) failed to add metadata in ${instance}. Retrying.${color_norm}" >&2
|
2015-01-28 14:57:10 +00:00
|
|
|
attempt=$(($attempt+1))
|
2015-10-23 20:57:13 +00:00
|
|
|
sleep $((5 * $attempt))
|
2015-01-28 14:57:10 +00:00
|
|
|
else
|
|
|
|
break
|
2014-12-09 23:37:06 +00:00
|
|
|
fi
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
# Robustly try to add metadata on an instance, from a file.
|
2015-04-17 17:58:26 +00:00
|
|
|
# $1: The name of the instance.
|
|
|
|
# $2...$n: The metadata key=file pairs to add.
|
2016-08-02 07:08:05 +00:00
|
|
|
function add-instance-metadata-from-file() {
|
2015-04-17 17:58:26 +00:00
|
|
|
local -r instance=$1
|
|
|
|
shift 1
|
|
|
|
local -r kvs=( "$@" )
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
detect-project
|
|
|
|
local attempt=0
|
|
|
|
while true; do
|
2015-04-17 17:58:26 +00:00
|
|
|
echo "${kvs[@]}"
|
|
|
|
if ! gcloud compute instances add-metadata "${instance}" \
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
--project "${PROJECT}" \
|
|
|
|
--zone "${ZONE}" \
|
2015-05-23 04:07:09 +00:00
|
|
|
--metadata-from-file "$(join_csv ${kvs[@]})"; then
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
if (( attempt > 5 )); then
|
2015-10-07 18:19:32 +00:00
|
|
|
echo -e "${color_red}Failed to add instance metadata in ${instance} ${color_norm}" >&2
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
exit 2
|
|
|
|
fi
|
2015-10-07 18:19:32 +00:00
|
|
|
echo -e "${color_yellow}Attempt $(($attempt+1)) failed to add metadata in ${instance}. Retrying.${color_norm}" >&2
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
attempt=$(($attempt+1))
|
2015-10-23 20:57:13 +00:00
|
|
|
sleep $(($attempt * 5))
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
else
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
2014-07-14 17:50:04 +00:00
|
|
|
# Instantiate a kubernetes cluster
|
2014-09-23 22:54:27 +00:00
|
|
|
#
|
|
|
|
# Assumed vars
|
2014-10-03 21:58:49 +00:00
|
|
|
# KUBE_ROOT
|
2014-09-23 22:54:27 +00:00
|
|
|
# <Various vars set in config file>
|
2016-08-02 07:08:05 +00:00
|
|
|
function kube-up() {
|
2017-03-11 06:18:38 +00:00
|
|
|
kube::util::ensure-temp-dir
|
2014-07-14 17:50:04 +00:00
|
|
|
detect-project
|
|
|
|
|
2015-10-26 17:38:53 +00:00
|
|
|
load-or-gen-kube-basicauth
|
|
|
|
load-or-gen-kube-bearertoken
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
|
2014-09-23 22:54:27 +00:00
|
|
|
# Make sure we have the tar files staged on Google Storage
|
|
|
|
find-release-tars
|
|
|
|
upload-server-tars
|
2014-09-24 17:55:58 +00:00
|
|
|
|
2016-02-08 09:21:04 +00:00
|
|
|
# ensure that environmental variables specifying number of migs to create
|
|
|
|
set_num_migs
|
|
|
|
|
2015-11-29 19:38:03 +00:00
|
|
|
if [[ ${KUBE_USE_EXISTING_MASTER:-} == "true" ]]; then
|
2016-12-12 14:46:39 +00:00
|
|
|
detect-master
|
2016-03-05 20:50:28 +00:00
|
|
|
parse-master-env
|
2017-05-19 22:23:39 +00:00
|
|
|
create-subnetworks
|
2015-11-29 19:38:03 +00:00
|
|
|
create-nodes
|
2016-11-07 11:47:04 +00:00
|
|
|
elif [[ ${KUBE_REPLICATE_EXISTING_MASTER:-} == "true" ]]; then
|
2017-04-18 18:47:23 +00:00
|
|
|
if [[ "${MASTER_OS_DISTRIBUTION}" != "gci" && "${MASTER_OS_DISTRIBUTION}" != "debian" && "${MASTER_OS_DISTRIBUTION}" != "ubuntu" ]]; then
|
|
|
|
echo "Master replication supported only for gci, debian, and ubuntu"
|
2016-08-02 07:08:05 +00:00
|
|
|
return 1
|
|
|
|
fi
|
2016-07-20 14:37:31 +00:00
|
|
|
create-loadbalancer
|
2016-08-02 07:08:05 +00:00
|
|
|
# If replication of master fails, we need to ensure that the replica is removed from etcd clusters.
|
|
|
|
if ! replicate-master; then
|
2016-09-07 14:10:55 +00:00
|
|
|
remove-replica-from-etcd 2379 || true
|
2016-08-02 07:08:05 +00:00
|
|
|
remove-replica-from-etcd 4002 || true
|
|
|
|
fi
|
2015-11-29 19:38:03 +00:00
|
|
|
else
|
|
|
|
check-existing
|
|
|
|
create-network
|
2017-05-19 22:23:39 +00:00
|
|
|
create-subnetworks
|
2016-02-26 00:00:16 +00:00
|
|
|
write-cluster-name
|
2016-05-09 14:23:00 +00:00
|
|
|
create-autoscaler-config
|
2015-11-29 19:38:03 +00:00
|
|
|
create-master
|
|
|
|
create-nodes-firewall
|
|
|
|
create-nodes-template
|
|
|
|
create-nodes
|
|
|
|
check-cluster
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
function check-existing() {
|
2015-06-15 16:21:27 +00:00
|
|
|
local running_in_terminal=false
|
|
|
|
# May be false if tty is not allocated (for example with ssh -T).
|
2017-06-22 07:59:07 +00:00
|
|
|
if [[ -t 1 ]]; then
|
2015-06-15 16:21:27 +00:00
|
|
|
running_in_terminal=true
|
|
|
|
fi
|
|
|
|
|
2015-06-19 20:04:16 +00:00
|
|
|
if [[ ${running_in_terminal} == "true" || ${KUBE_UP_AUTOMATIC_CLEANUP} == "true" ]]; then
|
2015-06-15 16:21:27 +00:00
|
|
|
if ! check-resources; then
|
|
|
|
local run_kube_down="n"
|
|
|
|
echo "${KUBE_RESOURCE_FOUND} found." >&2
|
|
|
|
# Get user input only if running in terminal.
|
|
|
|
if [[ ${running_in_terminal} == "true" && ${KUBE_UP_AUTOMATIC_CLEANUP} == "false" ]]; then
|
|
|
|
read -p "Would you like to shut down the old cluster (call kube-down)? [y/N] " run_kube_down
|
|
|
|
fi
|
|
|
|
if [[ ${run_kube_down} == "y" || ${run_kube_down} == "Y" || ${KUBE_UP_AUTOMATIC_CLEANUP} == "true" ]]; then
|
|
|
|
echo "... calling kube-down" >&2
|
|
|
|
kube-down
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
fi
|
2015-11-29 19:38:03 +00:00
|
|
|
}
|
2015-06-15 16:21:27 +00:00
|
|
|
|
2015-11-29 19:38:03 +00:00
|
|
|
function create-network() {
|
2015-01-07 23:02:35 +00:00
|
|
|
if ! gcloud compute networks --project "${PROJECT}" describe "${NETWORK}" &>/dev/null; then
|
2014-11-25 18:32:27 +00:00
|
|
|
echo "Creating new network: ${NETWORK}"
|
2014-09-24 17:55:58 +00:00
|
|
|
# The network needs to be created synchronously or we have a race. The
|
|
|
|
# firewalls can be added concurrent with instance creation.
|
2017-04-11 21:35:18 +00:00
|
|
|
gcloud compute networks create --project "${PROJECT}" "${NETWORK}" --mode=auto
|
2017-06-14 11:23:41 +00:00
|
|
|
else
|
|
|
|
PREEXISTING_NETWORK=true
|
|
|
|
PREEXISTING_NETWORK_MODE="$(gcloud compute networks list ${NETWORK} --format='value(x_gcloud_mode)' || true)"
|
|
|
|
echo "Found existing network ${NETWORK} in ${PREEXISTING_NETWORK_MODE} mode."
|
2014-10-28 20:47:49 +00:00
|
|
|
fi
|
|
|
|
|
2016-12-13 19:21:14 +00:00
|
|
|
if ! gcloud compute firewall-rules --project "${PROJECT}" describe "${CLUSTER_NAME}-default-internal-master" &>/dev/null; then
|
|
|
|
gcloud compute firewall-rules create "${CLUSTER_NAME}-default-internal-master" \
|
2014-09-24 23:03:38 +00:00
|
|
|
--project "${PROJECT}" \
|
|
|
|
--network "${NETWORK}" \
|
2014-11-25 18:32:27 +00:00
|
|
|
--source-ranges "10.0.0.0/8" \
|
2016-09-20 14:34:56 +00:00
|
|
|
--allow "tcp:1-2379,tcp:2382-65535,udp:1-65535,icmp" \
|
|
|
|
--target-tags "${MASTER_TAG}"&
|
|
|
|
fi
|
|
|
|
|
2016-12-13 19:21:14 +00:00
|
|
|
if ! gcloud compute firewall-rules --project "${PROJECT}" describe "${CLUSTER_NAME}-default-internal-node" &>/dev/null; then
|
|
|
|
gcloud compute firewall-rules create "${CLUSTER_NAME}-default-internal-node" \
|
2016-09-20 14:34:56 +00:00
|
|
|
--project "${PROJECT}" \
|
|
|
|
--network "${NETWORK}" \
|
|
|
|
--source-ranges "10.0.0.0/8" \
|
|
|
|
--allow "tcp:1-65535,udp:1-65535,icmp" \
|
|
|
|
--target-tags "${NODE_TAG}"&
|
2014-10-28 20:47:49 +00:00
|
|
|
fi
|
|
|
|
|
2015-01-07 23:02:35 +00:00
|
|
|
if ! gcloud compute firewall-rules describe --project "${PROJECT}" "${NETWORK}-default-ssh" &>/dev/null; then
|
2014-11-25 18:32:27 +00:00
|
|
|
gcloud compute firewall-rules create "${NETWORK}-default-ssh" \
|
2014-09-24 23:03:38 +00:00
|
|
|
--project "${PROJECT}" \
|
|
|
|
--network "${NETWORK}" \
|
2014-11-25 18:32:27 +00:00
|
|
|
--source-ranges "0.0.0.0/0" \
|
|
|
|
--allow "tcp:22" &
|
2014-09-24 23:03:38 +00:00
|
|
|
fi
|
2015-11-29 19:38:03 +00:00
|
|
|
}
|
2014-09-24 23:03:38 +00:00
|
|
|
|
2017-06-14 11:23:41 +00:00
|
|
|
function expand-default-subnetwork() {
|
|
|
|
gcloud compute networks switch-mode "${NETWORK}" \
|
|
|
|
--mode custom \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--quiet || true
|
|
|
|
gcloud compute networks subnets expand-ip-range "${NETWORK}" \
|
|
|
|
--region="${REGION}" \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--prefix-length=19 \
|
|
|
|
--quiet
|
|
|
|
}
|
|
|
|
|
2017-05-19 22:23:39 +00:00
|
|
|
function create-subnetworks() {
|
2017-02-27 08:31:13 +00:00
|
|
|
case ${ENABLE_IP_ALIASES} in
|
2017-06-14 11:23:41 +00:00
|
|
|
true) echo "IP aliases are enabled. Creating subnetworks.";;
|
|
|
|
false)
|
|
|
|
echo "IP aliases are disabled."
|
|
|
|
if [[ "${ENABLE_BIG_CLUSTER_SUBNETS}" = "true" ]]; then
|
|
|
|
if [[ "${PREEXISTING_NETWORK}" != "true" ]]; then
|
|
|
|
expand-default-subnetwork
|
|
|
|
else
|
|
|
|
echo "${color_yellow}Using pre-existing network ${NETWORK}, subnets won't be expanded to /19!${color_norm}"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
return;;
|
2017-02-27 08:31:13 +00:00
|
|
|
*) echo "${color_red}Invalid argument to ENABLE_IP_ALIASES${color_norm}"
|
|
|
|
exit 1;;
|
|
|
|
esac
|
|
|
|
|
2017-05-19 22:23:39 +00:00
|
|
|
# Look for the alias subnet, it must exist and have a secondary
|
|
|
|
# range configured.
|
2017-05-17 23:26:23 +00:00
|
|
|
local subnet=$(gcloud beta compute networks subnets describe \
|
2017-04-13 19:08:35 +00:00
|
|
|
--project "${PROJECT}" \
|
|
|
|
--region ${REGION} \
|
|
|
|
${IP_ALIAS_SUBNETWORK} 2>/dev/null)
|
2017-02-27 08:31:13 +00:00
|
|
|
if [[ -z ${subnet} ]]; then
|
|
|
|
# Only allow auto-creation for default subnets
|
|
|
|
if [[ ${IP_ALIAS_SUBNETWORK} != ${INSTANCE_PREFIX}-subnet-default ]]; then
|
|
|
|
echo "${color_red}Subnetwork ${NETWORK}:${IP_ALIAS_SUBNETWORK} does not exist${color_norm}"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2017-06-22 07:59:07 +00:00
|
|
|
if [[ -z ${NODE_IP_RANGE:-} ]]; then
|
2017-02-27 08:31:13 +00:00
|
|
|
echo "${color_red}NODE_IP_RANGE must be specified{color_norm}"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo "Creating subnet ${NETWORK}:${IP_ALIAS_SUBNETWORK}"
|
2017-05-17 23:26:23 +00:00
|
|
|
gcloud beta compute networks subnets create \
|
2017-02-27 08:31:13 +00:00
|
|
|
${IP_ALIAS_SUBNETWORK} \
|
|
|
|
--description "Automatically generated subnet for ${INSTANCE_PREFIX} cluster. This will be removed on cluster teardown." \
|
2017-04-13 19:08:35 +00:00
|
|
|
--project "${PROJECT}" \
|
2017-02-27 08:31:13 +00:00
|
|
|
--network ${NETWORK} \
|
|
|
|
--region ${REGION} \
|
|
|
|
--range ${NODE_IP_RANGE} \
|
2017-05-26 23:41:01 +00:00
|
|
|
--secondary-range "pods-default=${CLUSTER_IP_RANGE}"
|
2017-02-27 08:31:13 +00:00
|
|
|
echo "Created subnetwork ${IP_ALIAS_SUBNETWORK}"
|
|
|
|
else
|
|
|
|
if ! echo ${subnet} | grep --quiet secondaryIpRanges ${subnet}; then
|
|
|
|
echo "${color_red}Subnet ${IP_ALIAS_SUBNETWORK} does not have a secondary range${color_norm}"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
fi
|
2017-05-19 22:23:39 +00:00
|
|
|
|
|
|
|
# Services subnetwork.
|
|
|
|
local subnet=$(gcloud beta compute networks subnets describe \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--region ${REGION} \
|
|
|
|
${SERVICE_CLUSTER_IP_SUBNETWORK} 2>/dev/null)
|
|
|
|
|
|
|
|
if [[ -z ${subnet} ]]; then
|
|
|
|
if [[ ${SERVICE_CLUSTER_IP_SUBNETWORK} != ${INSTANCE_PREFIX}-subnet-services ]]; then
|
|
|
|
echo "${color_red}Subnetwork ${NETWORK}:${SERVICE_CLUSTER_IP_SUBNETWORK} does not exist${color_norm}"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo "Creating subnet for reserving service cluster IPs ${NETWORK}:${SERVICE_CLUSTER_IP_SUBNETWORK}"
|
|
|
|
gcloud beta compute networks subnets create \
|
|
|
|
${SERVICE_CLUSTER_IP_SUBNETWORK} \
|
|
|
|
--description "Automatically generated subnet for ${INSTANCE_PREFIX} cluster. This will be removed on cluster teardown." \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--network ${NETWORK} \
|
|
|
|
--region ${REGION} \
|
|
|
|
--range ${SERVICE_CLUSTER_IP_RANGE}
|
|
|
|
echo "Created subnetwork ${SERVICE_CLUSTER_IP_SUBNETWORK}"
|
|
|
|
else
|
|
|
|
echo "Subnet ${SERVICE_CLUSTER_IP_SUBNETWORK} already exists"
|
|
|
|
fi
|
2017-02-27 08:31:13 +00:00
|
|
|
}
|
|
|
|
|
2016-10-11 23:50:30 +00:00
|
|
|
function delete-firewall-rules() {
|
|
|
|
for fw in $@; do
|
|
|
|
if [[ -n $(gcloud compute firewall-rules --project "${PROJECT}" describe "${fw}" --format='value(name)' 2>/dev/null || true) ]]; then
|
|
|
|
gcloud compute firewall-rules delete --project "${PROJECT}" --quiet "${fw}" &
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
kube::util::wait-for-jobs || {
|
|
|
|
echo -e "${color_red}Failed to delete firewall rules.${color_norm}" >&2
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function delete-network() {
|
|
|
|
if [[ -n $(gcloud compute networks --project "${PROJECT}" describe "${NETWORK}" --format='value(name)' 2>/dev/null || true) ]]; then
|
|
|
|
if ! gcloud compute networks delete --project "${PROJECT}" --quiet "${NETWORK}"; then
|
|
|
|
echo "Failed to delete network '${NETWORK}'. Listing firewall-rules:"
|
|
|
|
gcloud compute firewall-rules --project "${PROJECT}" list --filter="network=${NETWORK}"
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2017-05-19 22:23:39 +00:00
|
|
|
function delete-subnetworks() {
|
2017-02-27 08:31:13 +00:00
|
|
|
if [[ ${ENABLE_IP_ALIASES:-} != "true" ]]; then
|
2017-06-14 11:23:41 +00:00
|
|
|
if [[ "${ENABLE_BIG_CLUSTER_SUBNETS}" = "true" ]]; then
|
|
|
|
# If running in custom mode network we need to delete subnets
|
|
|
|
mode="$(gcloud compute networks list ${NETWORK} --format='value(x_gcloud_mode)' || true)"
|
|
|
|
if [[ "${mode}" == "custom" ]]; then
|
|
|
|
echo "Deleting default subnets..."
|
|
|
|
# This value should be kept in sync with number of regions.
|
|
|
|
local parallelism=9
|
|
|
|
gcloud compute networks subnets list --network="${NETWORK}" --format='value(region.basename())' | \
|
|
|
|
xargs -i -P ${parallelism} gcloud --quiet compute networks subnets delete "${NETWORK}" --region="{}" || true
|
|
|
|
fi
|
|
|
|
fi
|
2017-02-27 08:31:13 +00:00
|
|
|
return
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Only delete automatically created subnets.
|
2017-05-19 22:23:39 +00:00
|
|
|
if [[ ${IP_ALIAS_SUBNETWORK} == ${INSTANCE_PREFIX}-subnet-default ]]; then
|
|
|
|
echo "Removing auto-created subnet ${NETWORK}:${IP_ALIAS_SUBNETWORK}"
|
|
|
|
if [[ -n $(gcloud beta compute networks subnets describe \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--region ${REGION} \
|
|
|
|
${IP_ALIAS_SUBNETWORK} 2>/dev/null) ]]; then
|
|
|
|
gcloud beta --quiet compute networks subnets delete \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--region ${REGION} \
|
|
|
|
${IP_ALIAS_SUBNETWORK}
|
|
|
|
fi
|
2017-02-27 08:31:13 +00:00
|
|
|
fi
|
|
|
|
|
2017-05-19 22:23:39 +00:00
|
|
|
if [[ ${SERVICE_CLUSTER_IP_SUBNETWORK} == ${INSTANCE_PREFIX}-subnet-services ]]; then
|
|
|
|
echo "Removing auto-created subnet ${NETWORK}:${SERVICE_CLUSTER_IP_SUBNETWORK}"
|
|
|
|
if [[ -n $(gcloud beta compute networks subnets describe \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--region ${REGION} \
|
|
|
|
${SERVICE_CLUSTER_IP_SUBNETWORK} 2>/dev/null) ]]; then
|
|
|
|
gcloud --quiet beta compute networks subnets delete \
|
2017-04-13 19:08:35 +00:00
|
|
|
--project "${PROJECT}" \
|
|
|
|
--region ${REGION} \
|
2017-05-19 22:23:39 +00:00
|
|
|
${SERVICE_CLUSTER_IP_SUBNETWORK}
|
|
|
|
fi
|
2017-02-27 08:31:13 +00:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2016-12-20 13:18:01 +00:00
|
|
|
# Generates SSL certificates for etcd cluster. Uses cfssl program.
|
|
|
|
#
|
|
|
|
# Assumed vars:
|
|
|
|
# KUBE_TEMP: temporary directory
|
2017-08-08 12:09:15 +00:00
|
|
|
# NUM_NODES: #nodes in the cluster
|
2016-12-20 13:18:01 +00:00
|
|
|
#
|
|
|
|
# Args:
|
|
|
|
# $1: host name
|
|
|
|
# $2: CA certificate
|
|
|
|
# $3: CA key
|
|
|
|
#
|
|
|
|
# If CA cert/key is empty, the function will also generate certs for CA.
|
|
|
|
#
|
|
|
|
# Vars set:
|
|
|
|
# ETCD_CA_KEY_BASE64
|
|
|
|
# ETCD_CA_CERT_BASE64
|
|
|
|
# ETCD_PEER_KEY_BASE64
|
|
|
|
# ETCD_PEER_CERT_BASE64
|
|
|
|
#
|
|
|
|
function create-etcd-certs {
|
|
|
|
local host=${1}
|
|
|
|
local ca_cert=${2:-}
|
|
|
|
local ca_key=${3:-}
|
|
|
|
|
2017-02-13 19:20:27 +00:00
|
|
|
GEN_ETCD_CA_CERT="${ca_cert}" GEN_ETCD_CA_KEY="${ca_key}" \
|
|
|
|
generate-etcd-cert "${KUBE_TEMP}/cfssl" "${host}" "peer" "peer"
|
2016-12-20 13:18:01 +00:00
|
|
|
|
|
|
|
pushd "${KUBE_TEMP}/cfssl"
|
2016-10-20 09:08:43 +00:00
|
|
|
ETCD_CA_KEY_BASE64=$(cat "ca-key.pem" | base64 | tr -d '\r\n')
|
|
|
|
ETCD_CA_CERT_BASE64=$(cat "ca.pem" | gzip | base64 | tr -d '\r\n')
|
2017-02-13 19:20:27 +00:00
|
|
|
ETCD_PEER_KEY_BASE64=$(cat "peer-key.pem" | base64 | tr -d '\r\n')
|
|
|
|
ETCD_PEER_CERT_BASE64=$(cat "peer.pem" | gzip | base64 | tr -d '\r\n')
|
2016-10-20 09:08:43 +00:00
|
|
|
popd
|
|
|
|
}
|
|
|
|
|
2015-11-29 19:38:03 +00:00
|
|
|
function create-master() {
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
echo "Starting master and configuring firewalls"
|
2014-11-25 18:32:27 +00:00
|
|
|
gcloud compute firewall-rules create "${MASTER_NAME}-https" \
|
2014-10-06 20:25:27 +00:00
|
|
|
--project "${PROJECT}" \
|
|
|
|
--network "${NETWORK}" \
|
2014-11-25 18:32:27 +00:00
|
|
|
--target-tags "${MASTER_TAG}" \
|
|
|
|
--allow tcp:443 &
|
2014-07-14 17:50:04 +00:00
|
|
|
|
2015-02-23 21:57:09 +00:00
|
|
|
# We have to make sure the disk is created before creating the master VM, so
|
|
|
|
# run this in the foreground.
|
|
|
|
gcloud compute disks create "${MASTER_NAME}-pd" \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--zone "${ZONE}" \
|
2015-05-11 12:30:57 +00:00
|
|
|
--type "${MASTER_DISK_TYPE}" \
|
|
|
|
--size "${MASTER_DISK_SIZE}"
|
2015-02-23 21:57:09 +00:00
|
|
|
|
2015-07-27 18:50:31 +00:00
|
|
|
# Create disk for cluster registry if enabled
|
|
|
|
if [[ "${ENABLE_CLUSTER_REGISTRY}" == true && -n "${CLUSTER_REGISTRY_DISK}" ]]; then
|
|
|
|
gcloud compute disks create "${CLUSTER_REGISTRY_DISK}" \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--zone "${ZONE}" \
|
2015-08-19 22:47:55 +00:00
|
|
|
--type "${CLUSTER_REGISTRY_DISK_TYPE_GCE}" \
|
2015-07-27 18:50:31 +00:00
|
|
|
--size "${CLUSTER_REGISTRY_DISK_SIZE}" &
|
|
|
|
fi
|
|
|
|
|
2016-09-20 14:34:56 +00:00
|
|
|
# Create rule for accessing and securing etcd servers.
|
|
|
|
if ! gcloud compute firewall-rules --project "${PROJECT}" describe "${MASTER_NAME}-etcd" &>/dev/null; then
|
|
|
|
gcloud compute firewall-rules create "${MASTER_NAME}-etcd" \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--network "${NETWORK}" \
|
|
|
|
--source-tags "${MASTER_TAG}" \
|
|
|
|
--allow "tcp:2380,tcp:2381" \
|
|
|
|
--target-tags "${MASTER_TAG}" &
|
|
|
|
fi
|
|
|
|
|
2015-04-22 17:55:08 +00:00
|
|
|
# Generate a bearer token for this cluster. We push this separately
|
|
|
|
# from the other cluster variables so that the client (this
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
# computer) can forget it later. This should disappear with
|
2015-08-06 01:08:26 +00:00
|
|
|
# http://issue.k8s.io/3168
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
KUBELET_TOKEN=$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64 | tr -d "=+/" | dd bs=32 count=1 2>/dev/null)
|
Generate a token for kube-proxy.
Tested on GCE.
Includes untested modifications for AWS and Vagrant.
No changes for any other distros.
Probably will work on other up-to-date providers
but beware. Symptom would be that service proxying
stops working.
1. Generates a token kube-proxy in AWS, GCE, and Vagrant setup scripts.
1. Distributes the token via salt-overlay, and salt to /var/lib/kube-proxy/kubeconfig
1. Changes kube-proxy args:
- use the --kubeconfig argument
- changes --master argument from http://MASTER:7080 to https://MASTER
- http -> https
- explicit port 7080 -> implied 443
Possible ways this might break other distros:
Mitigation: there is an default empty kubeconfig file.
If the distro does not populate the salt-overlay, then
it should get the empty, which parses to an empty
object, which, combined with the --master argument,
should still work.
Mitigation:
- azure: Special case to use 7080 in
- rackspace: way out of date, so don't care.
- vsphere: way out of date, so don't care.
- other distros: not using salt.
2015-04-24 16:27:11 +00:00
|
|
|
KUBE_PROXY_TOKEN=$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64 | tr -d "=+/" | dd bs=32 count=1 2>/dev/null)
|
2017-01-19 09:20:43 +00:00
|
|
|
if [[ "${ENABLE_NODE_PROBLEM_DETECTOR:-}" == "standalone" ]]; then
|
|
|
|
NODE_PROBLEM_DETECTOR_TOKEN=$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64 | tr -d "=+/" | dd bs=32 count=1 2>/dev/null)
|
|
|
|
fi
|
2014-09-24 17:55:58 +00:00
|
|
|
|
2015-04-17 17:35:19 +00:00
|
|
|
# Reserve the master's IP so that it can later be transferred to another VM
|
2016-07-20 15:25:25 +00:00
|
|
|
# without disrupting the kubelets.
|
2015-10-07 20:48:28 +00:00
|
|
|
create-static-ip "${MASTER_NAME}-ip" "${REGION}"
|
|
|
|
MASTER_RESERVED_IP=$(gcloud compute addresses describe "${MASTER_NAME}-ip" \
|
2016-05-04 21:10:00 +00:00
|
|
|
--project "${PROJECT}" --region "${REGION}" -q --format='value(address)')
|
2016-11-04 08:58:09 +00:00
|
|
|
|
|
|
|
if [[ "${REGISTER_MASTER_KUBELET:-}" == "true" ]]; then
|
|
|
|
KUBELET_APISERVER="${MASTER_RESERVED_IP}"
|
|
|
|
fi
|
|
|
|
|
2016-09-28 13:25:18 +00:00
|
|
|
KUBERNETES_MASTER_NAME="${MASTER_RESERVED_IP}"
|
2016-11-07 09:21:07 +00:00
|
|
|
MASTER_ADVERTISE_ADDRESS="${MASTER_RESERVED_IP}"
|
2015-04-17 17:35:19 +00:00
|
|
|
|
2015-05-11 18:43:44 +00:00
|
|
|
create-certs "${MASTER_RESERVED_IP}"
|
2016-10-11 12:52:51 +00:00
|
|
|
create-etcd-certs ${MASTER_NAME}
|
2015-05-11 18:43:44 +00:00
|
|
|
|
2017-08-08 12:09:15 +00:00
|
|
|
if [[ "${NUM_NODES}" -ge "50" ]]; then
|
|
|
|
# We block on master creation for large clusters to avoid doing too much
|
|
|
|
# unnecessary work in case master start-up fails (like creation of nodes).
|
|
|
|
create-master-instance "${MASTER_RESERVED_IP}"
|
|
|
|
else
|
|
|
|
create-master-instance "${MASTER_RESERVED_IP}" &
|
|
|
|
fi
|
2015-11-29 19:38:03 +00:00
|
|
|
}
|
2014-07-14 17:50:04 +00:00
|
|
|
|
2016-08-02 07:08:05 +00:00
|
|
|
# Adds master replica to etcd cluster.
|
|
|
|
#
|
|
|
|
# Assumed vars:
|
|
|
|
# REPLICA_NAME
|
|
|
|
# PROJECT
|
|
|
|
# EXISTING_MASTER_NAME
|
|
|
|
# EXISTING_MASTER_ZONE
|
|
|
|
#
|
|
|
|
# $1: etcd client port
|
|
|
|
# $2: etcd internal port
|
|
|
|
# returns the result of ssh command which adds replica
|
|
|
|
function add-replica-to-etcd() {
|
|
|
|
local -r client_port="${1}"
|
|
|
|
local -r internal_port="${2}"
|
|
|
|
gcloud compute ssh "${EXISTING_MASTER_NAME}" \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--zone "${EXISTING_MASTER_ZONE}" \
|
|
|
|
--command \
|
2016-10-11 12:52:51 +00:00
|
|
|
"curl localhost:${client_port}/v2/members -XPOST -H \"Content-Type: application/json\" -d '{\"peerURLs\":[\"https://${REPLICA_NAME}:${internal_port}\"]}' -s"
|
2016-08-02 07:08:05 +00:00
|
|
|
return $?
|
|
|
|
}
|
|
|
|
|
|
|
|
# Sets EXISTING_MASTER_NAME and EXISTING_MASTER_ZONE variables.
|
|
|
|
#
|
|
|
|
# Assumed vars:
|
|
|
|
# PROJECT
|
|
|
|
#
|
|
|
|
# NOTE: Must be in sync with get-replica-name-regexp
|
|
|
|
function set-existing-master() {
|
|
|
|
local existing_master=$(gcloud compute instances list \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--regexp "$(get-replica-name-regexp)" \
|
|
|
|
--format "value(name,zone)" | head -n1)
|
|
|
|
EXISTING_MASTER_NAME="$(echo "${existing_master}" | cut -f1)"
|
|
|
|
EXISTING_MASTER_ZONE="$(echo "${existing_master}" | cut -f2)"
|
|
|
|
}
|
|
|
|
|
|
|
|
function replicate-master() {
|
|
|
|
set-replica-name
|
|
|
|
set-existing-master
|
|
|
|
|
2016-08-30 09:50:22 +00:00
|
|
|
echo "Experimental: replicating existing master ${EXISTING_MASTER_ZONE}/${EXISTING_MASTER_NAME} as ${ZONE}/${REPLICA_NAME}"
|
2016-08-02 07:08:05 +00:00
|
|
|
|
|
|
|
# Before we do anything else, we should configure etcd to expect more replicas.
|
2016-09-07 14:10:55 +00:00
|
|
|
if ! add-replica-to-etcd 2379 2380; then
|
2016-08-02 07:08:05 +00:00
|
|
|
echo "Failed to add master replica to etcd cluster."
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
if ! add-replica-to-etcd 4002 2381; then
|
|
|
|
echo "Failed to add master replica to etcd events cluster."
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
# We have to make sure the disk is created before creating the master VM, so
|
|
|
|
# run this in the foreground.
|
|
|
|
gcloud compute disks create "${REPLICA_NAME}-pd" \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--zone "${ZONE}" \
|
|
|
|
--type "${MASTER_DISK_TYPE}" \
|
|
|
|
--size "${MASTER_DISK_SIZE}"
|
|
|
|
|
|
|
|
local existing_master_replicas="$(get-all-replica-names)"
|
|
|
|
replicate-master-instance "${EXISTING_MASTER_ZONE}" "${EXISTING_MASTER_NAME}" "${existing_master_replicas}"
|
|
|
|
|
|
|
|
# Add new replica to the load balancer.
|
|
|
|
gcloud compute target-pools add-instances "${MASTER_NAME}" \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--zone "${ZONE}" \
|
|
|
|
--instances "${REPLICA_NAME}"
|
|
|
|
}
|
|
|
|
|
2016-07-20 14:37:31 +00:00
|
|
|
# Detaches old and ataches new external IP to a VM.
|
|
|
|
#
|
|
|
|
# Arguments:
|
|
|
|
# $1 - VM name
|
|
|
|
# $2 - VM zone
|
|
|
|
# $3 - external static IP; if empty will use an ephemeral IP address.
|
|
|
|
function attach-external-ip() {
|
|
|
|
local NAME=${1}
|
|
|
|
local ZONE=${2}
|
|
|
|
local IP_ADDR=${3:-}
|
|
|
|
local ACCESS_CONFIG_NAME=$(gcloud compute instances describe "${NAME}" \
|
|
|
|
--project "${PROJECT}" --zone "${ZONE}" \
|
|
|
|
--format="value(networkInterfaces[0].accessConfigs[0].name)")
|
|
|
|
gcloud compute instances delete-access-config "${NAME}" \
|
|
|
|
--project "${PROJECT}" --zone "${ZONE}" \
|
|
|
|
--access-config-name "${ACCESS_CONFIG_NAME}"
|
|
|
|
if [[ -z ${IP_ADDR} ]]; then
|
|
|
|
gcloud compute instances add-access-config "${NAME}" \
|
|
|
|
--project "${PROJECT}" --zone "${ZONE}" \
|
|
|
|
--access-config-name "${ACCESS_CONFIG_NAME}"
|
|
|
|
else
|
|
|
|
gcloud compute instances add-access-config "${NAME}" \
|
|
|
|
--project "${PROJECT}" --zone "${ZONE}" \
|
|
|
|
--access-config-name "${ACCESS_CONFIG_NAME}" \
|
|
|
|
--address "${IP_ADDR}"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
# Creates load balancer in front of apiserver if it doesn't exists already. Assumes there's only one
|
|
|
|
# existing master replica.
|
|
|
|
#
|
|
|
|
# Assumes:
|
|
|
|
# PROJECT
|
|
|
|
# MASTER_NAME
|
|
|
|
# ZONE
|
2016-07-20 15:25:25 +00:00
|
|
|
# REGION
|
2016-07-20 14:37:31 +00:00
|
|
|
function create-loadbalancer() {
|
|
|
|
detect-master
|
|
|
|
|
|
|
|
# Step 0: Return early if LB is already configured.
|
|
|
|
if gcloud compute forwarding-rules describe ${MASTER_NAME} \
|
|
|
|
--project "${PROJECT}" --region ${REGION} > /dev/null 2>&1; then
|
|
|
|
echo "Load balancer already exists"
|
|
|
|
return
|
|
|
|
fi
|
2016-11-22 13:27:55 +00:00
|
|
|
|
|
|
|
local EXISTING_MASTER_NAME="$(get-all-replica-names)"
|
|
|
|
local EXISTING_MASTER_ZONE=$(gcloud compute instances list "${EXISTING_MASTER_NAME}" \
|
2016-07-20 14:37:31 +00:00
|
|
|
--project "${PROJECT}" --format="value(zone)")
|
2016-11-22 13:27:55 +00:00
|
|
|
|
2016-07-20 14:37:31 +00:00
|
|
|
echo "Creating load balancer in front of an already existing master in ${EXISTING_MASTER_ZONE}"
|
|
|
|
|
|
|
|
# Step 1: Detach master IP address and attach ephemeral address to the existing master
|
2016-11-22 13:27:55 +00:00
|
|
|
attach-external-ip "${EXISTING_MASTER_NAME}" "${EXISTING_MASTER_ZONE}"
|
2016-07-20 14:37:31 +00:00
|
|
|
|
|
|
|
# Step 2: Create target pool.
|
2016-12-01 11:59:41 +00:00
|
|
|
gcloud compute target-pools create "${MASTER_NAME}" --project "${PROJECT}" --region "${REGION}"
|
2016-07-20 14:37:31 +00:00
|
|
|
# TODO: We should also add master instances with suffixes
|
2016-12-01 11:59:41 +00:00
|
|
|
gcloud compute target-pools add-instances "${MASTER_NAME}" --instances "${EXISTING_MASTER_NAME}" --project "${PROJECT}" --zone "${EXISTING_MASTER_ZONE}"
|
2016-07-20 14:37:31 +00:00
|
|
|
|
|
|
|
# Step 3: Create forwarding rule.
|
|
|
|
# TODO: This step can take up to 20 min. We need to speed this up...
|
|
|
|
gcloud compute forwarding-rules create ${MASTER_NAME} \
|
|
|
|
--project "${PROJECT}" --region ${REGION} \
|
|
|
|
--target-pool ${MASTER_NAME} --address=${KUBE_MASTER_IP} --ports=443
|
|
|
|
|
|
|
|
echo -n "Waiting for the load balancer configuration to propagate..."
|
2016-07-20 15:25:25 +00:00
|
|
|
local counter=0
|
|
|
|
until $(curl -k -m1 https://${KUBE_MASTER_IP} &> /dev/null); do
|
|
|
|
counter=$((counter+1))
|
|
|
|
echo -n .
|
|
|
|
if [[ ${counter} -ge 1800 ]]; then
|
|
|
|
echo -e "${color_red}TIMEOUT${color_norm}" >&2
|
|
|
|
echo -e "${color_red}Load balancer failed to initialize within ${counter} seconds.${color_norm}" >&2
|
|
|
|
exit 2
|
|
|
|
fi
|
|
|
|
done
|
2016-07-20 14:37:31 +00:00
|
|
|
echo "DONE"
|
|
|
|
}
|
|
|
|
|
2015-11-29 19:38:03 +00:00
|
|
|
function create-nodes-firewall() {
|
2014-12-16 18:22:29 +00:00
|
|
|
# Create a single firewall rule for all minions.
|
2015-11-24 03:06:00 +00:00
|
|
|
create-firewall-rule "${NODE_TAG}-all" "${CLUSTER_IP_RANGE}" "${NODE_TAG}" &
|
2014-12-09 23:37:06 +00:00
|
|
|
|
2015-02-23 21:57:09 +00:00
|
|
|
# Report logging choice (if any).
|
|
|
|
if [[ "${ENABLE_NODE_LOGGING-}" == "true" ]]; then
|
|
|
|
echo "+++ Logging using Fluentd to ${LOGGING_DESTINATION:-unknown}"
|
|
|
|
fi
|
|
|
|
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
# Wait for last batch of jobs
|
2016-01-11 23:23:21 +00:00
|
|
|
kube::util::wait-for-jobs || {
|
2016-01-22 22:42:32 +00:00
|
|
|
echo -e "${color_red}Some commands failed.${color_norm}" >&2
|
2016-01-11 23:23:21 +00:00
|
|
|
}
|
2015-11-29 19:38:03 +00:00
|
|
|
}
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
|
2017-06-28 17:50:58 +00:00
|
|
|
function get-scope-flags() {
|
2015-06-29 23:47:36 +00:00
|
|
|
local scope_flags=
|
2017-06-22 07:59:07 +00:00
|
|
|
if [[ -n "${NODE_SCOPES}" ]]; then
|
2015-11-24 03:05:07 +00:00
|
|
|
scope_flags="--scopes ${NODE_SCOPES}"
|
2014-12-09 23:37:06 +00:00
|
|
|
else
|
2015-06-29 23:47:36 +00:00
|
|
|
scope_flags="--no-scopes"
|
2014-12-09 23:37:06 +00:00
|
|
|
fi
|
2017-06-28 17:50:58 +00:00
|
|
|
echo "${scope_flags}"
|
|
|
|
}
|
|
|
|
|
|
|
|
function create-nodes-template() {
|
|
|
|
echo "Creating nodes."
|
|
|
|
|
|
|
|
local scope_flags=$(get-scope-flags)
|
2015-01-28 14:57:10 +00:00
|
|
|
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
write-node-env
|
2015-09-28 23:22:13 +00:00
|
|
|
|
|
|
|
local template_name="${NODE_INSTANCE_PREFIX}-template"
|
|
|
|
create-node-instance-template $template_name
|
2015-11-29 19:38:03 +00:00
|
|
|
}
|
|
|
|
|
2016-02-08 09:21:04 +00:00
|
|
|
# Assumes:
|
|
|
|
# - MAX_INSTANCES_PER_MIG
|
|
|
|
# - NUM_NODES
|
2016-02-26 00:00:16 +00:00
|
|
|
# exports:
|
2016-02-08 09:21:04 +00:00
|
|
|
# - NUM_MIGS
|
|
|
|
function set_num_migs() {
|
2016-03-14 11:19:51 +00:00
|
|
|
local defaulted_max_instances_per_mig=${MAX_INSTANCES_PER_MIG:-1000}
|
2015-12-11 08:09:09 +00:00
|
|
|
|
|
|
|
if [[ ${defaulted_max_instances_per_mig} -le "0" ]]; then
|
2016-03-14 11:19:51 +00:00
|
|
|
echo "MAX_INSTANCES_PER_MIG cannot be negative. Assuming default 1000"
|
|
|
|
defaulted_max_instances_per_mig=1000
|
2015-12-11 08:09:09 +00:00
|
|
|
fi
|
2016-02-08 09:21:04 +00:00
|
|
|
export NUM_MIGS=$(((${NUM_NODES} + ${defaulted_max_instances_per_mig} - 1) / ${defaulted_max_instances_per_mig}))
|
|
|
|
}
|
|
|
|
|
|
|
|
# Assumes:
|
|
|
|
# - NUM_MIGS
|
|
|
|
# - NODE_INSTANCE_PREFIX
|
|
|
|
# - NUM_NODES
|
|
|
|
# - PROJECT
|
|
|
|
# - ZONE
|
|
|
|
function create-nodes() {
|
|
|
|
local template_name="${NODE_INSTANCE_PREFIX}-template"
|
|
|
|
|
2017-06-28 17:50:58 +00:00
|
|
|
if [[ -z "${HEAPSTER_MACHINE_TYPE:-}" ]]; then
|
|
|
|
local -r nodes="${NUM_NODES}"
|
|
|
|
else
|
|
|
|
local -r nodes=$(( NUM_NODES - 1 ))
|
|
|
|
fi
|
|
|
|
|
|
|
|
local instances_left=${nodes}
|
2015-12-11 08:09:09 +00:00
|
|
|
|
|
|
|
#TODO: parallelize this loop to speed up the process
|
2016-05-09 14:23:00 +00:00
|
|
|
for ((i=1; i<=${NUM_MIGS}; i++)); do
|
|
|
|
local group_name="${NODE_INSTANCE_PREFIX}-group-$i"
|
|
|
|
if [[ $i == ${NUM_MIGS} ]]; then
|
|
|
|
# TODO: We don't add a suffix for the last group to keep backward compatibility when there's only one MIG.
|
|
|
|
# We should change it at some point, but note #18545 when changing this.
|
|
|
|
group_name="${NODE_INSTANCE_PREFIX}-group"
|
|
|
|
fi
|
|
|
|
# Spread the remaining number of nodes evenly
|
|
|
|
this_mig_size=$((${instances_left} / (${NUM_MIGS}-${i}+1)))
|
|
|
|
instances_left=$((instances_left-${this_mig_size}))
|
2016-06-23 18:22:04 +00:00
|
|
|
|
2015-12-11 08:09:09 +00:00
|
|
|
gcloud compute instance-groups managed \
|
2016-05-09 14:23:00 +00:00
|
|
|
create "${group_name}" \
|
2015-12-11 08:09:09 +00:00
|
|
|
--project "${PROJECT}" \
|
|
|
|
--zone "${ZONE}" \
|
2016-05-23 12:36:08 +00:00
|
|
|
--base-instance-name "${group_name}" \
|
2016-05-09 14:23:00 +00:00
|
|
|
--size "${this_mig_size}" \
|
2015-12-11 08:09:09 +00:00
|
|
|
--template "$template_name" || true;
|
|
|
|
gcloud compute instance-groups managed wait-until-stable \
|
2016-05-09 14:23:00 +00:00
|
|
|
"${group_name}" \
|
2016-04-13 19:40:34 +00:00
|
|
|
--zone "${ZONE}" \
|
|
|
|
--project "${PROJECT}" || true;
|
2015-12-11 08:09:09 +00:00
|
|
|
done
|
2017-06-28 17:50:58 +00:00
|
|
|
|
|
|
|
if [[ -n "${HEAPSTER_MACHINE_TYPE:-}" ]]; then
|
|
|
|
echo "Creating a special node for heapster with machine-type ${HEAPSTER_MACHINE_TYPE}"
|
|
|
|
create-heapster-node
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
# Assumes:
|
|
|
|
# - NODE_INSTANCE_PREFIX
|
|
|
|
# - PROJECT
|
|
|
|
# - ZONE
|
|
|
|
# - HEAPSTER_MACHINE_TYPE
|
|
|
|
# - NODE_DISK_TYPE
|
|
|
|
# - NODE_DISK_SIZE
|
|
|
|
# - NODE_IMAGE_PROJECT
|
|
|
|
# - NODE_IMAGE
|
|
|
|
# - NODE_TAG
|
|
|
|
# - NETWORK
|
|
|
|
# - ENABLE_IP_ALIASES
|
|
|
|
# - IP_ALIAS_SUBNETWORK
|
|
|
|
# - IP_ALIAS_SIZE
|
|
|
|
function create-heapster-node() {
|
|
|
|
local network=$(make-gcloud-network-argument \
|
|
|
|
"${NETWORK}" "" \
|
|
|
|
"${ENABLE_IP_ALIASES:-}" \
|
|
|
|
"${IP_ALIAS_SUBNETWORK:-}" \
|
|
|
|
"${IP_ALIAS_SIZE:-}")
|
|
|
|
|
|
|
|
gcloud compute instances \
|
|
|
|
create "${NODE_INSTANCE_PREFIX}-heapster" \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--zone "${ZONE}" \
|
|
|
|
--machine-type="${HEAPSTER_MACHINE_TYPE}" \
|
|
|
|
--boot-disk-type "${NODE_DISK_TYPE}" \
|
|
|
|
--boot-disk-size "${NODE_DISK_SIZE}" \
|
|
|
|
--image-project="${NODE_IMAGE_PROJECT}" \
|
|
|
|
--image "${NODE_IMAGE}" \
|
|
|
|
--tags "${NODE_TAG}" \
|
|
|
|
${network} \
|
|
|
|
$(get-scope-flags) \
|
|
|
|
--metadata-from-file "$(get-node-instance-metadata)"
|
2016-05-09 14:23:00 +00:00
|
|
|
}
|
2015-12-11 08:09:09 +00:00
|
|
|
|
2016-05-09 14:23:00 +00:00
|
|
|
# Assumes:
|
|
|
|
# - NUM_MIGS
|
|
|
|
# - NODE_INSTANCE_PREFIX
|
|
|
|
# - PROJECT
|
|
|
|
# - ZONE
|
|
|
|
# - AUTOSCALER_MAX_NODES
|
|
|
|
# - AUTOSCALER_MIN_NODES
|
|
|
|
# Exports
|
|
|
|
# - AUTOSCALER_MIG_CONFIG
|
|
|
|
function create-cluster-autoscaler-mig-config() {
|
|
|
|
|
|
|
|
# Each MIG must have at least one node, so the min number of nodes
|
2016-06-23 18:22:04 +00:00
|
|
|
# must be greater or equal to the number of migs.
|
2017-06-14 05:36:18 +00:00
|
|
|
if [[ ${AUTOSCALER_MIN_NODES} -lt 0 ]]; then
|
|
|
|
echo "AUTOSCALER_MIN_NODES must be greater or equal 0"
|
2016-05-31 17:41:54 +00:00
|
|
|
exit 2
|
2016-05-09 14:23:00 +00:00
|
|
|
fi
|
|
|
|
|
|
|
|
# Each MIG must have at least one node, so the min number of nodes
|
2016-06-23 18:22:04 +00:00
|
|
|
# must be greater or equal to the number of migs.
|
2017-05-19 12:50:55 +00:00
|
|
|
if [[ ${AUTOSCALER_MAX_NODES} -lt ${NUM_MIGS} ]]; then
|
2016-05-09 14:23:00 +00:00
|
|
|
echo "AUTOSCALER_MAX_NODES must be greater or equal ${NUM_MIGS}"
|
2016-05-31 17:41:54 +00:00
|
|
|
exit 2
|
2016-05-09 14:23:00 +00:00
|
|
|
fi
|
|
|
|
|
2016-06-23 18:22:04 +00:00
|
|
|
# The code assumes that the migs were created with create-nodes
|
2016-05-09 14:23:00 +00:00
|
|
|
# function which tries to evenly spread nodes across the migs.
|
|
|
|
AUTOSCALER_MIG_CONFIG=""
|
|
|
|
|
|
|
|
local left_min=${AUTOSCALER_MIN_NODES}
|
|
|
|
local left_max=${AUTOSCALER_MAX_NODES}
|
|
|
|
|
|
|
|
for ((i=1; i<=${NUM_MIGS}; i++)); do
|
|
|
|
local group_name="${NODE_INSTANCE_PREFIX}-group-$i"
|
|
|
|
if [[ $i == ${NUM_MIGS} ]]; then
|
|
|
|
# TODO: We don't add a suffix for the last group to keep backward compatibility when there's only one MIG.
|
|
|
|
# We should change it at some point, but note #18545 when changing this.
|
|
|
|
group_name="${NODE_INSTANCE_PREFIX}-group"
|
|
|
|
fi
|
|
|
|
|
|
|
|
this_mig_min=$((${left_min}/(${NUM_MIGS}-${i}+1)))
|
|
|
|
this_mig_max=$((${left_max}/(${NUM_MIGS}-${i}+1)))
|
|
|
|
left_min=$((left_min-$this_mig_min))
|
|
|
|
left_max=$((left_max-$this_mig_max))
|
|
|
|
|
|
|
|
local mig_url="https://www.googleapis.com/compute/v1/projects/${PROJECT}/zones/${ZONE}/instanceGroups/${group_name}"
|
|
|
|
AUTOSCALER_MIG_CONFIG="${AUTOSCALER_MIG_CONFIG} --nodes=${this_mig_min}:${this_mig_max}:${mig_url}"
|
|
|
|
done
|
2016-05-30 15:07:54 +00:00
|
|
|
|
2016-06-07 19:42:56 +00:00
|
|
|
AUTOSCALER_MIG_CONFIG="${AUTOSCALER_MIG_CONFIG} --scale-down-enabled=${AUTOSCALER_ENABLE_SCALE_DOWN}"
|
2015-11-29 19:38:03 +00:00
|
|
|
}
|
2015-12-11 08:09:09 +00:00
|
|
|
|
2016-02-08 09:21:04 +00:00
|
|
|
# Assumes:
|
|
|
|
# - NUM_MIGS
|
|
|
|
# - NODE_INSTANCE_PREFIX
|
|
|
|
# - PROJECT
|
|
|
|
# - ZONE
|
2016-06-07 20:10:17 +00:00
|
|
|
# - ENABLE_CLUSTER_AUTOSCALER
|
2016-02-08 09:21:04 +00:00
|
|
|
# - AUTOSCALER_MAX_NODES
|
|
|
|
# - AUTOSCALER_MIN_NODES
|
2016-05-09 14:23:00 +00:00
|
|
|
function create-autoscaler-config() {
|
|
|
|
# Create autoscaler for nodes configuration if requested
|
2016-06-07 20:10:17 +00:00
|
|
|
if [[ "${ENABLE_CLUSTER_AUTOSCALER}" == "true" ]]; then
|
2016-05-09 14:23:00 +00:00
|
|
|
create-cluster-autoscaler-mig-config
|
2017-06-16 07:54:22 +00:00
|
|
|
echo "Using autoscaler config: ${AUTOSCALER_MIG_CONFIG} ${AUTOSCALER_EXPANDER_CONFIG}"
|
2015-07-08 14:48:33 +00:00
|
|
|
fi
|
2015-11-29 19:38:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function check-cluster() {
|
|
|
|
detect-node-names
|
|
|
|
detect-master
|
2015-07-08 14:48:33 +00:00
|
|
|
|
2015-10-07 01:51:27 +00:00
|
|
|
echo "Waiting up to ${KUBE_CLUSTER_INITIALIZATION_TIMEOUT} seconds for cluster initialization."
|
2014-07-14 17:50:04 +00:00
|
|
|
echo
|
|
|
|
echo " This will continually check to see if the API for kubernetes is reachable."
|
2015-10-07 01:51:27 +00:00
|
|
|
echo " This may time out if there was some uncaught error during start up."
|
2014-07-14 17:50:04 +00:00
|
|
|
echo
|
|
|
|
|
2015-05-28 02:53:24 +00:00
|
|
|
# curl in mavericks is borked.
|
|
|
|
secure=""
|
2015-11-03 04:32:42 +00:00
|
|
|
if which sw_vers >& /dev/null; then
|
2015-05-28 02:53:24 +00:00
|
|
|
if [[ $(sw_vers | grep ProductVersion | awk '{print $2}') = "10.9."* ]]; then
|
|
|
|
secure="--insecure"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
2015-10-07 01:51:27 +00:00
|
|
|
local start_time=$(date +%s)
|
2015-05-11 18:43:44 +00:00
|
|
|
until curl --cacert "${CERT_DIR}/pki/ca.crt" \
|
|
|
|
-H "Authorization: Bearer ${KUBE_BEARER_TOKEN}" \
|
2015-05-28 02:53:24 +00:00
|
|
|
${secure} \
|
2015-04-17 21:04:14 +00:00
|
|
|
--max-time 5 --fail --output /dev/null --silent \
|
2015-06-30 02:30:14 +00:00
|
|
|
"https://${KUBE_MASTER_IP}/api/v1/pods"; do
|
2015-10-07 01:51:27 +00:00
|
|
|
local elapsed=$(($(date +%s) - ${start_time}))
|
|
|
|
if [[ ${elapsed} -gt ${KUBE_CLUSTER_INITIALIZATION_TIMEOUT} ]]; then
|
2015-10-07 18:19:32 +00:00
|
|
|
echo -e "${color_red}Cluster failed to initialize within ${KUBE_CLUSTER_INITIALIZATION_TIMEOUT} seconds.${color_norm}" >&2
|
2015-10-07 01:51:27 +00:00
|
|
|
exit 2
|
|
|
|
fi
|
2014-07-14 17:50:04 +00:00
|
|
|
printf "."
|
|
|
|
sleep 2
|
|
|
|
done
|
|
|
|
|
|
|
|
echo "Kubernetes cluster created."
|
2014-08-06 16:57:00 +00:00
|
|
|
|
2015-05-11 18:43:44 +00:00
|
|
|
export KUBE_CERT="${CERT_DIR}/pki/issued/kubecfg.crt"
|
|
|
|
export KUBE_KEY="${CERT_DIR}/pki/private/kubecfg.key"
|
|
|
|
export CA_CERT="${CERT_DIR}/pki/ca.crt"
|
2015-03-06 22:49:25 +00:00
|
|
|
export CONTEXT="${PROJECT}_${INSTANCE_PREFIX}"
|
2015-02-02 21:49:03 +00:00
|
|
|
(
|
|
|
|
umask 077
|
2016-06-08 00:30:15 +00:00
|
|
|
|
|
|
|
# Update the user's kubeconfig to include credentials for this apiserver.
|
2015-03-06 22:49:25 +00:00
|
|
|
create-kubeconfig
|
2016-06-08 00:30:15 +00:00
|
|
|
|
2016-06-20 23:10:47 +00:00
|
|
|
create-kubeconfig-for-federation
|
2014-09-23 22:54:27 +00:00
|
|
|
)
|
2014-12-09 23:37:06 +00:00
|
|
|
|
2015-08-22 01:47:31 +00:00
|
|
|
# ensures KUBECONFIG is set
|
|
|
|
get-kubeconfig-basicauth
|
2014-12-09 23:37:06 +00:00
|
|
|
echo
|
|
|
|
echo -e "${color_green}Kubernetes cluster is running. The master is running at:"
|
|
|
|
echo
|
|
|
|
echo -e "${color_yellow} https://${KUBE_MASTER_IP}"
|
|
|
|
echo
|
2015-03-06 22:49:25 +00:00
|
|
|
echo -e "${color_green}The user name and password to use is located in ${KUBECONFIG}.${color_norm}"
|
2014-12-09 23:37:06 +00:00
|
|
|
echo
|
|
|
|
|
2014-07-14 17:50:04 +00:00
|
|
|
}
|
|
|
|
|
2016-08-02 07:08:05 +00:00
|
|
|
# Removes master replica from etcd cluster.
|
|
|
|
#
|
|
|
|
# Assumed vars:
|
|
|
|
# REPLICA_NAME
|
|
|
|
# PROJECT
|
|
|
|
# EXISTING_MASTER_NAME
|
|
|
|
# EXISTING_MASTER_ZONE
|
|
|
|
#
|
|
|
|
# $1: etcd client port
|
|
|
|
# returns the result of ssh command which removes replica
|
|
|
|
function remove-replica-from-etcd() {
|
|
|
|
local -r port="${1}"
|
2016-10-19 00:32:56 +00:00
|
|
|
[[ -n "${EXISTING_MASTER_NAME}" ]] || return
|
2016-08-02 07:08:05 +00:00
|
|
|
gcloud compute ssh "${EXISTING_MASTER_NAME}" \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--zone "${EXISTING_MASTER_ZONE}" \
|
|
|
|
--command \
|
2016-09-28 13:25:18 +00:00
|
|
|
"curl -s localhost:${port}/v2/members/\$(curl -s localhost:${port}/v2/members -XGET | sed 's/{\\\"id/\n/g' | grep ${REPLICA_NAME}\\\" | cut -f 3 -d \\\") -XDELETE -L 2>/dev/null"
|
|
|
|
local -r res=$?
|
|
|
|
echo "Removing etcd replica, name: ${REPLICA_NAME}, port: ${port}, result: ${res}"
|
|
|
|
return "${res}"
|
2016-08-02 07:08:05 +00:00
|
|
|
}
|
|
|
|
|
2014-12-09 23:07:54 +00:00
|
|
|
# Delete a kubernetes cluster. This is called from test-teardown.
|
2014-12-09 00:52:43 +00:00
|
|
|
#
|
|
|
|
# Assumed vars:
|
|
|
|
# MASTER_NAME
|
2015-01-28 14:57:10 +00:00
|
|
|
# NODE_INSTANCE_PREFIX
|
2014-12-09 00:52:43 +00:00
|
|
|
# ZONE
|
|
|
|
# This function tears down cluster resources 10 at a time to avoid issuing too many
|
|
|
|
# API calls and exceeding API quota. It is important to bring down the instances before bringing
|
|
|
|
# down the firewall rules and routes.
|
2016-08-02 07:08:05 +00:00
|
|
|
function kube-down() {
|
2016-06-13 21:01:59 +00:00
|
|
|
local -r batch=200
|
|
|
|
|
2014-07-14 17:50:04 +00:00
|
|
|
detect-project
|
2015-12-11 08:09:09 +00:00
|
|
|
detect-node-names # For INSTANCE_GROUPS
|
2014-07-14 17:50:04 +00:00
|
|
|
|
|
|
|
echo "Bringing down cluster"
|
2015-05-12 23:12:15 +00:00
|
|
|
set +e # Do not stop on error
|
2014-12-09 00:52:43 +00:00
|
|
|
|
2016-09-16 14:51:52 +00:00
|
|
|
if [[ "${KUBE_DELETE_NODES:-}" != "false" ]]; then
|
|
|
|
# Get the name of the managed instance group template before we delete the
|
|
|
|
# managed instance group. (The name of the managed instance group template may
|
|
|
|
# change during a cluster upgrade.)
|
|
|
|
local templates=$(get-template "${PROJECT}")
|
|
|
|
|
|
|
|
for group in ${INSTANCE_GROUPS[@]:-}; do
|
|
|
|
if gcloud compute instance-groups managed describe "${group}" --project "${PROJECT}" --zone "${ZONE}" &>/dev/null; then
|
|
|
|
gcloud compute instance-groups managed delete \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--quiet \
|
|
|
|
--zone "${ZONE}" \
|
|
|
|
"${group}" &
|
|
|
|
fi
|
|
|
|
done
|
2016-06-13 21:01:59 +00:00
|
|
|
|
2016-09-16 14:51:52 +00:00
|
|
|
# Wait for last batch of jobs
|
|
|
|
kube::util::wait-for-jobs || {
|
|
|
|
echo -e "Failed to delete instance group(s)." >&2
|
|
|
|
}
|
|
|
|
|
|
|
|
for template in ${templates[@]:-}; do
|
|
|
|
if gcloud compute instance-templates describe --project "${PROJECT}" "${template}" &>/dev/null; then
|
|
|
|
gcloud compute instance-templates delete \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--quiet \
|
|
|
|
"${template}"
|
|
|
|
fi
|
|
|
|
done
|
2017-06-28 17:50:58 +00:00
|
|
|
|
|
|
|
# Delete the special heapster node (if it exists).
|
|
|
|
if [[ -n "${HEAPSTER_MACHINE_TYPE:-}" ]]; then
|
|
|
|
local -r heapster_machine_name="${NODE_INSTANCE_PREFIX}-heapster"
|
|
|
|
if gcloud compute instances describe "${heapster_machine_name}" --zone "${ZONE}" --project "${PROJECT}" &>/dev/null; then
|
|
|
|
# Now we can safely delete the VM.
|
|
|
|
gcloud compute instances delete \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--quiet \
|
|
|
|
--delete-disks all \
|
|
|
|
--zone "${ZONE}" \
|
|
|
|
"${heapster_machine_name}"
|
|
|
|
fi
|
|
|
|
fi
|
2016-09-16 14:51:52 +00:00
|
|
|
fi
|
2015-01-28 14:57:10 +00:00
|
|
|
|
2016-11-23 14:41:54 +00:00
|
|
|
local -r REPLICA_NAME="${KUBE_REPLICA_NAME:-$(get-replica-name)}"
|
2016-08-02 07:08:05 +00:00
|
|
|
|
|
|
|
set-existing-master
|
|
|
|
|
|
|
|
# Un-register the master replica from etcd and events etcd.
|
2016-09-07 14:10:55 +00:00
|
|
|
remove-replica-from-etcd 2379
|
2016-08-02 07:08:05 +00:00
|
|
|
remove-replica-from-etcd 4002
|
|
|
|
|
|
|
|
# Delete the master replica (if it exists).
|
|
|
|
if gcloud compute instances describe "${REPLICA_NAME}" --zone "${ZONE}" --project "${PROJECT}" &>/dev/null; then
|
|
|
|
# If there is a load balancer in front of apiservers we need to first update its configuration.
|
|
|
|
if gcloud compute target-pools describe "${MASTER_NAME}" --region "${REGION}" --project "${PROJECT}" &>/dev/null; then
|
|
|
|
gcloud compute target-pools remove-instances "${MASTER_NAME}" \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--zone "${ZONE}" \
|
|
|
|
--instances "${REPLICA_NAME}"
|
|
|
|
fi
|
|
|
|
# Now we can safely delete the VM.
|
2015-05-29 18:46:10 +00:00
|
|
|
gcloud compute instances delete \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--quiet \
|
|
|
|
--delete-disks all \
|
|
|
|
--zone "${ZONE}" \
|
2016-08-02 07:08:05 +00:00
|
|
|
"${REPLICA_NAME}"
|
2015-05-29 18:46:10 +00:00
|
|
|
fi
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
|
2016-08-02 07:08:05 +00:00
|
|
|
# Delete the master replica pd (possibly leaked by kube-up if master create failed).
|
2016-09-14 10:00:46 +00:00
|
|
|
# TODO(jszczepkowski): remove also possibly leaked replicas' pds
|
2016-09-19 19:00:08 +00:00
|
|
|
local -r replica_pd="${REPLICA_NAME:-${MASTER_NAME}}-pd"
|
|
|
|
if gcloud compute disks describe "${replica_pd}" --zone "${ZONE}" --project "${PROJECT}" &>/dev/null; then
|
2015-05-29 18:46:10 +00:00
|
|
|
gcloud compute disks delete \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--quiet \
|
|
|
|
--zone "${ZONE}" \
|
2016-09-19 19:00:08 +00:00
|
|
|
"${replica_pd}"
|
2015-05-29 18:46:10 +00:00
|
|
|
fi
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
|
2015-07-27 18:50:31 +00:00
|
|
|
# Delete disk for cluster registry if enabled
|
|
|
|
if [[ "${ENABLE_CLUSTER_REGISTRY}" == true && -n "${CLUSTER_REGISTRY_DISK}" ]]; then
|
|
|
|
if gcloud compute disks describe "${CLUSTER_REGISTRY_DISK}" --zone "${ZONE}" --project "${PROJECT}" &>/dev/null; then
|
|
|
|
gcloud compute disks delete \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--quiet \
|
|
|
|
--zone "${ZONE}" \
|
|
|
|
"${CLUSTER_REGISTRY_DISK}"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
2016-07-20 14:37:31 +00:00
|
|
|
# Check if this are any remaining master replicas.
|
|
|
|
local REMAINING_MASTER_COUNT=$(gcloud compute instances list \
|
|
|
|
--project "${PROJECT}" \
|
2016-08-02 07:08:05 +00:00
|
|
|
--regexp "$(get-replica-name-regexp)" \
|
2016-07-20 14:37:31 +00:00
|
|
|
--format "value(zone)" | wc -l)
|
|
|
|
|
|
|
|
# In the replicated scenario, if there's only a single master left, we should also delete load balancer in front of it.
|
2016-11-29 17:50:31 +00:00
|
|
|
if [[ "${REMAINING_MASTER_COUNT}" -eq 1 ]]; then
|
2016-07-20 14:37:31 +00:00
|
|
|
if gcloud compute forwarding-rules describe "${MASTER_NAME}" --region "${REGION}" --project "${PROJECT}" &>/dev/null; then
|
|
|
|
detect-master
|
2016-10-11 12:52:51 +00:00
|
|
|
local REMAINING_REPLICA_NAME="$(get-all-replica-names)"
|
2016-09-28 13:25:18 +00:00
|
|
|
local REMAINING_REPLICA_ZONE=$(gcloud compute instances list "${REMAINING_REPLICA_NAME}" \
|
2016-07-20 14:37:31 +00:00
|
|
|
--project "${PROJECT}" --format="value(zone)")
|
|
|
|
gcloud compute forwarding-rules delete \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--region "${REGION}" \
|
|
|
|
--quiet \
|
|
|
|
"${MASTER_NAME}"
|
2016-09-28 13:25:18 +00:00
|
|
|
attach-external-ip "${REMAINING_REPLICA_NAME}" "${REMAINING_REPLICA_ZONE}" "${KUBE_MASTER_IP}"
|
2016-07-20 14:37:31 +00:00
|
|
|
gcloud compute target-pools delete \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--region "${REGION}" \
|
|
|
|
--quiet \
|
|
|
|
"${MASTER_NAME}"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
# If there are no more remaining master replicas, we should delete all remaining network resources.
|
2016-11-29 17:50:31 +00:00
|
|
|
if [[ "${REMAINING_MASTER_COUNT}" -eq 0 ]]; then
|
2016-10-11 23:50:30 +00:00
|
|
|
# Delete firewall rule for the master, etcd servers, and nodes.
|
|
|
|
delete-firewall-rules "${MASTER_NAME}-https" "${MASTER_NAME}-etcd" "${NODE_TAG}-all"
|
2016-07-20 14:37:31 +00:00
|
|
|
# Delete the master's reserved IP
|
|
|
|
if gcloud compute addresses describe "${MASTER_NAME}-ip" --region "${REGION}" --project "${PROJECT}" &>/dev/null; then
|
|
|
|
gcloud compute addresses delete \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--region "${REGION}" \
|
|
|
|
--quiet \
|
|
|
|
"${MASTER_NAME}-ip"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
2016-09-16 14:51:52 +00:00
|
|
|
if [[ "${KUBE_DELETE_NODES:-}" != "false" ]]; then
|
|
|
|
# Find out what minions are running.
|
|
|
|
local -a minions
|
|
|
|
minions=( $(gcloud compute instances list \
|
|
|
|
--project "${PROJECT}" --zones "${ZONE}" \
|
|
|
|
--regexp "${NODE_INSTANCE_PREFIX}-.+" \
|
|
|
|
--format='value(name)') )
|
|
|
|
# If any minions are running, delete them in batches.
|
|
|
|
while (( "${#minions[@]}" > 0 )); do
|
|
|
|
echo Deleting nodes "${minions[*]::${batch}}"
|
|
|
|
gcloud compute instances delete \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--quiet \
|
|
|
|
--delete-disks boot \
|
|
|
|
--zone "${ZONE}" \
|
|
|
|
"${minions[@]::${batch}}"
|
|
|
|
minions=( "${minions[@]:${batch}}" )
|
|
|
|
done
|
|
|
|
fi
|
2014-08-13 20:26:03 +00:00
|
|
|
|
2016-09-28 13:25:18 +00:00
|
|
|
# If there are no more remaining master replicas: delete routes, pd for influxdb and update kubeconfig
|
2016-11-29 17:50:31 +00:00
|
|
|
if [[ "${REMAINING_MASTER_COUNT}" -eq 0 ]]; then
|
2016-09-28 13:25:18 +00:00
|
|
|
# Delete routes.
|
|
|
|
local -a routes
|
|
|
|
# Clean up all routes w/ names like "<cluster-name>-<node-GUID>"
|
|
|
|
# e.g. "kubernetes-12345678-90ab-cdef-1234-567890abcdef". The name is
|
|
|
|
# determined by the node controller on the master.
|
|
|
|
# Note that this is currently a noop, as synchronously deleting the node MIG
|
|
|
|
# first allows the master to cleanup routes itself.
|
|
|
|
local TRUNCATED_PREFIX="${INSTANCE_PREFIX:0:26}"
|
|
|
|
routes=( $(gcloud compute routes list --project "${PROJECT}" \
|
|
|
|
--regexp "${TRUNCATED_PREFIX}-.{8}-.{4}-.{4}-.{4}-.{12}" \
|
|
|
|
--format='value(name)') )
|
|
|
|
while (( "${#routes[@]}" > 0 )); do
|
|
|
|
echo Deleting routes "${routes[*]::${batch}}"
|
|
|
|
gcloud compute routes delete \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--quiet \
|
|
|
|
"${routes[@]::${batch}}"
|
|
|
|
routes=( "${routes[@]:${batch}}" )
|
|
|
|
done
|
2014-07-14 17:50:04 +00:00
|
|
|
|
2016-09-28 13:25:18 +00:00
|
|
|
# Delete persistent disk for influx-db.
|
|
|
|
if gcloud compute disks describe "${INSTANCE_PREFIX}"-influxdb-pd --zone "${ZONE}" --project "${PROJECT}" &>/dev/null; then
|
|
|
|
gcloud compute disks delete \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--quiet \
|
|
|
|
--zone "${ZONE}" \
|
|
|
|
"${INSTANCE_PREFIX}"-influxdb-pd
|
|
|
|
fi
|
2016-06-21 07:43:36 +00:00
|
|
|
|
2016-09-28 13:25:18 +00:00
|
|
|
# Delete all remaining firewall rules and network.
|
|
|
|
delete-firewall-rules \
|
2016-12-13 19:21:14 +00:00
|
|
|
"${CLUSTER_NAME}-default-internal-master" \
|
|
|
|
"${CLUSTER_NAME}-default-internal-node" \
|
2016-09-28 13:25:18 +00:00
|
|
|
"${NETWORK}-default-ssh" \
|
|
|
|
"${NETWORK}-default-internal" # Pre-1.5 clusters
|
2017-02-27 08:31:13 +00:00
|
|
|
|
2016-09-28 13:25:18 +00:00
|
|
|
if [[ "${KUBE_DELETE_NETWORK}" == "true" ]]; then
|
2017-06-14 11:23:41 +00:00
|
|
|
delete-subnetworks || true
|
2016-09-28 13:25:18 +00:00
|
|
|
delete-network || true # might fail if there are leaked firewall rules
|
|
|
|
fi
|
2016-10-11 23:50:30 +00:00
|
|
|
|
2016-09-28 13:25:18 +00:00
|
|
|
# If there are no more remaining master replicas, we should update kubeconfig.
|
2016-07-20 15:25:25 +00:00
|
|
|
export CONTEXT="${PROJECT}_${INSTANCE_PREFIX}"
|
|
|
|
clear-kubeconfig
|
2016-10-11 12:52:51 +00:00
|
|
|
else
|
|
|
|
# If some master replicas remain: cluster has been changed, we need to re-validate it.
|
|
|
|
echo "... calling validate-cluster" >&2
|
|
|
|
# Override errexit
|
|
|
|
(validate-cluster) && validate_result="$?" || validate_result="$?"
|
|
|
|
|
|
|
|
# We have two different failure modes from validate cluster:
|
|
|
|
# - 1: fatal error - cluster won't be working correctly
|
|
|
|
# - 2: weak error - something went wrong, but cluster probably will be working correctly
|
|
|
|
# We just print an error message in case 2).
|
2016-11-29 17:50:31 +00:00
|
|
|
if [[ "${validate_result}" -eq 1 ]]; then
|
2016-10-11 12:52:51 +00:00
|
|
|
exit 1
|
2016-11-29 17:50:31 +00:00
|
|
|
elif [[ "${validate_result}" -eq 2 ]]; then
|
2016-10-11 12:52:51 +00:00
|
|
|
echo "...ignoring non-fatal errors in validate-cluster" >&2
|
|
|
|
fi
|
2016-07-20 15:25:25 +00:00
|
|
|
fi
|
2015-05-12 23:12:15 +00:00
|
|
|
set -e
|
2014-07-14 17:50:04 +00:00
|
|
|
}
|
|
|
|
|
2016-08-02 07:08:05 +00:00
|
|
|
# Prints name of one of the master replicas in the current zone. It will be either
|
|
|
|
# just MASTER_NAME or MASTER_NAME with a suffix for a replica (see get-replica-name-regexp).
|
|
|
|
#
|
|
|
|
# Assumed vars:
|
|
|
|
# PROJECT
|
|
|
|
# ZONE
|
|
|
|
# MASTER_NAME
|
|
|
|
#
|
|
|
|
# NOTE: Must be in sync with get-replica-name-regexp and set-replica-name.
|
|
|
|
function get-replica-name() {
|
|
|
|
echo $(gcloud compute instances list \
|
|
|
|
--project "${PROJECT}" \
|
2016-10-11 23:52:09 +00:00
|
|
|
--zones "${ZONE}" \
|
2016-08-02 07:08:05 +00:00
|
|
|
--regexp "$(get-replica-name-regexp)" \
|
|
|
|
--format "value(name)" | head -n1)
|
|
|
|
}
|
|
|
|
|
|
|
|
# Prints comma-separated names of all of the master replicas in all zones.
|
|
|
|
#
|
|
|
|
# Assumed vars:
|
|
|
|
# PROJECT
|
|
|
|
# MASTER_NAME
|
|
|
|
#
|
|
|
|
# NOTE: Must be in sync with get-replica-name-regexp and set-replica-name.
|
|
|
|
function get-all-replica-names() {
|
|
|
|
echo $(gcloud compute instances list \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--regexp "$(get-replica-name-regexp)" \
|
|
|
|
--format "value(name)" | tr "\n" "," | sed 's/,$//')
|
|
|
|
}
|
|
|
|
|
2016-10-11 12:52:51 +00:00
|
|
|
# Prints the number of all of the master replicas in all zones.
|
|
|
|
#
|
|
|
|
# Assumed vars:
|
|
|
|
# MASTER_NAME
|
|
|
|
function get-master-replicas-count() {
|
|
|
|
detect-project
|
|
|
|
local num_masters=$(gcloud compute instances list \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--regexp "$(get-replica-name-regexp)" \
|
|
|
|
--format "value(zone)" | wc -l)
|
|
|
|
echo -n "${num_masters}"
|
|
|
|
}
|
|
|
|
|
2016-08-02 07:08:05 +00:00
|
|
|
# Prints regexp for full master machine name. In a cluster with replicated master,
|
|
|
|
# VM names may either be MASTER_NAME or MASTER_NAME with a suffix for a replica.
|
|
|
|
function get-replica-name-regexp() {
|
|
|
|
echo "${MASTER_NAME}(-...)?"
|
|
|
|
}
|
|
|
|
|
|
|
|
# Sets REPLICA_NAME to a unique name for a master replica that will match
|
|
|
|
# expected regexp (see get-replica-name-regexp).
|
|
|
|
#
|
|
|
|
# Assumed vars:
|
|
|
|
# PROJECT
|
|
|
|
# ZONE
|
|
|
|
# MASTER_NAME
|
|
|
|
#
|
|
|
|
# Sets:
|
|
|
|
# REPLICA_NAME
|
|
|
|
function set-replica-name() {
|
|
|
|
local instances=$(gcloud compute instances list \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--regexp "$(get-replica-name-regexp)" \
|
|
|
|
--format "value(name)")
|
|
|
|
|
|
|
|
suffix=""
|
|
|
|
while echo "${instances}" | grep "${suffix}" &>/dev/null; do
|
|
|
|
suffix="$(date | md5sum | head -c3)"
|
|
|
|
done
|
|
|
|
REPLICA_NAME="${MASTER_NAME}-${suffix}"
|
|
|
|
}
|
|
|
|
|
2016-02-22 12:05:34 +00:00
|
|
|
# Gets the instance template for given NODE_INSTANCE_PREFIX. It echos the template name so that the function
|
2015-07-09 19:01:06 +00:00
|
|
|
# output can be used.
|
2016-02-22 12:05:34 +00:00
|
|
|
# Assumed vars:
|
|
|
|
# NODE_INSTANCE_PREFIX
|
2015-07-09 19:01:06 +00:00
|
|
|
#
|
|
|
|
# $1: project
|
2016-08-02 07:08:05 +00:00
|
|
|
function get-template() {
|
2016-06-22 12:09:37 +00:00
|
|
|
gcloud compute instance-templates list -r "${NODE_INSTANCE_PREFIX}-template(-(${KUBE_RELEASE_VERSION_DASHED_REGEX}|${KUBE_CI_VERSION_DASHED_REGEX}))?" \
|
2016-05-04 21:10:00 +00:00
|
|
|
--project="${1}" --format='value(name)'
|
2015-07-09 19:01:06 +00:00
|
|
|
}
|
|
|
|
|
2015-06-15 16:21:27 +00:00
|
|
|
# Checks if there are any present resources related kubernetes cluster.
|
|
|
|
#
|
|
|
|
# Assumed vars:
|
|
|
|
# MASTER_NAME
|
|
|
|
# NODE_INSTANCE_PREFIX
|
|
|
|
# ZONE
|
2016-07-20 15:25:25 +00:00
|
|
|
# REGION
|
2015-06-15 16:21:27 +00:00
|
|
|
# Vars set:
|
|
|
|
# KUBE_RESOURCE_FOUND
|
2016-08-02 07:08:05 +00:00
|
|
|
function check-resources() {
|
2015-06-15 16:21:27 +00:00
|
|
|
detect-project
|
2015-12-11 08:09:09 +00:00
|
|
|
detect-node-names
|
2015-06-15 16:21:27 +00:00
|
|
|
|
|
|
|
echo "Looking for already existing resources"
|
|
|
|
KUBE_RESOURCE_FOUND=""
|
|
|
|
|
2015-12-11 08:09:09 +00:00
|
|
|
if [[ -n "${INSTANCE_GROUPS[@]:-}" ]]; then
|
|
|
|
KUBE_RESOURCE_FOUND="Managed instance groups ${INSTANCE_GROUPS[@]}"
|
2015-06-15 16:21:27 +00:00
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
2015-06-17 12:59:12 +00:00
|
|
|
if gcloud compute instance-templates describe --project "${PROJECT}" "${NODE_INSTANCE_PREFIX}-template" &>/dev/null; then
|
2015-06-15 16:21:27 +00:00
|
|
|
KUBE_RESOURCE_FOUND="Instance template ${NODE_INSTANCE_PREFIX}-template"
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
2015-06-17 12:59:12 +00:00
|
|
|
if gcloud compute instances describe --project "${PROJECT}" "${MASTER_NAME}" --zone "${ZONE}" &>/dev/null; then
|
2015-06-15 16:21:27 +00:00
|
|
|
KUBE_RESOURCE_FOUND="Kubernetes master ${MASTER_NAME}"
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
2015-06-17 12:59:12 +00:00
|
|
|
if gcloud compute disks describe --project "${PROJECT}" "${MASTER_NAME}"-pd --zone "${ZONE}" &>/dev/null; then
|
2015-06-15 16:21:27 +00:00
|
|
|
KUBE_RESOURCE_FOUND="Persistent disk ${MASTER_NAME}-pd"
|
|
|
|
return 1
|
|
|
|
fi
|
2015-07-27 18:50:31 +00:00
|
|
|
|
|
|
|
if gcloud compute disks describe --project "${PROJECT}" "${CLUSTER_REGISTRY_DISK}" --zone "${ZONE}" &>/dev/null; then
|
|
|
|
KUBE_RESOURCE_FOUND="Persistent disk ${CLUSTER_REGISTRY_DISK}"
|
|
|
|
return 1
|
|
|
|
fi
|
2015-06-15 16:21:27 +00:00
|
|
|
|
|
|
|
# Find out what minions are running.
|
|
|
|
local -a minions
|
|
|
|
minions=( $(gcloud compute instances list \
|
2016-08-01 10:44:13 +00:00
|
|
|
--project "${PROJECT}" --zones "${ZONE}" \
|
2015-06-15 16:21:27 +00:00
|
|
|
--regexp "${NODE_INSTANCE_PREFIX}-.+" \
|
2016-05-04 21:10:00 +00:00
|
|
|
--format='value(name)') )
|
2015-06-15 16:21:27 +00:00
|
|
|
if (( "${#minions[@]}" > 0 )); then
|
|
|
|
KUBE_RESOURCE_FOUND="${#minions[@]} matching matching ${NODE_INSTANCE_PREFIX}-.+"
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
2015-06-17 12:59:12 +00:00
|
|
|
if gcloud compute firewall-rules describe --project "${PROJECT}" "${MASTER_NAME}-https" &>/dev/null; then
|
2015-06-19 15:17:06 +00:00
|
|
|
KUBE_RESOURCE_FOUND="Firewall rules for ${MASTER_NAME}-https"
|
2015-06-15 16:21:27 +00:00
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
2015-11-24 03:06:00 +00:00
|
|
|
if gcloud compute firewall-rules describe --project "${PROJECT}" "${NODE_TAG}-all" &>/dev/null; then
|
2015-06-19 15:17:06 +00:00
|
|
|
KUBE_RESOURCE_FOUND="Firewall rules for ${MASTER_NAME}-all"
|
2015-06-15 16:21:27 +00:00
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
local -a routes
|
|
|
|
routes=( $(gcloud compute routes list --project "${PROJECT}" \
|
2016-05-04 21:10:00 +00:00
|
|
|
--regexp "${INSTANCE_PREFIX}-minion-.{4}" --format='value(name)') )
|
2015-06-15 16:21:27 +00:00
|
|
|
if (( "${#routes[@]}" > 0 )); then
|
|
|
|
KUBE_RESOURCE_FOUND="${#routes[@]} routes matching ${INSTANCE_PREFIX}-minion-.{4}"
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
2015-06-17 12:59:12 +00:00
|
|
|
if gcloud compute addresses describe --project "${PROJECT}" "${MASTER_NAME}-ip" --region "${REGION}" &>/dev/null; then
|
2015-06-15 16:21:27 +00:00
|
|
|
KUBE_RESOURCE_FOUND="Master's reserved IP"
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
# No resources found.
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
2015-06-01 15:59:12 +00:00
|
|
|
# Prepare to push new binaries to kubernetes cluster
|
|
|
|
# $1 - whether prepare push to node
|
|
|
|
function prepare-push() {
|
2016-06-23 18:22:04 +00:00
|
|
|
local node="${1-}"
|
2016-12-29 23:10:06 +00:00
|
|
|
#TODO(dawnchen): figure out how to upgrade a Container Linux node
|
2016-06-23 18:22:04 +00:00
|
|
|
if [[ "${node}" == "true" && "${NODE_OS_DISTRIBUTION}" != "debian" ]]; then
|
|
|
|
echo "Updating nodes in a kubernetes cluster with ${NODE_OS_DISTRIBUTION} is not supported yet." >&2
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
if [[ "${node}" != "true" && "${MASTER_OS_DISTRIBUTION}" != "debian" ]]; then
|
|
|
|
echo "Updating the master in a kubernetes cluster with ${MASTER_OS_DISTRIBUTION} is not supported yet." >&2
|
2015-06-01 15:59:12 +00:00
|
|
|
exit 1
|
2015-04-28 15:50:43 +00:00
|
|
|
fi
|
|
|
|
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
OUTPUT=${KUBE_ROOT}/_output/logs
|
|
|
|
mkdir -p ${OUTPUT}
|
|
|
|
|
2017-03-11 06:18:38 +00:00
|
|
|
kube::util::ensure-temp-dir
|
2014-09-23 22:54:27 +00:00
|
|
|
detect-project
|
2014-07-14 17:50:04 +00:00
|
|
|
detect-master
|
2015-11-09 07:33:06 +00:00
|
|
|
detect-node-names
|
2015-08-22 01:47:31 +00:00
|
|
|
get-kubeconfig-basicauth
|
|
|
|
get-kubeconfig-bearertoken
|
2014-07-14 17:50:04 +00:00
|
|
|
|
2014-09-23 22:54:27 +00:00
|
|
|
# Make sure we have the tar files staged on Google Storage
|
2015-06-01 15:59:12 +00:00
|
|
|
tars_from_version
|
|
|
|
|
|
|
|
# Prepare node env vars and update MIG template
|
2016-06-23 18:22:04 +00:00
|
|
|
if [[ "${node}" == "true" ]]; then
|
2015-06-01 15:59:12 +00:00
|
|
|
write-node-env
|
|
|
|
|
2017-06-28 17:50:58 +00:00
|
|
|
local scope_flags=$(get-scope-flags)
|
2015-06-01 15:59:12 +00:00
|
|
|
|
|
|
|
# Ugly hack: Since it is not possible to delete instance-template that is currently
|
|
|
|
# being used, create a temp one, then delete the old one and recreate it once again.
|
2015-09-28 23:22:13 +00:00
|
|
|
local tmp_template_name="${NODE_INSTANCE_PREFIX}-template-tmp"
|
|
|
|
create-node-instance-template $tmp_template_name
|
2015-06-01 15:59:12 +00:00
|
|
|
|
2015-09-28 23:22:13 +00:00
|
|
|
local template_name="${NODE_INSTANCE_PREFIX}-template"
|
2015-12-18 10:12:07 +00:00
|
|
|
for group in ${INSTANCE_GROUPS[@]:-}; do
|
2015-12-11 08:09:09 +00:00
|
|
|
gcloud compute instance-groups managed \
|
|
|
|
set-instance-template "${group}" \
|
|
|
|
--template "$tmp_template_name" \
|
|
|
|
--zone "${ZONE}" \
|
|
|
|
--project "${PROJECT}" || true;
|
|
|
|
done
|
2015-06-01 15:59:12 +00:00
|
|
|
|
|
|
|
gcloud compute instance-templates delete \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--quiet \
|
2015-09-28 23:22:13 +00:00
|
|
|
"$template_name" || true
|
2015-06-01 15:59:12 +00:00
|
|
|
|
2015-09-28 23:22:13 +00:00
|
|
|
create-node-instance-template "$template_name"
|
2015-06-01 15:59:12 +00:00
|
|
|
|
2015-12-18 10:12:07 +00:00
|
|
|
for group in ${INSTANCE_GROUPS[@]:-}; do
|
2015-12-11 08:09:09 +00:00
|
|
|
gcloud compute instance-groups managed \
|
|
|
|
set-instance-template "${group}" \
|
|
|
|
--template "$template_name" \
|
|
|
|
--zone "${ZONE}" \
|
|
|
|
--project "${PROJECT}" || true;
|
|
|
|
done
|
2014-09-23 22:54:27 +00:00
|
|
|
|
2015-06-01 15:59:12 +00:00
|
|
|
gcloud compute instance-templates delete \
|
|
|
|
--project "${PROJECT}" \
|
|
|
|
--quiet \
|
2015-09-28 23:22:13 +00:00
|
|
|
"$tmp_template_name" || true
|
2015-06-01 15:59:12 +00:00
|
|
|
fi
|
|
|
|
}
|
2014-09-23 22:54:27 +00:00
|
|
|
|
2015-06-01 15:59:12 +00:00
|
|
|
# Push binaries to kubernetes master
|
2016-08-02 07:08:05 +00:00
|
|
|
function push-master() {
|
2015-04-17 17:58:26 +00:00
|
|
|
echo "Updating master metadata ..."
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
write-master-env
|
2016-04-11 22:13:02 +00:00
|
|
|
prepare-startup-script
|
|
|
|
add-instance-metadata-from-file "${KUBE_MASTER}" "kube-env=${KUBE_TEMP}/master-kube-env.yaml" "startup-script=${KUBE_TEMP}/configure-vm.sh"
|
2015-04-17 17:58:26 +00:00
|
|
|
|
2015-06-01 15:59:12 +00:00
|
|
|
echo "Pushing to master (log at ${OUTPUT}/push-${KUBE_MASTER}.log) ..."
|
2016-04-11 22:13:02 +00:00
|
|
|
cat ${KUBE_TEMP}/configure-vm.sh | gcloud compute ssh --ssh-flag="-o LogLevel=quiet" --project "${PROJECT}" --zone "${ZONE}" "${KUBE_MASTER}" --command "sudo bash -s -- --push" &> ${OUTPUT}/push-"${KUBE_MASTER}".log
|
2015-06-01 15:59:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Push binaries to kubernetes node
|
|
|
|
function push-node() {
|
|
|
|
node=${1}
|
|
|
|
|
|
|
|
echo "Updating node ${node} metadata... "
|
2016-04-11 22:13:02 +00:00
|
|
|
prepare-startup-script
|
|
|
|
add-instance-metadata-from-file "${node}" "kube-env=${KUBE_TEMP}/node-kube-env.yaml" "startup-script=${KUBE_TEMP}/configure-vm.sh"
|
2015-06-01 15:59:12 +00:00
|
|
|
|
|
|
|
echo "Start upgrading node ${node} (log at ${OUTPUT}/push-${node}.log) ..."
|
2016-04-11 22:13:02 +00:00
|
|
|
cat ${KUBE_TEMP}/configure-vm.sh | gcloud compute ssh --ssh-flag="-o LogLevel=quiet" --project "${PROJECT}" --zone "${ZONE}" "${node}" --command "sudo bash -s -- --push" &> ${OUTPUT}/push-"${node}".log
|
2015-06-01 15:59:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Push binaries to kubernetes cluster
|
2016-08-02 07:08:05 +00:00
|
|
|
function kube-push() {
|
2015-12-15 22:50:41 +00:00
|
|
|
# Disable this until it's fixed.
|
|
|
|
# See https://github.com/kubernetes/kubernetes/issues/17397
|
|
|
|
echo "./cluster/kube-push.sh is currently not supported in GCE."
|
|
|
|
echo "Please use ./cluster/gce/upgrade.sh."
|
|
|
|
exit 1
|
|
|
|
|
2015-06-01 15:59:12 +00:00
|
|
|
prepare-push true
|
2014-07-14 17:50:04 +00:00
|
|
|
|
2015-06-01 15:59:12 +00:00
|
|
|
push-master
|
2014-07-14 17:50:04 +00:00
|
|
|
|
2015-11-24 03:04:40 +00:00
|
|
|
for (( i=0; i<${#NODE_NAMES[@]}; i++)); do
|
|
|
|
push-node "${NODE_NAMES[$i]}" &
|
2015-06-01 15:59:12 +00:00
|
|
|
done
|
2016-01-11 23:23:21 +00:00
|
|
|
|
|
|
|
kube::util::wait-for-jobs || {
|
2016-01-22 22:42:32 +00:00
|
|
|
echo -e "${color_red}Some commands failed.${color_norm}" >&2
|
2016-01-11 23:23:21 +00:00
|
|
|
}
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
|
|
|
|
# TODO(zmerlynn): Re-create instance-template with the new
|
|
|
|
# node-kube-env. This isn't important until the node-ip-range issue
|
|
|
|
# is solved (because that's blocking automatic dynamic nodes from
|
2015-04-23 14:41:56 +00:00
|
|
|
# working). The node-kube-env has to be composed with the KUBELET_TOKEN
|
Generate a token for kube-proxy.
Tested on GCE.
Includes untested modifications for AWS and Vagrant.
No changes for any other distros.
Probably will work on other up-to-date providers
but beware. Symptom would be that service proxying
stops working.
1. Generates a token kube-proxy in AWS, GCE, and Vagrant setup scripts.
1. Distributes the token via salt-overlay, and salt to /var/lib/kube-proxy/kubeconfig
1. Changes kube-proxy args:
- use the --kubeconfig argument
- changes --master argument from http://MASTER:7080 to https://MASTER
- http -> https
- explicit port 7080 -> implied 443
Possible ways this might break other distros:
Mitigation: there is an default empty kubeconfig file.
If the distro does not populate the salt-overlay, then
it should get the empty, which parses to an empty
object, which, combined with the --master argument,
should still work.
Mitigation:
- azure: Special case to use 7080 in
- rackspace: way out of date, so don't care.
- vsphere: way out of date, so don't care.
- other distros: not using salt.
2015-04-24 16:27:11 +00:00
|
|
|
# and KUBE_PROXY_TOKEN. Ideally we would have
|
2015-08-06 01:08:26 +00:00
|
|
|
# http://issue.k8s.io/3168
|
Change GCE to use standalone Saltstack config:
Change provisioning to pass all variables to both master and node. Run
Salt in a masterless setup on all nodes ala
http://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html,
which involves ensuring Salt daemon is NOT running after install. Kill
Salt master install. And fix push to actually work in this new flow.
As part of this, the GCE Salt config no longer has access to the Salt
mine, which is primarily obnoxious for two reasons: - The minions
can't use Salt to see the master: this is easily fixed by static
config. - The master can't see the list of all the minions: this is
fixed temporarily by static config in util.sh, but later, by other
means (see
https://github.com/GoogleCloudPlatform/kubernetes/issues/156, which
should eventually remove this direction).
As part of it, flatten all of cluster/gce/templates/* into
configure-vm.sh, using a single, separate piece of YAML to drive the
environment variables, rather than constantly rewriting the startup
script.
2015-03-02 22:38:58 +00:00
|
|
|
# implemented before then, though, so avoiding this mess until then.
|
2014-07-14 17:50:04 +00:00
|
|
|
|
|
|
|
echo
|
2014-09-29 20:11:31 +00:00
|
|
|
echo "Kubernetes cluster is running. The master is running at:"
|
|
|
|
echo
|
|
|
|
echo " https://${KUBE_MASTER_IP}"
|
|
|
|
echo
|
2015-04-28 05:39:39 +00:00
|
|
|
echo "The user name and password to use is located in ~/.kube/config"
|
2014-07-14 17:50:04 +00:00
|
|
|
echo
|
|
|
|
}
|
|
|
|
|
2014-09-23 22:54:27 +00:00
|
|
|
# -----------------------------------------------------------------------------
|
2016-02-16 22:54:50 +00:00
|
|
|
# Cluster specific test helpers used from hack/e2e.go
|
2014-09-23 22:54:27 +00:00
|
|
|
|
|
|
|
# Execute prior to running tests to build a release if required for env.
|
|
|
|
#
|
|
|
|
# Assumed Vars:
|
2014-10-03 21:58:49 +00:00
|
|
|
# KUBE_ROOT
|
2016-08-02 07:08:05 +00:00
|
|
|
function test-build-release() {
|
2014-07-14 17:50:04 +00:00
|
|
|
# Make a release
|
2016-12-14 00:03:06 +00:00
|
|
|
"${KUBE_ROOT}/build/release.sh"
|
2014-07-14 17:50:04 +00:00
|
|
|
}
|
|
|
|
|
2014-09-23 22:54:27 +00:00
|
|
|
# Execute prior to running tests to initialize required structure. This is
|
2016-02-18 00:49:07 +00:00
|
|
|
# called from hack/e2e.go only when running -up.
|
2014-09-23 22:54:27 +00:00
|
|
|
#
|
|
|
|
# Assumed vars:
|
|
|
|
# Variables from config.sh
|
2016-08-02 07:08:05 +00:00
|
|
|
function test-setup() {
|
2014-07-14 17:50:04 +00:00
|
|
|
# Detect the project into $PROJECT if it isn't set
|
|
|
|
detect-project
|
|
|
|
|
2016-10-11 12:52:51 +00:00
|
|
|
if [[ ${MULTIZONE:-} == "true" && -n ${E2E_ZONES:-} ]]; then
|
2017-07-24 10:10:22 +00:00
|
|
|
for KUBE_GCE_ZONE in ${E2E_ZONES}; do
|
2016-02-18 00:49:07 +00:00
|
|
|
KUBE_GCE_ZONE="${KUBE_GCE_ZONE}" KUBE_USE_EXISTING_MASTER="${KUBE_USE_EXISTING_MASTER:-}" "${KUBE_ROOT}/cluster/kube-up.sh"
|
|
|
|
KUBE_USE_EXISTING_MASTER="true" # For subsequent zones we use the existing master
|
|
|
|
done
|
|
|
|
else
|
|
|
|
"${KUBE_ROOT}/cluster/kube-up.sh"
|
|
|
|
fi
|
|
|
|
|
2014-10-23 00:49:40 +00:00
|
|
|
# Open up port 80 & 8080 so common containers on minions can be reached
|
2015-03-02 18:15:34 +00:00
|
|
|
# TODO(roberthbailey): Remove this once we are no longer relying on hostPorts.
|
2015-06-11 09:39:22 +00:00
|
|
|
local start=`date +%s`
|
2014-11-25 18:32:27 +00:00
|
|
|
gcloud compute firewall-rules create \
|
2014-10-23 00:49:40 +00:00
|
|
|
--project "${PROJECT}" \
|
2015-11-24 03:06:00 +00:00
|
|
|
--target-tags "${NODE_TAG}" \
|
2015-05-25 07:46:24 +00:00
|
|
|
--allow tcp:80,tcp:8080 \
|
2014-10-23 00:49:40 +00:00
|
|
|
--network "${NETWORK}" \
|
2015-11-24 03:06:00 +00:00
|
|
|
"${NODE_TAG}-${INSTANCE_PREFIX}-http-alt" 2> /dev/null || true
|
2015-06-11 09:39:22 +00:00
|
|
|
# As there is no simple way to wait longer for this operation we need to manually
|
|
|
|
# wait some additional time (20 minutes altogether).
|
2016-02-01 20:30:45 +00:00
|
|
|
while ! gcloud compute firewall-rules describe --project "${PROJECT}" "${NODE_TAG}-${INSTANCE_PREFIX}-http-alt" 2> /dev/null; do
|
|
|
|
if [[ $(($start + 1200)) -lt `date +%s` ]]; then
|
|
|
|
echo -e "${color_red}Failed to create firewall ${NODE_TAG}-${INSTANCE_PREFIX}-http-alt in ${PROJECT}" >&2
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
sleep 5
|
2015-06-11 09:39:22 +00:00
|
|
|
done
|
2015-05-23 02:39:40 +00:00
|
|
|
|
|
|
|
# Open up the NodePort range
|
|
|
|
# TODO(justinsb): Move to main setup, if we decide whether we want to do this by default.
|
2015-06-11 09:39:22 +00:00
|
|
|
start=`date +%s`
|
2015-05-23 02:39:40 +00:00
|
|
|
gcloud compute firewall-rules create \
|
|
|
|
--project "${PROJECT}" \
|
2015-11-24 03:06:00 +00:00
|
|
|
--target-tags "${NODE_TAG}" \
|
2015-05-23 02:39:40 +00:00
|
|
|
--allow tcp:30000-32767,udp:30000-32767 \
|
|
|
|
--network "${NETWORK}" \
|
2015-11-24 03:06:00 +00:00
|
|
|
"${NODE_TAG}-${INSTANCE_PREFIX}-nodeports" 2> /dev/null || true
|
2015-06-11 09:39:22 +00:00
|
|
|
# As there is no simple way to wait longer for this operation we need to manually
|
|
|
|
# wait some additional time (20 minutes altogether).
|
2016-02-01 20:30:45 +00:00
|
|
|
while ! gcloud compute firewall-rules describe --project "${PROJECT}" "${NODE_TAG}-${INSTANCE_PREFIX}-nodeports" 2> /dev/null; do
|
|
|
|
if [[ $(($start + 1200)) -lt `date +%s` ]]; then
|
|
|
|
echo -e "${color_red}Failed to create firewall ${NODE_TAG}-${INSTANCE_PREFIX}-nodeports in ${PROJECT}" >&2
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
sleep 5
|
2015-06-11 09:39:22 +00:00
|
|
|
done
|
2014-07-14 17:50:04 +00:00
|
|
|
}
|
|
|
|
|
2014-12-09 23:07:54 +00:00
|
|
|
# Execute after running tests to perform any required clean-up. This is called
|
|
|
|
# from hack/e2e.go
|
2016-08-02 07:08:05 +00:00
|
|
|
function test-teardown() {
|
2014-12-09 23:07:54 +00:00
|
|
|
detect-project
|
2014-07-14 17:50:04 +00:00
|
|
|
echo "Shutting down test cluster in background."
|
2016-10-11 23:50:30 +00:00
|
|
|
delete-firewall-rules \
|
|
|
|
"${NODE_TAG}-${INSTANCE_PREFIX}-http-alt" \
|
|
|
|
"${NODE_TAG}-${INSTANCE_PREFIX}-nodeports"
|
2016-10-11 12:52:51 +00:00
|
|
|
if [[ ${MULTIZONE:-} == "true" && -n ${E2E_ZONES:-} ]]; then
|
2017-07-24 10:10:22 +00:00
|
|
|
local zones=( ${E2E_ZONES} )
|
|
|
|
# tear them down in reverse order, finally tearing down the master too.
|
|
|
|
for ((zone_num=${#zones[@]}-1; zone_num>0; zone_num--)); do
|
|
|
|
KUBE_GCE_ZONE="${zones[zone_num]}" KUBE_USE_EXISTING_MASTER="true" "${KUBE_ROOT}/cluster/kube-down.sh"
|
|
|
|
done
|
|
|
|
KUBE_GCE_ZONE="${zones[0]}" KUBE_USE_EXISTING_MASTER="false" "${KUBE_ROOT}/cluster/kube-down.sh"
|
2016-01-26 02:36:40 +00:00
|
|
|
else
|
2017-07-24 10:10:22 +00:00
|
|
|
"${KUBE_ROOT}/cluster/kube-down.sh"
|
2016-01-26 02:36:40 +00:00
|
|
|
fi
|
2014-07-14 17:50:04 +00:00
|
|
|
}
|
2014-10-10 05:38:00 +00:00
|
|
|
|
|
|
|
# SSH to a node by name ($1) and run a command ($2).
|
2016-08-02 07:08:05 +00:00
|
|
|
function ssh-to-node() {
|
2014-10-10 05:38:00 +00:00
|
|
|
local node="$1"
|
|
|
|
local cmd="$2"
|
2015-04-21 22:27:38 +00:00
|
|
|
# Loop until we can successfully ssh into the box
|
2016-06-03 17:42:38 +00:00
|
|
|
for try in {1..5}; do
|
2016-03-07 21:29:04 +00:00
|
|
|
if gcloud compute ssh --ssh-flag="-o LogLevel=quiet" --ssh-flag="-o ConnectTimeout=30" --project "${PROJECT}" --zone="${ZONE}" "${node}" --command "echo test > /dev/null"; then
|
2015-01-29 23:50:46 +00:00
|
|
|
break
|
|
|
|
fi
|
2015-04-21 22:27:38 +00:00
|
|
|
sleep 5
|
2015-01-29 23:50:46 +00:00
|
|
|
done
|
2015-04-21 22:27:38 +00:00
|
|
|
# Then actually try the command.
|
2016-03-07 21:29:04 +00:00
|
|
|
gcloud compute ssh --ssh-flag="-o LogLevel=quiet" --ssh-flag="-o ConnectTimeout=30" --project "${PROJECT}" --zone="${ZONE}" "${node}" --command "${cmd}"
|
2014-10-10 05:38:00 +00:00
|
|
|
}
|
|
|
|
|
2014-11-11 19:03:07 +00:00
|
|
|
# Perform preparations required to run e2e tests
|
|
|
|
function prepare-e2e() {
|
|
|
|
detect-project
|
|
|
|
}
|
2016-04-11 22:13:02 +00:00
|
|
|
|
2016-02-24 08:06:24 +00:00
|
|
|
# Writes configure-vm.sh to a temporary location with comments stripped. GCE
|
|
|
|
# limits the size of metadata fields to 32K, and stripping comments is the
|
|
|
|
# easiest way to buy us a little more room.
|
2016-04-11 22:13:02 +00:00
|
|
|
function prepare-startup-script() {
|
2016-11-28 17:47:29 +00:00
|
|
|
# Find a standard sed instance (and ensure that the command works as expected on a Mac).
|
|
|
|
SED=sed
|
|
|
|
if which gsed &>/dev/null; then
|
|
|
|
SED=gsed
|
|
|
|
fi
|
|
|
|
if ! ($SED --version 2>&1 | grep -q GNU); then
|
|
|
|
echo "!!! GNU sed is required. If on OS X, use 'brew install gnu-sed'."
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
$SED '/^\s*#\([^!].*\)*$/ d' ${KUBE_ROOT}/cluster/gce/configure-vm.sh > ${KUBE_TEMP}/configure-vm.sh
|
2016-04-11 22:13:02 +00:00
|
|
|
}
|