kubernetes/cluster/centos/util.sh
k8s-merge-robot 5df9284ff4 Merge pull request #26746 from MHBauer/enable-ssh-compression
Automatic merge from submit-queue

Ubuntu: Enable ssh compression when downloading binaries during cluster creation

<!--
Checklist for submitting a Pull Request

Please remove this comment block before submitting.

1. Please read our [contributor guidelines](https://github.com/kubernetes/kubernetes/blob/master/CONTRIBUTING.md).
2. See our [developer guide](https://github.com/kubernetes/kubernetes/blob/master/docs/devel/development.md).
3. If you want this PR to automatically close an issue when it is merged,
   add `fixes #<issue number>` or `fixes #<issue number>, fixes #<issue number>`
   to close multiple issues (see: https://github.com/blog/1506-closing-issues-via-pull-requests).
4. Follow the instructions for [labeling and writing a release note for this PR](https://github.com/kubernetes/kubernetes/blob/master/docs/devel/pull-requests.md#release-notes) in the block below.
-->
resolves #20971 by using the options provided by ssh. 

Native ssh compression has existed for years, and the server is free to disregard the setting, so this should be safe.

With things like the kube binaries I see about a 2x speed increase. 

```
λ time scp kubes-bin.tar   9.30.182.251:/mnt/build/kubin
kubes-bin.tar                                                                                                            100%  344MB  10.7MB/s   00:32

real	0m32.284s
user	0m1.679s
sys	0m1.263s

λ time scp -C kubes-bin.tar   9.30.182.251:/mnt/build/kubin
kubes-bin.tar                                                                                                            100%  344MB  22.9MB/s   00:15

real	0m14.810s
user	0m12.858s
sys	0m0.994s

λ ls -lah kubes-bin.tar
-rw-r--r--  1 mhb  staff   344M Jun  2 15:29 kubes-bin.tar

λ tar -tf kubes-bin.tar
kubectl
master/
master/etcd
master/etcdctl
master/flanneld
master/kube-apiserver
master/kube-controller-manager
master/kube-scheduler
node/
node/flanneld
node/kube-proxy
node/kubelet
```
2016-07-19 19:21:46 -07:00

303 lines
9.1 KiB
Bash
Executable File

#!/bin/bash
# Copyright 2015 The Kubernetes Authors.
#
# 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 -C"
# 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 node provisioning.
KUBE_TEMP="~/kube_temp"
# 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 node IP addresses and store in KUBE_NODE_IP_ADDRESSES[]
function detect-nodes() {
KUBE_NODE_IP_ADDRESSES=()
for node in ${NODES}; do
KUBE_NODE_IP_ADDRESSES+=("${node#*@}")
done
echo "KUBE_NODE_IP_ADDRESSES: [${KUBE_NODE_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.
set +e
"${KUBE_ROOT}/cluster/validate-cluster.sh"
if [[ "$?" -ne "0" ]]; then
troubleshoot-master
for node in ${NODES}; do
troubleshoot-node ${node}
done
exit 1
fi
set -e
}
# Instantiate a kubernetes cluster
function kube-up() {
provision-master
for node in ${NODES}; do
provision-node ${node}
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 node in ${NODES}; do
tear-down-node ${node}
done
}
function troubleshoot-master() {
# Troubleshooting on master if all required daemons are active.
echo "[INFO] Troubleshooting on master ${MASTER}"
local -a required_daemon=("kube-apiserver" "kube-controller-manager" "kube-scheduler")
local daemon
local daemon_status
printf "%-24s %-10s \n" "PROCESS" "STATUS"
for daemon in "${required_daemon[@]}"; do
local rc=0
kube-ssh "${MASTER}" "sudo systemctl is-active ${daemon}" >/dev/null 2>&1 || rc="$?"
if [[ "${rc}" -ne "0" ]]; then
daemon_status="inactive"
else
daemon_status="active"
fi
printf "%-24s %s\n" ${daemon} ${daemon_status}
done
printf "\n"
}
function troubleshoot-node() {
# Troubleshooting on node if all required daemons are active.
echo "[INFO] Troubleshooting on node ${1}"
local -a required_daemon=("kube-proxy" "kubelet" "docker" "flannel")
local daemon
local daemon_status
printf "%-24s %-10s \n" "PROCESS" "STATUS"
for daemon in "${required_daemon[@]}"; do
local rc=0
kube-ssh "${1}" "sudo systemctl is-active ${daemon}" >/dev/null 2>&1 || rc="$?"
if [[ "${rc}" -ne "0" ]]; then
daemon_status="inactive"
else
daemon_status="active"
fi
printf "%-24s %s\n" ${daemon} ${daemon_status}
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"
kube-ssh "$MASTER" " \
if [[ -f $service_file ]]; then \
sudo systemctl stop $service_name; \
sudo systemctl disable $service_name; \
sudo rm -f $service_file; \
fi"
done
kube-ssh "${MASTER}" "sudo rm -rf /opt/kubernetes"
kube-ssh "${MASTER}" "sudo rm -rf ${KUBE_TEMP}"
kube-ssh "${MASTER}" "sudo rm -rf /var/lib/etcd"
}
# Clean up on node
function tear-down-node() {
echo "[INFO] tear-down-node on $1"
for service_name in kube-proxy kubelet docker flannel ; do
service_file="/usr/lib/systemd/system/${service_name}.service"
kube-ssh "$1" " \
if [[ -f $service_file ]]; then \
sudo systemctl stop $service_name; \
sudo systemctl disable $service_name; \
sudo rm -f $service_file; \
fi"
done
kube-ssh "$1" "sudo rm -rf /run/flannel"
kube-ssh "$1" "sudo rm -rf /opt/kubernetes"
kube-ssh "$1" "sudo 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}/../saltbase/salt/generate-cert/make-ca-cert.sh ${ROOT}/binaries/master ${ROOT}/master ${ROOT}/config-default.sh ${ROOT}/util.sh" "${KUBE_TEMP}"
kube-ssh "${MASTER}" " \
sudo cp -r ${KUBE_TEMP}/master/bin /opt/kubernetes; \
sudo chmod -R +x /opt/kubernetes/bin; \
sudo bash ${KUBE_TEMP}/make-ca-cert.sh ${master_ip} IP:${master_ip},IP:${SERVICE_CLUSTER_IP_RANGE%.*}.1,DNS:kubernetes,DNS:kubernetes.default,DNS:kubernetes.default.svc,DNS:kubernetes.default.svc.cluster.local; \
sudo bash ${KUBE_TEMP}/master/scripts/etcd.sh; \
sudo bash ${KUBE_TEMP}/master/scripts/apiserver.sh ${master_ip} ${ETCD_SERVERS} ${SERVICE_CLUSTER_IP_RANGE} ${ADMISSION_CONTROL}; \
sudo bash ${KUBE_TEMP}/master/scripts/controller-manager.sh ${master_ip}; \
sudo bash ${KUBE_TEMP}/master/scripts/scheduler.sh ${master_ip}"
}
# Provision node
#
# Assumed vars:
# $1 (node)
# MASTER
# KUBE_TEMP
# ETCD_SERVERS
# FLANNEL_NET
# DOCKER_OPTS
function provision-node() {
echo "[INFO] Provision node on $1"
local master_ip=${MASTER#*@}
local node=$1
local node_ip=${node#*@}
ensure-setup-dir ${node}
kube-scp ${node} "${ROOT}/binaries/node ${ROOT}/node ${ROOT}/config-default.sh ${ROOT}/util.sh" ${KUBE_TEMP}
kube-ssh "${node}" " \
sudo cp -r ${KUBE_TEMP}/node/bin /opt/kubernetes; \
sudo chmod -R +x /opt/kubernetes/bin; \
sudo bash ${KUBE_TEMP}/node/scripts/flannel.sh ${ETCD_SERVERS} ${FLANNEL_NET}; \
sudo bash ${KUBE_TEMP}/node/scripts/docker.sh \"${DOCKER_OPTS}\"; \
sudo bash ${KUBE_TEMP}/node/scripts/kubelet.sh ${master_ip} ${node_ip}; \
sudo bash ${KUBE_TEMP}/node/scripts/proxy.sh ${master_ip}"
}
# Create dirs that'll be used during setup on target machine.
#
# Assumed vars:
# KUBE_TEMP
function ensure-setup-dir() {
kube-ssh "${1}" "mkdir -p ${KUBE_TEMP}; \
sudo mkdir -p /opt/kubernetes/bin; \
sudo mkdir -p /opt/kubernetes/cfg"
}
# Run command over ssh
function kube-ssh() {
local host="$1"
shift
ssh ${SSH_OPTS} -t "${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 {
load-or-gen-kube-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
}