feat(aula-08): adicionar seleção de arquitetura (arm64/amd64) e detectar tofu/terraform
- Variável `arch` no Terraform: arm64 (CAX11 em nbg1) ou amd64 (CPX21 em fsn1) - locals map traduz arch → server_type + location - setup.sh pergunta arquitetura interativamente (default: arm64) - Detecta OpenTofu ou Terraform automaticamente (preferência tofu) - Autoscaler: sed troca CAX→CPX nos server_types quando amd64 - tfvars gerado inclui arch selecionado
This commit is contained in:
+21
-8
@@ -38,6 +38,19 @@ locals {
|
|||||||
# Endpoint: LoadBalancer IP if enabled, otherwise Floating IP
|
# Endpoint: LoadBalancer IP if enabled, otherwise Floating IP
|
||||||
cluster_endpoint_ip = var.enable_loadbalancer ? hcloud_load_balancer.cluster[0].ipv4 : hcloud_floating_ip.control_plane[0].ip_address
|
cluster_endpoint_ip = var.enable_loadbalancer ? hcloud_load_balancer.cluster[0].ipv4 : hcloud_floating_ip.control_plane[0].ip_address
|
||||||
|
|
||||||
|
# Arquitetura: mapeia arm64→CAX (Nuremberg) ou amd64→CPX (Frankfurt)
|
||||||
|
arch_config = {
|
||||||
|
arm64 = {
|
||||||
|
server_type_cp = "cax11"
|
||||||
|
location = "nbg1"
|
||||||
|
}
|
||||||
|
amd64 = {
|
||||||
|
server_type_cp = "cpx21"
|
||||||
|
location = "fsn1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selected_arch = local.arch_config[var.arch]
|
||||||
|
|
||||||
common_labels = {
|
common_labels = {
|
||||||
cluster = local.cluster_name
|
cluster = local.cluster_name
|
||||||
environment = var.environment
|
environment = var.environment
|
||||||
@@ -192,15 +205,15 @@ resource "hcloud_placement_group" "cluster" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# CONTROL PLANE NODES (HA with 3 CAX11 nodes)
|
# CONTROL PLANE NODES (HA com 3 nodes)
|
||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
resource "hcloud_server" "control_plane" {
|
resource "hcloud_server" "control_plane" {
|
||||||
count = local.control_plane_count
|
count = local.control_plane_count
|
||||||
name = "${local.cluster_name}-cp-${count.index}"
|
name = "${local.cluster_name}-cp-${count.index}"
|
||||||
server_type = "cax11"
|
server_type = local.selected_arch.server_type_cp
|
||||||
image = data.hcloud_image.talos.id
|
image = data.hcloud_image.talos.id
|
||||||
location = "nbg1" # CAX11 only available in Nuremberg
|
location = local.selected_arch.location
|
||||||
ssh_keys = [local.ssh_key_id]
|
ssh_keys = [local.ssh_key_id]
|
||||||
|
|
||||||
firewall_ids = [hcloud_firewall.cluster.id]
|
firewall_ids = [hcloud_firewall.cluster.id]
|
||||||
@@ -209,7 +222,7 @@ resource "hcloud_server" "control_plane" {
|
|||||||
labels = merge(local.common_labels, {
|
labels = merge(local.common_labels, {
|
||||||
role = "control-plane"
|
role = "control-plane"
|
||||||
node = "cp-${count.index}"
|
node = "cp-${count.index}"
|
||||||
arch = "arm64"
|
arch = var.arch
|
||||||
})
|
})
|
||||||
|
|
||||||
public_net {
|
public_net {
|
||||||
@@ -373,15 +386,15 @@ resource "hcloud_load_balancer_target" "worker" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# WORKER NODE (Single CAX11)
|
# WORKER NODE
|
||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
resource "hcloud_server" "worker" {
|
resource "hcloud_server" "worker" {
|
||||||
count = 1
|
count = 1
|
||||||
name = "${local.cluster_name}-worker-${count.index}"
|
name = "${local.cluster_name}-worker-${count.index}"
|
||||||
server_type = "cax11"
|
server_type = local.selected_arch.server_type_cp
|
||||||
image = data.hcloud_image.talos.id
|
image = data.hcloud_image.talos.id
|
||||||
location = "nbg1"
|
location = local.selected_arch.location
|
||||||
ssh_keys = [local.ssh_key_id]
|
ssh_keys = [local.ssh_key_id]
|
||||||
|
|
||||||
firewall_ids = [hcloud_firewall.cluster.id]
|
firewall_ids = [hcloud_firewall.cluster.id]
|
||||||
@@ -390,7 +403,7 @@ resource "hcloud_server" "worker" {
|
|||||||
labels = merge(local.common_labels, {
|
labels = merge(local.common_labels, {
|
||||||
role = "worker"
|
role = "worker"
|
||||||
node = "worker-${count.index}"
|
node = "worker-${count.index}"
|
||||||
arch = "arm64"
|
arch = var.arch
|
||||||
})
|
})
|
||||||
|
|
||||||
public_net {
|
public_net {
|
||||||
|
|||||||
+71
-29
@@ -18,6 +18,9 @@ NC='\033[0m' # No Color
|
|||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
cd "$SCRIPT_DIR"
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
|
# Variáveis com defaults
|
||||||
|
ARCH="${ARCH:-arm64}"
|
||||||
|
|
||||||
# Funções de log
|
# Funções de log
|
||||||
log_info() {
|
log_info() {
|
||||||
echo -e "${BLUE}[INFO]${NC} $1"
|
echo -e "${BLUE}[INFO]${NC} $1"
|
||||||
@@ -47,18 +50,23 @@ echo ""
|
|||||||
|
|
||||||
log_info "Verificando pré-requisitos..."
|
log_info "Verificando pré-requisitos..."
|
||||||
|
|
||||||
# Verificar OpenTofu
|
# Detectar OpenTofu ou Terraform
|
||||||
if ! command -v tofu &> /dev/null; then
|
if command -v tofu &> /dev/null; then
|
||||||
log_error "OpenTofu não encontrado!"
|
TF_CMD="tofu"
|
||||||
|
log_success "OpenTofu $(tofu version | head -1)"
|
||||||
|
elif command -v terraform &> /dev/null; then
|
||||||
|
TF_CMD="terraform"
|
||||||
|
log_success "Terraform $(terraform version | head -1)"
|
||||||
|
else
|
||||||
|
log_error "OpenTofu ou Terraform não encontrado!"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Instale o OpenTofu:"
|
echo "Instale um deles:"
|
||||||
echo " brew install opentofu # macOS"
|
echo " brew install opentofu # OpenTofu (recomendado)"
|
||||||
echo " snap install opentofu # Linux"
|
echo " brew install terraform # Terraform"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Mais info: https://opentofu.org/docs/intro/install/"
|
echo "Mais info: https://opentofu.org/docs/intro/install/"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
log_success "OpenTofu $(tofu version | head -1)"
|
|
||||||
|
|
||||||
# Verificar talosctl
|
# Verificar talosctl
|
||||||
if ! command -v talosctl &> /dev/null; then
|
if ! command -v talosctl &> /dev/null; then
|
||||||
@@ -228,6 +236,23 @@ if [ "$SKIP_CREDENTIALS" != "true" ]; then
|
|||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
# Arquitetura
|
||||||
|
echo "6. Arquitetura dos nodes"
|
||||||
|
echo ""
|
||||||
|
echo " arm64 (CAX) - Ampere Altra, melhor custo/benefício"
|
||||||
|
echo " amd64 (CPX) - AMD EPYC, mais disponível"
|
||||||
|
echo ""
|
||||||
|
read -p " Arquitetura? (arm64/amd64) [arm64]: " arch_input
|
||||||
|
ARCH="${arch_input:-arm64}"
|
||||||
|
|
||||||
|
if [[ "$ARCH" == "amd64" ]]; then
|
||||||
|
log_success "AMD64 selecionado (CPX em fsn1)"
|
||||||
|
else
|
||||||
|
log_success "ARM64 selecionado (CAX em nbg1)"
|
||||||
|
ARCH="arm64"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
# Criar terraform.tfvars
|
# Criar terraform.tfvars
|
||||||
log_info "Criando terraform.tfvars..."
|
log_info "Criando terraform.tfvars..."
|
||||||
cat > terraform.tfvars << EOF
|
cat > terraform.tfvars << EOF
|
||||||
@@ -241,6 +266,7 @@ talos_image_id = $TALOS_IMAGE_ID
|
|||||||
environment = "prod"
|
environment = "prod"
|
||||||
enable_ha = $ENABLE_HA
|
enable_ha = $ENABLE_HA
|
||||||
enable_loadbalancer = $ENABLE_LB
|
enable_loadbalancer = $ENABLE_LB
|
||||||
|
arch = "$ARCH"
|
||||||
EOF
|
EOF
|
||||||
log_success "terraform.tfvars criado"
|
log_success "terraform.tfvars criado"
|
||||||
fi
|
fi
|
||||||
@@ -256,8 +282,8 @@ echo " Inicializando OpenTofu"
|
|||||||
echo "============================================"
|
echo "============================================"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
log_info "Executando tofu init..."
|
log_info "Executando $TF_CMD init..."
|
||||||
tofu init
|
$TF_CMD init
|
||||||
|
|
||||||
log_success "OpenTofu inicializado"
|
log_success "OpenTofu inicializado"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -271,8 +297,8 @@ echo " Planejando Infraestrutura"
|
|||||||
echo "============================================"
|
echo "============================================"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
log_info "Executando tofu plan..."
|
log_info "Executando $TF_CMD plan..."
|
||||||
tofu plan -out=tfplan
|
$TF_CMD plan -out=tfplan
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
log_success "Plano criado!"
|
log_success "Plano criado!"
|
||||||
@@ -322,7 +348,7 @@ if [[ ! "$apply" =~ ^[Ss]$ ]]; then
|
|||||||
log_warn "Operação cancelada pelo usuário"
|
log_warn "Operação cancelada pelo usuário"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Para aplicar manualmente:"
|
echo "Para aplicar manualmente:"
|
||||||
echo " tofu apply tfplan"
|
echo " $TF_CMD apply tfplan"
|
||||||
echo ""
|
echo ""
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
@@ -331,7 +357,7 @@ echo ""
|
|||||||
log_info "Aplicando infraestrutura..."
|
log_info "Aplicando infraestrutura..."
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
tofu apply tfplan
|
$TF_CMD apply tfplan
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
log_success "Infraestrutura provisionada!"
|
log_success "Infraestrutura provisionada!"
|
||||||
@@ -356,7 +382,7 @@ if [ -f "talosconfig" ]; then
|
|||||||
export TALOSCONFIG="$SCRIPT_DIR/talosconfig"
|
export TALOSCONFIG="$SCRIPT_DIR/talosconfig"
|
||||||
|
|
||||||
# Obter IP do control plane
|
# Obter IP do control plane
|
||||||
CP_IP=$(tofu output -raw control_plane_ip 2>/dev/null || echo "")
|
CP_IP=$($TF_CMD output -raw control_plane_ip 2>/dev/null || echo "")
|
||||||
|
|
||||||
if [ -n "$CP_IP" ]; then
|
if [ -n "$CP_IP" ]; then
|
||||||
log_info "Aguardando API do Talos em $CP_IP..."
|
log_info "Aguardando API do Talos em $CP_IP..."
|
||||||
@@ -405,7 +431,7 @@ echo ""
|
|||||||
|
|
||||||
# Obter token do terraform.tfvars
|
# Obter token do terraform.tfvars
|
||||||
HCLOUD_TOKEN=$(grep 'hcloud_token' terraform.tfvars | cut -d'"' -f2)
|
HCLOUD_TOKEN=$(grep 'hcloud_token' terraform.tfvars | cut -d'"' -f2)
|
||||||
NETWORK_ID=$(tofu output -raw network_id 2>/dev/null || echo "")
|
NETWORK_ID=$($TF_CMD output -raw network_id 2>/dev/null || echo "")
|
||||||
|
|
||||||
if [ -z "$HCLOUD_TOKEN" ]; then
|
if [ -z "$HCLOUD_TOKEN" ]; then
|
||||||
log_error "Não foi possível obter HCLOUD_TOKEN!"
|
log_error "Não foi possível obter HCLOUD_TOKEN!"
|
||||||
@@ -469,11 +495,11 @@ echo ""
|
|||||||
# Obter configurações do OpenTofu
|
# Obter configurações do OpenTofu
|
||||||
log_info "Obtendo configurações do OpenTofu..."
|
log_info "Obtendo configurações do OpenTofu..."
|
||||||
|
|
||||||
WORKER_CONFIG_BASE64=$(tofu output -raw autoscaler_worker_config 2>/dev/null)
|
WORKER_CONFIG_BASE64=$($TF_CMD output -raw autoscaler_worker_config 2>/dev/null)
|
||||||
TALOS_IMAGE_ID=$(tofu output -raw autoscaler_image_id 2>/dev/null)
|
TALOS_IMAGE_ID=$($TF_CMD output -raw autoscaler_image_id 2>/dev/null)
|
||||||
CLUSTER_NAME=$(tofu output -raw cluster_name 2>/dev/null)
|
CLUSTER_NAME=$($TF_CMD output -raw cluster_name 2>/dev/null)
|
||||||
FIREWALL_ID=$(tofu output -raw firewall_id 2>/dev/null)
|
FIREWALL_ID=$($TF_CMD output -raw firewall_id 2>/dev/null)
|
||||||
SSH_KEY_NAME=$(tofu output -raw ssh_key_name 2>/dev/null)
|
SSH_KEY_NAME=$($TF_CMD output -raw ssh_key_name 2>/dev/null)
|
||||||
|
|
||||||
if [ -z "$WORKER_CONFIG_BASE64" ]; then
|
if [ -z "$WORKER_CONFIG_BASE64" ]; then
|
||||||
log_error "Não foi possível obter configuração do worker!"
|
log_error "Não foi possível obter configuração do worker!"
|
||||||
@@ -495,7 +521,7 @@ kubectl label namespace cluster-autoscaler pod-security.kubernetes.io/enforce=pr
|
|||||||
CLUSTER_CONFIG_JSON=$(cat <<CCEOF
|
CLUSTER_CONFIG_JSON=$(cat <<CCEOF
|
||||||
{
|
{
|
||||||
"imagesForArch": {
|
"imagesForArch": {
|
||||||
"arm64": "$TALOS_IMAGE_ID"
|
"$ARCH": "$TALOS_IMAGE_ID"
|
||||||
},
|
},
|
||||||
"nodeConfigs": {
|
"nodeConfigs": {
|
||||||
"worker-pool": {
|
"worker-pool": {
|
||||||
@@ -536,12 +562,25 @@ log_success "Secret criado"
|
|||||||
|
|
||||||
# Aplicar manifesto
|
# Aplicar manifesto
|
||||||
log_info "Aplicando manifesto do cluster-autoscaler..."
|
log_info "Aplicando manifesto do cluster-autoscaler..."
|
||||||
cat cluster-autoscaler.yaml | \
|
# Ajustar server_types do autoscaler conforme arquitetura
|
||||||
sed "s|\${TALOS_IMAGE_ID}|$TALOS_IMAGE_ID|g" | \
|
if [[ "$ARCH" == "amd64" ]]; then
|
||||||
sed "s|\${NETWORK_NAME}|$CLUSTER_NAME-network|g" | \
|
AUTOSCALER_FILE="${SCRIPT_DIR}/cluster-autoscaler.yaml"
|
||||||
sed "s|\${FIREWALL_NAME}|$CLUSTER_NAME-firewall|g" | \
|
# CPX equivalentes: CAX21→CPX31, CAX31→CPX41, CAX11→CPX21
|
||||||
sed "s|\${SSH_KEY_NAME}|$SSH_KEY_NAME|g" | \
|
cat "$AUTOSCALER_FILE" | \
|
||||||
kubectl apply -f -
|
sed "s|\${TALOS_IMAGE_ID}|$TALOS_IMAGE_ID|g" | \
|
||||||
|
sed "s|\${NETWORK_NAME}|$CLUSTER_NAME-network|g" | \
|
||||||
|
sed "s|\${FIREWALL_NAME}|$CLUSTER_NAME-firewall|g" | \
|
||||||
|
sed "s|\${SSH_KEY_NAME}|$SSH_KEY_NAME|g" | \
|
||||||
|
sed -e 's/CAX21/CPX31/g' -e 's/CAX31/CPX41/g' -e 's/CAX11/CPX21/g' | \
|
||||||
|
kubectl apply -f -
|
||||||
|
else
|
||||||
|
cat cluster-autoscaler.yaml | \
|
||||||
|
sed "s|\${TALOS_IMAGE_ID}|$TALOS_IMAGE_ID|g" | \
|
||||||
|
sed "s|\${NETWORK_NAME}|$CLUSTER_NAME-network|g" | \
|
||||||
|
sed "s|\${FIREWALL_NAME}|$CLUSTER_NAME-firewall|g" | \
|
||||||
|
sed "s|\${SSH_KEY_NAME}|$SSH_KEY_NAME|g" | \
|
||||||
|
kubectl apply -f -
|
||||||
|
fi
|
||||||
|
|
||||||
# Aguardar pod ficar pronto
|
# Aguardar pod ficar pronto
|
||||||
log_info "Aguardando pod do autoscaler..."
|
log_info "Aguardando pod do autoscaler..."
|
||||||
@@ -641,8 +680,8 @@ echo ""
|
|||||||
|
|
||||||
# Mostrar outputs
|
# Mostrar outputs
|
||||||
echo "Endpoints:"
|
echo "Endpoints:"
|
||||||
tofu output -raw kubernetes_api_endpoint 2>/dev/null && echo "" || true
|
$TF_CMD output -raw kubernetes_api_endpoint 2>/dev/null && echo "" || true
|
||||||
tofu output -raw talos_api_endpoint 2>/dev/null && echo "" || true
|
$TF_CMD output -raw talos_api_endpoint 2>/dev/null && echo "" || true
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
echo "Componentes instalados:"
|
echo "Componentes instalados:"
|
||||||
@@ -651,6 +690,9 @@ echo " - Cluster Autoscaler (1-5 workers)"
|
|||||||
echo " - Hetzner CSI Driver (StorageClass: hcloud-volumes)"
|
echo " - Hetzner CSI Driver (StorageClass: hcloud-volumes)"
|
||||||
echo " - NGINX Ingress Controller + LoadBalancer"
|
echo " - NGINX Ingress Controller + LoadBalancer"
|
||||||
echo ""
|
echo ""
|
||||||
|
echo "Configuração:"
|
||||||
|
echo " - Arquitetura: $ARCH"
|
||||||
|
echo ""
|
||||||
|
|
||||||
# Mostrar IP do LoadBalancer
|
# Mostrar IP do LoadBalancer
|
||||||
LB_IP=$(kubectl get svc -n ingress-nginx ingress-nginx-controller \
|
LB_IP=$(kubectl get svc -n ingress-nginx ingress-nginx-controller \
|
||||||
|
|||||||
@@ -24,6 +24,11 @@ talos_image_id = 123456789
|
|||||||
# Ambiente (prod, staging, dev)
|
# Ambiente (prod, staging, dev)
|
||||||
environment = "workshop"
|
environment = "workshop"
|
||||||
|
|
||||||
|
# Arquitetura dos nodes: arm64 (CAX) ou amd64 (CPX)
|
||||||
|
# arm64 = CAX11/21/31 em Nuremberg (nbg1) - melhor custo
|
||||||
|
# amd64 = CPX21/31/41 em Frankfurt (fsn1) - mais disponível
|
||||||
|
# arch = "arm64"
|
||||||
|
|
||||||
# Versão do Talos OS (opcional - default: v1.11.2)
|
# Versão do Talos OS (opcional - default: v1.11.2)
|
||||||
# talos_version = "v1.11.2"
|
# talos_version = "v1.11.2"
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,21 @@ variable "talos_version" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ==========================================================
|
||||||
|
# ARQUITETURA
|
||||||
|
# ==========================================================
|
||||||
|
|
||||||
|
variable "arch" {
|
||||||
|
type = string
|
||||||
|
description = "Arquitetura dos nodes: arm64 (CAX - Ampere Altra, melhor custo) ou amd64 (CPX - AMD EPYC, mais disponível)"
|
||||||
|
default = "arm64"
|
||||||
|
|
||||||
|
validation {
|
||||||
|
condition = contains(["arm64", "amd64"], var.arch)
|
||||||
|
error_message = "arch deve ser arm64 ou amd64."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# ==========================================================
|
# ==========================================================
|
||||||
# LABELS CUSTOMIZADAS
|
# LABELS CUSTOMIZADAS
|
||||||
# ==========================================================
|
# ==========================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user