
Kubernetes sobre Hyper-V 624m6g
v6o2y
La virtualización se ha convertido en un estándar en entornos empresariales, y Kubernetes es el orquestador por excelencia para gestionar contenedores a gran escala. Si combinas ambas tecnologías en una infraestructura de Hyper-V, puedes lograr un entorno flexible, escalable y altamente automatizado.
Pero ¿por qué hacerlo manualmente si podemos automatizarlo? PowerShell nos permite desplegar un clúster de Kubernetes en Hyper-V de forma rápida y eficiente, asegurando una configuración homogénea y minimizando errores humanos.
En esta guía, te mostraremos paso a paso cómo automatizar la creación de máquinas virtuales mediante una plantilla de Debian, la configuración de redes, la instalación de Kubernetes y la validación del clúster, todo a través de PowerShell. Además, incluiremos pruebas de conectividad y monitoreo para garantizar que todo funcione correctamente dentro de tu red LAN.
Al final de esta guía, tendrás un clúster de Kubernetes funcional en Hyper-V, listo para desplegar aplicaciones de manera eficiente y sin intervención manual.
Requisitos previos 53h5i
Antes de ejecutar el script del Powershell (si queréis saber como construir vuestro primer script, os dejamos una entrada), asegúrate de contar con lo siguiente:
- Mínimo Windows Server 2022 o Windows 10/11 Pro/Enterprise con Hyper-V activado. Lo podéis instalar con el siguiente comando:
- Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
- Mínimo 16 GB de RAM.
- Procesador con virtualización habilitada (VT-x o AMD-V).
- PowerShell con permisos de .
- En nuestro caso, usaremos una plantilla de Debian Cloud para generar todas las máquinas virtuales.
- a internet en la máquina host para descargar paquetes.
- Instalar paquete en plantilla "hv_kvp":
sudo apt update && sudo apt install linux-cloud-tools-common linux-cloud-tools-generic linux-cloud-tools-$(uname -r)
sudo systemctl enable hv-kvp-daemon
sudo systemctl start hv-kvp-daemon
- Para instalar "cloud-init", que es una herramienta utilizada para la configuración automática de instancias en la nube o máquinas virtuales en su primer arranque. Permite personalizar servidores con configuraciones específicas como s, claves SSH, paquetes, scripts de inicialización y más, sin intervención manual:
sudo apt update && sudo apt install -y cloud-init
Para sellar la máquina virtual utilizar el siguiente comando:
sudo cloud-init clean --logs
- Instalar Kubernetes en plantilla Debian:
apt install -y apt-transport-https ca-certificates curl gnupg2 software-properties-common
mkdir -p /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo tee /etc/apt/keyrings/kubernetes-apt-keyring.asc > /dev/null
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.asc] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list
apt update
apt install -y kubelet kube kubectl
apt-mark hold kubelet kube kubectl
- Paquete ADK instalado en el host de Hyper-V:
Crear una Plantilla de Debian en Hyper-V 2u576h
Si utilizamos una plantilla pre-creada de Debian en Hyper-V, podemos clonar y personalizar las máquinas virtuales en el momento del arranque usando PowerShell y Cloud-Init.
Esta estrategia optimiza el despliegue, ya que evita reinstalar el sistema operativo desde cero y permite modificar cada nodo (master o worker) en función de su rol.
Os explicamos como lo podemos hacer:
- Descargamos la imagen oficial de Debian Cloud (Qcow2 o Raw), lo podéis hacer vía comando o directamente con la URL:
- wget https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2
- Convierte la imagen a formato VHDX (para Hyper-V) con qemu-img:
- qemu-img convert -f qcow2 -O vhdx debian-12-genericcloud-amd64.qcow2 debian-template.vhdx
- Crea una VM en Hyper-V con el disco
debian-template.vhdx
y Cloud-Init activado. - Configura SSH y Cloud-Init en la plantilla:
- apt update && apt install -y cloud-init
systemctl enable cloud-init
- cloud-init clean
Crea el archivo
/etc/cloud/cloud.cfg.d/99-hyperv.cfg
y añade:datasource_list: [NoCloud, None]
- apt update && apt install -y cloud-init
- Apaga la máquina y conviértela en una plantilla de solo lectura:
- Set-VM -Name "Debian-Template" -CheckpointType Disabled
Script Powershell para generar plantilla de VM en Hyper-V 5w1z6y
- Opcionalmente, podéis usar un script de powershell para generarla una vez parametrizada:
PowerShell: Script para Crear la Infraestructura 4o4e1e
El siguiente script, automatiza la creación del clúster Kubernetes generando las máquinas virtuales (1 Master y 2 Workers), configurando redes y preparando los nodos para Kubernetes:
# ========================
# CONFIGURACIÓN DEL SCRIPT
# Definimos variables de configuración
# ========================
# Variables de configuración
$VMSwitchName = "K8S-External-Network"
$VMPath = "D:\Hyper-V"
$CloudInitPath = "$VMPath\CloudInit"
$TemplateVHD = "$VMPath\Templates\debian-template.vhdx"
$OscdimgPath = "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg\oscdimg.exe"
# Validar si oscdimg.exe existe
if (!(Test-Path $OscdimgPath)) {
Write-Host "Error: oscdimg.exe no encontrado en $OscdimgPath. Instala el Windows ADK."
exit
}
# Crear directorio de Cloud-Init si no existe
if (!(Test-Path $CloudInitPath)) {
Write-Host "Creando directorio de Cloud-Init..."
New-Item -ItemType Directory -Path $CloudInitPath | Out-Null
}
# ========================
# SOLICITAR DATOS AL
# Pide un y contraseña para las VMs
# ========================
$name = Read-Host "Introduce el nombre de para los nodos"
$ = Read-Host "Introduce la contraseña para los nodos" -AsSecureString
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($)
$Plain = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
# Generar clave SSH si no existe
$SSHKeyPath = "$env:PROFILE\.ssh\id_rsa"
if (!(Test-Path $SSHKeyPath)) {
Write-Host "Generando clave SSH..."
ssh-keygen -t rsa -b 4096 -N "" -f $SSHKeyPath
}
$SSHKeyPub = Get-Content "$SSHKeyPath.pub"
# ========================
# CREAR SWITCH VIRTUAL EXTERNO SI NO EXISTE
# Creamos la red para nuestras VMs
# ========================
if (!(Get-VMSwitch -Name $VMSwitchName -ErrorAction SilentlyContinue)) {
$NetAdapter = (Get-NetAdapter | Where-Object { $_.Status -eq 'Up' } | Select-Object -ExpandProperty Name -First 1)
if ($NetAdapter) {
Write-Host "Creando switch virtual externo: $VMSwitchName en $NetAdapter"
New-VMSwitch -Name $VMSwitchName -NetAdapterName $NetAdapter -AllowManagementOS $true
} else {
Write-Host "Error: No se encontró un adaptador de red activo."
exit
}
}
# ========================
# CREAR LAS VMs Y CONFIGURAR CLOUD-INIT
# Definimos las características de las VMs y los ficheros para Cloud-Init
# ========================
$VMs = @(
@{ Name = "K8S-Master"; RAM = 4GB; U = 2; Role = "master"; IP = "192.168.2.120" },
@{ Name = "K8S-Worker1"; RAM = 3GB; U = 2; Role = "worker"; IP = "192.168.2.121" },
@{ Name = "K8S-Worker2"; RAM = 3GB; U = 2; Role = "worker"; IP = "192.168.2.122" }
)
foreach ($VM in $VMs) {
$VHDPath = "$VMPath\$($VM.Name).vhdx"
$CloudISO = "$CloudInitPath\$($VM.Name)-Config.iso"
if (Get-VM -Name $VM.Name -ErrorAction SilentlyContinue) {
Write-Host "La máquina virtual $($VM.Name) ya existe. Omitiendo..."
continue
}
Write-Host "Creando VM: $($VM.Name)"
Copy-Item -Path $TemplateVHD -Destination $VHDPath -Force
# ========================
# GENERAR ARCHIVOS DE CLOUD-INIT
# ========================
Write-Host "Generando archivos de Cloud-Init para $($VM.Name)..."
# Meta-Data
$MetaData = @"
instance-id: $($VM.Name)
local-hostname: $($VM.Name)
"@
$MetaData | Set-Content -Path "$CloudInitPath\meta-data" -Encoding UTF8
# -Data
$Data = @"
#cloud-config
s:
- default
- name: ${name}
sudo: ALL=(ALL) NOWD:ALL
shell: /bin/bash
ssh_authorized_keys:
- ${SSHKeyPub}
ssh_import_id:
- gh:${name}
lock_wd: false
wd: "${Plain}"
chwd: { expire: false }
groups: sudo, s
home: /home/${name}
chwd:
list: |
root:${Plain}
${name}:${Plain}
expire: false
ssh_pwauth: true
disable_root: false
runcmd:
- sudo apt-get update
- sudo apt-get install -y qemu-guest-agent curl openssh-server net-tools
- sudo systemctl enable --now qemu-guest-agent
- sudo mkdir -p /home/${name}/.ssh
- echo "${SSHKeyPub}" | sudo tee /home/${name}/.ssh/authorized_keys
- sudo chown -R ${name}:${name} /home/${name}/.ssh
- sudo chmod 700 /home/${name}/.ssh
- sudo chmod 600 /home/${name}/.ssh/authorized_keys
- echo "PermitRoot yes" | sudo tee -a /etc/ssh/sshd_config
- echo "Authentication yes" | sudo tee -a /etc/ssh/sshd_config
- echo "Allows ${name}" | sudo tee -a /etc/ssh/sshd_config
- sudo systemctl restart sshd
- sudo cloud-init clean
"@
$Data | Set-Content -Path "$CloudInitPath\-data" -Encoding UTF8
# Configuración de IP estática en la LAN
$NetworkConfig = @"
version: 2
ethernets:
eth0:
addresses:
- $($VM.IP)/24
gateway4: 192.168.2.69
nameservers:
addresses:
- 8.8.8.8
- 1.1.1.1
"@
$NetworkConfig | Set-Content -Path "$CloudInitPath\network-config" -Encoding UTF8
# ========================
# GENERAR ISO DE CLOUD-INIT
# ========================
Write-Host "Generando ISO de Cloud-Init para $($VM.Name)..."
Start-Process -FilePath $OscdimgPath `
-ArgumentList "-d -m `"$CloudInitPath`" `"$CloudISO`"" `
-NoNewWindow -Wait
if (!(Test-Path $CloudISO)) {
Write-Host "ERROR: No se pudo generar el archivo Cloud-Init ISO en $CloudISO"
exit
}
# ========================
# CREAR VM
# ========================
New-VM -Name $VM.Name -MemoryStartupBytes $VM.RAM -Generation 2 `
-VHDPath $VHDPath -SwitchName $VMSwitchName
Set-VMProcessor -VMName $VM.Name -Count $VM.U
Set-VMMemory -VMName $VM.Name -DynamicMemoryEnabled $true `
-MinimumBytes 512MB -MaximumBytes 8GB
Add-VMDvdDrive -VMName $VM.Name
Set-VMDvdDrive -VMName $VM.Name -Path $CloudISO
# Configurar firmware
Set-VMFirmware -VMName $VM.Name -EnableSecureBoot Off
$HardDrive = Get-VMHardDiskDrive -VMName $VM.Name
Set-VMFirmware -VMName $VM.Name -BootOrder $HardDrive
# Iniciar VM
Start-VM -Name $VM.Name
Start-Sleep -Seconds 10
}
# ========================
# VALIDACIÓN DE RED
# Espera 60 segundos para obtener IP
# ========================
Write-Host "Esperando que las VMs obtengan IP..."
Start-Sleep -Seconds 60
Write-Host "Comprobando IPs de las VMs..."
foreach ($VM in $VMs) {
$VMIP = (Get-VMNetworkAdapter -VMName $VM.Name).IPAddresses
if ($VMIP) {
Write-Host "$($VM.Name) tiene la IP: $VMIP"
} else {
Write-Host "ERROR: $($VM.Name) sigue sin IP."
}
}
# ========================
# VALIDACIÓN DE CLOUD-INIT Y SSH
# ========================
Write-Host "Esperando que Cloud-Init termine en $($VM.Name)..."
Start-Sleep -Seconds 120 # Espera inicial antes de validar
Write-Host "Verificando conectividad con ${VM.IP}..."
$pingTest = Test-Connection -ComputerName $VM.IP -Count 2 -Quiet
if (-not $pingTest) {
Write-Host "No se pudo hacer ping a ${VM.IP}. Revisa la configuración de red."
continue
}
Write-Host "Intentando SSH a $($VM.Name) en ${VM.IP}..."
for ($i=1; $i -le 5; $i++) {
$SSHTest = ssh -o "StrictHostKeyChecking=no" -o "ConnectTimeout=5" "$name@${VM.IP}" "echo 'SSH funcionando'"
if ($SSHTest -match "SSH funcionando") {
Write-Host "SSH funcionando en $($VM.Name)."
break
} else {
Write-Host "Intento $i No se pudo acceder por SSH a $($VM.Name). Reintentando..."
Start-Sleep -Seconds 10
}
}
}
# ========================
# VALIDACIÓN DE CLUSTER KUBERNETES
# Validamos que el cluster Kubernetes está bien creado
# ========================
Write-Host "Validando el clúster Kubernetes..."
$MasterVM = "K8S-Master"
$K8SStatus = Invoke-Command -VMName $MasterVM -ScriptBlock {
if (Test-Path "/etc/kubernetes/.conf") {
$Status = kubectl get nodes --no-headers | ForEach-Object { $_ -match ' Ready ' }
if ($Status) {
return "OK"
} else {
return "ERROR"
}
} else {
return "ERROR"
}
}
if ($K8SStatus -eq "OK") {
Write-Host "Kubernetes está funcionando correctamente en el nodo master."
} else {
Write-Host "ERROR: Kubernetes no está correctamente configurado en el nodo master."
}
Write-Host "¡Clúster Kubernetes desplegado exitosamente!"
Ejecución Script Powershell 6n6v2u
Ejecuta PowerShell como y lanza el script de la siguiente forma:
Set-ExecutionPolicy By -Scope Process -Force
O lanzamos la aplicación Powershell_ISE o la consola de Powershell como :
Ejecutamos script, que irá haciendo varias validaciones:
.\Deploy-KubernetesCluster.ps1
Veremos como se van generando cada fichero de cloud-init:
Si todo ha ido correctamente, podréis ver las máquinas que irán arrancando una a una y el conmutador virtual creados:
Podremos acceder a cada máquina, ya sea vía SSH como vía consola:
Y comprobar el estado de los nodos:
kubernetes@K8S-Master:~$ kubectl get node
NAME STATUS ROLES AGE VERSION
K8S-Master Ready master 6d v1.32.115
K8S-Worker1 Ready 7m7s v1.32.115
K8S-Worker2 Ready 6d v1.32.115
Conclusión: La automatización de procesos ahorra trabajo y fallos 2p722f
La automatización de procesos permite optimizar el tiempo y reducir la posibilidad de errores humanos. Al implementar soluciones automatizadas, se mejora la eficiencia, se minimizan fallos y se garantiza una mayor precisión en las tareas repetitivas. Esto no solo ahorra trabajo, sino que también facilita la gestión y el mantenimiento de sistemas complejos.
Fin del Artículo. ¡Cuéntanos algo en los Comentarios!