#!/bin/bash # Set up error handling set -e # Define colors for better readability GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' RED='\033[0;31m' NC='\033[0m' # No Color # Load environment variables if [ -f "$(dirname "$0")/../load-env.sh" ]; then echo -e "${YELLOW}Loading environment variables...${NC}" source "$(dirname "$0")/../load-env.sh" fi # Get cluster IP echo -e "${YELLOW}Getting cluster IP address...${NC}" CLUSTER_IP=$(kubectl get -n kube-system service traefik -o jsonpath='{.status.loadBalancer.ingress[0].ip}') if [ -z "$CLUSTER_IP" ]; then echo -e "${RED}Failed to get cluster IP. Is Traefik running?${NC}" exit 1 fi echo -e "${YELLOW}Using cluster IP: ${CLUSTER_IP}${NC}" # Domain settings DOMAIN="cloud.payne.io" INTERNAL_DOMAIN="in.${DOMAIN}" DASHBOARD_DOMAIN="kubernetes-dashboard.${INTERNAL_DOMAIN}" echo -e "${BLUE}=== Setting up Split DNS with systemd-resolved ===${NC}" echo -e "${YELLOW}Internal Domain: ${INTERNAL_DOMAIN}${NC}" echo -e "${YELLOW}Dashboard Domain: ${DASHBOARD_DOMAIN}${NC}" echo # Check if running as root if [ "$EUID" -ne 0 ]; then echo -e "${RED}This script must be run as root to configure systemd-resolved.${NC}" echo -e "${YELLOW}Please run: sudo $0${NC}" exit 1 fi # Create systemd-resolved configuration directory if it doesn't exist echo -e "${YELLOW}Creating systemd-resolved configuration directory...${NC}" mkdir -p /etc/systemd/resolved.conf.d/ # Create the configuration file for split DNS echo -e "${YELLOW}Creating split DNS configuration...${NC}" cat > /etc/systemd/resolved.conf.d/split-dns.conf << EOF [Resolve] # Use Google DNS servers as fallback FallbackDNS=8.8.8.8 8.8.4.4 # Define our domain for special handling Domains=~${INTERNAL_DOMAIN} # Enable split DNS DNSStubListenerExtra=${CLUSTER_IP} EOF # Create a static host entry for the dashboard domain echo -e "${YELLOW}Creating static address mapping for ${DASHBOARD_DOMAIN}...${NC}" mkdir -p /etc/systemd/resolved.conf.d/ cat > /etc/systemd/resolved.conf.d/static-domains.conf << EOF [Resolve] # Map our dashboard domain to the cluster IP $(echo "${DASHBOARD_DOMAIN} ${CLUSTER_IP}" | awk '{print "DNS=" $2 "#" $1}') EOF # Restart systemd-resolved echo -e "${YELLOW}Restarting systemd-resolved...${NC}" systemctl restart systemd-resolved # Remove immutable flag from resolv.conf if set if lsattr /etc/resolv.conf 2>/dev/null | grep -q 'i'; then echo -e "${YELLOW}Removing immutable flag from /etc/resolv.conf...${NC}" chattr -i /etc/resolv.conf fi # Configure resolv.conf to use systemd-resolved echo -e "${YELLOW}Configuring /etc/resolv.conf to use systemd-resolved...${NC}" ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf # Now for the Kubernetes parts echo -e "${YELLOW}Setting up Kubernetes components...${NC}" # Get email for Let's Encrypt echo -e "${YELLOW}Please enter an email address for Let's Encrypt registration:${NC}" read -p "Email: " EMAIL_ADDRESS # Ensure cert-manager namespace exists kubectl get namespace cert-manager >/dev/null 2>&1 || kubectl create namespace cert-manager # Install cert-manager if needed if ! kubectl get deployment -n cert-manager cert-manager >/dev/null 2>&1; then echo -e "${YELLOW}Installing cert-manager...${NC}" helm repo add jetstack https://charts.jetstack.io helm repo update helm upgrade --install cert-manager jetstack/cert-manager \ --namespace cert-manager \ --set installCRDs=true # Wait for cert-manager to be ready echo -e "${YELLOW}Waiting for cert-manager to be ready (this may take a minute)...${NC}" sleep 30 kubectl wait --for=condition=available --timeout=300s deployment/cert-manager -n cert-manager kubectl wait --for=condition=available --timeout=300s deployment/cert-manager-webhook -n cert-manager fi # Ensure kubernetes-dashboard namespace exists kubectl get namespace kubernetes-dashboard >/dev/null 2>&1 || kubectl create namespace kubernetes-dashboard # Install the dashboard if not already installed if ! kubectl get deployment -n kubernetes-dashboard kubernetes-dashboard >/dev/null 2>&1; then echo -e "${YELLOW}Installing Kubernetes Dashboard...${NC}" "$(dirname "$0")/install-simple-dashboard" fi # Create a ClusterIssuer for Let's Encrypt echo -e "${YELLOW}Setting up Let's Encrypt ClusterIssuer...${NC}" cat << EOF | kubectl apply -f - apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: ${EMAIL_ADDRESS} privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: traefik EOF # Check dashboard service name and port echo -e "${YELLOW}Checking kubernetes-dashboard service...${NC}" DASHBOARD_SERVICE=$(kubectl get svc -n kubernetes-dashboard -o name | grep kubernetes-dashboard | grep -v metrics-scraper | grep -v api | grep -v auth | head -1) if [ -z "$DASHBOARD_SERVICE" ]; then echo -e "${RED}Kubernetes Dashboard service not found. Please check your installation.${NC}" exit 1 fi # Get the service name without the "service/" prefix DASHBOARD_SERVICE_NAME=$(echo $DASHBOARD_SERVICE | cut -d'/' -f2) echo -e "${YELLOW}Found dashboard service: ${DASHBOARD_SERVICE_NAME}${NC}" # Get the service port DASHBOARD_PORT=$(kubectl get svc $DASHBOARD_SERVICE_NAME -n kubernetes-dashboard -o jsonpath='{.spec.ports[0].port}') echo -e "${YELLOW}Dashboard port: ${DASHBOARD_PORT}${NC}" # Create an Ingress with TLS echo -e "${YELLOW}Creating ingress with TLS for ${DASHBOARD_DOMAIN}...${NC}" cat << EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: kubernetes-dashboard namespace: kubernetes-dashboard annotations: kubernetes.io/ingress.class: traefik cert-manager.io/cluster-issuer: letsencrypt-prod traefik.ingress.kubernetes.io/service.serversscheme: https traefik.ingress.kubernetes.io/service.serverstransport.insecureskipverify: "true" spec: tls: - hosts: - ${DASHBOARD_DOMAIN} secretName: kubernetes-dashboard-tls rules: - host: ${DASHBOARD_DOMAIN} http: paths: - path: / pathType: Prefix backend: service: name: ${DASHBOARD_SERVICE_NAME} port: number: ${DASHBOARD_PORT} EOF echo echo -e "${GREEN}=== Split DNS Setup Complete! ===${NC}" echo echo -e "${YELLOW}Your Kubernetes Dashboard will be available at:${NC}" echo -e "${BLUE}https://${DASHBOARD_DOMAIN}${NC}" echo echo -e "${YELLOW}Key points:${NC}" echo "1. systemd-resolved is now configured to resolve ${INTERNAL_DOMAIN} domains locally" echo "2. The dashboard domain ${DASHBOARD_DOMAIN} is mapped to ${CLUSTER_IP}" echo "3. Let's Encrypt will issue a valid certificate for secure HTTPS (may take a few minutes)" echo "4. External users cannot access these domains (special DNS configuration required)" echo echo -e "${YELLOW}To test the DNS resolution:${NC}" echo -e "${BLUE}nslookup ${DASHBOARD_DOMAIN}${NC}" echo echo -e "${YELLOW}To verify systemd-resolved configuration:${NC}" echo -e "${BLUE}resolvectl status${NC}" echo echo -e "${YELLOW}Certificate status:${NC}" echo -e "${BLUE}kubectl get certificate -n kubernetes-dashboard${NC}" echo