diff --git a/arch_install.sh b/arch_install.sh deleted file mode 100644 index 9cec33c..0000000 --- a/arch_install.sh +++ /dev/null @@ -1,326 +0,0 @@ -#!/usr/bin/env bash -set -Eeuo pipefail - -############################################################################### -# Arch Linux Kubernetes bootstrap script -# -# Purpose: -# Fully automate a single-node Kubernetes control-plane install on Arch Linux -# using: -# - containerd -# - kubeadm -# - kubectl -# - Flannel CNI -# -# What this script does: -# 1. Updates the system -# 2. Replaces legacy iptables with iptables-nft in the same pacman transaction -# 3. Installs Kubernetes packages and dependencies -# 4. Configures containerd for systemd cgroups -# 5. Enables required kernel modules and sysctl values -# 6. Disables swap now and on boot -# 7. Enables and starts containerd and kubelet -# 8. Initializes the cluster with kubeadm (if not already initialized) -# 9. Configures kubectl for the invoking user -# 10. Installs Flannel CNI -# 11. Optionally removes the control-plane taint for single-node use -# -# Usage: -# chmod +x arch_install.sh -# sudo ./arch_install.sh -# -# Re-run behavior: -# This script is written to be mostly idempotent. If the cluster is already -# initialized, it will skip kubeadm init and preserve the existing cluster. -############################################################################### - -####################################### -# User-configurable values -####################################### - -# Pod CIDR for Flannel -POD_CIDR="${POD_CIDR:-10.244.0.0/16}" - -# Flannel manifest -FLANNEL_URL="${FLANNEL_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 normal workloads to run -# on the control-plane node. -ALLOW_SINGLE_NODE_SCHEDULING="${ALLOW_SINGLE_NODE_SCHEDULING:-true}" - -# Which user should receive ~/.kube/config -TARGET_USER="${SUDO_USER:-root}" - -####################################### -# Helper functions -####################################### - -log() { - printf '\n[%s] %s\n' "$(date '+%F %T')" "$*" -} - -die() { - printf '\n[ERROR] %s\n' "$*" >&2 - exit 1 -} - -run_as_target_user() { - if [[ "$TARGET_USER" == "root" ]]; then - "$@" - else - sudo -u "$TARGET_USER" "$@" - fi -} - -####################################### -# Root check -####################################### - -if [[ "${EUID}" -ne 0 ]]; then - die "Run this script with sudo or as root." -fi - -####################################### -# Resolve target home directory -####################################### - -if [[ "$TARGET_USER" == "root" ]]; then - TARGET_HOME="/root" -else - TARGET_HOME="$(getent passwd "$TARGET_USER" | cut -d: -f6)" -fi - -[[ -n "${TARGET_HOME:-}" && -d "$TARGET_HOME" ]] || die "Could not determine home directory for $TARGET_USER" - -log "Starting Arch Kubernetes bootstrap" -log "Target kubectl user: $TARGET_USER" -log "Target home: $TARGET_HOME" - -####################################### -# 1) Update system -####################################### - -log "Updating package databases and upgrading system" -pacman -Syu --noconfirm - -####################################### -# 2) Install packages -# -# Important: -# iptables-nft conflicts with legacy iptables, so we must allow pacman to -# replace iptables during the SAME transaction. -# -# Why we use yes | pacman here: -# pacman may ask: -# "Remove iptables? [y/N]" -# and then: -# "Proceed with installation? [Y/n]" -# Using yes feeds "y" to both prompts so the script does not stop there. -####################################### - -log "Installing container runtime, Kubernetes tools, networking tools, and iptables-nft" - -yes | pacman -S --needed \ - ca-certificates \ - curl \ - wget \ - containerd \ - crictl \ - kubelet \ - kubeadm \ - kubectl \ - conntrack-tools \ - socat \ - ethtool \ - cni-plugins \ - iptables-nft - -####################################### -# 3) Verify iptables backend -####################################### - -log "Verifying iptables backend" -iptables --version || true - -####################################### -# 4) Persist required kernel modules -####################################### - -log "Writing required kernel modules" -cat > /etc/modules-load.d/k8s.conf <<'EOF' -overlay -br_netfilter -EOF - -log "Loading kernel modules now" -modprobe overlay -modprobe br_netfilter - -####################################### -# 5) Persist required sysctl settings -####################################### - -log "Writing 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 - -log "Applying sysctl settings" -sysctl --system - -####################################### -# 6) Disable swap now and on boot -####################################### - -log "Disabling swap immediately" -swapoff -a || true - -log "Commenting 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 - -####################################### -# 7) Configure containerd -# -# Kubernetes works better with systemd cgroups. -####################################### - -log "Preparing /etc/containerd" -mkdir -p /etc/containerd - -log "Generating default containerd config if needed" -if [[ ! -f /etc/containerd/config.toml ]]; then - containerd config default > /etc/containerd/config.toml -fi - -log "Ensuring SystemdCgroup = true" -sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml - -####################################### -# 8) Enable and start services -####################################### - -log "Enabling and starting containerd" -systemctl enable --now containerd.service - -log "Enabling and starting kubelet" -systemctl enable --now kubelet.service - -log "Showing containerd status" -systemctl --no-pager --full status containerd.service || true - -log "Showing kubelet status" -systemctl --no-pager --full status kubelet.service || true - -####################################### -# 9) Initialize cluster if needed -####################################### - -if [[ ! -f /etc/kubernetes/admin.conf ]]; then - log "Initializing Kubernetes control plane" - kubeadm init --pod-network-cidr="$POD_CIDR" -else - log "Cluster already initialized; skipping kubeadm init" -fi - -####################################### -# 10) 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" - -####################################### -# 11) Wait for API responsiveness -####################################### - -log "Waiting for Kubernetes API server" -for _ in $(seq 1 90); do - if run_as_target_user kubectl --kubeconfig="$TARGET_HOME/.kube/config" get nodes >/dev/null 2>&1; then - break - fi - sleep 2 -done - -####################################### -# 12) Install Flannel if missing -####################################### - -log "Installing Flannel CNI if needed" -if ! run_as_target_user kubectl --kubeconfig="$TARGET_HOME/.kube/config" get namespace kube-flannel >/dev/null 2>&1; then - run_as_target_user kubectl --kubeconfig="$TARGET_HOME/.kube/config" apply -f "$FLANNEL_URL" -else - log "Flannel already present; skipping apply" -fi - -####################################### -# 13) Allow single-node scheduling if requested -####################################### - -if [[ "$ALLOW_SINGLE_NODE_SCHEDULING" == "true" ]]; then - log "Removing control-plane taint for single-node scheduling" - run_as_target_user kubectl --kubeconfig="$TARGET_HOME/.kube/config" taint nodes --all node-role.kubernetes.io/control-plane- || true -else - log "Leaving control-plane taint in place" -fi - -####################################### -# 14) Final status -####################################### - -log "Final cluster checks" - -echo -echo "==== iptables backend ====" -iptables --version || true - -echo -echo "==== containerd status ====" -systemctl --no-pager --full status containerd.service || true - -echo -echo "==== kubelet status ====" -systemctl --no-pager --full status kubelet.service || true - -echo -echo "==== nodes ====" -run_as_target_user kubectl --kubeconfig="$TARGET_HOME/.kube/config" get nodes -o wide || true - -echo -echo "==== pods (all namespaces) ====" -run_as_target_user kubectl --kubeconfig="$TARGET_HOME/.kube/config" get pods -A -o wide || true - -cat <