Files
proxmox-script/k3s.sh
2025-05-27 01:01:56 +08:00

177 lines
4.8 KiB
Bash

#!/bin/bash
set -e
# Script to create and configure a Proxmox LXC container with k3s, kubectl, Helm, NGINX Ingress, and MetalLB
# Variables
CTID=117
HOSTNAME="k3s-master"
CORES=4
MEMORY=8192
SWAP=512
DISK_SIZE=20
BRIDGE="vmbr0"
IP="dhcp" # Change to static IP like "192.168.1.100/24" if needed
GATEWAY=""
TEMPLATE="/var/lib/vz/template/cache/debian-12-standard_12.7-1_amd64.tar.zst"
K3S_VERSION="v1.30.1+k3s1"
KUBECTL_VERSION="v1.30.0"
# Verify template
if [ ! -f "$TEMPLATE" ]; then
echo "Error: Template $TEMPLATE not found!"
exit 1
fi
# Check kernel modules
echo "Checking kernel modules on host..."
for module in br_netfilter overlay; do
if ! lsmod | grep -q "$module"; then
modprobe "$module" || {
echo "Error: Kernel module $module missing!"
exit 1
}
fi
done
echo -e "br_netfilter\noverlay" > /etc/modules-load.d/k3s.conf
# Enable IP forwarding
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1
sed -i '/net.ipv4.ip_forward/s/^#//g' /etc/sysctl.conf
sed -i '/net.ipv6.conf.all.forwarding/s/^#//g' /etc/sysctl.conf
# Create LXC container
pct create $CTID $TEMPLATE \
--ostype debian \
--hostname $HOSTNAME \
--cores $CORES \
--memory $MEMORY \
--swap $SWAP \
--rootfs local-lvm:$DISK_SIZE \
--net0 name=eth0,bridge=$BRIDGE,ip=$IP \
--features nesting=1,keyctl=1 \
--unprivileged 0
# Modify LXC config
cat <<EOF >> /etc/pve/lxc/$CTID.conf
lxc.apparmor.profile: unconfined
lxc.cap.drop:
lxc.mount.auto: proc:rw sys:rw
lxc.cgroup2.devices.allow: c 10:200 rwm
EOF
# Start container
pct start $CTID
# Setup inside the container
pct exec $CTID -- bash -c "
set -e
# Install dependencies
apt-get update && apt-get install -y curl ca-certificates bash-completion iptables iproute2 gnupg2
# Install the English UTF-8 locale
apt-get update
apt-get install -y locales
# Generate the locale
sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen
locale-gen
# Set environment variables for locale
update-locale LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8
# Export for current shell (needed for script to work immediately)
export LANG=en_US.UTF-8
export LANGUAGE=en_US:en
export LC_ALL=en_US.UTF-8
# Create /dev/kmsg link for k3s
ln -sf /dev/console /dev/kmsg
echo -e '#!/bin/sh -e\nln -sf /dev/console /dev/kmsg\nmount --make-rshared /' > /etc/rc.local
chmod +x /etc/rc.local
# Install k3s
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=$K3S_VERSION sh -s - \
--disable=traefik \
--disable=servicelb \
--write-kubeconfig-mode 644 \
--node-name $HOSTNAME
# Setup kubectl
mkdir -p /root/.kube
cp /etc/rancher/k3s/k3s.yaml /root/.kube/config
chmod 600 /root/.kube/config
export KUBECONFIG=/root/.kube/config
# Install kubectl binary
cd /usr/local/bin
ARCH=amd64
OS=linux
curl -LO https://dl.k8s.io/release/$KUBECTL_VERSION/bin/\$OS/\$ARCH/kubectl
curl -LO https://dl.k8s.io/release/$KUBECTL_VERSION/bin/\$OS/\$ARCH/kubectl.sha256
echo \"\$(cat kubectl.sha256) kubectl\" | sha256sum --check || exit 1
chmod +x kubectl
rm kubectl.sha256
# Fix PATH
echo 'export PATH=\$PATH:/usr/local/bin' >> /root/.bashrc
echo 'export KUBECONFIG=/root/.kube/config' >> /root/.bashrc
echo 'alias k=kubectl' >> /root/.bashrc
echo 'source <(kubectl completion bash)' >> /root/.bashrc
echo 'complete -o default -F __start_kubectl k' >> /root/.bashrc
# Install git for Helm plugins
apt-get install -y git
# Fixed Helm installation: manual download and extraction
echo "Installing Helm manually..."
HELM_VERSION="v3.18.0"
curl -LO "https://get.helm.sh/helm-${HELM_VERSION}-linux-amd64.tar.gz"
tar -zxvf "helm-${HELM_VERSION}-linux-amd64.tar.gz"
mv linux-amd64/helm /usr/local/bin/helm
chmod +x /usr/local/bin/helm
rm -rf linux-amd64 "helm-${HELM_VERSION}-linux-amd64.tar.gz"
# Verify Helm installation
helm version
# Add Ingress-NGINX via Helm
kubectl create namespace ingress-nginx
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx --namespace ingress-nginx
# Install MetalLB
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml
kubectl wait --namespace metallb-system --for=condition=ready pod --selector=app=controller --timeout=120s
# Configure MetalLB IP address pool (change CIDR to your local subnet range)
cat <<EOF2 | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: clinic-pool
namespace: metallb-system
spec:
addresses:
- 192.168.100.240-192.168.100.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: clinic-adv
namespace: metallb-system
EOF2
"
# Wait and test cluster
echo "Waiting for k3s to stabilize..."
sleep 60
pct exec $CTID -- kubectl get nodes
echo " k3s + kubectl + Helm + Ingress + MetalLB setup complete!"
echo " Access KUBECONFIG inside container: /root/.kube/config"