#!/bin/bash # Info: Script to install/create/delete/update Kubernetes from file settings # Author: JesusPerezLorenzo # Release: 1.0 # Date: 30-10-2023 USAGE="install-kubernetes.sh full-path-settings-file [ -m controlplane (hostname -cp-) | worker] [*install | update | makejoin | remove | fullremove]" [ "$1" == "-h" ] && echo "$USAGE" && exit 1 _save_target() { [ -z "$TARGET_SAVE_PATH" ] && return local file_path=$1 mkdir -p "$TARGET_SAVE_PATH" if cp "$file_path" "$TARGET_SAVE_PATH" ; then echo "$file_path saved in $TARGET_SAVE_PATH" fi } # shellcheck disable=SC1090 [[ "$1" == *setting* ]] && [ -r "$1" ] && . "$1" && shift # shellcheck disable=SC1090 [[ "$1" == env-* ]] && [ -r "$1" ] && . "$1" && shift [ -r "env-kubernetes" ] && . env-kubernetes [ -z "$CLUSTER_NAME" ] && echo "No CLUSTER_NAME value " && exit 1 [ -z "$VERSION" ] && echo "No VERSION value " && exit 1 INSTALL_LOG=${INSTALL_LOG:-/tmp/k8s.log} WORK_PATH=${WORK_PATH:-/tmp} [ ! -d "$WORK_PATH" ] && sudo mkdir -p "$WORK_PATH" export LC_CTYPE=C.UTF-8 export LANG=C.UTF-8 cmd_out=/dev/null echo "Log path to $INSTALL_LOG" [ ! -d "$(dirname "$INSTALL_LOG")" ] && mkdir -p "$(dirname "$INSTALL_LOG")" echo "Work path to $WORK_PATH" if [ -z "$K8S_MODE" ] ; then if [[ "$HOSTNAME" == *-cp-* ]] ; then K8S_MODE="controlplane" else K8S_MODE="worker" fi fi [ "$1" == "-m" ] && K8S_MODE=$2 && shift 2 [ -n "$1" ] && CMD_TSK=$1 && shift _check_resolution() { local hostname="" hostname=$HOSTNAME local clustername="" local ip="" [ "$K8S_MODE" == "controlplane" ] && clustername="$CLUSTER_NAME" #sudo sed -i /^127.0.1.1/d /etc/hosts 2>>$cmd_out ip=$(grep "$hostname" /etc/hosts | grep -v "^#" | awk '{print $1}') [ -n "$ip" ] && [ "$ip" == "127.0.1.1" ] && sudo sed -i /^"$ip"/d /etc/hosts 2>>$cmd_out ip=$(grep "$MAIN_IP" /etc/hosts | grep -v "^#" | awk '{print $1}') [ -z "$ip" ] && echo "$MAIN_IP $hostname $clustername" | sudo tee -a /etc/hosts 2>>$cmd_out if [ "$hostname" != "$(cat /etc/hostname)" ] ; then echo "$hostname" | sudo tee /etc/hostname 2>>$cmd_out sudo hostname "$hostname" fi } _off_swap() { local fs_swap local fs_tab fs_tab=/etc/fstab fs_swap=$(grep -v "^#" $fs_tab | grep swap) if [ -n "$fs_swap" ] ; then sudo sed -i "s;$fs_swap;#$fs_swap;g" $fs_tab fi sudo swapoff -a } _kubernetes_init() { [ -z "$VERSION" ] && exit 1 _check_resolution curr_vers=$(kubectl version 2>/dev/null | grep Client | awk '{print $3}' | sed 's/^v//g' 2>/dev/null) chmod 1777 /tmp if [ "v$curr_vers" != "$K8S_VERSION" ]; then echo "Install packages" #if [ "$CMD_TSK" != "update" ] && [ ! -r "/etc/apt/keyrings/kubernetes-apt-keyring.gpg" ]; then sudo DEBIAN_FRONTEND=noninteractive apt-get update && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y apt-transport-https gnupg2 curl sudo rm -f /etc/apt/keyrings/kubernetes-apt-keyring.gpg curl -fsSL https://pkgs.k8s.io/core:/stable:/v"$MAJOR_VERSION"/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v$MAJOR_VERSION/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list #fi _off_swap sudo DEBIAN_FRONTEND=noninteractive apt-get update -q sudo DEBIAN_FRONTEND=noninteractive apt-mark unhold kubelet kubectl kubeadm if ! sudo DEBIAN_FRONTEND=noninteractive apt-get install -y kubectl kubelet kubeadm ; then echo "error installing kubernetes" return 1 fi # Hold your horse ! sudo DEBIAN_FRONTEND=noninteractive apt-mark hold kubelet kubectl kubeadm echo "init done" fi } _kubernetes_taint() { case "$TAINT_NODE" in no_schedule) kubectl taint nodes "$HOSTNAME" node-role.kubernetes.io/master:NoSchedule ;; schedule) kubectl taint nodes "$HOSTNAME" node-role.kubernetes.io/master:NoSchedule kubectl taint nodes "$HOSTNAME" node-role.kubernetes.io/master:NoSchedule- 2>>$cmd_out ;; esac return 0 } _kubernetes_cri() { [ ! -d "/etc/${K8S_CRI}" ] && echo "No /etc/${K8S_CRI} path found! " && exit 1 # if [ -r "cri/$K8S_CRI/install.sh" ] ; then # #PKG_ORG=cri/"$K8S_CRI" # echo "cri $K8S_CRI" # # shellcheck disable=SC1090 # . "cri/$K8S_CRI/install.sh" | sudo tee -a "$INSTALL_LOG" >>$cmd_out # else # echo "$K8S_CRI not defined" && exit 1 # fi return 0 } _kubernetes_cni() { if [ -r "cni/$K8S_CNI/install.sh" ] ; then echo "cni $K8S_CNI" # shellcheck disable=SC1090 . "cni/$K8S_CNI/install.sh" | sudo tee -a "$INSTALL_LOG" 2>>$cmd_out else echo "mode $K8S_CNI not defined" && exit 1 fi } _kubernetes_addons() { local yaml_file for item in ${K8S_ADDONS//,/ } #ls addons 2>/dev/null) do if [ -r "addons/$item/install.sh" ] ; then echo "Install addon $item "| sudo tee -a "$INSTALL_LOG" # shellcheck disable=SC1090 . "addons/$item/install.sh" if [ "$item" == "istio" ] && [ -n "$K8S_EXTERNAL_IPS" ]; then yaml_file=/tmp/externalIPs.yaml echo "spec:" > $yaml_file echo " externalIPs: " >> $yaml_file for ip in ${K8S_EXTERNAL_IPS//,/ } do echo " - $ip" >> "$yaml_file" done # Patch istio ingressgateway to use ExternalIPs kubectl patch service -n istio-system istio-ingressgateway --type merge --patch-file $yaml_file fi fi done } _kubernetes_kube() { local user=${1:-root} local home_user=${2:-/home/root} local uid local gid local has_aliases uid=$(sudo id -u "$user" 2>/dev/null) gid=$(sudo id -g "$user" 2>/dev/null) if [ -f "/etc/kubernetes/admin.conf" ] ; then sudo mkdir -p /root/.kube sudo cp /etc/kubernetes/admin.conf /root/.kube/config sudo chown root:root /root/.kube/config if [ "$uid" == "0" ] ; then mkdir -p "$home_user"/.kube sudo cp /etc/kubernetes/admin.conf "$home_user"/.kube/config sudo chown -R "$uid:$gid" "$home_user"/.kube fi has_aliases=$(grep bash_aliases "$HOME"/.bashrc) [ -z "$has_aliases" ] && echo "[ -f ~/.bash_aliases ] && . ~/.bash_aliases" | sudo tee -a "$HOME"/.bashrc if [ -r "$USER_HOME" ] && [ -n "$USER" ] ; then mkdir -p "$USER_HOME"/.kube sudo cp /etc/kubernetes/admin.conf "$USER_HOME"/.kube/config sudo chown -R "$USER" "$USER_HOME"/.kube if [ -r "$USER_HOME/.bash_aliases" ] && [ ! -r "$HOME/.bash_aliases" ] ; then has_aliases=$(grep bash_aliases "$USER_HOME"/.bashrc) [ -z "$has_aliases" ] && echo "[ -f ~/.bash_aliases ] && . ~/.bash_aliases" | sudo tee -a "$USER_HOME"/.bashrc sudo cp "$USER_HOME"/.bash_aliases "$HOME" sudo chown -R "$uid:$gid" "$HOME"/.bash_aliases fi fi fi } _kubectl_appy() { export KUBECONFIG=/etc/kubernetes/admin.conf [ ! -r "$KUBECONFIG" ] && echo "$KUBECONFIG not found " && return 1 [ ! -r "$1" ] && echo "File $1 not found" && return 1 if ! kubectl apply -f "$1" ; then echo "Error kubectl apply $1 " fi } _kubernetes_install_master_0() { _check_resolution local has_apiserver="" has_apiserver=$(sudo ps -aux | awk '{print $11}'| grep "kube-apiserver") if [ ! -r "resources/$K8S_CONFIG" ] ; then echo "resources/$K8S_CONFIG not found" exit 1 fi if [ "$ETCD_MODE" == "external" ] && [ -d "etcd_certs" ] ; then [ ! -d "/etc/kubernetes/pki/etcd" ] && sudo mkdir -p /etc/kubernetes/pki/etcd sudo cp -pr etcd_certs/* /etc/kubernetes/pki/etcd if [ -n "$HOSTNAME" ] && [ "$HOSTNAME" != "$INSTALL_MASTER" ] && [ -d "pki" ] ; then sudo cp -pr pki/* /etc/kubernetes/pki fi fi echo "Install kubernetes master" [ ! -r "resources/$K8S_CONFIG" ] && echo "Error resources/$K8S_CONFIG not found !" && exit 1 [ "resources/$K8S_CONFIG" != "$WORK_PATH/kubeadm-config.yaml" ] && cp "resources/$K8S_CONFIG" "$WORK_PATH"/kubeadm-config.yaml if [ -z "$has_apiserver" ] ; then sudo systemctl start kubelet 2>>$cmd_out echo "You can follow kubeadm installation by using in another terminal: tail -f $INSTALL_LOG" sudo kubeadm init --config "$WORK_PATH"/kubeadm-config.yaml --ignore-preflight-errors=all | sudo tee "$INSTALL_LOG" _save_target "$WORK_PATH"/kubeadm-config.yaml fi local has_success="" has_success=$(sudo grep "initialized successfully" "$INSTALL_LOG") if [ -n "$has_success" ]; then echo "$has_success" _save_target "$INSTALL_LOG" sudo grep -A1 "^kubeadm join" "$INSTALL_LOG" | sudo tee "$WORK_PATH"/k8s_join.sh sudo chmod +x "$WORK_PATH/k8s_join.sh" [ "$WORK_PATH" != "/tmp" ] && cp "$WORK_PATH/k8s_join.sh" /tmp _kubernetes_kube "$(whoami)" _kubernetes_cni _kubernetes_addons sudo mv "$INSTALL_LOG" "$WORK_PATH" [ -r "runtimes.yaml" ] && _kubectl_appy runtimes.yaml fi } _make_join_kubernetes() { if ! kubeadm token create --print-join-command > "$WORK_PATH"/k8s_join.sh ; then echo "Error to get token for join node " exit 1 fi } _join_kubernetes() { local join_path [ -r "k8s_join.sh" ] && join_path="k8s_join.sh" [ -r "/tmp/k8s_join.sh" ] && join_path="/tmp/k8s_join.sh" if [ -r "$join_path" ] ; then local cmd_join if [ "$1" == "controlplane" ] ; then cmd_join=$(sed 's/join /join --control-plane /g' < $join_path) else cmd_join=$(cat $join_path | sed 's/\\//g') fi [ -z "$cmd_join" ] && echo "Error cmd_join content" && exit 1 # shellcheck disable=SC2086 if ! sudo $cmd_join --ignore-preflight-errors=all | sudo tee "$INSTALL_LOG" >"$cmd_out"; then echo "Error $HOSTNAME join command -> $cmd_join " exit 1 fi else echo "No k8s_join.sh found" return 0 fi return 0 } _install_kubernetes_controlplane() { if [ "$ETCD_MODE" == "external" ] && [ -d "etcd_certs" ] ; then [ ! -d "/etc/kubernetes/pki/etcd" ] && sudo mkdir -p /etc/kubernetes/pki/etcd sudo cp -pr etcd_certs/* /etc/kubernetes/pki/etcd if [ -n "$HOSTNAME" ] && [ "$HOSTNAME" != "$INSTALL_MASTER" ] && [ -d "pki" ] ; then sudo cp -pr pki/* /etc/kubernetes/pki fi fi if ! _join_kubernetes controlplane ; then exit 2 else _kubernetes_kube "$USER" "$USER_HOME" _kubernetes_cni _kubernetes_addons fi return 0 } _install_kubernetes_worker() { if ! _join_kubernetes worker ; then exit 2 fi return 0 } _install_kubernetes() { [ ! -d "/etc/${K8S_CRI}" ] && echo "No /etc/${K8S_CRI} path found! " && exit 1 sudo systemctl start "${K8S_CRI}" _check_resolution if [ -f "/etc/kubernetes/admin.conf" ] ; then local server="" local has_apiserver="" has_apiserver=$(sudo ps -aux | awk '{print $11}'| grep "kube-apiserver") server=$(sudo grep "server: " /etc/kubernetes/admin.conf | awk '{print $2}') echo "$(date +%Y_%m_%d_%H%M%S) | Kubernetes already installed in $HOSTNAME with server: $server ($has_apiserver)" | sudo tee -a "$INSTALL_LOG" if [ "$CMD_TSK" == "reinstall" ] ; then echo "$(date +%Y_%m_%d_%H%M%S) | Kubernetes RESET installation in $HOSTNAME with server: $server ($has_apiserver) ..." | sudo tee -a "$INSTALL_LOG" if sudo kubeadm reset -f ; then echo "$(date +%Y_%m_%d_%H%M%S) | Kubernetes ready to be re-installed in $HOSTNAME " | sudo tee -a "$INSTALL_LOG" fi else _kubernetes_kube "$USER" "$USER_HOME" return fi elif [ -f "/etc/kubernetes/kubelet.conf" ] ; then echo "$(date +%Y_%m_%d_%H%M%S) | Kubernetes kubelet already running in $HOSTNAME" if [ "$CMD_TSK" == "reinstall" ] ; then echo "$(date +%Y_%m_%d_%H%M%S) | Kubernetes kubelet RESET in $HOSTNAME ..." if sudo kubeadm reset -f ; then echo "$(date +%Y_%m_%d_%H%M%S) | Kubernetes ready to be re-installed in $HOSTNAME " | sudo tee -a "$INSTALL_LOG" fi else return fi fi has_kubelet=$(sudo ps -aux | awk '{print $11}'| grep "kubelet") if [ -n "$has_kubelet" ] ; then if [ "$CMD_TSK" == "reinstall" ] ; then if sudo kubeadm reset -f ; then echo "$(date +%Y_%m_%d_%H%M%S) | Kubernetes ready to be re-installed in $HOSTNAME " | sudo tee -a "$INSTALL_LOG" fi else echo "$(date +%Y_%m_%d_%H%M%S) | Kubernetes kubelet already runnint in $HOSTNAME" return fi fi if [ -n "$HOSTNAME" ] && [ "$HOSTNAME" == "$K8S_MASTER" ] ; then #IS_MASTER_0="yes" _kubernetes_install_master_0 _kubernetes_taint else case "$K8S_MODE" in controlplane) _install_kubernetes_controlplane _kubernetes_taint ;; worker) _install_kubernetes_worker ;; *) echo "mode $K8S_MODE not defined" && exit 1 esac fi } _config_kubernetes() { [ ! -d "/etc/${K8S_CRI}" ] && echo "No /etc/${K8S_CRI} path found! " && exit 1 sudo systemctl start "${K8S_CRI}" sudo sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf has_nolocal_bind=$(sudo grep "net.ipv4.ip_nonlocal_bind = 1" /etc/sysctl.conf) if [ -z "$has_nolocal_bind" ] ; then echo "net.ipv4.ip_nonlocal_bind = 1" | sudo tee -a /etc/sysctl.conf >>$cmd_out #echo "net.bridge.bridge-nf-call-iptables=1" | sudo tee -a /etc/sysctl.conf sudo modprobe br_netfilter echo 1 | sudo tee -a /proc/sys/net/bridge/bridge-nf-call-iptables >>$cmd_out fi sudo sysctl -p >>$cmd_out return 0 } _remove_kubernetes() { sudo systemctl stop kubelet sudo systemctl disable kubelet } _full_remove_kubernetes() { _remove_kubernetes sudo kubeadm reset -y sudo rm -r /etc/kubernetes /etc/cni } _start_kubernetes() { if [ "$SYSTEMCTL_MODE" == "enabled" ] ; then sudo systemctl enable kubelet else sudo systemctl disable kubelet fi sudo systemctl start kubelet } _restart_kubernetes() { sudo systemctl restart kubelet } case "$CMD_TSK" in remove) _remove_kubernetes exit 0 ;; fullremove|full-remove) _full_remove_kubernetes exit 0 ;; update) _restart_kubernetes ;; makejoin) _make_join_kubernetes exit 0 ;; reinstall) ;; esac if ! _kubernetes_cri ; then echo "error CRI install" exit 1 fi if ! _kubernetes_init ; then echo "error kubernetes install" exit 1 fi if ! _config_kubernetes ; then echo "error kubernetes config" exit 1 fi if ! _install_kubernetes ; then echo "error kubernetes install" exit 1 fi if ! _start_kubernetes ; then echo "error kubernetes start" exit 1 fi echo "Work path: $WORK_PATH" echo "Log info: $INSTALL_LOG"