k3s/cluster/gce/coreos/configure-node.sh

345 lines
13 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.
set -o errexit
set -o nounset
set -o pipefail
readonly KNOWN_TOKENS_FILE="/srv/salt-overlay/salt/kube-apiserver/known_tokens.csv"
readonly BASIC_AUTH_FILE="/srv/salt-overlay/salt/kube-apiserver/basic_auth.csv"
# evaluate-manifest evalutes the source manifest with the environment variables.
function evaluate-manifest() {
local src=$1
local dst=$2
cp ${src} ${dst}
sed -i 's/\"/\\\"/g' ${dst} # eval will remove the double quotes if they are not escaped
eval "echo \"$(< ${dst})\"" > ${dst}
}
# evaluate-manifests-dir evalutes the source manifests within $1 and put the result
# in $2.
function evaluate-manifests-dir() {
local src=$1
local dst=$2
mkdir -p ${dst}
for f in ${src}/*
do
evaluate-manifest $f ${dst}/${f##*/}
done
}
function configure-kube-proxy() {
echo "Configuring kube-proxy"
mkdir -p /var/lib/kube-proxy
evaluate-manifest ${MANIFESTS_DIR}/kubeproxy-config.yaml /var/lib/kube-proxy/kubeconfig
}
function configure-logging() {
if [[ "${LOGGING_DESTINATION}" == "gcp" ]];then
echo "Configuring fluentd-gcp"
# fluentd-gcp
evaluate-manifest ${MANIFESTS_DIR}/fluentd-gcp.yaml /etc/kubernetes/manifests/fluentd-gcp.yaml
elif [[ "${LOGGING_DESTINATION}" == "elasticsearch" ]];then
echo "Configuring fluentd-es"
# fluentd-es
evaluate-manifest ${MANIFESTS_DIR}/fluentd-es.yaml /etc/kubernetes/manifests/fluentd-es.yaml
fi
}
function configure-admission-controls() {
echo "Configuring admission controls"
mkdir -p /etc/kubernetes/admission-controls
cp -r ${SALT_DIR}/salt/kube-admission-controls/limit-range /etc/kubernetes/admission-controls/
}
function configure-etcd() {
echo "Configuring etcd"
touch /var/log/etcd.log
evaluate-manifest ${MANIFESTS_DIR}/etcd.yaml /etc/kubernetes/manifests/etcd.yaml
}
function configure-etcd-events() {
echo "Configuring etcd-events"
touch /var/log/etcd-events.log
evaluate-manifest ${MANIFESTS_DIR}/etcd-events.yaml /etc/kubernetes/manifests/etcd-events.yaml
}
function configure-addon-manager() {
echo "Configuring addon-manager"
evaluate-manifest ${MANIFESTS_DIR}/kube-addon-manager.yaml /etc/kubernetes/manifests/kube-addon-manager.yaml
}
function configure-kube-apiserver() {
echo "Configuring kube-apiserver"
# Wait for etcd to be up.
wait-url-up http://127.0.0.1:2379/version
touch /var/log/kube-apiserver.log
# Copying known_tokens and basic_auth file.
cp ${SALT_OVERLAY}/salt/kube-apiserver/*.csv /srv/kubernetes/
evaluate-manifest ${MANIFESTS_DIR}/kube-apiserver.yaml /etc/kubernetes/manifests/kube-apiserver.yaml
}
function configure-kube-scheduler() {
echo "Configuring kube-scheduler"
touch /var/log/kube-scheduler.log
evaluate-manifest ${MANIFESTS_DIR}/kube-scheduler.yaml /etc/kubernetes/manifests/kube-scheduler.yaml
}
function configure-kube-controller-manager() {
# Wait for api server.
wait-url-up http://127.0.0.1:8080/version
echo "Configuring kube-controller-manager"
touch /var/log/kube-controller-manager.log
evaluate-manifest ${MANIFESTS_DIR}/kube-controller-manager.yaml /etc/kubernetes/manifests/kube-controller-manager.yaml
}
# Wait until $1 become reachable.
function wait-url-up() {
until curl --silent $1
do
sleep 5
done
}
# Configure addon yamls, and run salt/kube-addons/kube-addons.sh
function configure-master-addons() {
echo "Configuring master addons"
local addon_dir=/etc/kubernetes/addons
mkdir -p ${addon_dir}
# Copy namespace.yaml
evaluate-manifest ${MANIFESTS_DIR}/addons/namespace.yaml ${addon_dir}/namespace.yaml
if [[ "${ENABLE_L7_LOADBALANCING}" == "glbc" ]]; then
evaluate-manifests-dir ${MANIFESTS_DIR}/addons/cluster-loadbalancing/glbc ${addon_dir}/cluster-loadbalancing/glbc
fi
if [[ "${ENABLE_CLUSTER_DNS}" == "true" ]]; then
evaluate-manifests-dir ${MANIFESTS_DIR}/addons/dns ${addon_dir}/dns
fi
if [[ "${ENABLE_CLUSTER_UI}" == "true" ]]; then
evaluate-manifests-dir ${MANIFESTS_DIR}/addons/dashboard ${addon_dir}/dashboard
fi
if [[ "${ENABLE_CLUSTER_LOGGING}" == "true" ]]; then
evaluate-manifests-dir ${MANIFESTS_DIR}/addons/fluentd-elasticsearch ${addon_dir}/fluentd-elasticsearch
fi
if [[ "${ENABLE_CLUSTER_MONITORING}" == "influxdb" ]]; then
evaluate-manifests-dir ${MANIFESTS_DIR}/addons/cluster-monitoring/influxdb ${addon_dir}/cluster-monitoring/influxdb
elif [[ "${ENABLE_CLUSTER_MONITORING}" == "google" ]]; then
evaluate-manifests-dir ${MANIFESTS_DIR}/addons/cluster-monitoring/google ${addon_dir}/cluster-monitoring/google
elif [[ "${ENABLE_CLUSTER_MONITORING}" == "standalone" ]]; then
evaluate-manifests-dir ${MANIFESTS_DIR}/addons/cluster-monitoring/standalone ${addon_dir}/cluster-monitoring/standalone
elif [[ "${ENABLE_CLUSTER_MONITORING}" == "googleinfluxdb" ]]; then
evaluate-manifests-dir ${MANIFESTS_DIR}/addons/cluster-monitoring/googleinfluxdb ${addon_dir}/cluster-monitoring/googleinfluxdb
fi
# Note that, KUBE_ENABLE_INSECURE_REGISTRY is not supported yet.
if [[ "${ENABLE_CLUSTER_REGISTRY}" == "true" ]]; then
CLUSTER_REGISTRY_DISK_SIZE=$(convert-bytes-gce-kube "${CLUSTER_REGISTRY_DISK_SIZE}")
evaluate-manifests-dir ${MANIFESTS_DIR}/addons/registry ${addon_dir}/registry
fi
if [[ "${ENABLE_NODE_PROBLEM_DETECTOR}" == "true" ]]; then
evaluate-manifests-dir ${MANIFESTS_DIR}/addons/node-problem-detector ${addon_dir}/node-problem-detector
fi
}
function configure-master-components() {
configure-admission-controls
configure-etcd
configure-etcd-events
configure-kube-apiserver
configure-kube-scheduler
configure-kube-controller-manager
configure-master-addons
configure-addon-manager
}
# TODO(yifan): Merge this with mount-master-pd() in configure-vm.sh
# Pass ${save_format_and_mount} as an argument.
function mount-master-pd() {
if [[ ! -e /dev/disk/by-id/google-master-pd ]]; then
return
fi
device_info=$(ls -l /dev/disk/by-id/google-master-pd)
relative_path=${device_info##* }
device_path="/dev/disk/by-id/${relative_path}"
# Format and mount the disk, create directories on it for all of the master's
# persistent data, and link them to where they're used.
echo "Mounting master-pd"
mkdir -p /mnt/master-pd
safe_format_and_mount=${SALT_DIR}/salt/helpers/safe_format_and_mount
chmod +x ${safe_format_and_mount}
${safe_format_and_mount} -m "mkfs.ext4 -F" "${device_path}" /mnt/master-pd &>/var/log/master-pd-mount.log || \
{ echo "!!! master-pd mount failed, review /var/log/master-pd-mount.log !!!"; return 1; }
# Contains all the data stored in etcd
mkdir -m 700 -p /mnt/master-pd/var/etcd
# Contains the dynamically generated apiserver auth certs and keys
mkdir -p /mnt/master-pd/srv/kubernetes
# Contains the cluster's initial config parameters and auth tokens
mkdir -p /mnt/master-pd/srv/salt-overlay
# Directory for kube-apiserver to store SSH key (if necessary)
mkdir -p /mnt/master-pd/srv/sshproxy
ln -s -f /mnt/master-pd/var/etcd /var/etcd
ln -s -f /mnt/master-pd/srv/kubernetes /srv/kubernetes
ln -s -f /mnt/master-pd/srv/sshproxy /srv/sshproxy
ln -s -f /mnt/master-pd/srv/salt-overlay /srv/salt-overlay
# This is a bit of a hack to get around the fact that salt has to run after the
# PD and mounted directory are already set up. We can't give ownership of the
# directory to etcd until the etcd user and group exist, but they don't exist
# until salt runs if we don't create them here. We could alternatively make the
# permissions on the directory more permissive, but this seems less bad.
if ! id etcd &>/dev/null; then
useradd -s /sbin/nologin -d /var/etcd etcd
fi
chown -R etcd /mnt/master-pd/var/etcd
chgrp -R etcd /mnt/master-pd/var/etcd
}
# The job of this function is simple, but the basic regular expression syntax makes
# this difficult to read. What we want to do is convert from [0-9]+B, KB, KiB, MB, etc
# into [0-9]+, Ki, Mi, Gi, etc.
# This is done in two steps:
# 1. Convert from [0-9]+X?i?B into [0-9]X? (X denotes the prefix, ? means the field
# is optional.
# 2. Attach an 'i' to the end of the string if we find a letter.
# The two step process is needed to handle the edge case in which we want to convert
# a raw byte count, as the result should be a simple number (e.g. 5B -> 5).
#
# TODO(yifan): Reuse the one defined in configure-vm.sh to remove duplication.
function convert-bytes-gce-kube() {
local -r storage_space=$1
echo "${storage_space}" | sed -e 's/^\([0-9]\+\)\([A-Z]\)\?i\?B$/\1\2/g' -e 's/\([A-Z]\)$/\1i/'
}
# TODO(yifan): Use create-salt-master-auth() in configure-vm.sh
function create-salt-master-auth() {
if [[ ! -e /srv/kubernetes/ca.crt ]]; then
if [[ ! -z "${CA_CERT:-}" ]] && [[ ! -z "${MASTER_CERT:-}" ]] && [[ ! -z "${MASTER_KEY:-}" ]]; then
mkdir -p /srv/kubernetes
(umask 077;
echo "${CA_CERT}" | base64 --decode > /srv/kubernetes/ca.crt;
echo "${MASTER_CERT}" | base64 --decode > /srv/kubernetes/server.cert;
echo "${MASTER_KEY}" | base64 --decode > /srv/kubernetes/server.key;
# Kubecfg cert/key are optional and included for backwards compatibility.
# TODO(roberthbailey): Remove these two lines once GKE no longer requires
# fetching clients certs from the master VM.
echo "${KUBECFG_CERT:-}" | base64 --decode > /srv/kubernetes/kubecfg.crt;
echo "${KUBECFG_KEY:-}" | base64 --decode > /srv/kubernetes/kubecfg.key)
fi
fi
if [ ! -e "${BASIC_AUTH_FILE}" ]; then
mkdir -p /srv/salt-overlay/salt/kube-apiserver
(umask 077;
echo "${KUBE_PASSWORD},${KUBE_USER},admin" > "${BASIC_AUTH_FILE}")
fi
if [ ! -e "${KNOWN_TOKENS_FILE}" ]; then
mkdir -p /srv/salt-overlay/salt/kube-apiserver
(umask 077;
echo "${KUBE_BEARER_TOKEN},admin,admin" > "${KNOWN_TOKENS_FILE}";
echo "${KUBELET_TOKEN},kubelet,kubelet" >> "${KNOWN_TOKENS_FILE}";
echo "${KUBE_PROXY_TOKEN},kube_proxy,kube_proxy" >> "${KNOWN_TOKENS_FILE}")
# Generate tokens for other "service accounts". Append to known_tokens.
#
# NB: If this list ever changes, this script actually has to
# change to detect the existence of this file, kill any deleted
# old tokens and add any new tokens (to handle the upgrade case).
local -r service_accounts=("system:scheduler" "system:controller_manager" "system:logging" "system:monitoring")
for account in "${service_accounts[@]}"; do
token=$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64 | tr -d "=+/" | dd bs=32 count=1 2>/dev/null)
echo "${token},${account},${account}" >> "${KNOWN_TOKENS_FILE}"
done
fi
}
# $1 is the directory containing all of the docker images
function load-docker-images() {
local success
local restart_docker
while true; do
success=true
restart_docker=false
for image in "$1/"*; do
timeout 30 docker load -i "${image}" &>/dev/null
rc=$?
if [[ "$rc" == 124 ]]; then
restart_docker=true
elif [[ "$rc" != 0 ]]; then
success=false
fi
done
if [[ "$success" == "true" ]]; then break; fi
if [[ "$restart_docker" == "true" ]]; then systemctl restart docker; fi
sleep 15
done
}
function load-master-components-images() {
echo "Loading images for master components"
export RKT_BIN=/opt/rkt/rkt
export DOCKER2ACI_BIN=/opt/docker2aci/docker2aci
${SALT_DIR}/install.sh ${KUBE_BIN_TAR}
${SALT_DIR}/salt/kube-master-addons/kube-master-addons.sh
# Get the image tags.
KUBE_APISERVER_DOCKER_TAG=$(cat ${KUBE_BIN_DIR}/kube-apiserver.docker_tag)
KUBE_CONTROLLER_MANAGER_DOCKER_TAG=$(cat ${KUBE_BIN_DIR}/kube-controller-manager.docker_tag)
KUBE_SCHEDULER_DOCKER_TAG=$(cat ${KUBE_BIN_DIR}/kube-scheduler.docker_tag)
}
##########
# main #
##########
KUBE_BIN_TAR=/opt/downloads/kubernetes-server-linux-amd64.tar.gz
KUBE_BIN_DIR=/opt/kubernetes/server/bin
SALT_DIR=/opt/kubernetes/saltbase
SALT_OVERLAY=/srv/salt-overlay
MANIFESTS_DIR=/opt/kube-manifests/kubernetes
# On CoreOS, the hosts is in /usr/share/baselayout/hosts
# So we need to manually populdate the hosts file here on gce.
echo "127.0.0.1 localhost" >> /etc/hosts
echo "::1 localhost" >> /etc/hosts
if [[ "${KUBERNETES_MASTER}" == "true" ]]; then
mount-master-pd
create-salt-master-auth
load-master-components-images
configure-master-components
else
configure-kube-proxy
fi
if [[ "${ENABLE_NODE_LOGGING}" == "true" ]];then
configure-logging
fi
echo "Finish configuration successfully!"