611 lines
16 KiB
Markdown
611 lines
16 KiB
Markdown
# Guía de instalación K8s + KubeVirt en Ubuntu 24.04
|
|
|
|
## 0. Ejemplo de configuración de red (Netplan)
|
|
|
|
Aquí defines cómo se conectará tu servidor físicamente a la red: enlaces redundantes (bonding), VLANs para separar tráfico y bridges para que las máquinas virtuales y pods se conecten a varias redes internas. Es la base para un clúster flexible y segmentado.
|
|
|
|
**Archivo:** `/etc/netplan/50-cloud-init.yaml`
|
|
|
|
```yaml
|
|
network:
|
|
version: 2
|
|
ethernets:
|
|
enp2s0f0np0: {}
|
|
enp2s0f1np1: {}
|
|
bonds:
|
|
bond0:
|
|
interfaces:
|
|
- enp2s0f0np0
|
|
- enp2s0f1np1
|
|
parameters:
|
|
mode: "802.3ad"
|
|
lacp-rate: "fast"
|
|
transmit-hash-policy: "layer3+4"
|
|
vlans:
|
|
bond0.20:
|
|
id: 20
|
|
link: bond0
|
|
dhcp4: no
|
|
bond0.30:
|
|
id: 30
|
|
link: bond0
|
|
addresses:
|
|
- "192.168.3.4/24"
|
|
bond0.40:
|
|
id: 40
|
|
link: bond0
|
|
addresses:
|
|
- "192.168.4.4/24"
|
|
bridges:
|
|
br0:
|
|
interfaces:
|
|
- bond0
|
|
addresses:
|
|
- "192.168.1.14/24"
|
|
nameservers:
|
|
addresses:
|
|
- 192.168.1.1
|
|
- 1.1.1.1
|
|
- 8.8.8.8
|
|
routes:
|
|
- to: "default"
|
|
via: "192.168.1.1"
|
|
parameters:
|
|
stp: false
|
|
forward-delay: 0
|
|
br-servicios:
|
|
interfaces:
|
|
- bond0.20
|
|
addresses:
|
|
- 192.168.200.4/22
|
|
parameters:
|
|
stp: false
|
|
forward-delay: 0
|
|
```
|
|
|
|
*No olvides aplicar cambios con:*
|
|
`sudo netplan apply`
|
|
|
|
---
|
|
|
|
## 1. Prerrequisitos del sistema
|
|
|
|
Hay que partir de un Ubuntu 24.04 actualizado y con permisos de administrador. En este paso instalamos utilidades básicas y configuramos el repositorio oficial de Kubernetes, necesario para instalar sus componentes más adelante.
|
|
|
|
### a) Actualiza el sistema y paquetes básicos
|
|
|
|
```bash
|
|
sudo apt-get update
|
|
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg
|
|
```
|
|
|
|
### b) Añade el repositorio oficial de Kubernetes
|
|
|
|
```bash
|
|
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
|
|
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
|
|
sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg
|
|
sudo chmod 644 /etc/apt/sources.list.d/kubernetes.list
|
|
sudo apt-get update
|
|
```
|
|
### c) Ponerle el nombre correcto al nodo
|
|
```bash
|
|
sudo hostnamectl set-hostname srvfkvmX
|
|
```
|
|
---
|
|
|
|
## 2. Desactiva SWAP (requisito Kubernetes)
|
|
|
|
Kubernetes requiere que el intercambio de memoria (swap) esté desactivado para gestionar los recursos de forma predecible y evitar problemas de rendimiento y estabilidad.
|
|
|
|
```bash
|
|
sudo swapoff -a
|
|
sudo sed -i '/ swap / s/^/#/' /etc/fstab
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Instala containerd (runtime recomendado)
|
|
|
|
containerd es el motor que gestiona los contenedores en el clúster. Kubernetes necesita un “runtime” para crear y controlar los pods, y containerd es la opción oficial y más estable.
|
|
|
|
```bash
|
|
sudo apt-get install -y containerd
|
|
sudo mkdir -p /etc/containerd
|
|
containerd config default | sudo tee /etc/containerd/config.toml
|
|
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
|
|
sudo systemctl restart containerd
|
|
sudo systemctl enable containerd
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Prepara el kernel y sysctl
|
|
|
|
En este paso se habilitan módulos y parámetros de red necesarios para que Kubernetes gestione correctamente el tráfico entre pods y nodos.
|
|
|
|
```bash
|
|
sudo modprobe overlay
|
|
sudo modprobe br_netfilter
|
|
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
|
|
net.bridge.bridge-nf-call-iptables = 1
|
|
net.ipv4.ip_forward = 1
|
|
net.bridge.bridge-nf-call-ip6tables = 1
|
|
EOF
|
|
sudo sysctl --system
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Instala kubeadm, kubelet, kubectl
|
|
|
|
Aquí se instalan los tres componentes esenciales de Kubernetes:
|
|
|
|
* kubelet: agente que corre en cada nodo y gestiona los pods
|
|
* kubeadm: herramienta para iniciar y gestionar el clúster
|
|
* kubectl: cliente de línea de comandos para operar el clúster
|
|
|
|
```bash
|
|
sudo apt-get install -y kubelet kubeadm kubectl
|
|
sudo apt-mark hold kubelet kubeadm kubectl
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Inicializa el clúster (mononodo/laboratorio)
|
|
|
|
Este paso crea el clúster de Kubernetes en el nodo principal (control-plane). Aquí defines la red interna para los pods.
|
|
|
|
> Si usas Flannel, usa este parámetro:
|
|
|
|
```bash
|
|
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
|
|
```
|
|
|
|
---
|
|
|
|
### a) Configura kubectl para tu usuario
|
|
|
|
Permite usar el comando `kubectl` como usuario normal copiando la configuración de administración del clúster a tu carpeta personal.
|
|
|
|
```bash
|
|
mkdir -p $HOME/.kube
|
|
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
|
|
sudo chown $(id -u):$(id -g) $HOME/.kube/config
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Instala la red de pods (Flannel)
|
|
|
|
Kubernetes solo define la infraestructura; necesitas un complemento de red (CNI) para que los pods puedan comunicarse entre sí. Flannel es la opción más sencilla y compatible.
|
|
|
|
```bash
|
|
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
|
|
```
|
|
|
|
---
|
|
|
|
## 8. Instala Multus (opcional, para múltiples redes)
|
|
|
|
Multus permite que un pod tenga más de una interfaz de red, útil para aplicaciones avanzadas (firewalls, balanceadores, appliances virtuales). Instálalo solo si necesitas múltiples redes.
|
|
|
|
```bash
|
|
kubectl apply -f https://raw.githubusercontent.com/k8snetworkplumbingwg/multus-cni/master/deployments/multus-daemonset.yml
|
|
```
|
|
|
|
* Verifica:
|
|
|
|
```bash
|
|
kubectl get pods -n kube-system | grep multus
|
|
```
|
|
|
|
---
|
|
|
|
## 9. (Opcional) Quita el taint del nodo master para poder programar pods en él
|
|
|
|
Por defecto, Kubernetes no programa pods de usuario en el nodo principal (control-plane). Si tienes solo un nodo (laboratorio), elimina este bloqueo para poder desplegar aplicaciones ahí.
|
|
|
|
```bash
|
|
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
|
|
kubectl taint nodes --all node-role.kubernetes.io/master-
|
|
```
|
|
|
|
---
|
|
|
|
## 10. Test rápido de Multus
|
|
|
|
Aquí puedes comprobar que Multus funciona: se crea una red secundaria y un pod de prueba que recibe dos interfaces (una para la red de pods y otra para la red adicional configurada).
|
|
|
|
La carpeta `multus/` del repositorio contiene el NAD y el pod de prueba:
|
|
|
|
* `multus/nad-br-servicios.yaml` (NetworkAttachmentDefinition)
|
|
* `multus/test-multus-pod.yaml` (pod alpine)
|
|
|
|
**Despliega la NAD:**
|
|
|
|
```bash
|
|
kubectl apply -f multus/nad-br-servicios.yaml
|
|
```
|
|
|
|
**Despliega el pod de test:**
|
|
|
|
```bash
|
|
kubectl apply -f multus/test-multus-pod.yaml
|
|
```
|
|
|
|
Comprueba las interfaces:
|
|
|
|
```bash
|
|
kubectl exec -it multus-test -- sh
|
|
ip a
|
|
```
|
|
|
|
El pod debería tener una interfaz extra de la red `br-servicios` además de la de Flannel.
|
|
|
|
Para limpiar:
|
|
|
|
```bash
|
|
kubectl delete pod multus-test
|
|
```
|
|
|
|
---
|
|
|
|
## 11. Instalación y configuración de MetalLB (LoadBalancer local)
|
|
|
|
MetalLB permite a tu clúster on-premise asignar IPs flotantes de tu red LAN a servicios tipo `LoadBalancer`, igual que hacen los clústeres en la nube. Es necesario si quieres exponer servicios (ingress, dashboards, etc.) con una IP accesible desde tu red.
|
|
|
|
### a) Instala MetalLB
|
|
|
|
```bash
|
|
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml
|
|
```
|
|
|
|
Esto crea el namespace `metallb-system` y despliega los pods necesarios.
|
|
|
|
---
|
|
|
|
### b) Crea la configuración del pool de IPs
|
|
|
|
Aquí defines qué rango de IPs puede repartir MetalLB dentro de tu red local. Estos archivos suelen estar versionados en la carpeta `metallb/` del repositorio.
|
|
|
|
```shell
|
|
metallb/
|
|
├── ipaddresspool.yaml
|
|
├── l2advertisement.yaml
|
|
└── kustomization.yaml
|
|
```
|
|
|
|
**Para aplicar:**
|
|
|
|
```bash
|
|
kubectl apply -k metallb/
|
|
```
|
|
|
|
---
|
|
|
|
### c) Uso de MetalLB
|
|
|
|
A partir de aquí, cualquier Service tipo LoadBalancer obtiene una IP flotante LAN automáticamente.
|
|
|
|
**Ejemplo mínimo de Service:**
|
|
|
|
```yaml
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: ejemplo
|
|
spec:
|
|
selector:
|
|
app: ejemplo
|
|
ports:
|
|
- port: 80
|
|
targetPort: 80
|
|
type: LoadBalancer
|
|
```
|
|
|
|
Verás la IP asignada en la columna `EXTERNAL-IP` al ejecutar:
|
|
|
|
```bash
|
|
kubectl get svc
|
|
```
|
|
|
|
Puedes acceder desde tu red local a esa IP.
|
|
|
|
---
|
|
|
|
## 12. Instalación de Traefik y cert-manager (Ingress + TLS)
|
|
|
|
Traefik actúa como el "router" de aplicaciones dentro de tu clúster, permitiendo exponer servicios a Internet o la red local de forma sencilla. cert-manager se encarga de gestionar certificados TLS automáticamente para que tus aplicaciones estén siempre seguras.
|
|
|
|
### a) Instala Traefik como Ingress Controller
|
|
|
|
* Aplica todos los recursos con Kustomize:
|
|
|
|
```bash
|
|
kubectl apply -k traefik/
|
|
```
|
|
|
|
* Comprueba que MetalLB asigna una IP al Service principal:
|
|
|
|
```bash
|
|
kubectl get pods -n traefik
|
|
kubectl get svc -n traefik
|
|
```
|
|
|
|
### b) Instala cert-manager
|
|
|
|
* Crea el namespace:
|
|
|
|
```bash
|
|
kubectl apply -f cert-manager/namespace.yaml
|
|
```
|
|
|
|
* Aplica el manifiesto oficial de cert-manager:
|
|
|
|
```bash
|
|
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
|
|
```
|
|
|
|
* Crea los `ClusterIssuer` para staging y producción:
|
|
|
|
```bash
|
|
kubectl apply -f cert-manager/clusterissuer-staging.yaml
|
|
kubectl apply -f cert-manager/clusterissuer-prod.yaml
|
|
```
|
|
|
|
* Comprueba los pods:
|
|
|
|
```bash
|
|
kubectl get pods -n cert-manager
|
|
```
|
|
|
|
---
|
|
|
|
## 13. Instala KubeVirt y CDI
|
|
|
|
KubeVirt permite crear y gestionar máquinas virtuales dentro de Kubernetes, integrando cargas virtualizadas junto a contenedores. CDI (Containerized Data Importer) facilita la gestión y carga de discos e ISOs para esas VMs.
|
|
|
|
**Nota:** Puedes usar manifiestos oficiales, o crear tu carpeta kubevirt/ si deseas versionar los YAML personalizados.
|
|
|
|
```bash
|
|
# Instala KubeVirt (recomendado hacerlo tras tener la red y almacenamiento)
|
|
export KUBEVIRT_VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases/latest | grep tag_name | cut -d '"' -f 4)
|
|
kubectl create namespace kubevirt
|
|
kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-operator.yaml
|
|
kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-cr.yaml
|
|
|
|
# Instala CDI (para gestión de discos/ISOs)
|
|
export CDI_VERSION=$(curl -s https://api.github.com/repos/kubevirt/containerized-data-importer/releases/latest | grep tag_name | cut -d '"' -f 4)
|
|
kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/${CDI_VERSION}/cdi-operator.yaml
|
|
kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/${CDI_VERSION}/cdi-cr.yaml
|
|
```
|
|
|
|
---
|
|
|
|
## 14. Instala virtctl (CLI de KubeVirt)
|
|
|
|
virtctl es una herramienta de línea de comandos para interactuar fácilmente con las máquinas virtuales de KubeVirt: arranque, apagado, consola, etc.
|
|
|
|
```bash
|
|
curl -L -o virtctl https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/virtctl-${KUBEVIRT_VERSION}-linux-amd64
|
|
chmod +x virtctl
|
|
sudo mv virtctl /usr/local/bin/
|
|
```
|
|
|
|
---
|
|
|
|
## 15. Habilita KVM para tu usuario
|
|
|
|
Para poder crear y gestionar máquinas virtuales, tu usuario debe pertenecer al grupo `kvm` (acceso al hardware de virtualización).
|
|
|
|
```bash
|
|
sudo usermod -aG kvm $(whoami)
|
|
# Reinicia sesión o ejecuta 'newgrp kvm' para aplicar
|
|
```
|
|
|
|
---
|
|
|
|
## 16. Despliega kubevirt-manager
|
|
|
|
kubevirt-manager es una interfaz web sencilla para gestionar tus máquinas virtuales desde el navegador. Esta sección aplica sus manifiestos en Kubernetes.
|
|
|
|
La carpeta `kubevirt-manager/` contiene todos los manifiestos organizados por tipo:
|
|
|
|
```bash
|
|
kubectl apply -k kubevirt-manager/
|
|
```
|
|
|
|
Puedes comprobar el estado:
|
|
|
|
```bash
|
|
kubectl get pods -n kubevirt-manager
|
|
```
|
|
|
|
---
|
|
|
|
## 17. Despliega el stack de almacenamiento NFS
|
|
|
|
Esta sección despliega tanto el servidor NFS (almacenamiento en red) como el "provisioner" para que Kubernetes pueda crear volúmenes dinámicos de manera automática. Es la forma más sencilla de tener almacenamiento persistente en el clúster.
|
|
|
|
La carpeta `storage/` tiene todos los manifiestos del servidor y provisioner NFS, organizados en subcarpetas:
|
|
|
|
```bash
|
|
kubectl apply -k storage/
|
|
```
|
|
|
|
Puedes comprobar el estado:
|
|
|
|
```bash
|
|
kubectl get pods -n nfs-provisioner
|
|
```
|
|
|
|
* Instala el cliente NFS en el nodo:
|
|
|
|
```bash
|
|
sudo apt install nfs-common
|
|
```
|
|
|
|
---
|
|
|
|
# 12. Instalación de Traefik y cert-manager (Ingress + TLS)
|
|
|
|
Traefik actúa como router de aplicaciones dentro de tu clúster, exponiendo servicios HTTP/HTTPS en LAN o Internet. Cert-manager se encarga de gestionar automáticamente los certificados TLS (Let's Encrypt, CA propia, etc.), pero también puedes usar un certificado comprado (wildcard) y aplicarlo a múltiples dominios.
|
|
|
|
---
|
|
|
|
## a) Instala Traefik como Ingress Controller
|
|
|
|
1. Prepara tu carpeta de manifiestos (`traefik/`) con recursos desglosados:
|
|
|
|
* Namespace, ServiceAccount, RBAC
|
|
* Deployment o DaemonSet (según tu preferencia)
|
|
* Service tipo `LoadBalancer` (usará MetalLB)
|
|
* IngressClass (si lo quieres explícito)
|
|
* ConfigMap con parámetros de Traefik
|
|
|
|
2. Aplica los manifiestos con Kustomize:
|
|
|
|
```bash
|
|
kubectl apply -k traefik/
|
|
```
|
|
|
|
3. Comprueba el estado y la IP asignada:
|
|
|
|
```bash
|
|
kubectl get pods -n traefik
|
|
kubectl get svc -n traefik
|
|
```
|
|
|
|
* El Service principal (`traefik` o `traefik-lb`) debería tener una IP del pool de MetalLB (`EXTERNAL-IP`).
|
|
|
|
---
|
|
|
|
## b) Instala cert-manager (opcional si solo usas certificados propios)
|
|
|
|
1. Crea el namespace:
|
|
|
|
```bash
|
|
kubectl apply -f cert-manager/namespace.yaml
|
|
```
|
|
|
|
2. Aplica el manifiesto oficial de cert-manager:
|
|
|
|
```bash
|
|
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
|
|
```
|
|
|
|
3. (Opcional) Crea los ClusterIssuer para Let's Encrypt (staging y producción):
|
|
|
|
```bash
|
|
kubectl apply -f cert-manager/clusterissuer-staging.yaml
|
|
kubectl apply -f cert-manager/clusterissuer-prod.yaml
|
|
```
|
|
|
|
4. Comprueba los pods:
|
|
|
|
```bash
|
|
kubectl get pods -n cert-manager
|
|
```
|
|
|
|
* Espera a que estén todos en estado `Running`.
|
|
|
|
---
|
|
|
|
## c) **¿Cómo usar un certificado SSL wildcard comprado?**
|
|
|
|
Si has adquirido un certificado wildcard (ej: `*.miempresa.com`) y tienes el `.crt` (certificado), `.key` (clave privada) y, opcionalmente, el CA bundle:
|
|
|
|
1. **Crea un Secret TLS en el namespace donde están tus Ingress:**
|
|
|
|
```bash
|
|
kubectl -n traefik create secret tls wildcard-cert \
|
|
--cert=certificado_wildcard.crt \
|
|
--key=clave_wildcard.key
|
|
```
|
|
|
|
* Si necesitas añadir la cadena de CA, concaténala al `.crt`:
|
|
|
|
```bash
|
|
cat wildcard.crt ca-bundle.crt > fullchain.crt
|
|
kubectl -n traefik create secret tls wildcard-cert --cert=fullchain.crt --key=clave.key
|
|
```
|
|
|
|
2. **Referéncialo en tus Ingress:**
|
|
|
|
```yaml
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: ejemplo-wildcard
|
|
namespace: traefik
|
|
spec:
|
|
ingressClassName: traefik
|
|
tls:
|
|
- hosts:
|
|
- app1.miempresa.com
|
|
- app2.miempresa.com
|
|
secretName: wildcard-cert
|
|
rules:
|
|
- host: app1.miempresa.com
|
|
http:
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: servicio1
|
|
port:
|
|
number: 80
|
|
- host: app2.miempresa.com
|
|
http:
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: servicio2
|
|
port:
|
|
number: 80
|
|
```
|
|
|
|
* Todos los Ingress que referencien `secretName: wildcard-cert` usarán ese mismo certificado SSL, y funcionarán para todos los subdominios cubiertos por el wildcard.
|
|
|
|
---
|
|
|
|
## d) ¿Dónde se guardan los certificados en Kubernetes?
|
|
|
|
Los certificados (wildcard, Let's Encrypt, CA propia…) se almacenan como objetos `Secret` de tipo `kubernetes.io/tls` en el namespace correspondiente. No están en disco ni en ninguna ruta específica del pod o nodo. Traefik accede al Secret por nombre, a través de la API de Kubernetes.
|
|
|
|
Puedes ver los secrets así:
|
|
|
|
```bash
|
|
kubectl get secrets -n traefik
|
|
```
|
|
|
|
El contenido real está en la base de datos interna de Kubernetes (etcd).
|
|
|
|
---
|
|
|
|
## e) **Cómo crear un Secret TLS a partir de tus archivos de certificado**
|
|
|
|
Para cualquier certificado SSL (wildcard, multiSAN, CA interna, etc.), el comando general es:
|
|
|
|
```bash
|
|
kubectl -n <namespace> create secret tls <nombre-del-secret> \
|
|
--cert=certificado.crt \
|
|
--key=clave.key
|
|
```
|
|
|
|
* `<namespace>`: donde esté el Ingress (ejemplo: `traefik`)
|
|
* `<nombre-del-secret>`: el que quieras (ejemplo: `wildcard-cert`)
|
|
* `--cert`: debe incluir el certificado y, opcionalmente, la cadena completa de CA (fullchain)
|
|
* `--key`: la clave privada
|
|
|
|
**¿Qué hace este comando?**
|
|
|
|
* Sube el contenido de los archivos al clúster y crea un objeto `Secret` de tipo `kubernetes.io/tls`.
|
|
* Kubernetes lo guarda cifrado en etcd y lo inyecta a los pods/controllers cuando un Ingress lo solicita.
|
|
|
|
---
|