From ff9d482c8261a437dd1bae9bfb28846278eb4681 Mon Sep 17 00:00:00 2001 From: Kevin Date: Wed, 19 Aug 2015 17:04:08 +0000 Subject: [PATCH] Add CentOS BareMetal deployment scripts. --- cluster/centos/.gitignore | 13 + cluster/centos/build.sh | 149 ++++++++ cluster/centos/config-build.sh | 38 ++ cluster/centos/config-default.sh | 50 +++ cluster/centos/master/scripts/apiserver.sh | 85 +++++ .../master/scripts/controller-manager.sh | 47 +++ cluster/centos/master/scripts/etcd.sh | 79 +++++ cluster/centos/master/scripts/scheduler.sh | 58 ++++ cluster/centos/minion/bin/mk-docker-opts.sh | 108 ++++++ cluster/centos/minion/bin/remove-docker0.sh | 27 ++ cluster/centos/minion/scripts/docker.sh | 49 +++ cluster/centos/minion/scripts/flannel.sh | 66 ++++ cluster/centos/minion/scripts/kubelet.sh | 75 ++++ cluster/centos/minion/scripts/proxy.sh | 51 +++ cluster/centos/util.sh | 324 ++++++++++++++++++ 15 files changed, 1219 insertions(+) create mode 100644 cluster/centos/.gitignore create mode 100755 cluster/centos/build.sh create mode 100755 cluster/centos/config-build.sh create mode 100755 cluster/centos/config-default.sh create mode 100755 cluster/centos/master/scripts/apiserver.sh create mode 100755 cluster/centos/master/scripts/controller-manager.sh create mode 100755 cluster/centos/master/scripts/etcd.sh create mode 100755 cluster/centos/master/scripts/scheduler.sh create mode 100755 cluster/centos/minion/bin/mk-docker-opts.sh create mode 100755 cluster/centos/minion/bin/remove-docker0.sh create mode 100755 cluster/centos/minion/scripts/docker.sh create mode 100755 cluster/centos/minion/scripts/flannel.sh create mode 100755 cluster/centos/minion/scripts/kubelet.sh create mode 100755 cluster/centos/minion/scripts/proxy.sh create mode 100755 cluster/centos/util.sh diff --git a/cluster/centos/.gitignore b/cluster/centos/.gitignore new file mode 100644 index 00000000000..56aad3778f4 --- /dev/null +++ b/cluster/centos/.gitignore @@ -0,0 +1,13 @@ +binaries + +master/bin/etcd +master/bin/etcdctl +master/bin/kube* + +minion/bin/brctl +minion/bin/docker +minion/bin/etcd +minion/bin/etcdctl +minion/bin/flanneld +minion/bin/kube* +test.sh \ No newline at end of file diff --git a/cluster/centos/build.sh b/cluster/centos/build.sh new file mode 100755 index 00000000000..a8b6a5aafdb --- /dev/null +++ b/cluster/centos/build.sh @@ -0,0 +1,149 @@ +#!/bin/bash + +# Copyright 2015 The Kubernetes Authors All rights reserved. +# +# 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. + +# Download the flannel, etcd, docker, bridge-utils and K8s binaries automatically +# and store into binaries directory. +# Run as root only + +# author @kevin-wangzefeng + +set -o errexit +set -o nounset +set -o pipefail + +readonly ROOT=$(dirname "${BASH_SOURCE}") +source ${ROOT}/config-build.sh + +# ensure $RELEASES_DIR is an absolute file path +mkdir -p ${RELEASES_DIR} +RELEASES_DIR=$(cd ${RELEASES_DIR}; pwd) + +# get absolute file path of binaries +BINARY_DIR=$(cd ${ROOT}; pwd)/binaries + +function clean-up() { + rm -rf ${RELEASES_DIR} + rm -rf ${BINARY_DIR} +} + +function download-releases() { + rm -rf ${RELEASES_DIR} + mkdir -p ${RELEASES_DIR} + + echo "Download flannel release v${FLANNEL_VERSION} ..." + curl -L ${FLANNEL_DOWNLOAD_URL} -o ${RELEASES_DIR}/flannel.tar.gz + + echo "Download etcd release v${ETCD_VERSION} ..." + curl -L ${ETCD_DOWNLOAD_URL} -o ${RELEASES_DIR}/etcd.tar.gz + + echo "Download kubernetes release v${K8S_VERSION} ..." + curl -L ${K8S_DOWNLOAD_URL} -o ${RELEASES_DIR}/kubernetes.tar.gz + + echo "Download docker-latest ..." + curl -L https://get.docker.com/builds/Linux/x86_64/docker-latest -o ${RELEASES_DIR}/docker + + echo "Download bridge-utils from yum repo ..." + yum --downloadonly --downloaddir=${RELEASES_DIR} install bridge-utils + + mkdir -p ${RELEASES_DIR}/brctl-tmp + local rpm_file=$(ls ${RELEASES_DIR}/bridge-utils-*.rpm) + pushd ${RELEASES_DIR}/brctl-tmp >/dev/null 2>&1 + rpm2cpio ${rpm_file} | cpio -id + popd >/dev/null 2>&1 + cp ${RELEASES_DIR}/brctl-tmp/usr/sbin/brctl ${RELEASES_DIR} +} + +function unpack-releases() { + rm -rf ${BINARY_DIR} + mkdir -p ${BINARY_DIR}/master/bin + mkdir -p ${BINARY_DIR}/minion/bin + + # flannel + if [[ -f ${RELEASES_DIR}/flannel.tar.gz ]] ; then + tar xzf ${RELEASES_DIR}/flannel.tar.gz -C ${RELEASES_DIR} + cp ${RELEASES_DIR}/flannel-${FLANNEL_VERSION}/flanneld ${BINARY_DIR}/master/bin + cp ${RELEASES_DIR}/flannel-${FLANNEL_VERSION}/flanneld ${BINARY_DIR}/minion/bin + fi + + # ectd + if [[ -f ${RELEASES_DIR}/etcd.tar.gz ]] ; then + tar xzf ${RELEASES_DIR}/etcd.tar.gz -C ${RELEASES_DIR} + ETCD="etcd-v${ETCD_VERSION}-linux-amd64" + cp ${RELEASES_DIR}/$ETCD/etcd \ + ${RELEASES_DIR}/$ETCD/etcdctl ${BINARY_DIR}/master/bin + cp ${RELEASES_DIR}/$ETCD/etcd \ + ${RELEASES_DIR}/$ETCD/etcdctl ${BINARY_DIR}/minion/bin + fi + + # k8s + if [[ -f ${RELEASES_DIR}/kubernetes.tar.gz ]] ; then + tar xzf ${RELEASES_DIR}/kubernetes.tar.gz -C ${RELEASES_DIR} + + pushd ${RELEASES_DIR}/kubernetes/server + tar xzf kubernetes-server-linux-amd64.tar.gz + popd + cp ${RELEASES_DIR}/kubernetes/server/kubernetes/server/bin/kube-apiserver \ + ${RELEASES_DIR}/kubernetes/server/kubernetes/server/bin/kube-controller-manager \ + ${RELEASES_DIR}/kubernetes/server/kubernetes/server/bin/kube-scheduler ${BINARY_DIR}/master/bin + + cp ${RELEASES_DIR}/kubernetes/server/kubernetes/server/bin/kubelet \ + ${RELEASES_DIR}/kubernetes/server/kubernetes/server/bin/kube-proxy ${BINARY_DIR}/minion/bin + + cp ${RELEASES_DIR}/kubernetes/server/kubernetes/server/bin/kubectl ${BINARY_DIR} + fi + + if [[ -f ${RELEASES_DIR}/docker ]]; then + cp ${RELEASES_DIR}/docker ${BINARY_DIR}/minion/bin + fi + + if [[ -f ${RELEASES_DIR}/brctl ]]; then + cp ${RELEASES_DIR}/brctl ${BINARY_DIR}/minion/bin + fi + + chmod -R +x ${BINARY_DIR} + echo "Done! All binaries are stored in ${BINARY_DIR}" +} + +function parse-opt() { + local opt=${1-} + + case $opt in + download) + download-releases + ;; + unpack) + unpack-releases + ;; + clean) + clean-up + ;; + all) + download-releases + unpack-releases + ;; + *) + echo "Usage: " + echo " build.sh " + echo "Commands:" + echo " clean Clean up downloaded releases and unpacked binaries." + echo " download Download releases to \"${RELEASES_DIR}\"." + echo " unpack Unpack releases downloaded in \"${RELEASES_DIR}\", and copy binaries to \"${BINARY_DIR}\"." + echo " all Download releases and unpack them." + ;; + esac +} + +parse-opt $@ diff --git a/cluster/centos/config-build.sh b/cluster/centos/config-build.sh new file mode 100755 index 00000000000..a3fc754752b --- /dev/null +++ b/cluster/centos/config-build.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# Copyright 2015 The Kubernetes Authors All rights reserved. +# +# 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. + +## Contains configuration values for the Binaries downloading and unpacking. + +# Directory to store release packages that will be downloaded. +RELEASES_DIR=${RELEASES_DIR:-/tmp/downloads} + +# Define flannel version to use. +FLANNEL_VERSION=${FLANNEL_VERSION:-"0.4.0"} + +# Define etcd version to use. +ETCD_VERSION=${ETCD_VERSION:-"2.0.12"} + +# Define k8s version to use. +K8S_VERSION=${K8S_VERSION:-"1.0.1"} + +FLANNEL_DOWNLOAD_URL=\ +"https://github.com/coreos/flannel/releases/download/v${FLANNEL_VERSION}/flannel-${FLANNEL_VERSION}-linux-amd64.tar.gz" + +ETCD_DOWNLOAD_URL=\ +"https://github.com/coreos/etcd/releases/download/v${ETCD_VERSION}/etcd-v${ETCD_VERSION}-linux-amd64.tar.gz" + +K8S_DOWNLOAD_URL=\ +"https://github.com/kubernetes/kubernetes/releases/download/v${K8S_VERSION}/kubernetes.tar.gz" diff --git a/cluster/centos/config-default.sh b/cluster/centos/config-default.sh new file mode 100755 index 00000000000..559300a7ba4 --- /dev/null +++ b/cluster/centos/config-default.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# Copyright 2015 The Kubernetes Authors All rights reserved. +# +# 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. + +## Contains configuration values for the CentOS cluster + +# Currently only support root user. +export MASTER=${MASTER:-"root@8.8.8.18"} +export MASTER_IP=${MASTER#*@} + +# Define all your minion nodes, +# And separated with blank space like . +# Currently only support root user. +export MINIONS=${MINIONS:-"root@8.8.8.20 root@8.8.8.21"} +# If it practically impossible to set an array as an environment variable +# from a script, so assume variable is a string then convert it to an array +export MINIONS_ARRAY=($MINIONS) + +# Number of nodes in your cluster. +export NUM_MINIONS=${NUM_MINIONS:-2} + +# By default, the cluster will use the etcd installed on master. +export ETCD_SERVERS=${ETCD_SERVERS:-"http://$MASTER_IP:4001"} + +# define the IP range used for service cluster IPs. +# according to rfc 1918 ref: https://tools.ietf.org/html/rfc1918 choose a private ip range here. +export SERVICE_CLUSTER_IP_RANGE=${SERVICE_CLUSTER_IP_RANGE:-"192.168.3.0/24"} + +# define the IP range used for flannel overlay network, should not conflict with above SERVICE_CLUSTER_IP_RANGE +export FLANNEL_NET=${FLANNEL_NET:-"172.16.0.0/16"} + +# Extra options to set on the Docker command line. +# This is useful for setting --insecure-registry for local registries. +export DOCKER_OPTS=${DOCKER_OPTS:-""} + + +# Timeouts for process checking on master and minion +export PROCESS_CHECK_TIMEOUT=${PROCESS_CHECK_TIMEOUT:-180} # seconds. diff --git a/cluster/centos/master/scripts/apiserver.sh b/cluster/centos/master/scripts/apiserver.sh new file mode 100755 index 00000000000..967bc1a5f31 --- /dev/null +++ b/cluster/centos/master/scripts/apiserver.sh @@ -0,0 +1,85 @@ +#!/bin/bash + +# Copyright 2014 The Kubernetes Authors All rights reserved. +# +# 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. + + +MASTER_ADDRESS=${1:-"8.8.8.18"} +ETCD_SERVERS=${2:-"http://8.8.8.18:4001"} +SERVICE_CLUSTER_IP_RANGE=${3:-"10.10.10.0/24"} + +cat </opt/kubernetes/cfg/kube-apiserver +# --logtostderr=true: log to standard error instead of files +KUBE_LOGTOSTDERR="--logtostderr=true" + +# --v=0: log level for V logs +KUBE_LOG_LEVEL="--v=4" + +# --etcd-servers=[]: List of etcd servers to watch (http://ip:port), +# comma separated. Mutually exclusive with -etcd-config +KUBE_ETCD_SERVERS="--etcd-servers=${ETCD_SERVERS}" + +# --address=127.0.0.1: DEPRECATED: see --insecure-bind-address instead +KUBE_API_ADDRESS="--address=${MASTER_ADDRESS}" + +# --port=8080: DEPRECATED: see --insecure-port instead +KUBE_API_PORT="--port=8080" + +# --kubelet-port=10250: Kubelet port +MINION_PORT="--kubelet-port=10250" + +# --allow-privileged=false: If true, allow privileged containers. +KUBE_ALLOW_PRIV="--allow-privileged=false" + +# --service-cluster-ip-range=: A CIDR notation IP range from which to assign service cluster IPs. +# This must not overlap with any IP ranges assigned to nodes for pods. +KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=${SERVICE_CLUSTER_IP_RANGE}" + +# --admission-control="AlwaysAdmit": Ordered list of plug-ins +# to do admission control of resources into cluster. +# Comma-delimited list of: +# LimitRanger, AlwaysDeny, SecurityContextDeny, NamespaceExists, +# NamespaceLifecycle, NamespaceAutoProvision, DenyExecOnPrivileged, +# AlwaysAdmit, ServiceAccount, ResourceQuota +#KUBE_ADMISSION_CONTROL="" + +EOF + +KUBE_APISERVER_OPTS=" \${KUBE_LOGTOSTDERR} \\ + \${KUBE_LOG_LEVEL} \\ + \${KUBE_ETCD_SERVERS} \\ + \${KUBE_API_ADDRESS} \\ + \${KUBE_API_PORT} \\ + \${MINION_PORT} \\ + \${KUBE_ALLOW_PRIV} \\ + \${KUBE_SERVICE_ADDRESSES}" + + +cat </usr/lib/systemd/system/kube-apiserver.service +[Unit] +Description=Kubernetes API Server +Documentation=https://github.com/GoogleCloudPlatform/kubernetes + +[Service] +EnvironmentFile=-/opt/kubernetes/cfg/kube-apiserver +ExecStart=/opt/kubernetes/bin/kube-apiserver ${KUBE_APISERVER_OPTS} +Restart=on-failure + +[Install] +WantedBy=multi-user.target +EOF + +systemctl daemon-reload +systemctl enable kube-apiserver +systemctl start kube-apiserver diff --git a/cluster/centos/master/scripts/controller-manager.sh b/cluster/centos/master/scripts/controller-manager.sh new file mode 100755 index 00000000000..3631a88c751 --- /dev/null +++ b/cluster/centos/master/scripts/controller-manager.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# Copyright 2014 The Kubernetes Authors All rights reserved. +# +# 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. + + +MASTER_ADDRESS=${1:-"8.8.8.18"} + +cat </opt/kubernetes/cfg/kube-controller-manager +KUBE_LOGTOSTDERR="--logtostderr=true" +KUBE_LOG_LEVEL="--v=4" +KUBE_MASTER="--master=${MASTER_ADDRESS}:8080" + +EOF + +KUBE_CONTROLLER_MANAGER_OPTS=" \${KUBE_LOGTOSTDERR} \\ + \${KUBE_LOG_LEVEL} \\ + \${KUBE_MASTER}" + +cat </usr/lib/systemd/system/kube-controller-manager.service +[Unit] +Description=Kubernetes Controller Manager +Documentation=https://github.com/GoogleCloudPlatform/kubernetes + +[Service] +EnvironmentFile=-/opt/kubernetes/cfg/kube-controller-manager +ExecStart=/opt/kubernetes/bin/kube-controller-manager ${KUBE_CONTROLLER_MANAGER_OPTS} +Restart=on-failure + +[Install] +WantedBy=multi-user.target +EOF + +systemctl daemon-reload +systemctl enable kube-controller-manager +systemctl start kube-controller-manager diff --git a/cluster/centos/master/scripts/etcd.sh b/cluster/centos/master/scripts/etcd.sh new file mode 100755 index 00000000000..31c458538d8 --- /dev/null +++ b/cluster/centos/master/scripts/etcd.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +# Copyright 2014 The Kubernetes Authors All rights reserved. +# +# 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. + +## Create etcd.conf, etcd.service, and start etcd service. + + +etcd_data_dir=/var/lib/etcd/ +mkdir -p ${etcd_data_dir} + +cat </opt/kubernetes/cfg/etcd.conf +# [member] +ETCD_NAME=default +ETCD_DATA_DIR="${etcd_data_dir}/default.etcd" +#ETCD_SNAPSHOT_COUNTER="10000" +#ETCD_HEARTBEAT_INTERVAL="100" +#ETCD_ELECTION_TIMEOUT="1000" +#ETCD_LISTEN_PEER_URLS="http://localhost:2380,http://localhost:7001" +ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:4001" +#ETCD_MAX_SNAPSHOTS="5" +#ETCD_MAX_WALS="5" +#ETCD_CORS="" +# +#[cluster] +#ETCD_INITIAL_ADVERTISE_PEER_URLS="http://localhost:2380,http://localhost:7001" +# if you use different ETCD_NAME (e.g. test), +# set ETCD_INITIAL_CLUSTER value for this name, i.e. "test=http://..." +#ETCD_INITIAL_CLUSTER="default=http://localhost:2380,default=http://localhost:7001" +#ETCD_INITIAL_CLUSTER_STATE="new" +#ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" +ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379,http://localhost:4001" +#ETCD_DISCOVERY="" +#ETCD_DISCOVERY_SRV="" +#ETCD_DISCOVERY_FALLBACK="proxy" +#ETCD_DISCOVERY_PROXY="" +# +#[proxy] +#ETCD_PROXY="off" +# +#[security] +#ETCD_CA_FILE="" +#ETCD_CERT_FILE="" +#ETCD_KEY_FILE="" +#ETCD_PEER_CA_FILE="" +#ETCD_PEER_CERT_FILE="" +#ETCD_PEER_KEY_FILE="" +EOF + +cat <//usr/lib/systemd/system/etcd.service +[Unit] +Description=Etcd Server +After=network.target + +[Service] +Type=simple +WorkingDirectory=${etcd_data_dir} +EnvironmentFile=-/opt/kubernetes/cfg/etcd.conf +# set GOMAXPROCS to number of processors +ExecStart=/bin/bash -c "GOMAXPROCS=\$(nproc) /opt/kubernetes/bin/etcd" + +[Install] +WantedBy=multi-user.target +EOF + +systemctl daemon-reload +systemctl enable etcd +systemctl start etcd diff --git a/cluster/centos/master/scripts/scheduler.sh b/cluster/centos/master/scripts/scheduler.sh new file mode 100755 index 00000000000..beafd8c9278 --- /dev/null +++ b/cluster/centos/master/scripts/scheduler.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# Copyright 2014 The Kubernetes Authors All rights reserved. +# +# 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. + + +MASTER_ADDRESS=${1:-"8.8.8.18"} + +cat </opt/kubernetes/cfg/kube-scheduler +### +# kubernetes scheduler config + +# --logtostderr=true: log to standard error instead of files +KUBE_LOGTOSTDERR="--logtostderr=true" + +# --v=0: log level for V logs +KUBE_LOG_LEVEL="--v=4" + +KUBE_MASTER="--master=${MASTER_ADDRESS}:8080" + +# Add your own! +KUBE_SCHEDULER_ARGS="" + +EOF + +KUBE_SCHEDULER_OPTS=" \${KUBE_LOGTOSTDERR} \\ + \${KUBE_LOG_LEVEL} \\ + \${KUBE_MASTER} \\ + \${KUBE_SCHEDULER_ARGS}" + +cat </usr/lib/systemd/system/kube-scheduler.service +[Unit] +Description=Kubernetes Scheduler +Documentation=https://github.com/GoogleCloudPlatform/kubernetes + +[Service] +EnvironmentFile=-/opt/kubernetes/cfg/kube-scheduler +ExecStart=/opt/kubernetes/bin/kube-scheduler ${KUBE_SCHEDULER_OPTS} +Restart=on-failure + +[Install] +WantedBy=multi-user.target +EOF + +systemctl daemon-reload +systemctl enable kube-scheduler +systemctl start kube-scheduler diff --git a/cluster/centos/minion/bin/mk-docker-opts.sh b/cluster/centos/minion/bin/mk-docker-opts.sh new file mode 100755 index 00000000000..f3c50531bda --- /dev/null +++ b/cluster/centos/minion/bin/mk-docker-opts.sh @@ -0,0 +1,108 @@ +#!/bin/bash + +# Copyright 2014 The Kubernetes Authors All rights reserved. +# +# 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. + +# Generate Docker daemon options based on flannel env file. + +# exit on any error +set -e + +usage() { + echo "$0 [-f FLANNEL-ENV-FILE] [-d DOCKER-ENV-FILE] [-i] [-c] [-m] [-k COMBINED-KEY] + +Generate Docker daemon options based on flannel env file +OPTIONS: + -f Path to flannel env file. Defaults to /run/flannel/subnet.env + -d Path to Docker env file to write to. Defaults to /run/docker_opts.env + -i Output each Docker option as individual var. e.g. DOCKER_OPT_MTU=1500 + -c Output combined Docker options into DOCKER_OPTS var + -k Set the combined options key to this value (default DOCKER_OPTS=) + -m Do not output --ip-masq (useful for older Docker version) +" >/dev/stderr + exit 1 +} + +flannel_env="/run/flannel/subnet.env" +docker_env="/run/docker_opts.env" +combined_opts_key="DOCKER_OPTS" +indiv_opts=false +combined_opts=false +ipmasq=true + +while getopts "f:d:ick:" opt; do + case $opt in + f) + flannel_env=$OPTARG + ;; + d) + docker_env=$OPTARG + ;; + i) + indiv_opts=true + ;; + c) + combined_opts=true + ;; + m) + ipmasq=false + ;; + k) + combined_opts_key=$OPTARG + ;; + \?) + usage + ;; + esac +done + +if [[ $indiv_opts = false ]] && [[ $combined_opts = false ]]; then + indiv_opts=true + combined_opts=true +fi + +if [[ -f "$flannel_env" ]]; then + source $flannel_env +fi + +if [[ -n "$FLANNEL_SUBNET" ]]; then + DOCKER_OPT_BIP="--bip=$FLANNEL_SUBNET" +fi + +if [[ -n "$FLANNEL_MTU" ]]; then + DOCKER_OPT_MTU="--mtu=$FLANNEL_MTU" +fi + +if [[ "$FLANNEL_IPMASQ" = true ]] && [[ $ipmasq = true ]]; then + DOCKER_OPT_IPMASQ="--ip-masq=false" +fi + +eval docker_opts="\$${combined_opts_key}" +docker_opts+=" " + +echo -n "" >$docker_env +for opt in $(compgen -v DOCKER_OPT_); do + eval val=\$$opt + + if [[ "$indiv_opts" = true ]]; then + echo "$opt=\"$val\"" >>$docker_env + fi + + docker_opts+="$val " +done + +if [[ "$combined_opts" = true ]]; then + echo "${combined_opts_key}=\"${docker_opts}\"" >>$docker_env +fi + diff --git a/cluster/centos/minion/bin/remove-docker0.sh b/cluster/centos/minion/bin/remove-docker0.sh new file mode 100755 index 00000000000..4d016fc9246 --- /dev/null +++ b/cluster/centos/minion/bin/remove-docker0.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Copyright 2014 The Kubernetes Authors All rights reserved. +# +# 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. + +# Delete default docker bridge, so that docker can start with flannel network. + +# exit on any error +set -e + +rc=0 +ip link show docker0 >/dev/null 2>&1 || rc="$?" +if [[ "$rc" -eq "0" ]]; then + ip link set dev docker0 down + /opt/kubernetes/bin/brctl delbr docker0 +fi \ No newline at end of file diff --git a/cluster/centos/minion/scripts/docker.sh b/cluster/centos/minion/scripts/docker.sh new file mode 100755 index 00000000000..74039e601c1 --- /dev/null +++ b/cluster/centos/minion/scripts/docker.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# Copyright 2014 The Kubernetes Authors All rights reserved. +# +# 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. + + +DOCKER_OPTS=${1:-""} + +DOCKER_CONFIG=/opt/kubernetes/cfg/docker + +cat <$DOCKER_CONFIG +DOCKER_OPTS="-H tcp://127.0.0.1:4243 -H unix:///var/run/docker.sock --selinux-enabled=false ${DOCKER_OPTS}" +EOF + +cat </usr/lib/systemd/system/docker.service +[Unit] +Description=Docker Application Container Engine +Documentation=http://docs.docker.com +After=network.target flannel.service +Requires=flannel.service + +[Service] +Type=notify +EnvironmentFile=-/run/flannel/docker +EnvironmentFile=-/opt/kubernetes/cfg/docker +WorkingDirectory=/opt/kubernetes/bin +ExecStartPre=/opt/kubernetes/bin/remove-docker0.sh +ExecStart=/opt/kubernetes/bin/docker -d \$DOCKER_OPT_BIP \$DOCKER_OPT_MTU \$DOCKER_OPTS +LimitNOFILE=1048576 +LimitNPROC=1048576 + +[Install] +WantedBy=multi-user.target +EOF + +systemctl daemon-reload +systemctl enable docker +systemctl start docker diff --git a/cluster/centos/minion/scripts/flannel.sh b/cluster/centos/minion/scripts/flannel.sh new file mode 100755 index 00000000000..c19480d93a3 --- /dev/null +++ b/cluster/centos/minion/scripts/flannel.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +# Copyright 2014 The Kubernetes Authors All rights reserved. +# +# 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. + + +ETCD_SERVERS=${1:-"http://8.8.8.18:4001"} +FLANNEL_NET=${2:-"172.16.0.0/16"} + + +cat </opt/kubernetes/cfg/flannel +FLANNEL_ETCD="-etcd-endpoints=${ETCD_SERVERS}" +FLANNEL_ETCD_KEY="-etcd-prefix=/coreos.com/network" +EOF + +cat </usr/lib/systemd/system/flannel.service +[Unit] +Description=Flanneld overlay address etcd agent +After=network.target +Before=docker.service + +[Service] +EnvironmentFile=-/opt/kubernetes/cfg/flannel +ExecStart=/opt/kubernetes/bin/flanneld \${FLANNEL_ETCD} \${FLANNEL_ETCD_KEY} +ExecStartPost=/opt/kubernetes/bin/mk-docker-opts.sh -d /run/flannel/docker + +Type=notify + +[Install] +WantedBy=multi-user.target +RequiredBy=docker.service +EOF + +# Store FLANNEL_NET to etcd. +attempt=0 +while true; do + /opt/kubernetes/bin/etcdctl --no-sync -C ${ETCD_SERVERS} \ + get /coreos.com/network/config >/dev/null 2>&1 + if [[ "$?" == 0 ]]; then + break + else + if (( attempt > 600 )); then + echo "timeout for waiting network config" > ~/kube/err.log + exit 2 + fi + + /opt/kubernetes/bin/etcdctl --no-sync -C ${ETCD_SERVERS} \ + mk /coreos.com/network/config "{\"Network\":\"${FLANNEL_NET}\"}" >/dev/null 2>&1 + attempt=$((attempt+1)) + sleep 3 + fi +done +wait + +systemctl daemon-reload \ No newline at end of file diff --git a/cluster/centos/minion/scripts/kubelet.sh b/cluster/centos/minion/scripts/kubelet.sh new file mode 100755 index 00000000000..c186c36939e --- /dev/null +++ b/cluster/centos/minion/scripts/kubelet.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +# Copyright 2014 The Kubernetes Authors All rights reserved. +# +# 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. + + +MASTER_ADDRESS=${1:-"8.8.8.18"} +NODE_ADDRESS=${2:-"8.8.8.20"} + + +cat </opt/kubernetes/cfg/kubelet +# --logtostderr=true: log to standard error instead of files +KUBE_LOGTOSTDERR="--logtostderr=true" + +# --v=0: log level for V logs +KUBE_LOG_LEVEL="--v=4" + +# --address=0.0.0.0: The IP address for the Kubelet to serve on (set to 0.0.0.0 for all interfaces) +MINION_ADDRESS="--address=${NODE_ADDRESS}" + +# --port=10250: The port for the Kubelet to serve on. Note that "kubectl logs" will not work if you set this flag. +MINION_PORT="--port=10250" + +# --hostname-override="": If non-empty, will use this string as identification instead of the actual hostname. +MINION_HOSTNAME="--hostname-override=${NODE_ADDRESS}" + +# --api-servers=[]: List of Kubernetes API servers for publishing events, +# and reading pods and services. (ip:port), comma separated. +KUBELET_API_SERVER="--api-servers=${MASTER_ADDRESS}:8080" + +# --allow-privileged=false: If true, allow containers to request privileged mode. [default=false] +KUBE_ALLOW_PRIV="--allow-privileged=false" + +# Add your own! +KUBELET_ARGS="" +EOF + +KUBE_PROXY_OPTS=" \${KUBE_LOGTOSTDERR} \\ + \${KUBE_LOG_LEVEL} \\ + \${MINION_ADDRESS} \\ + \${MINION_PORT} \\ + \${MINION_HOSTNAME} \\ + \${KUBELET_API_SERVER} \\ + \${KUBE_ALLOW_PRIV} \\ + \${KUBELET_ARGS}" + +cat </usr/lib/systemd/system/kubelet.service +[Unit] +Description=Kubernetes Kubelet +After=docker.service +Requires=docker.service + +[Service] +EnvironmentFile=-/opt/kubernetes/cfg/kubelet +ExecStart=/opt/kubernetes/bin/kubelet ${KUBE_PROXY_OPTS} +Restart=on-failure + +[Install] +WantedBy=multi-user.target +EOF + +systemctl daemon-reload +systemctl enable kubelet +systemctl start kubelet \ No newline at end of file diff --git a/cluster/centos/minion/scripts/proxy.sh b/cluster/centos/minion/scripts/proxy.sh new file mode 100755 index 00000000000..5e4181f2c1b --- /dev/null +++ b/cluster/centos/minion/scripts/proxy.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Copyright 2014 The Kubernetes Authors All rights reserved. +# +# 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. + + +MASTER_ADDRESS=${1:-"8.8.8.18"} + +cat </opt/kubernetes/cfg/kube-proxy +# --logtostderr=true: log to standard error instead of files +KUBE_LOGTOSTDERR="--logtostderr=true" + +# --v=0: log level for V logs +KUBE_LOG_LEVEL="--v=4" + +# --master="": The address of the Kubernetes API server (overrides any value in kubeconfig) +KUBE_MASTER="--master=http://${MASTER_ADDRESS}:8080" +EOF + +KUBE_PROXY_OPTS=" \${KUBE_LOGTOSTDERR} \\ + \${KUBE_LOG_LEVEL} \\ + \${KUBE_MASTER}" + +cat </usr/lib/systemd/system/kube-proxy.service +[Unit] +Description=Kubernetes Proxy +After=network.target + +[Service] +EnvironmentFile=-/opt/kubernetes/cfg/kube-proxy +ExecStart=/opt/kubernetes/bin/kube-proxy ${KUBE_PROXY_OPTS} +Restart=on-failure + +[Install] +WantedBy=multi-user.target +EOF + +systemctl daemon-reload +systemctl enable kube-proxy +systemctl start kube-proxy \ No newline at end of file diff --git a/cluster/centos/util.sh b/cluster/centos/util.sh new file mode 100755 index 00000000000..0fd54d788bd --- /dev/null +++ b/cluster/centos/util.sh @@ -0,0 +1,324 @@ +#!/bin/bash + +# Copyright 2015 The Kubernetes Authors All rights reserved. +# +# 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 that each provider hosting Kubernetes must implement to use cluster/kube-*.sh scripts. + +# exit on any error +set -e + +SSH_OPTS="-oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oLogLevel=ERROR" + +# Use the config file specified in $KUBE_CONFIG_FILE, or default to +# config-default.sh. +KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../.. +readonly ROOT=$(dirname "${BASH_SOURCE}") +source "${ROOT}/${KUBE_CONFIG_FILE:-"config-default.sh"}" +source "$KUBE_ROOT/cluster/common.sh" + + +KUBECTL_PATH=${KUBE_ROOT}/cluster/centos/binaries/kubectl + +# Directory to be used for master and minion provisioning. +KUBE_TEMP="~/kubernetes" + + +# Must ensure that the following ENV vars are set +function detect-master() { + KUBE_MASTER=$MASTER + KUBE_MASTER_IP=${MASTER#*@} + echo "KUBE_MASTER_IP: ${KUBE_MASTER_IP}" 1>&2 + echo "KUBE_MASTER: ${MASTER}" 1>&2 +} + +# Get minion IP addresses and store in KUBE_MINION_IP_ADDRESSES[] +function detect-minions() { + KUBE_MINION_IP_ADDRESSES=() + for minion in ${MINIONS}; do + KUBE_MINION_IP_ADDRESSES+=("${minion#*@}") + done + echo "KUBE_MINION_IP_ADDRESSES: [${KUBE_MINION_IP_ADDRESSES[*]}]" 1>&2 +} + +# Verify prereqs on host machine +function verify-prereqs() { + local rc + rc=0 + ssh-add -L 1> /dev/null 2> /dev/null || rc="$?" + # "Could not open a connection to your authentication agent." + if [[ "${rc}" -eq 2 ]]; then + eval "$(ssh-agent)" > /dev/null + trap-add "kill ${SSH_AGENT_PID}" EXIT + fi + rc=0 + ssh-add -L 1> /dev/null 2> /dev/null || rc="$?" + # "The agent has no identities." + if [[ "${rc}" -eq 1 ]]; then + # Try adding one of the default identities, with or without passphrase. + ssh-add || true + fi + rc=0 + # Expect at least one identity to be available. + if ! ssh-add -L 1> /dev/null 2> /dev/null; then + echo "Could not find or add an SSH identity." + echo "Please start ssh-agent, add your identity, and retry." + exit 1 + fi +} + +# Install handler for signal trap +function trap-add { + local handler="$1" + local signal="${2-EXIT}" + local cur + + cur="$(eval "sh -c 'echo \$3' -- $(trap -p ${signal})")" + if [[ -n "${cur}" ]]; then + handler="${cur}; ${handler}" + fi + + trap "${handler}" ${signal} +} + +# Validate a kubernetes cluster +function validate-cluster() { + # by default call the generic validate-cluster.sh script, customizable by + # any cluster provider if this does not fit. + "${KUBE_ROOT}/cluster/validate-cluster.sh" +} + +# Instantiate a kubernetes cluster +function kube-up() { + provision-master + + for minion in ${MINIONS}; do + provision-minion ${minion} + done + + verify-master + for minion in ${MINIONS}; do + verify-minion ${minion} + done + + detect-master + + # set CONTEXT and KUBE_SERVER values for create-kubeconfig() and get-password() + export CONTEXT="centos" + export KUBE_SERVER="http://${KUBE_MASTER_IP}:8080" + source "${KUBE_ROOT}/cluster/common.sh" + + # set kubernetes user and password + get-password + create-kubeconfig +} + +# Delete a kubernetes cluster +function kube-down() { + tear-down-master + for minion in ${MINIONS}; do + tear-down-minion ${minion} + done +} + + +function verify-master() { + # verify master has all required daemons + printf "[INFO] Validating master ${MASTER}" + local -a required_daemon=("kube-apiserver" "kube-controller-manager" "kube-scheduler") + local validated="1" + local try_count=0 + until [[ "$validated" == "0" ]]; do + validated="0" + local daemon + for daemon in "${required_daemon[@]}"; do + local rc=0 + kube-ssh "${MASTER}" "pgrep -f ${daemon}" >/dev/null 2>&1 || rc="$?" + if [[ "${rc}" -ne "0" ]]; then + printf "." + validated="1" + ((try_count=try_count+2)) + if [[ ${try_count} -gt ${PROCESS_CHECK_TIMEOUT} ]]; then + printf "\nWarning: Process \"${daemon}\" status check timeout, please check manually.\n" + exit 1 + fi + sleep 2 + fi + done + done + printf "\n" + +} + +function verify-minion() { + # verify minion has all required daemons + printf "[INFO] Validating minion ${1}" + local -a required_daemon=("kube-proxy" "kubelet" "docker") + local validated="1" + local try_count=0 + until [[ "$validated" == "0" ]]; do + validated="0" + local daemon + for daemon in "${required_daemon[@]}"; do + local rc=0 + kube-ssh "${1}" "pgrep -f ${daemon}" >/dev/null 2>&1 || rc="$?" + if [[ "${rc}" -ne "0" ]]; then + printf "." + validated="1" + ((try_count=try_count+2)) + if [[ ${try_count} -gt ${PROCESS_CHECK_TIMEOUT} ]] ; then + printf "\nWarning: Process \"${daemon}\" status check timeout, please check manually.\n" + exit 1 + fi + sleep 2 + fi + done + done + printf "\n" +} + +# Clean up on master +function tear-down-master() { +echo "[INFO] tear-down-master on ${MASTER}" + for service_name in etcd kube-apiserver kube-controller-manager kube-scheduler ; do + service_file="/usr/lib/systemd/system/${service_name}.service" + ( + echo "if [[ -f $service_file ]]; then" + echo "systemctl stop $service_name" + echo "systemctl disable $service_name" + echo "rm -f $service_file" + echo "fi" + ) | kube-ssh "$MASTER" + done + kube-ssh "${MASTER}" "rm -rf /opt/kubernetes" + kube-ssh "${MASTER}" "rm -rf ${KUBE_TEMP}" + kube-ssh "${MASTER}" "rm -rf /var/lib/etcd" +} + +# Clean up on minion +function tear-down-minion() { +echo "[INFO] tear-down-minion on $1" + for service_name in kube-proxy kubelet docker flannel ; do + service_file="/usr/lib/systemd/system/${service_name}.service" + ( + echo "if [[ -f $service_file ]]; then" + echo "systemctl stop $service_name" + echo "systemctl disable $service_name" + echo "rm -f $service_file" + echo "fi" + ) | kube-ssh "$1" + done + kube-ssh "$1" "rm -rf /run/flannel" + kube-ssh "$1" "rm -rf /opt/kubernetes" + kube-ssh "$1" "rm -rf ${KUBE_TEMP}" +} + +# Provision master +# +# Assumed vars: +# MASTER +# KUBE_TEMP +# ETCD_SERVERS +# SERVICE_CLUSTER_IP_RANGE +function provision-master() { + echo "[INFO] Provision master on ${MASTER}" + local master_ip=${MASTER#*@} + ensure-setup-dir ${MASTER} + + # scp -r ${SSH_OPTS} master config-default.sh copy-files.sh util.sh "${MASTER}:${KUBE_TEMP}" + kube-scp ${MASTER} "${ROOT}/binaries/master ${ROOT}/master ${ROOT}/config-default.sh ${ROOT}/util.sh" "${KUBE_TEMP}" + ( + echo "cp -r ${KUBE_TEMP}/master/bin /opt/kubernetes" + echo "chmod -R +x /opt/kubernetes/bin" + + echo "bash ${KUBE_TEMP}/master/scripts/etcd.sh" + echo "bash ${KUBE_TEMP}/master/scripts/apiserver.sh ${master_ip} ${ETCD_SERVERS} ${SERVICE_CLUSTER_IP_RANGE}" + echo "bash ${KUBE_TEMP}/master/scripts/controller-manager.sh ${master_ip}" + echo "bash ${KUBE_TEMP}/master/scripts/scheduler.sh ${master_ip}" + + ) | kube-ssh "${MASTER}" +} + + +# Provision minion +# +# Assumed vars: +# $1 (minion) +# MASTER +# KUBE_TEMP +# ETCD_SERVERS +# FLANNEL_NET +# DOCKER_OPTS +function provision-minion() { + echo "[INFO] Provision minion on $1" + local master_ip=${MASTER#*@} + local minion=$1 + local minion_ip=${minion#*@} + ensure-setup-dir ${minion_ip} + + # scp -r ${SSH_OPTS} minion config-default.sh copy-files.sh util.sh "${minion_ip}:${KUBE_TEMP}" + kube-scp ${minion_ip} "${ROOT}/binaries/minion ${ROOT}/minion ${ROOT}/config-default.sh ${ROOT}/util.sh" ${KUBE_TEMP} + ( + echo "cp -r ${KUBE_TEMP}/minion/bin /opt/kubernetes" + echo "chmod -R +x /opt/kubernetes/bin" + + echo "bash ${KUBE_TEMP}/minion/scripts/flannel.sh ${ETCD_SERVERS} ${FLANNEL_NET}" + echo "bash ${KUBE_TEMP}/minion/scripts/docker.sh ${DOCKER_OPTS}" + echo "bash ${KUBE_TEMP}/minion/scripts/kubelet.sh ${master_ip} ${minion_ip}" + echo "bash ${KUBE_TEMP}/minion/scripts/proxy.sh ${master_ip}" + + ) | kube-ssh "${minion_ip}" +} + +# Create dirs that'll be used during setup on target machine. +# +# Assumed vars: +# KUBE_TEMP +function ensure-setup-dir() { + ( + echo "mkdir -p ${KUBE_TEMP}" + echo "mkdir -p /opt/kubernetes/bin" + echo "mkdir -p /opt/kubernetes/cfg" + ) | kube-ssh "${1}" +} + +# Run command over ssh +function kube-ssh() { + local host="$1" + shift + ssh ${SSH_OPTS-} "${host}" "$@" >/dev/null 2>&1 +} + +# Copy file recursively over ssh +function kube-scp() { + local host="$1" + local src=($2) + local dst="$3" + scp -r ${SSH_OPTS-} ${src[*]} "${host}:${dst}" +} + +# Ensure that we have a password created for validating to the master. Will +# read from kubeconfig if available. +# +# Vars set: +# KUBE_USER +# KUBE_PASSWORD +function get-password { + get-kubeconfig-basicauth + if [[ -z "${KUBE_USER}" || -z "${KUBE_PASSWORD}" ]]; then + KUBE_USER=admin + KUBE_PASSWORD=$(python -c 'import string,random; \ + print "".join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(16))') + fi +}