Update arch_install.sh
This commit is contained in:
parent
e22245c4f3
commit
394dc98229
317
arch_install.sh
317
arch_install.sh
|
|
@ -1,20 +1,111 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
set -Eeuo pipefail
|
||||
|
||||
# Update system
|
||||
sudo pacman -Syu --noconfirm
|
||||
###############################################################################
|
||||
# Arch Linux Kubernetes bootstrap script
|
||||
#
|
||||
# What this script does:
|
||||
# 1. Updates the system
|
||||
# 2. Replaces legacy iptables with iptables-nft in one transaction
|
||||
# 3. Installs Kubernetes packages and containerd
|
||||
# 4. Configures containerd to use systemd cgroups
|
||||
# 5. Enables required kernel modules and sysctl settings
|
||||
# 6. Disables swap now and on reboot
|
||||
# 7. Enables containerd and kubelet
|
||||
# 8. Initializes a single control-plane node with kubeadm
|
||||
# 9. Configures kubectl for the invoking user
|
||||
# 10. Installs Flannel CNI
|
||||
# 11. Optionally allows scheduling pods on the control-plane node
|
||||
#
|
||||
# Notes:
|
||||
# - This script is intended for a fresh/single-node lab setup.
|
||||
# - Re-running is mostly safe; it skips kubeadm init if already initialized.
|
||||
# - Run it as:
|
||||
# sudo ./arch_k8s_bootstrap.sh
|
||||
###############################################################################
|
||||
|
||||
# Switch from legacy iptables to nft backend if needed
|
||||
if pacman -Q iptables >/dev/null 2>&1; then
|
||||
sudo pacman -Rns --noconfirm iptables || true
|
||||
#######################################
|
||||
# User-tunable variables
|
||||
#######################################
|
||||
|
||||
# Pod CIDR required by Flannel docs
|
||||
POD_CIDR="${POD_CIDR:-10.244.0.0/16}"
|
||||
|
||||
# Flannel manifest URL from current flannel docs/releases
|
||||
FLANNEL_MANIFEST_URL="${FLANNEL_MANIFEST_URL:-https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml}"
|
||||
|
||||
# Set to "true" if this is a single-node lab and you want workloads allowed
|
||||
# on the control-plane node after setup.
|
||||
ALLOW_PODS_ON_CONTROL_PLANE="${ALLOW_PODS_ON_CONTROL_PLANE:-true}"
|
||||
|
||||
# The user who should receive ~/.kube/config.
|
||||
# If script is run with sudo, prefer the original user.
|
||||
TARGET_USER="${SUDO_USER:-root}"
|
||||
|
||||
# Figure out that user's home directory safely.
|
||||
if [[ "${TARGET_USER}" == "root" ]]; then
|
||||
TARGET_HOME="/root"
|
||||
else
|
||||
TARGET_HOME="$(getent passwd "${TARGET_USER}" | cut -d: -f6)"
|
||||
fi
|
||||
|
||||
# Install Kubernetes prerequisites and container runtime
|
||||
yes | sudo pacman -S --needed \
|
||||
#######################################
|
||||
# Helper functions
|
||||
#######################################
|
||||
|
||||
log() {
|
||||
printf '\n[%s] %s\n' "$(date '+%F %T')" "$*"
|
||||
}
|
||||
|
||||
die() {
|
||||
printf '\n[ERROR] %s\n' "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
require_root() {
|
||||
[[ "${EUID}" -eq 0 ]] || die "Run this script with sudo or as root."
|
||||
}
|
||||
|
||||
command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
#######################################
|
||||
# Sanity checks
|
||||
#######################################
|
||||
|
||||
require_root
|
||||
|
||||
if [[ -z "${TARGET_HOME}" || ! -d "${TARGET_HOME}" ]]; then
|
||||
die "Could not determine home directory for target user: ${TARGET_USER}"
|
||||
fi
|
||||
|
||||
log "Starting Arch Kubernetes bootstrap"
|
||||
log "Target kubectl user: ${TARGET_USER}"
|
||||
log "Target home: ${TARGET_HOME}"
|
||||
|
||||
#######################################
|
||||
# 1) Fully update Arch
|
||||
#######################################
|
||||
|
||||
log "Updating package databases and upgrading system"
|
||||
pacman -Syu --noconfirm
|
||||
|
||||
#######################################
|
||||
# 2) Install required packages
|
||||
#
|
||||
# Important:
|
||||
# - iptables-nft must replace legacy iptables in the SAME transaction.
|
||||
# - We intentionally do not remove iptables first because that can break
|
||||
# dependency resolution temporarily for packages that need libxtables.
|
||||
#######################################
|
||||
|
||||
log "Installing container runtime, Kubernetes tools, networking tools, and iptables-nft"
|
||||
|
||||
yes | pacman -S --needed \
|
||||
ca-certificates \
|
||||
curl \
|
||||
wget \
|
||||
iptables-nft \
|
||||
containerd \
|
||||
crictl \
|
||||
kubelet \
|
||||
|
|
@ -22,61 +113,199 @@ yes | sudo pacman -S --needed \
|
|||
kubectl \
|
||||
conntrack-tools \
|
||||
socat \
|
||||
cni-plugins
|
||||
ethtool \
|
||||
cni-plugins \
|
||||
iptables-nft
|
||||
|
||||
# Enable and start containerd
|
||||
sudo systemctl enable --now containerd.service
|
||||
#######################################
|
||||
# 3) Verify iptables backend
|
||||
#######################################
|
||||
|
||||
# Generate default containerd config if missing
|
||||
log "Verifying iptables backend"
|
||||
iptables --version || true
|
||||
|
||||
#######################################
|
||||
# 4) Enable and configure containerd
|
||||
#
|
||||
# kubelet works best with containerd configured to use systemd cgroups.
|
||||
#######################################
|
||||
|
||||
log "Enabling and starting containerd"
|
||||
systemctl enable --now containerd.service
|
||||
|
||||
log "Creating default containerd config if missing"
|
||||
mkdir -p /etc/containerd
|
||||
if [[ ! -f /etc/containerd/config.toml ]]; then
|
||||
sudo mkdir -p /etc/containerd
|
||||
containerd config default | sudo tee /etc/containerd/config.toml >/dev/null
|
||||
containerd config default > /etc/containerd/config.toml
|
||||
fi
|
||||
|
||||
# Set SystemdCgroup = true for kubelet compatibility
|
||||
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
|
||||
sudo systemctl restart containerd
|
||||
log "Setting SystemdCgroup = true in /etc/containerd/config.toml"
|
||||
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
|
||||
|
||||
# Kernel modules for Kubernetes networking
|
||||
sudo tee /etc/modules-load.d/k8s.conf >/dev/null <<'EOF'
|
||||
log "Restarting containerd to apply config"
|
||||
systemctl restart containerd.service
|
||||
|
||||
#######################################
|
||||
# 5) Load required kernel modules now and on boot
|
||||
#######################################
|
||||
|
||||
log "Persisting required kernel modules"
|
||||
cat > /etc/modules-load.d/k8s.conf <<'EOF'
|
||||
overlay
|
||||
br_netfilter
|
||||
EOF
|
||||
|
||||
sudo modprobe overlay
|
||||
sudo modprobe br_netfilter
|
||||
log "Loading kernel modules immediately"
|
||||
modprobe overlay
|
||||
modprobe br_netfilter
|
||||
|
||||
# Sysctl settings required by Kubernetes
|
||||
sudo tee /etc/sysctl.d/k8s.conf >/dev/null <<'EOF'
|
||||
#######################################
|
||||
# 6) Apply required sysctl settings now and on boot
|
||||
#######################################
|
||||
|
||||
log "Persisting required sysctl settings"
|
||||
cat > /etc/sysctl.d/k8s.conf <<'EOF'
|
||||
net.bridge.bridge-nf-call-iptables = 1
|
||||
net.bridge.bridge-nf-call-ip6tables = 1
|
||||
net.ipv4.ip_forward = 1
|
||||
EOF
|
||||
|
||||
sudo sysctl --system
|
||||
log "Applying sysctl settings"
|
||||
sysctl --system
|
||||
|
||||
# Disable swap now
|
||||
sudo swapoff -a
|
||||
#######################################
|
||||
# 7) Disable swap now and comment swap entries in /etc/fstab
|
||||
#######################################
|
||||
|
||||
# Disable swap on boot by commenting swap lines in /etc/fstab
|
||||
sudo sed -i.bak '/\sswap\s/s/^/#/' /etc/fstab
|
||||
log "Disabling swap immediately"
|
||||
swapoff -a || true
|
||||
|
||||
# Enable kubelet
|
||||
sudo systemctl enable --now kubelet.service
|
||||
log "Commenting active swap entries in /etc/fstab"
|
||||
if [[ -f /etc/fstab ]]; then
|
||||
cp /etc/fstab /etc/fstab.bak.$(date +%s)
|
||||
sed -i '/^[^#].*\sswap\s/s/^/# /' /etc/fstab
|
||||
fi
|
||||
|
||||
#######################################
|
||||
# 8) Enable kubelet
|
||||
#
|
||||
# kubelet may show as active but waiting until kubeadm init finishes; that is
|
||||
# normal before the control plane exists.
|
||||
#######################################
|
||||
|
||||
log "Enabling and starting kubelet"
|
||||
systemctl enable --now kubelet.service
|
||||
|
||||
#######################################
|
||||
# 9) Preflight visibility
|
||||
#######################################
|
||||
|
||||
log "Container runtime status"
|
||||
systemctl --no-pager --full status containerd.service || true
|
||||
|
||||
log "Kubelet status"
|
||||
systemctl --no-pager --full status kubelet.service || true
|
||||
|
||||
#######################################
|
||||
# 10) Initialize cluster if not already initialized
|
||||
#######################################
|
||||
|
||||
if [[ ! -f /etc/kubernetes/admin.conf ]]; then
|
||||
log "Initializing Kubernetes control plane with kubeadm"
|
||||
kubeadm init --pod-network-cidr="${POD_CIDR}"
|
||||
else
|
||||
log "Skipping kubeadm init because /etc/kubernetes/admin.conf already exists"
|
||||
fi
|
||||
|
||||
#######################################
|
||||
# 11) Configure kubectl for target user
|
||||
#######################################
|
||||
|
||||
log "Configuring kubectl for ${TARGET_USER}"
|
||||
mkdir -p "${TARGET_HOME}/.kube"
|
||||
cp -f /etc/kubernetes/admin.conf "${TARGET_HOME}/.kube/config"
|
||||
chown -R "${TARGET_USER}:${TARGET_USER}" "${TARGET_HOME}/.kube"
|
||||
chmod 700 "${TARGET_HOME}/.kube"
|
||||
chmod 600 "${TARGET_HOME}/.kube/config"
|
||||
|
||||
#######################################
|
||||
# 12) Wait briefly for API server to become responsive
|
||||
#######################################
|
||||
|
||||
log "Waiting for Kubernetes API to become reachable"
|
||||
for _ in $(seq 1 60); do
|
||||
if sudo -u "${TARGET_USER}" kubectl --kubeconfig="${TARGET_HOME}/.kube/config" get nodes >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
#######################################
|
||||
# 13) Install Flannel if not already present
|
||||
#######################################
|
||||
|
||||
log "Installing Flannel CNI"
|
||||
if ! sudo -u "${TARGET_USER}" kubectl --kubeconfig="${TARGET_HOME}/.kube/config" get namespace kube-flannel >/dev/null 2>&1; then
|
||||
sudo -u "${TARGET_USER}" kubectl --kubeconfig="${TARGET_HOME}/.kube/config" apply -f "${FLANNEL_MANIFEST_URL}"
|
||||
else
|
||||
log "kube-flannel namespace already exists; skipping Flannel install"
|
||||
fi
|
||||
|
||||
#######################################
|
||||
# 14) Optionally allow scheduling on single-node control plane
|
||||
#######################################
|
||||
|
||||
if [[ "${ALLOW_PODS_ON_CONTROL_PLANE}" == "true" ]]; then
|
||||
log "Allowing workloads on the control-plane node (single-node lab mode)"
|
||||
sudo -u "${TARGET_USER}" kubectl --kubeconfig="${TARGET_HOME}/.kube/config" taint nodes --all node-role.kubernetes.io/control-plane- || true
|
||||
else
|
||||
log "Leaving default control-plane taint in place"
|
||||
fi
|
||||
|
||||
#######################################
|
||||
# 15) Final status / useful commands
|
||||
#######################################
|
||||
|
||||
log "Final checks"
|
||||
echo
|
||||
echo "==== iptables backend ===="
|
||||
iptables --version || true
|
||||
|
||||
echo
|
||||
echo "Base Kubernetes packages are installed."
|
||||
echo "Next step:"
|
||||
echo " sudo kubeadm init --pod-network-cidr=10.244.0.0/16"
|
||||
echo "==== containerd info ===="
|
||||
crictl info >/dev/null 2>&1 && echo "crictl can talk to the runtime" || echo "crictl check did not succeed yet"
|
||||
|
||||
echo
|
||||
echo "Then set up kubectl for your user:"
|
||||
echo " mkdir -p \$HOME/.kube"
|
||||
echo " sudo cp -i /etc/kubernetes/admin.conf \$HOME/.kube/config"
|
||||
echo " sudo chown \$(id -u):\$(id -g) \$HOME/.kube/config"
|
||||
echo "==== nodes ===="
|
||||
sudo -u "${TARGET_USER}" kubectl --kubeconfig="${TARGET_HOME}/.kube/config" get nodes -o wide || true
|
||||
|
||||
echo
|
||||
echo "Then install Flannel:"
|
||||
echo " kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml"
|
||||
echo
|
||||
echo "Check status with:"
|
||||
echo " systemctl status containerd kubelet --no-pager"
|
||||
echo " crictl info"
|
||||
echo "==== pods (all namespaces) ===="
|
||||
sudo -u "${TARGET_USER}" kubectl --kubeconfig="${TARGET_HOME}/.kube/config" get pods -A -o wide || true
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Bootstrap complete.
|
||||
|
||||
kubectl is configured for:
|
||||
user: ${TARGET_USER}
|
||||
config: ${TARGET_HOME}/.kube/config
|
||||
|
||||
Common next commands:
|
||||
kubectl get nodes
|
||||
kubectl get pods -A
|
||||
kubectl cluster-info
|
||||
|
||||
If the node is not Ready yet, wait a minute and re-run:
|
||||
kubectl get nodes
|
||||
kubectl get pods -A
|
||||
|
||||
To test the cluster:
|
||||
kubectl create deployment nginx --image=nginx
|
||||
kubectl expose deployment nginx --port=80 --type=NodePort
|
||||
kubectl get svc
|
||||
|
||||
To join worker nodes later, generate a join command with:
|
||||
kubeadm token create --print-join-command
|
||||
|
||||
EOF
|
||||
Loading…
Reference in New Issue