koris.provision package¶
Submodules¶
koris.provision.cloud_init module¶
This modules contains some helper functions to inject cloud-init to booted machines. At the moment only Cloud Inits for Ubunut 16.04 are provided
-
class
koris.provision.cloud_init.
BaseInit
(cloud_config)[source]¶ Bases:
object
Parameters: An OSCloudConfig instance describing the information (cloud_config) – necessary for sending requests to the underlying cloud. Needed e.g. for auto scaling. -
cloud_config_data this attribute contains the text/cloud-config
files that is passed to the instances
-
attachments this attribute contains other parts of the
userdata, e.g scripts that are directly executed by cloud-init. They should be instances of MIMEText with the header ‘Content-Disposition’ set to ‘attachment’
-
add_ssh_public_key
(ssh_key)[source]¶ ssh_key istance of
cryptography.hazmat.backends.openssl.rsa._RSAPrivateKey
-
write_file
(path, content, owner='root', group='root', permissions='0600', encoder=<function BaseInit.<lambda>>)[source]¶ writes a file to the instance path: e.g. /etc/kubernetes/koris.conf content: string of the content of the file owner: e.g. root group: e.g. root permissions: e.g. “0644”, as string encode: Optional encoder to use for the needed base64 encoding
-
-
class
koris.provision.cloud_init.
FirstMasterInit
(ssh_key, ca_bundle, cloud_config, os_type='ubuntu', os_version='16.04', dex=None, koris_env=None)[source]¶ Bases:
koris.provision.cloud_init.NthMasterInit
This node executes the bootstrap strip to create the initial cluster.
Parameters: - ssh_key (RSAkeypair) –
create_key()
- ca_bundle – The CA bundle for the CA that is used to permit accesses to the API server.
- cloud_config – An OSCloudConfig instance describing the information necessary for sending requests to the underlying cloud.
- os_type (str) – the OS type the bootstrap script runs on
- os_version (str) – OS version the bootstrap script runs on
- dex (dict) – A dictionary containg information for Dex
- koris_env (dict) – A dictionary containing information for the koris.env
- ssh_key (RSAkeypair) –
-
class
koris.provision.cloud_init.
NodeInit
(ca_cert, cloud_config, lb_ip, lb_port, bootstrap_token, discovery_hash, lb_dns='', os_type='ubuntu', os_version='16.04', k8s_version='1.14.1', pod_network='CALICO')[source]¶ Bases:
koris.provision.cloud_init.BaseInit
The node does nothing else than executing its bootstrap script.
-
class
koris.provision.cloud_init.
NthMasterInit
(cloud_config, ssh_key, os_type='ubuntu', os_version='16.04', dex=None, koris_env=None, k8s_conf=None)[source]¶ Bases:
koris.provision.cloud_init.BaseInit
Initialization userdata for an n-th master node. Nothing more than adding an public SSH key for access from the first master node needs to be done.
Module contents¶
koris.provison.userdata¶
bootstrap-k8s-master-ubuntu-16.04.sh¶
This script is executed on the first master on cluster boot.
One can also run this script on bare metal machines to create
a kubeadm
based kubernetes cluster.
The script needs /etc/kubernetes/koris.env
to run properly.
This file includes all the information on the cluster and
written via cloud-init
on the first boot.
See koris.provision.cloud_init.FirstMasterInit
#!/bin/bash
set -e
###
# A script to create a HA K8S cluster on OpenStack using pure bash and kubeadm
#
# The script is devided into a whole bunch of functions, look for the fuction
# called main at the bottom.
#
# The script will create mutliple kubernetes control plane members connected
# via an etcd cluster which is grown in a serial manner. That means we first
# create a single etcd host, and then add N hosts one after another.
#
# The addition of master nodes is done via SSH!
#
# This should be the content of /etc/kubernetes/koris.env
#
# export BOOTSTRAP_NODES=1 # for bootstrapping baremetal nodes (i.e. not an Openstack Image
# export SSH_USER="root" # for ubuntu use ubuntu
# export POD_SUBNET="10.233.0.0/16"
# export POD_NETWORK="CALICO"
# export LOAD_BALANCER_PORT="6443"
# export MASTERS_IPS=( 10.32.10.1 10.32.10.2 10.32.10.3 )
# export MASTERS=( master-1 master-2 master-3 )
# # specify one of the two LOAD_BALANCER_IP or LOAD_BALANCER_DNS
# export LOAD_BALANCER_IP=XX.YY.ZZ.WW
# export BOOTSTRAP_TOKEN=$(openssl rand -hex 3).$$(openssl rand -hex 8)
# export OPENSTACK=0
# export K8SNODES=( node-1 node-2 ) # a list of nodes to join
#
###
# load koris environment file if available
if [ -f /etc/kubernetes/koris.env ]; then
source /etc/kubernetes/koris.env
fi
export CURRENT_CLUSTER=""
export CLUSTER_STATE=""
#### Versions for Kube 1.12.X
export KUBE_VERSION=${KUBE_VERSION:-1.14.1}
export DOCKER_VERSION=18.06
export CALICO_VERSION=3.3
export POD_SUBNET=${POD_SUBNET:-"10.233.0.0/16"}
export SSH_USER=${SSH_USER:-"ubuntu"}
export BOOTSTRAP_NODES=${BOOTSTRAP_NODES:-0}
export OPENSTACK=${OPENSTACK:-1}
export K8SNODES=${K8SNODES:-""}
export OIDC_CLIENT_ID=${OIDC_CLIENT_ID:-""}
export OIDC_CA_FILE=${OIDC_CA_FILE:-""}
export ADDTOKEN=1
# find if better way to compare versions exists
# version numbers are splited in the "." and the second part is being compared
# ex. "1.12 vs 1.13 means compare 12 with 13"
KUBE_VERSION_COMPARE="$(echo $KUBE_VERSION | cut -d '.' -f 2 )"
LOGLEVEL=4
V=${LOGLEVEL}
LOGFILE=/dev/stderr
function log() {
datestring=`date +"%Y-%m-%d %H:%M:%S"`
echo -e "$datestring - $@" | tee $LOGFILE
}
SSHOPTS="-i /etc/ssh/ssh_host_rsa_key -o StrictHostKeyChecking=no -o ConnectTimeout=60"
SFTPOPTS=${SSHOPTS}
# used for k8s v1.13.X
function create_kubeadm_config_new_version () {
HOST_NAME=$1
HOST_IP=$2
cat <<TMPL > kubeadm-"${HOST_NAME}".yaml
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: v${KUBE_VERSION}
apiServer:
certSANs:
- "${LOAD_BALANCER_DNS:-${LOAD_BALANCER_IP}}"
controlPlaneEndpoint: "${LOAD_BALANCER_DNS:-${LOAD_BALANCER_IP}}:${LOAD_BALANCER_PORT}"
networking:
# This CIDR is a Calico default. Substitute or remove for your CNI provider.
podSubnet: ${POD_SUBNET}
# dnsDomain: cluster.local
# serviceSubnet: 10.96.0.0/12
controllerManager:
extraArgs:
allocate-node-cidrs: "true"
cluster-cidr: ${POD_SUBNET}
extraArgs:
external-cloud-volume-plugin: "openstack"
cloud-config: /etc/kubernetes/cloud-config
extraVolumes:
- hostPath: /etc/kubernetes/cloud-config
name: cloud-config
mountPath: /etc/kubernetes/cloud-config
pathType: File
TMPL
# If Dex is to be deployed, we need to start the apiserver with extra args.
if [[ ! -z ${OIDC_CLIENT_ID} ]]; then
cat <<TMPL > dex.yaml
apiServer:
extraArgs:
oidc-issuer-url: "${OIDC_ISSUER_URL}"
oidc-client-id: ${OIDC_CLIENT_ID}
oidc-ca-file: ${OIDC_CA_FILE}
oidc-username-claim: ${OIDC_USERNAME_CLAIM}
oidc-groups-claim: ${OIDC_GROUPS_CLAIM}
TMPL
yq m -i -a kubeadm-"${HOST_NAME}".yaml dex.yaml
fi
# add audit policy
cat <<AUDITPOLICY >> auditPolicy.yml
apiServer:
extraArgs:
audit-log-maxsize: "24"
audit-log-maxbackup: "30"
audit-log-maxage: "90"
audit-log-path: /var/log/kubernetes/audit.log
audit-policy-file: /etc/kubernetes/audit-policy.yml
AUDITPOLICY
yq m -i -a kubeadm-"${HOST_NAME}".yaml auditPolicy.yml
# add volumes for audit logs
cat << AV >> auditVolumes.yml
apiServer:
extraVolumes:
- name: var-log-kubernetes
hostPath: /var/log/kubernetes
mountPath: /var/log/kubernetes
pathType: DirectoryOrCreate
- name: "audit-policy"
hostPath: "/etc/kubernetes/audit-policy.yml"
mountPath: "/etc/kubernetes/audit-policy.yml"
readOnly: true
pathType: File
AV
yq m -i -a kubeadm-"${HOST_NAME}".yaml auditVolumes.yml
if [[ ${ADDTOKEN} -eq 1 ]]; then
cat <<TOKEN >> kubeadm-"${HOST_NAME}".yaml
---
apiVersion: kubeadm.k8s.io/v1beta1
kind: InitConfiguration
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: ${BOOTSTRAP_TOKEN}
ttl: 24h0m0s
usages:
- signing
- authentication
nodeRegistration:
criSocket: /var/run/dockershim.sock
name: ${HOSTNAME}
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
TOKEN
fi
DISCOVERY_HASH=$(openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | \
openssl rsa -pubin -outform der 2>/dev/null | \
openssl dgst -sha256 -hex | sed 's/^.* //')
}
# create secrets and config maps
# these are used by the master pod which we call from the CLI
function make_secrets() {
local k8senv="--kubeconfig=/etc/kubernetes/admin.conf -n kube-system"
local del_secret_args="${k8senv} --ignore-not-found=true delete secret"
local secret_args="${k8senv} create secret"
# shellcheck disable=SC2086
kubectl ${del_secret_args} ssh-key
# shellcheck disable=SC2086
kubectl ${secret_args} generic ssh-key --from-file=/etc/ssh/ssh_host_rsa_key
# shellcheck disable=SC2086
kubectl ${del_secret_args} "cluster-ca"
# shellcheck disable=SC2086
kubectl ${secret_args} tls "cluster-ca" --key /etc/kubernetes/pki/ca.key --cert /etc/kubernetes/pki/ca.crt
# shellcheck disable=SC2086
kubectl ${del_secret_args} "front-proxy"
# shellcheck disable=SC2086
kubectl ${secret_args} tls "front-proxy" --key /etc/kubernetes/pki/front-proxy-ca.key --cert /etc/kubernetes/pki/front-proxy-ca.crt
# shellcheck disable=SC2086
kubectl ${del_secret_args} "etcd-ca"
# shellcheck disable=SC2086
kubectl ${secret_args} tls "etcd-ca" --key /etc/kubernetes/pki/etcd/ca.key --cert /etc/kubernetes/pki/etcd/ca.crt
# shellcheck disable=SC2086
kubectl ${del_secret_args} "sa-pub"
# shellcheck disable=SC2086
kubectl ${secret_args} generic "sa-pub" --from-file=/etc/kubernetes/pki/sa.pub
# shellcheck disable=SC2086
kubectl ${del_secret_args} "sa-key"
# shellcheck disable=SC2086
kubectl ${secret_args} generic "sa-key" --from-file=/etc/kubernetes/pki/sa.key
# shellcheck disable=SC2086
kubectl ${del_secret_args} admin.conf
# shellcheck disable=SC2086
kubectl ${secret_args} generic admin.conf --from-file=/etc/kubernetes/admin.conf
# shellcheck disable=SC2086
kubectl ${k8senv} create configmap audit-policy --from-file="/etc/kubernetes/audit-policy.yml"
kubectl ${k8senv} create configmap kubeadm.yaml --from-file="kubeadm.yaml"
if [[ ${OPENSTACK} -eq 1 ]]; then
# shellcheck disable=SC2086
kubectl ${del_secret_args} cloud-config
kubectl ${del_secret_args} cloud-config
# shellcheck disable=SC2086
kubectl ${secret_args} generic cloud-config --from-file=/etc/kubernetes/cloud-config
fi
if [[ ! -z ${OIDC_CA_FILE} ]]; then
kubectl ${del_secret_args} oidc-ca
# shellcheck disable=SC2086
kubectl ${secret_args} generic oidc-ca --from-file="${OIDC_CA_FILE}"
# shellcheck disable=SC2086
kubectl ${k8senv} delete configmap dex-config --ignore-not-found=true
# shellcheck disable=SC2086
kubectl ${k8senv} create configmap dex-config --from-file="dex.tmpl"
fi
}
# distributes configuration file and certificates to a master node
function copy_keys() {
host=$1
USER=${SSH_USER:-ubuntu}
echo -n "waiting for ssh on $1"
until ssh ${SSHOPTS} "${USER}"@"$1" hostname; do
echo -n "."
sleep 1
done
echo "distributing keys to $host";
# clean and recreate directory structure
ssh ${SSHOPTS} ${USER}@$host sudo rm -vRf /etc/kubernetes
ssh ${SSHOPTS} ${USER}@$host mkdir -pv /home/${USER}/kubernetes/pki/etcd
ssh ${SSHOPTS} ${USER}@$host mkdir -pv /home/${USER}/kubernetes/manifests
# copy over everything PKI related, copy to temporary directory with
# non-root write access
sftp ${SFTPOPTS} ${USER}@$host << EOF
put /etc/kubernetes/pki/ca.crt /home/${USER}/kubernetes/pki/
put /etc/kubernetes/pki/ca.key /home/${USER}/kubernetes/pki/
put /etc/kubernetes/pki/sa.key /home/${USER}/kubernetes/pki/
put /etc/kubernetes/pki/sa.pub /home/${USER}/kubernetes/pki/
put /etc/kubernetes/pki/front-proxy-ca.crt /home/${USER}/kubernetes/pki/
put /etc/kubernetes/pki/front-proxy-ca.key /home/${USER}/kubernetes/pki/
put /etc/kubernetes/pki/etcd/ca.crt /home/${USER}/kubernetes/pki/etcd/
put /etc/kubernetes/pki/etcd/ca.key /home/${USER}/kubernetes/pki/etcd/
put /etc/kubernetes/admin.conf /home/${USER}/kubernetes/
chmod 0600 /home/${USER}/kubernetes/admin.conf
put /etc/kubernetes/koris.env /home/${USER}/kubernetes/
put /etc/kubernetes/audit-policy.yml /home/${USER}/kubernetes/
EOF
if [[ ${OPENSTACK} -eq 1 ]]; then
sftp ${SFTPOPTS} ${USER}@$host << EOF
put /etc/kubernetes/cloud-config /home/${USER}/kubernetes/
chmod 0600 /home/${USER}/kubernetes/cloud-config
EOF
fi
if [ ! -z "${OIDC_CA_FILE}" ]; then
local DESTDIR
DESTDIR="$(dirname "${OIDC_CA_FILE}")"
ssh ${SSHOPTS} "${USER}@$host" mkdir -pv /home/"${USER}"/"${DESTDIR}"
sftp ${SFTPOPTS} "${USER}@$host" << EOF
put ${OIDC_CA_FILE} /home/${USER}/${DESTDIR}
chmod 0600 /home/${USER}/${OIDC_CA_FILE}
EOF
fi
if [[ ${OPENSTACK} -eq 1 ]]; then
sftp ${SFTPOPTS} ${USER}@$host << EOF
put /etc/kubernetes/cloud-config /home/${USER}/kubernetes/
chmod 0600 /home/${USER}/kubernetes/cloud-config
EOF
fi
# move back to /etc on remote machine
ssh ${SSHOPTS} ${USER}@$host sudo mv -v /home/${USER}/kubernetes /etc/
ssh ${SSHOPTS} ${USER}@$host sudo chown root:root -vR /etc/kubernetes
ssh ${SSHOPTS} ${USER}@$host sudo chmod 0600 -vR /etc/kubernetes/admin.conf
echo "done distributing keys to $host";
}
# add audit minimal audit policy
function create_audit_policy(){
if [ ! -r /etc/kubernetes/audit-policy.yml ]; then
cat << EOF > /etc/kubernetes/audit-policy.yml
# Log all requests at the Metadata level.
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
EOF
fi
}
# check if a binary version is found
# version_check kube-scheduler --version v1.10.4 return 1 if binary is found
# in that version
function version_found() { return $("$1" "$2" | grep -qi "$3"); }
# bootstrap the first master.
# the process is slightly different than for the rest of the N masters
# we add
function bootstrap_first_master() {
HOST_NAME=$1
HOST_IP=$2
CONFIG=kubeadm-${HOST_NAME}.yaml
CURRENT_CLUSTER="$HOST_NAME=https://${HOST_IP}:2380"
echo "Bootstaping k8s ${KUBE_VERSION}"
create_kubeadm_config_new_version "${HOST_NAME}" "${HOST_IP}"
kubeadm init --config "${CONFIG}"
kubeadm -v=${V} init phase upload-config all --config "${CONFIG}"
test -d /root/.kube || mkdir -p /root/.kube
cp /etc/kubernetes/admin.conf /root/.kube/config
chown root:root /root/.kube/config
cp kubeadm-${HOST_NAME}.yaml kubeadm.yaml
kubectl get nodes
}
function add_master_one_thirteen() {
ssh ${SSHOPTS} ${USER}@$1 sudo kubeadm join --token ${BOOTSTRAP_TOKEN} --discovery-token-ca-cert-hash \
sha256:${DISCOVERY_HASH} --experimental-control-plane ${LOAD_BALANCER_DNS:-${LOAD_BALANCER_IP}}:${LOAD_BALANCER_PORT}
}
# add a master to the cluster
# the first argument is the host name to add
# the second argument is the host IP
function add_master {
set -x
USER=${SSH_USER:-ubuntu}
HOST_NAME=$1
HOST_IP=$2
CURRENT_CLUSTER=$3
ETCD_HOST=$4
ETCD_IP=$5
local CONFIG="/home/${USER}/kubeadm-${HOST_NAME}.yaml"
echo "*********** Bootstrapping $1 ******************"
until ssh ${SSHOPTS} ${USER}@$1 hostname; do
echo "waiting for ssh on $1"
sleep 2
done
ssh ${SSHOPTS} ${USER}@1 "kubeadm | grep -qi ${KUBE_VERSION}" || BOOTSTRAP_NODES=1
if [ ${BOOTSTRAP_NODES} -eq 1 ]; then
bootstrap_deps_node $1
fi
echo "******* Preparing kubeadm config for $1 ******"
echo "bootstrapping 1.13"
create_kubeadm_config_new_version "${HOST_NAME}" "${HOST_IP}"
add_master_one_thirteen $HOST_NAME $CONFIG
}
function wait_for_etcd () {
until [[ x"$(kubectl get pod etcd-$1 -n kube-system -o jsonpath='{.status.phase}' 2>/dev/null)" == x"Running" ]]; do
echo "waiting for etcd-$1 ... "
sleep 2
done
}
TRANSPORT_PACKAGES="apt-transport-https ca-certificates software-properties-common"
# fetch and prepare calico manifests
function get_calico(){
while [ ! -f rbac-kdd.yaml ]; do
curl --retry 10 -sfLO https://docs.projectcalico.org/v${CALICO_VERSION}/getting-started/kubernetes/installation/hosted/rbac-kdd.yaml
done
while [ ! -f calico.yaml ]; do
curl --retry 10 -sfLO https://docs.projectcalico.org/v${CALICO_VERSION}/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml
done
sed -i 's@192.168.0.0/16@'"${POD_SUBNET}"'@g' calico.yaml
}
# fetch the manifest for flannel
function get_flannel(){
while [ ! -r kube-flannel.yml ]; do
curl --retry 10 -sfLO https://raw.githubusercontent.com/coreos/flannel/bc79dd1505b0c8681ece4de4c0d86c5cd2643275/Documentation/kube-flannel.yml
done
sed -i "s@\"Type\": \"vxlan\"@\"Type\": \"ipip\"@g" kube-flannel.yml
sed -i "s@10.244.0.0/16@${POD_SUBNET}@g" kube-flannel.yml
}
# get the correct network plugin
function get_net_plugin(){
case "${POD_NETWORK}" in
"CALICO"|"")
get_calico
;;
"FLANNEL")
get_flannel
sysctl net.bridge.bridge-nf-call-iptables=1
;;
esac
}
# apply the correct network plugin
function apply_net_plugin(){
case "${POD_NETWORK}" in
"CALICO"|"")
echo "installing calico"
kubectl apply -f rbac-kdd.yaml
kubectl apply -f calico.yaml
;;
"FLANNEL")
echo "installing flannel"
kubectl apply -f kube-flannel.yml
;;
esac
}
function bootstrap_deps_node() {
ssh ${SSHOPTS} ${SSH_USER}@${1} sudo bash << EOF
set -ex;
iptables -P FORWARD ACCEPT;
swapoff -a;
export TRANSPORT_PACKAGES="${TRANSPORT_PACKAGES}";
export KUBE_VERSION="${KUBE_VERSION}";
export DOCKER_VERSION="${DOCKER_VERSION}";
export first_master="${first_master}";
$(typeset -f log);
$(typeset -f get_yq);
$(typeset -f get_docker);
$(typeset -f get_kubeadm);
$(typeset -f fetch_all);
fetch_all;
EOF
}
# enforce docker version
function get_docker() {
log "Started get_docker"
apt-get update
dpkg -l software-properties-common | grep ^ii || apt-get install ${TRANSPORT_PACKAGES} -y
curl --retry 10 -fssl https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
apt-get update
apt-get -y install docker-ce="${DOCKER_VERSION}*"
apt-get install -y socat conntrack ipset
log "started finished_docker"
}
# enforce kubeadm version
function get_kubeadm() {
apt-get update
dpkg -l software-properties-common | grep ^ii || apt-get install ${TRANSPORT_PACKAGES} -y
curl --retry 10 -fssL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
apt-add-repository -u "deb http://apt.kubernetes.io kubernetes-xenial main"
apt-get install -y --allow-downgrades kubeadm=${KUBE_VERSION}-00 kubelet=${KUBE_VERSION}-00
}
function get_yq() {
if [ -z "$(type -P yq)" ]; then
curl --retry 10 -fssL https://github.com/mikefarah/yq/releases/download/2.3.0/yq_linux_amd64 -o /usr/local/bin/yq
chmod +x /usr/local/bin/yq
fi
}
# the entry point of the whole script.
# this function bootstraps the who etcd cluster and control plane components
# accross N hosts
function main() {
get_net_plugin &
pid_get_net_plugin=$!
for i in $(seq 1 10); do get_yq && break; sleep 30; done;
for i in $(seq 1 10); do get_docker && break; sleep 30; done;
for i in $(seq 1 10); do get_kubeadm && break; sleep 30; done;
export first_master=${MASTERS[0]}
export first_master_ip=${MASTERS_IPS[0]}
bootstrap_first_master "${first_master}" "${first_master_ip}"
wait_for_etcd "${first_master}"
make_secrets
wait $pid_get_net_plugin
apply_net_plugin
# this is how we enbale the external CSI provider needed in kubenetes 1.16
# and later. Current, koris versions will provision volumes with the built
# in cloud-provider, all other cloud operations go through the external
# cloud provider
#kubectl apply -f https://raw.githubusercontent.com/kubernetes/cloud-provider-openstack/master/manifests/cinder-csi-plugin/cinder-csi-controllerplugin-rbac.yaml
#kubectl apply -f https://raw.githubusercontent.com/kubernetes/cloud-provider-openstack/master/manifests/cinder-csi-plugin/cinder-csi-controllerplugin.yaml
#kubectl apply -f https://raw.githubusercontent.com/kubernetes/cloud-provider-openstack/master/manifests/cinder-csi-plugin/cinder-csi-nodeplugin-rbac.yaml
#kubectl apply -f https://raw.githubusercontent.com/kubernetes/cloud-provider-openstack/master/manifests/cinder-csi-plugin/cinder-csi-nodeplugin.yaml
#kubectl apply -f https://raw.githubusercontent.com/kubernetes/cloud-provider-openstack/master/manifests/cinder-csi-plugin/csi-cinder-driver.yaml
# TODO: fix:
# [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver.
# The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
for (( i=1; i<${#MASTERS[@]}; i++ )); do
echo "bootstrapping master ${MASTERS[$i]}";
HOST_NAME=${MASTERS[$i]}
HOST_IP=${MASTERS_IPS[$i]}
CURRENT_CLUSTER="${CURRENT_CLUSTER},$HOST_NAME=https://${HOST_IP}:2380"
copy_keys "${HOST_IP}"
until add_master $HOST_NAME $HOST_IP $CURRENT_CLUSTER $first_master $first_master_ip; do
ssh ${SSHOPTS} $HOST_NAME sudo kubeadm reset -f
copy_keys $HOST_IP
done
wait_for_etcd $HOST_NAME
echo "done bootstrapping master ${MASTERS[$i]}";
done
if [[ -n ${K8SNODES} && "$(declare -p K8SNODES)" =~ "declare -a" ]]; then
echo "Joining worker nodes ..."
join_all_hosts
fi
echo "the installation has finished."
}
# when building bare metal cluster or vSphere clusters this is used to
# install dependencies on each host and join the host to the cluster
function join_all_hosts() {
export DISCOVERY_HASH=$(openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | \
openssl rsa -pubin -outform der 2>/dev/null | \
openssl dgst -sha256 -hex | sed 's/^.* //')
if [ -z ${BOOTSTRAP_TOKEN} ]; then
export BOOTSTRAP_TOKEN=$(kubeadm token list | grep -v TOK| cut -d" " -f 1 | grep '^\S')
fi
for K in "${K8SNODES[@]}"; do
echo "***** ${K} ******"
if [ ${BOOTSTRAP_NODES} -eq 1 ]; then
bootstrap_deps_node ${K}
fi
ssh ${K} sudo kubeadm reset -f
ssh ${K} sudo kubeadm join --token $BOOTSTRAP_TOKEN ${LOAD_BALANCER_DNS:-${LOAD_BALANCER_IP}}:$LOAD_BALANCER_PORT --discovery-token-ca-cert-hash sha256:${DISCOVERY_HASH}
done
}
# keep this function here, although we don't use it really, it's usefull for
# building bare metal cluster or vSphere clusters
function fetch_all() {
for i in $(seq 1 10); do get_docker && break; sleep 30; done;
for i in $(seq 1 10); do get_kubeadm && break; sleep 30; done;
}
# The script is called as user 'root' in the directory '/'. Since we add some
# files we want to change to root's home directory.
# This line and the if condition bellow allow sourcing the script without executing
# the main function
(return 0 2>/dev/null) && sourced=1 || sourced=0
if [[ $sourced == 1 ]]; then
set +e
echo "You can now use any of these functions:"
echo ""
typeset -F | cut -d" " -f 3
else
set -eu
cd /root
iptables -P FORWARD ACCEPT
swapoff -a
main "$@"
fi
# vi: sts=4 ts=4 sw=4 ai
#apiVersion: kubeadm.k8s.io/v1beta1
#discovery:
# bootstrapToken:
# apiServerEndpoint: "10.32.192.46:6443"
# token: mjmsw8.srj4flh6j5xkyzxz
# caCertHashes:
# - "sha256:6c932a865dd420ea08fed258e5f5b918f55ee1c7ca2aa287c9f7cda84071bf97"
# unsafeSkipCAVerification: false
# timeout: 5m0s
#kind: JoinConfiguration
#nodeRegistration:
# criSocket: /var/run/dockershim.sock
#controlPlane:
# LocalAPIEndpoint:
# advertiseAddress: 10.32.192.54
## bindPort: 6443
#
bootstrap-k8s-nth-master-ubuntu-16.04.sh¶
This script is executed on the nth master upon initial bootstrap.
#!/bin/bash
###
# install nth master required packages if not alredy installed
###
set -e
iptables -P FORWARD ACCEPT
swapoff -a
# load koris environment file if available
if [ -f /etc/kubernetes/koris.env ]; then
source /etc/kubernetes/koris.env
fi
#### Versions for Kube 1.14.1
export KUBE_VERSION=${KUBE_VERSION:-1.14.1}
export AUTO_JOIN=${AUTO_JOIN:-0}
export DOCKER_VERSION=18.06
export CALICO_VERSION=3.3
export KUBECONFIG=/etc/kubernetes/admin.conf
TRANSPORT_PACKAGES="apt-transport-https ca-certificates software-properties-common"
LOGLEVEL=4
V=${LOGLEVEL}
LOGFILE=/dev/stderr
function log() {
datestring=`date +"%Y-%m-%d %H:%M:%S"`
echo -e "$datestring - $@" | tee $LOGFILE
}
# minimal configuration so that the correct images are pulled
function create_kubeadm_config() {
HOST_NAME=$1
cat <<TMPL > kubeadm-"${HOST_NAME}".yaml
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: v${KUBE_VERSION}
TMPL
}
# check if a binary version is found
# version_check kube-scheduler --version v1.10.4 return 1 if binary is found
# in that version
function version_found() { return $("$1" "$2" | grep -qi "$3"); }
# enforce docker version
function get_docker() {
log "started ${FUNCNAME[0]}"
dpkg -l software-properties-common | grep ^ii || apt-get install ${TRANSPORT_PACKAGES} -y
curl --retry 10 -fssl https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
apt-get update
apt-get -y install docker-ce="${DOCKER_VERSION}*"
apt-get install -y socat conntrack ipset
log "Finished ${FUNCNAME[0]}"
}
# enforce kubeadm version
function get_kubeadm {
log "started ${FUNCNAME[0]}"
dpkg -l software-properties-common | grep ^ii || apt-get install ${TRANSPORT_PACKAGES} -y
curl --retry 10 -fssL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
apt-add-repository -u "deb http://apt.kubernetes.io kubernetes-xenial main"
apt-get install -y --allow-downgrades kubeadm=${KUBE_VERSION}-00 kubelet=${KUBE_VERSION}-00
log "Finished ${FUNCNAME[0]}"
}
function fetch_all() {
apt-get update
if [ -z "$(type -P docker)" ]; then
get_docker
for i in $(seq 1 10); do get_docker && break; sleep 30; done;
fi
for i in $(seq 1 10); do get_kubeadm && break; sleep 30; done;
}
# run commands needed for network plugins
function config_pod_network(){
case "${POD_NETWORK}" in
"CALICO")
;;
"FLANNEL")
sysctl net.bridge.bridge-nf-call-iptables=1
;;
esac
}
function fetch_secrets(){
mkdir -pv /etc/kubernetes/pki/etcd
kubectl get secrets -n kube-system cluster-ca -o json | jq -r '.data["tls.crt"]' | base64 -d > /etc/kubernetes/pki/ca.crt
kubectl get secrets -n kube-system cluster-ca -o json | jq -r '.data["tls.key"]' | base64 -d > /etc/kubernetes/pki/ca.key
kubectl get secrets -n kube-system front-proxy -o json | jq -r '.data["tls.crt"]' | base64 -d > /etc/kubernetes/pki/front-proxy-ca.crt
kubectl get secrets -n kube-system front-proxy -o json | jq -r '.data["tls.key"]' | base64 -d > /etc/kubernetes/pki/front-proxy-ca.key
kubectl get secrets -n kube-system etcd-ca -o json | jq -r '.data["tls.crt"]' | base64 -d > /etc/kubernetes/pki/etcd/ca.crt
kubectl get secrets -n kube-system etcd-ca -o json | jq -r '.data["tls.key"]' | base64 -d > /etc/kubernetes/pki/etcd/ca.key
kubectl get secrets -n kube-system sa-key -o "jsonpath={.data['sa\.key']}" | base64 -d > /etc/kubernetes/pki/sa.key
kubectl get secrets -n kube-system sa-pub -o "jsonpath={.data['sa\.pub']}" | base64 -d > /etc/kubernetes/pki/sa.pub
kubectl get cm -n kube-system audit-policy -o="jsonpath={.data['audit-policy\.yml']}" > /etc/kubernetes/audit-policy.yml
kubectl get secret -n kube-system cloud-config -o="jsonpath={.data['cloud-config']}" | base64 -d > /etc/kubernetes/cloud-config
# this should be reviewed
set +e
kubectl get secret oidc-ca -n kube-system && { kubectl get secret oidc-ca -n kube-system -o="jsonpath={.data['oidc\.ca']}" > /etc/kubernetes/pki/oidc.ca; }
kubectl get cm -n kube-system dex.tmpl && { kubectl get cm dex.tmpl -n kube-system -o="jsonpath={.data['dex\.tmpl']}" > /etc/kubernetes/dex.tmpl; }
set -e
}
function write_join_config() {
log "Started ${FUNCNAME[0]}"
DISCOVERY_HASH=$(openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | \
openssl rsa -pubin -outform der 2>/dev/null | \
openssl dgst -sha256 -hex | sed 's/^.* //')
cat <<EOF > /etc/kubernetes/join.yml
apiVersion: kubeadm.k8s.io/v1beta1
discovery:
bootstrapToken:
apiServerEndpoint: "${LOAD_BALANCER_DNS:-${LOAD_BALANCER_IP}}:${LOAD_BALANCER_PORT}"
token: ${BOOTSTRAP_TOKEN}
caCertHashes:
- "sha256:${DISCOVERY_HASH}"
unsafeSkipCAVerification: false
timeout: 5m0s
kind: JoinConfiguration
nodeRegistration:
criSocket: /var/run/dockershim.sock
controlPlane:
LocalAPIEndpoint:
advertiseAddress: $(hostname --ip-address)
bindPort: ${LOAD_BALANCER_PORT}
EOF
log "Finished ${FUNCNAME[0]}"
}
function get_jq() {
if [ -z "$(type -P jq)" ]; then
apt update
apt install -y jq
fi
}
# the entry point of the whole script.
# this function bootstraps the who etcd cluster and control plane components
# accross N hosts
function main() {
get_jq
kubeadm version | grep -qi "${KUBE_VERSION}" || fetch_all
create_kubeadm_config $(hostname -s)
kubeadm config images pull --config kubeadm-"$(hostname -s)".yaml
config_pod_network
if [ ${AUTO_JOIN} -eq 1 ]; then
fetch_secrets
write_join_config
kubeadm join --config /etc/kubernetes/join.yml
fi
echo "Success! ${HOSTNAME} should now be part of the cluster."
}
# The script is called as user 'root' in the directory '/'. Since we add some
# files we want to change to root's home directory.
cd /root
main
bootstrap-k8s-node-ubuntu-16.04.sh¶
#!/bin/bash
set -e
# --------------------------------------------------------------------------------------------------------------
# We are explicitly not using a templating language to inject the values as to encourage the user to limit their
# set of templating logic in these files. By design all injected values should be able to be set at runtime,
# and the shell script real work. If you need conditional logic, write it in bash or make another shell script.
# --------------------------------------------------------------------------------------------------------------
# ONLY CHANGE VERSIONS HERE IF YOU KNOW WHAT YOU ARE DOING!
# MAKE SURE THIS MATCHED THE MASTER K8S VERSION
# load koris environment file if available
if [ -f /etc/kubernetes/koris.env ]; then
# shellcheck disable=SC1091
source /etc/kubernetes/koris.env
fi
KUBE_VERSION_COMPARE="$(echo "${KUBE_VERSION}" | cut -d '.' -f 2 )"
export KUBE_VERSION=${KUBE_VERSION:-1.14.1}
export DOCKER_VERSION=18.06
iptables -P FORWARD ACCEPT
swapoff -a
# bootstrap the node
cat << EOF > /etc/kubernetes/cluster-info.yaml
---
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: ${B64_CA_CONTENT}
server: https://${LOAD_BALANCER_DNS:-${LOAD_BALANCER_IP}}:${LOAD_BALANCER_PORT}
name: ""
contexts: []
current-context: ""
kind: Config
preferences: {}
users: []
EOF
cat << EOF > /etc/kubernetes/kubeadm-node-"${KUBE_VERSION}".yaml
---
apiVersion: kubeadm.k8s.io/v1beta1
discovery:
bootstrapToken:
apiServerEndpoint: "${LOAD_BALANCER_DNS:-${LOAD_BALANCER_IP}}:${LOAD_BALANCER_PORT}"
token: ${BOOTSTRAP_TOKEN}
caCertHashes:
- "sha256:${DISCOVERY_HASH}"
unsafeSkipCAVerification: false
timeout: 15m0s
kind: JoinConfiguration
nodeRegistration:
criSocket: /var/run/dockershim.sock
EOF
function fetch_all() {
apt-get update
apt-get install -y software-properties-common apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
apt-add-repository -u "deb http://apt.kubernetes.io kubernetes-xenial main"
apt-get install -y --allow-downgrades kubeadm="${KUBE_VERSION}"-00 kubelet="${KUBE_VERSION}"-00
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
apt-get update
apt -y --allow-downgrades install docker-ce=${DOCKER_VERSION}*
apt-get install -y socat conntrack ipset
}
# check if a binary version is found
# version_check kube-scheduler --version v1.10.4 return 1 if binary is found
# in that version
function version_found() { return $("$1" "$2" | grep -qi "$3"); }
# run commands needed for network plugins
function config_pod_network(){
case "${POD_NETWORK}" in
"CALICO")
;;
"FLANNEL")
sysctl net.bridge.bridge-nf-call-iptables=1
;;
esac
}
function join() {
kubeadm -v=10 join --config /etc/kubernetes/kubeadm-node-"${KUBE_VERSION}".yaml "${LOAD_BALANCER_DNS:-${LOAD_BALANCER_IP}}:${LOAD_BALANCER_PORT}"
}
function main() {
version_found docker --version "${DOCKER_VERSION}" || for i in $(seq 1 10); do (fetch_all && break; sleep 30); done
version_found kubeadm version "${KUBE_VERSION}" || for i in $(seq 1 10); do (fetch_all && break; sleep 30); done
config_pod_network
# join !
until join; do sudo kubeadm reset --force
done
}
# This line and the if condition bellow allow sourcing the script without executing
# the main function
(return 0 2>/dev/null) && sourced=1 || sourced=0
if [[ $sourced == 1 ]]; then
set +e
echo "You can now use any of these functions:"
echo ""
typeset -F | cut -d" " -f 3
else
set -eu
cd /root
iptables -P FORWARD ACCEPT
swapoff -a
main "$@"
fi
# vi: ts=4 sw=4 ai