Last active
November 18, 2025 08:56
-
-
Save finnie2006/2dcc50251df3d93cd3e39c9794d1eab9 to your computer and use it in GitHub Desktop.
Bash script to install k3s node / worker node with option for kubernetes dashboard, interactive bash script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # K3s Interactive Installer | |
| # This script provides a menu-driven interface to install a k3s master or worker node, | |
| # and to install the Kubernetes Dashboard. | |
| # --- Colors for better readability --- | |
| NC='\033[0m' # No Color | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| BLUE='\033[0;34m' | |
| # --- Function to check for root privileges --- | |
| check_root() { | |
| if [ "$EUID" -ne 0 ]; then | |
| echo -e "${RED}Error: This script must be run as root. Please use 'sudo bash k3s_installer.sh'.${NC}" | |
| exit 1 | |
| fi | |
| } | |
| # --- Function to install k3s master node --- | |
| install_master() { | |
| echo -e "${BLUE}Starting k3s master node installation...${NC}" | |
| # The --write-kubeconfig-mode 644 makes the kubeconfig file readable by non-root users. | |
| # The --disable traefik is optional, but many users prefer to install their own ingress controller. | |
| curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--write-kubeconfig-mode 644 --disable traefik" sh - | |
| if [ $? -eq 0 ]; then | |
| echo -e "${GREEN}k3s master node installed successfully!${NC}" | |
| echo -e "${BLUE}Configuring firewall for master node...${NC}" | |
| # Port 6443 is required for workers to join the cluster. | |
| configure_firewall "6443" | |
| echo -e "${YELLOW}Wait for the node to be ready...${NC}" | |
| sleep 15 | |
| # Verify node status | |
| export KUBECONFIG=/etc/rancher/k3s/k3s.yaml | |
| if kubectl get node | grep -q "Ready"; then | |
| echo -e "${GREEN}Master node is Ready.${NC}" | |
| install_dashboard_prompt | |
| else | |
| echo -e "${RED}Master node installation seems to have failed or is taking too long to start.${NC}" | |
| echo -e "${YELLOW}Please check the service status with: 'sudo systemctl status k3s'${NC}" | |
| fi | |
| else | |
| echo -e "${RED}k3s master node installation failed.${NC}" | |
| fi | |
| show_token | |
| } | |
| # --- Function to prompt for Kubernetes Dashboard installation --- | |
| install_dashboard_prompt() { | |
| while true; do | |
| read -p "Do you want to install the Kubernetes Dashboard? (y/n): " yn | |
| case $yn in | |
| [Yy]* ) install_dashboard; break;; | |
| [Nn]* ) echo -e "${YELLOW}Skipping Kubernetes Dashboard installation.${NC}"; break;; | |
| * ) echo "Please answer yes or no.";; | |
| esac | |
| done | |
| } | |
| # --- Function to configure firewall for a specific port --- | |
| configure_firewall() { | |
| local port=$1 | |
| if [ -z "$port" ]; then | |
| echo -e "${RED}Error: No port provided to configure_firewall function.${NC}" | |
| return | |
| fi | |
| echo -e "${BLUE}Checking for active firewalls to open port ${port}...${NC}" | |
| # Check for firewalld | |
| if systemctl is-active --quiet firewalld; then | |
| echo -e "${YELLOW}Firewalld is active. Opening port ${port}/tcp...${NC}" | |
| firewall-cmd --permanent --add-port=${port}/tcp > /dev/null 2>&1 | |
| firewall-cmd --reload > /dev/null 2>&1 | |
| echo -e "${GREEN}Firewall rule for port ${port} added to firewalld.${NC}" | |
| # Check for ufw | |
| elif command -v ufw &> /dev/null && ufw status | grep -q 'Status: active'; then | |
| echo -e "${YELLOW}UFW is active. Allowing port ${port}/tcp...${NC}" | |
| ufw allow ${port}/tcp > /dev/null 2>&1 | |
| echo -e "${GREEN}Firewall rule for port ${port} added to UFW.${NC}" | |
| else | |
| echo -e "${YELLOW}No common active firewall (firewalld, ufw) detected.${NC}" | |
| read -p "Would you like to install and configure UFW (Uncomplicated Firewall)? (y/n): " install_ufw | |
| if [[ "$install_ufw" =~ ^[Yy]$ ]]; then | |
| echo -e "${BLUE}Installing UFW...${NC}" | |
| apt-get update -y > /dev/null 2>&1 | |
| apt-get install -y ufw > /dev/null 2>&1 | |
| echo -e "${GREEN}UFW installed.${NC}" | |
| echo -e "${BLUE}Configuring UFW rules...${NC}" | |
| ufw allow 22/tcp # SSH | |
| ufw allow 6443/tcp # Kubernetes API Server | |
| ufw allow 10250/tcp # Kubelet | |
| ufw allow ${port}/tcp # Dashboard NodePort or other ports | |
| ufw --force enable | |
| echo -e "${GREEN}UFW has been enabled and configured.${NC}" | |
| ufw status | |
| else | |
| echo -e "${YELLOW}Skipping UFW installation. You may need to configure your firewall manually for port ${port}.${NC}" | |
| fi | |
| fi | |
| } | |
| # --- Function to display Dashboard access info and token --- | |
| show_dashboard_info() { | |
| export KUBECONFIG=/etc/rancher/k3s/k3s.yaml | |
| echo -e "${BLUE}Retrieving Dashboard access information...${NC}" | |
| NODE_PORT=$(kubectl -n kubernetes-dashboard get svc kubernetes-dashboard -o=jsonpath='{.spec.ports[0].nodePort}') | |
| if [ -z "$NODE_PORT" ]; then | |
| echo -e "${RED}Could not determine Dashboard NodePort. Is the dashboard installed?${NC}" | |
| return | |
| fi | |
| echo -e "${YELLOW}Generating a new access token for the Dashboard...${NC}" | |
| DASHBOARD_TOKEN=$(kubectl -n kubernetes-dashboard create token admin-user --duration=8760h) | |
| echo -e "${GREEN}--- Kubernetes Dashboard Access Token ---${NC}" | |
| echo -e "Use the token below to log in to the Dashboard." | |
| echo -e "${YELLOW}$DASHBOARD_TOKEN${NC}" | |
| echo -e "${GREEN}------------------------------------------${NC}" | |
| IP_ADDR=$(hostname -I | awk '{print $1}') | |
| echo -e "\n${BLUE}You can access the dashboard securely at:${NC}" | |
| echo -e "${YELLOW}https://${IP_ADDR}:${NODE_PORT}${NC}" | |
| echo -e "${YELLOW}Note: Your browser will show a security warning for a self-signed certificate. This is expected. Please accept the risk to proceed.${NC}" | |
| } | |
| # --- Function to install Kubernetes Dashboard --- | |
| install_dashboard() { | |
| echo -e "${BLUE}Installing Kubernetes Dashboard...${NC}" | |
| export KUBECONFIG=/etc/rancher/k3s/k3s.yaml | |
| # Using the recommended manifest from the official Kubernetes Dashboard project | |
| DASHBOARD_VERSION="v2.7.0" | |
| kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/${DASHBOARD_VERSION}/aio/deploy/recommended.yaml | |
| # Create a service account for the dashboard | |
| cat <<EOF | kubectl apply -f - | |
| apiVersion: v1 | |
| kind: ServiceAccount | |
| metadata: | |
| name: admin-user | |
| namespace: kubernetes-dashboard | |
| --- | |
| apiVersion: rbac.authorization.k8s.io/v1 | |
| kind: ClusterRoleBinding | |
| metadata: | |
| name: admin-user | |
| roleRef: | |
| apiGroup: rbac.authorization.k8s.io | |
| kind: ClusterRole | |
| name: cluster-admin | |
| subjects: | |
| - kind: ServiceAccount | |
| name: admin-user | |
| namespace: kubernetes-dashboard | |
| EOF | |
| if [ $? -eq 0 ]; then | |
| echo -e "${GREEN}Kubernetes Dashboard deployed successfully.${NC}" | |
| echo -e "${BLUE}Switching Dashboard to NodePort service for secure HTTPS access...${NC}" | |
| kubectl -n kubernetes-dashboard patch svc kubernetes-dashboard -p '{"spec": {"type": "NodePort"}}' | |
| echo -e "${YELLOW}Waiting for NodePort to be assigned...${NC}" | |
| sleep 5 | |
| NODE_PORT_CHECK=$(kubectl -n kubernetes-dashboard get svc kubernetes-dashboard -o=jsonpath='{.spec.ports[0].nodePort}') | |
| if [ -z "$NODE_PORT_CHECK" ]; then | |
| echo -e "${RED}Could not determine Dashboard NodePort. Please check the service manually with 'kubectl -n kubernetes-dashboard get svc'.${NC}" | |
| return | |
| fi | |
| # Configure firewall for the newly assigned port | |
| configure_firewall "$NODE_PORT_CHECK" | |
| # Show access info | |
| show_dashboard_info | |
| else | |
| echo -e "${RED}Failed to install Kubernetes Dashboard.${NC}" | |
| fi | |
| } | |
| # --- Function to show master token --- | |
| show_token() { | |
| echo -e "${BLUE}Retrieving the join token for worker nodes...${NC}" | |
| if [ -f /var/lib/rancher/k3s/server/node-token ]; then | |
| TOKEN=$(cat /var/lib/rancher/k3s/server/node-token) | |
| IP_ADDR=$(hostname -I | awk '{print $1}') | |
| echo -e "${GREEN}--- Worker Join Information ---${NC}" | |
| echo -e "Run the installer on your worker nodes and choose the 'worker' option." | |
| echo -e "You will need the following information:" | |
| echo -e "Master IP: ${YELLOW}$IP_ADDR${NC}" | |
| echo -e "Join Token: ${YELLOW}$TOKEN${NC}" | |
| echo -e "${GREEN}-----------------------------${NC}" | |
| else | |
| echo -e "${RED}Could not find the node-token file. Is this a master node?${NC}" | |
| fi | |
| } | |
| # --- Function to install k3s worker node --- | |
| install_worker() { | |
| echo -e "${BLUE}Starting k3s worker node installation...${NC}" | |
| # Prompt for master IP and token | |
| read -p "Enter the IP address of the master node: " MASTER_IP | |
| read -p "Enter the join token from the master node: " K3S_TOKEN | |
| if [ -z "$MASTER_IP" ] || [ -z "$K3S_TOKEN" ]; then | |
| echo -e "${RED}Master IP and Token cannot be empty. Aborting.${NC}" | |
| return | |
| fi | |
| echo -e "${YELLOW}Installing worker node and connecting to master at ${MASTER_IP}...${NC}" | |
| # Install k3s agent | |
| curl -sfL https://get.k3s.io | K3S_URL="https://${MASTER_IP}:6443" K3S_TOKEN="${K3S_TOKEN}" sh - | |
| if [ $? -eq 0 ]; then | |
| echo -e "${GREEN}k3s worker node installed and connected successfully!${NC}" | |
| echo -e "${YELLOW}--- Important ---" | |
| echo -e "All 'kubectl' commands should be run from the MASTER node." | |
| echo -e "To verify the new node, go to your master and run: ${BLUE}kubectl get nodes${NC}" | |
| echo -e "${YELLOW}-----------------${NC}" | |
| else | |
| echo -e "${RED}k3s worker node installation failed.${NC}" | |
| echo -e "${YELLOW}Please check the master IP, token, and network connectivity.${NC}" | |
| fi | |
| } | |
| # --- Function to uninstall k3s --- | |
| uninstall_k3s() { | |
| echo -e "${YELLOW}This will completely remove k3s and all related data.${NC}" | |
| read -p "Are you sure you want to continue? (y/n): " confirm | |
| if [[ ! "$confirm" =~ ^[Yy]$ ]]; then | |
| echo "Uninstall cancelled." | |
| return | |
| fi | |
| if [ -f /usr/local/bin/k3s-uninstall.sh ]; then | |
| echo -e "${BLUE}Running master node uninstall script...${NC}" | |
| /usr/local/bin/k3s-uninstall.sh | |
| echo -e "${GREEN}k3s master uninstalled.${NC}" | |
| elif [ -f /usr/local/bin/k3s-agent-uninstall.sh ]; then | |
| echo -e "${BLUE}Running agent/worker node uninstall script...${NC}" | |
| /usr/local/bin/k3s-agent-uninstall.sh | |
| echo -e "${GREEN}k3s worker uninstalled.${NC}" | |
| else | |
| echo -e "${RED}Could not find a k3s uninstall script. Has k3s been installed on this node?${NC}" | |
| fi | |
| } | |
| # --- Main Menu --- | |
| main_menu() { | |
| echo -e "\n${BLUE}--- k3s Interactive Installer Menu ---${NC}" | |
| echo "1. Install k3s Master Node" | |
| echo "2. Install k3s Worker Node" | |
| echo "3. Show Master Join Token (run on master)" | |
| echo "4. Show Dashboard Access Info (run on master)" | |
| echo "5. Uninstall k3s (Master or Worker)" | |
| echo "6. Exit" | |
| echo -e "----------------------------------------" | |
| read -p "Enter your choice [1-6]: " choice | |
| case $choice in | |
| 1) | |
| install_master | |
| ;; | |
| 2) | |
| install_worker | |
| ;; | |
| 3) | |
| show_token | |
| ;; | |
| 4) | |
| show_dashboard_info | |
| ;; | |
| 5) | |
| uninstall_k3s | |
| ;; | |
| 6) | |
| echo "Exiting." | |
| exit 0 | |
| ;; | |
| *) | |
| echo -e "${RED}Invalid option. Please try again.${NC}" | |
| main_menu | |
| ;; | |
| esac | |
| } | |
| # --- Script Start --- | |
| check_root | |
| main_menu |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.