Update master_node_install.sh
This commit is contained in:
parent
009eb7f655
commit
cbfbe50d22
|
|
@ -1,36 +1,97 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -Eeuo pipefail
|
||||||
|
|
||||||
# Arch Kubernetes control-plane install with containerd + kubeadm + Calico
|
########################################
|
||||||
|
# Arch Linux Kubernetes Control Plane
|
||||||
|
# Fully automated master node installer
|
||||||
|
########################################
|
||||||
|
|
||||||
if [[ $EUID -ne 0 ]]; then
|
# ---------- Config ----------
|
||||||
echo "Please run this script with sudo or as root."
|
POD_CIDR="${POD_CIDR:-192.168.0.0/16}"
|
||||||
|
CALICO_VERSION="${CALICO_VERSION:-v3.31.4}"
|
||||||
|
KUBECONFIG_DIR_ROOT="/root/.kube"
|
||||||
|
JOIN_COMMAND_FILE="/root/kubeadm-join-command.sh"
|
||||||
|
|
||||||
|
# Detect the real invoking user when run with sudo
|
||||||
|
REAL_USER="${SUDO_USER:-root}"
|
||||||
|
REAL_HOME="$(getent passwd "$REAL_USER" | cut -d: -f6 || true)"
|
||||||
|
REAL_HOME="${REAL_HOME:-/root}"
|
||||||
|
REAL_KUBECONFIG_DIR="${REAL_HOME}/.kube"
|
||||||
|
|
||||||
|
# ---------- Logging ----------
|
||||||
|
log() {
|
||||||
|
echo
|
||||||
|
echo "============================================================"
|
||||||
|
echo "[INFO] $*"
|
||||||
|
echo "============================================================"
|
||||||
|
}
|
||||||
|
|
||||||
|
warn() {
|
||||||
|
echo
|
||||||
|
echo "[WARN] $*" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
die() {
|
||||||
|
echo
|
||||||
|
echo "[ERROR] $*" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------- Root check ----------
|
||||||
|
if [[ "${EUID}" -ne 0 ]]; then
|
||||||
|
die "Run this script as root, for example: sudo ./master_node_install.sh"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
read -r -p "Be sure swap is disabled. Press Enter to continue..."
|
# ---------- Cleanup on error ----------
|
||||||
|
on_error() {
|
||||||
|
local exit_code=$?
|
||||||
|
warn "Script failed on line $1 with exit code ${exit_code}"
|
||||||
|
warn "Useful diagnostics:"
|
||||||
|
echo " journalctl -u containerd -u kubelet -b --no-pager | tail -n 200"
|
||||||
|
echo " systemctl status containerd kubelet --no-pager"
|
||||||
|
exit "${exit_code}"
|
||||||
|
}
|
||||||
|
trap 'on_error $LINENO' ERR
|
||||||
|
|
||||||
# Use the original invoking user when script is run via sudo
|
# ---------- Step 1: Disable swap ----------
|
||||||
REAL_USER="${SUDO_USER:-root}"
|
log "Disabling swap immediately"
|
||||||
REAL_HOME="$(getent passwd "$REAL_USER" | cut -d: -f6)"
|
swapoff -a || true
|
||||||
|
|
||||||
# ---- Package install ----
|
log "Disabling swap persistently in /etc/fstab"
|
||||||
|
if [[ -f /etc/fstab ]]; then
|
||||||
|
cp /etc/fstab /etc/fstab.bak.$(date +%Y%m%d%H%M%S)
|
||||||
|
sed -ri '/\sswap\s/s/^/# DISABLED FOR KUBERNETES: /' /etc/fstab
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------- Step 2: Update system ----------
|
||||||
|
log "Updating package databases and system packages"
|
||||||
pacman -Syu --noconfirm
|
pacman -Syu --noconfirm
|
||||||
yes | pacman -S --needed \
|
|
||||||
|
# ---------- Step 3: Resolve iptables conflict automatically ----------
|
||||||
|
log "Resolving iptables backend for Kubernetes"
|
||||||
|
if pacman -Q iptables >/dev/null 2>&1; then
|
||||||
|
log "Removing legacy iptables package so iptables-nft can be installed"
|
||||||
|
pacman -Rdd --noconfirm iptables || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------- Step 4: Install required packages ----------
|
||||||
|
log "Installing Kubernetes and runtime packages"
|
||||||
|
pacman -S --needed --noconfirm \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
curl \
|
curl \
|
||||||
containerd \
|
containerd \
|
||||||
cni-plugins \
|
cni-plugins \
|
||||||
crictl \
|
crictl \
|
||||||
|
ethtool \
|
||||||
iptables-nft \
|
iptables-nft \
|
||||||
|
conntrack-tools \
|
||||||
|
socat \
|
||||||
kubeadm \
|
kubeadm \
|
||||||
kubectl \
|
kubectl \
|
||||||
kubelet \
|
kubelet
|
||||||
socat \
|
|
||||||
conntrack-tools \
|
|
||||||
ethtool
|
|
||||||
|
|
||||||
# ---- Kernel modules needed for Kubernetes networking ----
|
# ---------- Step 5: Kernel modules ----------
|
||||||
|
log "Configuring required kernel modules"
|
||||||
cat >/etc/modules-load.d/k8s.conf <<'EOF'
|
cat >/etc/modules-load.d/k8s.conf <<'EOF'
|
||||||
overlay
|
overlay
|
||||||
br_netfilter
|
br_netfilter
|
||||||
|
|
@ -39,7 +100,8 @@ EOF
|
||||||
modprobe overlay
|
modprobe overlay
|
||||||
modprobe br_netfilter
|
modprobe br_netfilter
|
||||||
|
|
||||||
# ---- Sysctl settings for Kubernetes networking ----
|
# ---------- Step 6: Sysctl ----------
|
||||||
|
log "Configuring Kubernetes sysctl settings"
|
||||||
cat >/etc/sysctl.d/99-kubernetes-cri.conf <<'EOF'
|
cat >/etc/sysctl.d/99-kubernetes-cri.conf <<'EOF'
|
||||||
net.bridge.bridge-nf-call-iptables = 1
|
net.bridge.bridge-nf-call-iptables = 1
|
||||||
net.bridge.bridge-nf-call-ip6tables = 1
|
net.bridge.bridge-nf-call-ip6tables = 1
|
||||||
|
|
@ -48,58 +110,101 @@ EOF
|
||||||
|
|
||||||
sysctl --system
|
sysctl --system
|
||||||
|
|
||||||
# ---- Configure containerd ----
|
# ---------- Step 7: containerd config ----------
|
||||||
|
log "Configuring containerd"
|
||||||
mkdir -p /etc/containerd
|
mkdir -p /etc/containerd
|
||||||
containerd config default >/etc/containerd/config.toml
|
|
||||||
|
|
||||||
# Use systemd cgroups for kubelet compatibility
|
if [[ ! -f /etc/containerd/config.toml ]]; then
|
||||||
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
|
containerd config default >/etc/containerd/config.toml
|
||||||
|
else
|
||||||
|
cp /etc/containerd/config.toml /etc/containerd/config.toml.bak.$(date +%Y%m%d%H%M%S)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure SystemdCgroup = true
|
||||||
|
sed -ri 's/^\s*SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
|
||||||
|
|
||||||
|
# Ensure sandbox image is left as default from containerd config or package
|
||||||
|
# No hardcoded pause image needed unless troubleshooting later
|
||||||
|
|
||||||
|
# ---------- Step 8: Enable services ----------
|
||||||
|
log "Enabling and starting containerd and kubelet"
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable --now containerd
|
systemctl enable --now containerd
|
||||||
systemctl enable --now kubelet
|
systemctl enable --now kubelet
|
||||||
|
|
||||||
echo
|
# ---------- Step 9: Wait for containerd ----------
|
||||||
echo "Container runtime status:"
|
log "Waiting for containerd to become active"
|
||||||
systemctl --no-pager --full status containerd || true
|
for i in {1..20}; do
|
||||||
echo
|
if systemctl is-active --quiet containerd; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
systemctl is-active --quiet containerd || die "containerd did not start successfully"
|
||||||
|
|
||||||
# ---- Initialize control plane ----
|
# ---------- Step 10: Pre-pull Kubernetes images ----------
|
||||||
# Calico commonly uses 192.168.0.0/16 for pod networking.
|
log "Pulling Kubernetes control-plane images"
|
||||||
# Change this if it overlaps with your LAN.
|
kubeadm config images pull
|
||||||
POD_CIDR="192.168.0.0/16"
|
|
||||||
|
|
||||||
kubeadm init --pod-network-cidr="${POD_CIDR}"
|
# ---------- Step 11: Initialize cluster ----------
|
||||||
|
if [[ -f /etc/kubernetes/admin.conf ]]; then
|
||||||
|
warn "/etc/kubernetes/admin.conf already exists; skipping kubeadm init"
|
||||||
|
else
|
||||||
|
log "Initializing Kubernetes control plane"
|
||||||
|
kubeadm init --pod-network-cidr="${POD_CIDR}"
|
||||||
|
fi
|
||||||
|
|
||||||
echo
|
# ---------- Step 12: Configure kubectl for root ----------
|
||||||
echo "IMPORTANT: Save the kubeadm join command shown above for worker nodes."
|
log "Configuring kubectl for root"
|
||||||
echo
|
mkdir -p "${KUBECONFIG_DIR_ROOT}"
|
||||||
|
cp -f /etc/kubernetes/admin.conf "${KUBECONFIG_DIR_ROOT}/config"
|
||||||
# ---- Configure kubectl for the invoking user ----
|
chmod 600 "${KUBECONFIG_DIR_ROOT}/config"
|
||||||
mkdir -p "${REAL_HOME}/.kube"
|
|
||||||
cp /etc/kubernetes/admin.conf "${REAL_HOME}/.kube/config"
|
|
||||||
chown "${REAL_USER}:${REAL_USER}" "${REAL_HOME}/.kube/config"
|
|
||||||
|
|
||||||
export KUBECONFIG=/etc/kubernetes/admin.conf
|
export KUBECONFIG=/etc/kubernetes/admin.conf
|
||||||
|
|
||||||
# ---- Install Calico ----
|
# ---------- Step 13: Configure kubectl for invoking user ----------
|
||||||
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.31.4/manifests/calico.yaml
|
if [[ -n "${REAL_HOME}" && -d "${REAL_HOME}" ]]; then
|
||||||
|
log "Configuring kubectl for user ${REAL_USER}"
|
||||||
|
mkdir -p "${REAL_KUBECONFIG_DIR}"
|
||||||
|
cp -f /etc/kubernetes/admin.conf "${REAL_KUBECONFIG_DIR}/config"
|
||||||
|
chown -R "${REAL_USER}:${REAL_USER}" "${REAL_KUBECONFIG_DIR}"
|
||||||
|
chmod 600 "${REAL_KUBECONFIG_DIR}/config"
|
||||||
|
else
|
||||||
|
warn "Could not determine invoking user's home directory; skipping user kubeconfig setup"
|
||||||
|
fi
|
||||||
|
|
||||||
# ---- Optional: allow workloads on single-node lab clusters ----
|
# ---------- Step 14: Install Calico ----------
|
||||||
# Uncomment if this is a one-node lab and you want to schedule normal pods on the control plane:
|
log "Installing Calico networking"
|
||||||
# kubectl taint nodes --all node-role.kubernetes.io/control-plane-
|
kubectl apply -f "https://raw.githubusercontent.com/projectcalico/calico/${CALICO_VERSION}/manifests/calico.yaml"
|
||||||
|
|
||||||
echo
|
# ---------- Step 15: Save worker join command ----------
|
||||||
echo "Waiting briefly for node and system pods to settle..."
|
log "Saving worker join command"
|
||||||
|
kubeadm token create --print-join-command > "${JOIN_COMMAND_FILE}"
|
||||||
|
chmod 700 "${JOIN_COMMAND_FILE}"
|
||||||
|
|
||||||
|
# ---------- Step 16: Show cluster status ----------
|
||||||
|
log "Waiting briefly for cluster components"
|
||||||
sleep 10
|
sleep 10
|
||||||
|
|
||||||
echo
|
log "Cluster status"
|
||||||
echo "Cluster status:"
|
|
||||||
kubectl get nodes -o wide || true
|
kubectl get nodes -o wide || true
|
||||||
echo
|
echo
|
||||||
kubectl get pods -A || true
|
kubectl get pods -A || true
|
||||||
|
|
||||||
|
# ---------- Final output ----------
|
||||||
echo
|
echo
|
||||||
echo "Done."
|
echo "Kubernetes control plane installation is complete."
|
||||||
echo "kubectl is configured for user: ${REAL_USER}"
|
echo
|
||||||
echo "If this is a multi-node cluster, run the kubeadm join command on each worker."
|
echo "kubectl configured for:"
|
||||||
|
echo " root: ${KUBECONFIG_DIR_ROOT}/config"
|
||||||
|
echo " ${REAL_USER}: ${REAL_KUBECONFIG_DIR}/config"
|
||||||
|
echo
|
||||||
|
echo "Worker join command saved to:"
|
||||||
|
echo " ${JOIN_COMMAND_FILE}"
|
||||||
|
echo
|
||||||
|
echo "To view it:"
|
||||||
|
echo " sudo cat ${JOIN_COMMAND_FILE}"
|
||||||
|
echo
|
||||||
|
echo "If this is a single-node lab cluster and you want to schedule normal pods on the control-plane node, run:"
|
||||||
|
echo " kubectl taint nodes --all node-role.kubernetes.io/control-plane-"
|
||||||
|
echo
|
||||||
Loading…
Reference in New Issue