#!/usr/bin/env bash set -euo pipefail # Talos Cluster Services Deployment Script # This script deploys core infrastructure services in the correct order SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" VNTX_INFRA_DIR="$(dirname "$SCRIPT_DIR")" echo "=== Talos Cluster Services Deployment ===" echo "" # Color output GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color step() { echo -e "${GREEN}==>${NC} $1" } wait_for_pods() { local namespace=$1 local label=$2 local timeout=${3:-120} echo "Waiting for pods in namespace $namespace with label $label..." kubectl wait --for=condition=ready pod \ -l "$label" \ -n "$namespace" \ --timeout="${timeout}s" 2>/dev/null || true } # Step 0: Remove control-plane taint step "0. Removing control-plane taint..." kubectl taint nodes --all node-role.kubernetes.io/control-plane:NoSchedule- 2>/dev/null || echo "Taint already removed or not present" echo "" # Step 1: Deploy MetalLB step "1. Deploying MetalLB..." kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.9/config/manifests/metallb-native.yaml echo "Waiting for MetalLB controller..." wait_for_pods metallb-system component=controller 120 # Create memberlist secret if needed kubectl get secret -n metallb-system memberlist &>/dev/null || \ kubectl create secret generic -n metallb-system memberlist \ --from-literal=secretkey="$(openssl rand -base64 128)" echo "Waiting for MetalLB speakers..." wait_for_pods metallb-system component=speaker 120 step "Applying MetalLB IP pool configuration..." kubectl apply -f "$VNTX_INFRA_DIR/contexts/metallb/ipaddresspool.yaml" echo "" # Step 2: Deploy NFS Provisioner step "2. Deploying NFS Provisioner..." helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/ 2>/dev/null || true helm repo update helm upgrade --install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \ --namespace nfs-provisioner \ --create-namespace \ --set nfs.server=10.0.0.253 \ --set nfs.path=/mnt/k8s/cluster \ --set storageClass.name=nfs \ --set storageClass.defaultClass=true \ --set storageClass.reclaimPolicy=Delete \ --wait echo "" # Step 3: Deploy Tailscale Operator step "3. Deploying Tailscale Operator..." # Set namespace to privileged for Tailscale proxies kubectl create namespace tailscale 2>/dev/null || true kubectl label namespace tailscale \ pod-security.kubernetes.io/enforce=privileged \ pod-security.kubernetes.io/audit=privileged \ pod-security.kubernetes.io/warn=privileged \ --overwrite # Get Tailscale OAuth credentials from 1Password TAILSCALE_CLIENT_ID=$(op item get almzem6nffphe3xv4pgxpkbaga --account=YOOATCZZSVGH7AD6VABUVPORLI --fields client_id --reveal) TAILSCALE_CLIENT_SECRET=$(op item get almzem6nffphe3xv4pgxpkbaga --account=YOOATCZZSVGH7AD6VABUVPORLI --fields client_secret --reveal) helm repo add tailscale https://pkgs.tailscale.com/helmcharts 2>/dev/null || true helm repo update helm upgrade --install tailscale-operator tailscale/tailscale-operator \ --namespace=tailscale \ --set-string oauth.clientId="$TAILSCALE_CLIENT_ID" \ --set-string oauth.clientSecret="$TAILSCALE_CLIENT_SECRET" \ --wait echo "" # Step 4: Deploy DNS Services (PowerDNS) step "4. Deploying DNS Services (PowerDNS)..." # Create PostgreSQL credentials secret from 1Password kubectl create secret generic postgresql-credentials -n dns \ --from-literal="POSTGRES_USER=$(op item get t3nqhjmeci6msx4qouu64yfr3q --account=YOOATCZZSVGH7AD6VABUVPORLI --fields POSTGRES_USER --reveal)" \ --from-literal="POSTGRES_PASSWORD=$(op item get t3nqhjmeci6msx4qouu64yfr3q --account=YOOATCZZSVGH7AD6VABUVPORLI --fields POSTGRES_PASSWORD --reveal)" \ --from-literal="POSTGRES_DB=$(op item get t3nqhjmeci6msx4qouu64yfr3q --account=YOOATCZZSVGH7AD6VABUVPORLI --fields POSTGRES_DB --reveal)" \ --dry-run=client -o yaml | kubectl apply -f - # Create PowerDNS API secret from 1Password kubectl create secret generic powerdns-secrets -n dns \ --from-literal="API_KEY=$(op item get t3nqhjmeci6msx4qouu64yfr3q --account=YOOATCZZSVGH7AD6VABUVPORLI --fields POWERDNS_API_KEY --reveal)" \ --dry-run=client -o yaml | kubectl apply -f - # Create PowerDNS config kubectl create configmap powerdns-config -n dns --from-literal="pdns.conf=launch=gpgsql gpgsql-host=10.0.0.252 gpgsql-port=5432 gpgsql-dbname=powerdns gpgsql-user=powerdns gpgsql-password=$(op item get t3nqhjmeci6msx4qouu64yfr3q --account=YOOATCZZSVGH7AD6VABUVPORLI --fields POSTGRES_PASSWORD --reveal) gpgsql-dnssec=yes receiver-threads=4 distributor-threads=4 reuseport=yes max-tcp-connections=100 api=yes api-key=$(op item get t3nqhjmeci6msx4qouu64yfr3q --account=YOOATCZZSVGH7AD6VABUVPORLI --fields POWERDNS_API_KEY --reveal) webserver=yes webserver-address=0.0.0.0 webserver-port=8081 webserver-allow-from=0.0.0.0/0 webserver-max-bodysize=10485760 local-address=0.0.0.0 local-port=53 log-dns-queries=yes loglevel=6" \ --dry-run=client -o yaml | kubectl apply -f - # Deploy PowerDNS services and deployment kubectl apply -f "$VNTX_INFRA_DIR/contexts/dns/powerdns-service.yaml" kubectl apply -f "$VNTX_INFRA_DIR/contexts/dns/powerdns-deployment.yaml" echo "Waiting for PowerDNS..." wait_for_pods dns app=powerdns 120 echo "" # Step 5: Verify deployment step "5. Verifying deployment..." echo "" echo "MetalLB Status:" kubectl get pods -n metallb-system echo "" kubectl get ipaddresspool,l2advertisement -n metallb-system echo "" echo "NFS Provisioner Status:" kubectl get pods -n nfs-provisioner echo "" kubectl get storageclass echo "" echo "Tailscale Operator Status:" kubectl get pods -n tailscale echo "" echo "" echo "DNS Services Status:" kubectl get pods,svc -n dns echo "" echo -e "${GREEN}=== Deployment Complete ===${NC}" echo "" echo "Services deployed:" echo " - MetalLB (Public LoadBalancer)" echo " - NFS Provisioner (Storage from 10.0.0.253)" echo " - Tailscale Operator (Private network access)" echo " - PowerDNS (Authoritative DNS)" echo "" echo "External Dependencies:" echo " - PostgreSQL: 10.0.0.252" echo " - NFS: 10.0.0.253:/mnt/k8s/cluster" echo "" echo "LoadBalancer Services:" kubectl get svc --all-namespaces -o wide | grep LoadBalancer || echo " No LoadBalancer services yet"