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:
ArgoCD Setup
2026-05-09 03:32:06 -03:00
parent 17a2891329
commit 72ffe47528
4 changed files with 112 additions and 37 deletions
+21 -8
View File
@@ -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 {
+66 -24
View File
@@ -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
if [[ "$ARCH" == "amd64" ]]; then
AUTOSCALER_FILE="${SCRIPT_DIR}/cluster-autoscaler.yaml"
# CPX equivalentes: CAX21→CPX31, CAX31→CPX41, CAX11→CPX21
cat "$AUTOSCALER_FILE" | \
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|\${TALOS_IMAGE_ID}|$TALOS_IMAGE_ID|g" | \
sed "s|\${NETWORK_NAME}|$CLUSTER_NAME-network|g" | \ sed "s|\${NETWORK_NAME}|$CLUSTER_NAME-network|g" | \
sed "s|\${FIREWALL_NAME}|$CLUSTER_NAME-firewall|g" | \ sed "s|\${FIREWALL_NAME}|$CLUSTER_NAME-firewall|g" | \
sed "s|\${SSH_KEY_NAME}|$SSH_KEY_NAME|g" | \ sed "s|\${SSH_KEY_NAME}|$SSH_KEY_NAME|g" | \
kubectl apply -f - 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 \
+5
View File
@@ -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"
+15
View File
@@ -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
# ========================================================== # ==========================================================