Primer commit
This commit is contained in:
109
docs/arquitectura.md
Normal file
109
docs/arquitectura.md
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
# 🏗️ Arquitectura del clúster K3s
|
||||||
|
|
||||||
|
Este documento describe la arquitectura del clúster Kubernetes desplegado con K3s, su distribución de roles, y los componentes principales.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧱 Nodos y roles
|
||||||
|
|
||||||
|
### 🖥️ tartaro (192.168.1.7)
|
||||||
|
- Rol: Control plane principal
|
||||||
|
- Prioridad Keepalived: MASTER
|
||||||
|
- Ejecuta:
|
||||||
|
- K3s (cluster-init)
|
||||||
|
- Ingress Controller
|
||||||
|
- cert-manager
|
||||||
|
- Gitea
|
||||||
|
- Argo CD
|
||||||
|
- App of Apps
|
||||||
|
- Guacamole
|
||||||
|
- KubeVirt Operator
|
||||||
|
- VS Code Server
|
||||||
|
- Servicios principales del clúster
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🖥️ styx (192.168.1.8)
|
||||||
|
- Rol: Segundo nodo control plane
|
||||||
|
- Prioridad Keepalived: BACKUP
|
||||||
|
- Ejecuta:
|
||||||
|
- K3s (join al control plane)
|
||||||
|
- Ingress Controller (DaemonSet)
|
||||||
|
- Réplicas de servicios distribuidos
|
||||||
|
- Nodo tolerante a caída del master
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🖥️ niflheim (192.168.1.10)
|
||||||
|
- Rol: Nodo dedicado a almacenamiento y tareas pesadas
|
||||||
|
- Taint: `storage=only:NoSchedule`
|
||||||
|
- Ejecuta:
|
||||||
|
- K3s (con taint para evitar pods no relacionados)
|
||||||
|
- ZFS + NFS server
|
||||||
|
- NFS client provisioner
|
||||||
|
- Volúmenes persistentes para el resto del clúster
|
||||||
|
- ISO server (para KubeVirt)
|
||||||
|
- Posibles futuras tareas de backup, observabilidad, etc.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔁 Alta disponibilidad
|
||||||
|
|
||||||
|
Se implementa con:
|
||||||
|
- **Bonding de red**: Interfaz `bond0` en todos los nodos.
|
||||||
|
- **IP virtual (192.168.1.9)** gestionada por `keepalived`.
|
||||||
|
- Redirección de puertos 80/443 desde el router a esta IP.
|
||||||
|
- Ingress Controller desplegado como `DaemonSet` para disponibilidad inmediata en todos los nodos.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧱 Almacenamiento
|
||||||
|
|
||||||
|
- **Backend principal**: ZFS pool `k8spool/k8s` montado en `/mnt/storage/k8s` (en niflheim).
|
||||||
|
- **NFS server** exporta este almacenamiento a todos los nodos.
|
||||||
|
- **nfs-subdir-external-provisioner** permite provisión dinámica de volúmenes desde Kubernetes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔐 TLS e Ingress
|
||||||
|
|
||||||
|
- **cert-manager** gestiona certificados con Let's Encrypt.
|
||||||
|
- **Ingress-NGINX** funciona como controlador de entrada.
|
||||||
|
- TLS completamente automatizado.
|
||||||
|
- Ingress de cada aplicación define el hostname correspondiente.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🌀 GitOps
|
||||||
|
|
||||||
|
- **Gitea** aloja todos los manifiestos como repositorios individuales.
|
||||||
|
- **Argo CD** sincroniza automáticamente los repositorios con el clúster.
|
||||||
|
- **App of Apps** en `k8s-master` gestiona la orquestación general.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🖥️ Virtualización
|
||||||
|
|
||||||
|
- **KubeVirt** permite ejecutar VMs dentro de Kubernetes.
|
||||||
|
- **CDI (Containerized Data Importer)** permite importar imágenes ISO.
|
||||||
|
- **ISO Server** expone imágenes desde NFS o HTTP.
|
||||||
|
- **Guacamole** permite acceso remoto vía navegador a VMs (VNC, RDP, SSH).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Herramientas de soporte
|
||||||
|
|
||||||
|
- **VS Code Server** accesible por navegador para edición remota en el clúster.
|
||||||
|
- **Scripts auxiliares** en la carpeta `docs/` para gestión de repositorios.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧪 Recomendaciones
|
||||||
|
|
||||||
|
- Etiquetar nodos con `kubectl label node <node> <key>=<value>`
|
||||||
|
- Usar `taints` para separar roles claramente
|
||||||
|
- Separar StorageClass por aplicación si se desea control granular
|
||||||
|
- Automatizar despliegue con Argo CD y sincronización automática
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
60
docs/direccionamiento.md
Normal file
60
docs/direccionamiento.md
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
# ⚔️ Valhalla Cluster - Homelab Personal (Infraestructura Actual)
|
||||||
|
|
||||||
|
## 📊 Tabla de Direccionamiento y VLANes
|
||||||
|
|
||||||
|
### 🌐 Segmentación por VLANes
|
||||||
|
|
||||||
|
| VLAN | Rango IP | Nombre | Uso principal |
|
||||||
|
|:-----|:-------------------|:-------------------|:--------------|
|
||||||
|
| VLAN 1 | 192.168.1.0/24 | Administración y acceso exterior | Gestión de infraestructura, acceso a Kubernetes, tráfico externo |
|
||||||
|
| VLAN 30 | 192.168.3.0/24 | Almacenamiento | Tráfico dedicado de almacenamiento NFS (sobre volúmenes ZFS replicados) |
|
||||||
|
| VLAN 40 | 192.168.4.0/24 | Tráfico Interno Kubernetes | Comunicación interna entre nodos Kubernetes (API Server, etcd, servicios internos) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📡 Diseño de Red y Resolución de Nombres
|
||||||
|
|
||||||
|
- **Puerta de enlace principal**: 192.168.1.1 (Router Ubiquiti).
|
||||||
|
- **DNS interno**: CoreDNS desplegado en Kubernetes.
|
||||||
|
- **DNS externos**: Cloudflare (1.1.1.1) y Google (8.8.8.8).
|
||||||
|
- **Almacenamiento**: Exportado vía NFS desde Niflheim (ZFS RAID10), replicado a futuro hacia Gehena mediante `zfs send/receive`.
|
||||||
|
- **Alta Disponibilidad de Almacenamiento**: IP flotante `192.168.3.10` en VLAN 30 gestionada por Keepalived.
|
||||||
|
- **Alta Disponibilidad del Control Plane**: IP flotante `192.168.1.9` en VLAN 1 gestionada por Keepalived.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧭 Tabla de Direccionamiento por Dispositivo
|
||||||
|
|
||||||
|
## 🧭 Tabla de Direccionamiento por Dispositivo
|
||||||
|
|
||||||
|
| Dispositivo | VLAN 1 (Admin/Acceso) | VLAN 30 (Storage) | VLAN 40 (Internode) | Observaciones |
|
||||||
|
|:----------------------------|:----------------------|:------------------|:--------------------|:--------------|
|
||||||
|
| Router Ubiquiti | 192.168.1.1 | — | — | Puerta de enlace principal |
|
||||||
|
| Switch QNAP 10GbE | 192.168.1.2 | — | — | Switch principal de 10Gbps |
|
||||||
|
| Switch MikroTik | 192.168.1.3 | — | — | Switch auxiliar / expansión |
|
||||||
|
| iLO de Niflheim | 192.168.1.4 | — | — | Gestión remota de servidor |
|
||||||
|
| iLO de Gehena | 192.168.1.5 | — | — | Gestión remota futuro nodo |
|
||||||
|
| IP Virtual Keepalived CP | 192.168.1.10 | — | — | IP flotante Kubernetes Control Plane |
|
||||||
|
| IP Virtual Keepalived Storage | — | 192.168.3.10 (planificado) | — | IP flotante almacenamiento NFS |
|
||||||
|
| Tartaro (Nodo Kubernetes) | 192.168.1.11 | 192.168.3.1 | 192.168.4.1 | Nodo K3s |
|
||||||
|
| Styx (Nodo Kubernetes) | 192.168.1.12 | 192.168.3.2 | 192.168.4.2 | Nodo K3s |
|
||||||
|
| Niflheim (Storage principal) | 192.168.1.13 | 192.168.3.3 | 192.168.4.3 | Nodo NFS + Provisioner K3s |
|
||||||
|
| Gehena (Futuro) | 192.168.1.14 (planificado) | 192.168.3.4 (planificado) | 192.168.4.4 (planificado) | Segundo nodo de almacenamiento |
|
||||||
|
| Respaldo Tartaro | 192.168.1.20 | — | — | Conexión alternativa de emergencia |
|
||||||
|
| Respaldo Styx | 192.168.1.21 | — | — | Conexión alternativa de emergencia |
|
||||||
|
| Respaldo Niflheim | 192.168.1.22 | — | — | Conexión alternativa de emergencia |
|
||||||
|
| Respaldo Gehena | 192.168.1.23 (planificado) | — | — | Conexión alternativa de emergencia |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔒 Conclusiones
|
||||||
|
|
||||||
|
- **Separación total de tráfico**: tráfico de usuario/API Server, almacenamiento, y comunicación interna de nodos segregados en VLANs independientes.
|
||||||
|
- **Alta disponibilidad** en almacenamiento y control plane mediante Keepalived.
|
||||||
|
- **IP de emergencia configurada** en interfaces físicas sueltas (`enp87s0`) para Tartaro, Styx y Niflheim, asegurando acceso fuera del bonding en caso de fallo.
|
||||||
|
- **Almacenamiento NFS montado sobre ZFS RAID10 replicable** a futuro, asegurando integridad de datos y resiliencia de infraestructura.
|
||||||
|
- Preparado para expansión multi-site mediante VPN y replicación cruzada de almacenamiento.
|
||||||
|
|
||||||
|
---
|
||||||
469
docs/guia-instalacion.md
Normal file
469
docs/guia-instalacion.md
Normal file
@@ -0,0 +1,469 @@
|
|||||||
|
# 📘 Guía de instalación del clúster K3s - Valhalla Cluster
|
||||||
|
|
||||||
|
## 1. Instalar el sistema operativo
|
||||||
|
|
||||||
|
En los tres servidores:
|
||||||
|
|
||||||
|
- Configurar **bond0** como interfaz principal.
|
||||||
|
- Crear un **bridge `br0`** sobre `bond0` para tráfico sin NAT de VLAN 1 (administración y acceso).
|
||||||
|
- Montar **VLAN 30 (almacenamiento)** y **VLAN 40 (internode)**.
|
||||||
|
- Configurar **una interfaz de respaldo** (`enp88s0`, `eno1`, etc.) con IP secundaria en VLAN 1.
|
||||||
|
|
||||||
|
### Asignación de IPs principales:
|
||||||
|
|
||||||
|
| Nodo | VLAN 1 (Administración) | VLAN 30 (Storage) | VLAN 40 (Internode) |
|
||||||
|
|:-----------|:------------------------|:------------------|:--------------------|
|
||||||
|
| tartaro | 192.168.1.11 | 192.168.3.1 | 192.168.4.1 |
|
||||||
|
| styx | 192.168.1.12 | 192.168.3.2 | 192.168.4.2 |
|
||||||
|
| niflheim | 192.168.1.13 | 192.168.3.3 | 192.168.4.3 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📄 Netplan para cada servidor
|
||||||
|
|
||||||
|
### Tartaro (`/etc/netplan/00-installer-config.yaml`):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
network:
|
||||||
|
version: 2
|
||||||
|
ethernets:
|
||||||
|
enp2s0f0np0: {}
|
||||||
|
enp2s0f1np1: {}
|
||||||
|
enp88s0:
|
||||||
|
addresses:
|
||||||
|
- "192.168.1.8/24"
|
||||||
|
bonds:
|
||||||
|
bond0:
|
||||||
|
interfaces:
|
||||||
|
- enp2s0f0np0
|
||||||
|
- enp2s0f1np1
|
||||||
|
parameters:
|
||||||
|
mode: "802.3ad"
|
||||||
|
lacp-rate: "fast"
|
||||||
|
transmit-hash-policy: "layer3+4"
|
||||||
|
vlans:
|
||||||
|
bond0.30:
|
||||||
|
id: 30
|
||||||
|
link: bond0
|
||||||
|
addresses:
|
||||||
|
- "192.168.3.1/24"
|
||||||
|
bond0.40:
|
||||||
|
id: 40
|
||||||
|
link: bond0
|
||||||
|
addresses:
|
||||||
|
- "192.168.4.1/24"
|
||||||
|
bridges:
|
||||||
|
br0:
|
||||||
|
interfaces:
|
||||||
|
- bond0
|
||||||
|
addresses:
|
||||||
|
- "192.168.1.11/24"
|
||||||
|
nameservers:
|
||||||
|
addresses:
|
||||||
|
- 192.168.1.1
|
||||||
|
- 1.1.1.1
|
||||||
|
- 8.8.8.8
|
||||||
|
search: []
|
||||||
|
routes:
|
||||||
|
- to: "default"
|
||||||
|
via: "192.168.1.1"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Styx (`/etc/netplan/00-installer-config.yaml`):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
network:
|
||||||
|
version: 2
|
||||||
|
ethernets:
|
||||||
|
enp2s0f0np0: {}
|
||||||
|
enp2s0f1np1: {}
|
||||||
|
enp88s0:
|
||||||
|
addresses:
|
||||||
|
- "192.168.1.21/24"
|
||||||
|
bonds:
|
||||||
|
bond0:
|
||||||
|
interfaces:
|
||||||
|
- enp2s0f0np0
|
||||||
|
- enp2s0f1np1
|
||||||
|
parameters:
|
||||||
|
mode: "802.3ad"
|
||||||
|
lacp-rate: "fast"
|
||||||
|
transmit-hash-policy: "layer3+4"
|
||||||
|
vlans:
|
||||||
|
bond0.30:
|
||||||
|
id: 30
|
||||||
|
link: bond0
|
||||||
|
addresses:
|
||||||
|
- "192.168.3.2/24"
|
||||||
|
bond0.40:
|
||||||
|
id: 40
|
||||||
|
link: bond0
|
||||||
|
addresses:
|
||||||
|
- "192.168.4.2/24"
|
||||||
|
bridges:
|
||||||
|
br0:
|
||||||
|
interfaces:
|
||||||
|
- bond0
|
||||||
|
addresses:
|
||||||
|
- "192.168.1.12/24"
|
||||||
|
nameservers:
|
||||||
|
addresses:
|
||||||
|
- 192.168.1.1
|
||||||
|
- 1.1.1.1
|
||||||
|
- 8.8.8.8
|
||||||
|
search: []
|
||||||
|
routes:
|
||||||
|
- to: "default"
|
||||||
|
via: "192.168.1.1"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Niflheim (`/etc/netplan/00-installer-config.yaml`):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
network:
|
||||||
|
version: 2
|
||||||
|
ethernets:
|
||||||
|
ens1f0: {}
|
||||||
|
ens1f1: {}
|
||||||
|
eno1:
|
||||||
|
addresses:
|
||||||
|
- "192.168.1.22/24"
|
||||||
|
bonds:
|
||||||
|
bond0:
|
||||||
|
interfaces:
|
||||||
|
- ens1f0
|
||||||
|
- ens1f1
|
||||||
|
parameters:
|
||||||
|
mode: "802.3ad"
|
||||||
|
lacp-rate: "fast"
|
||||||
|
transmit-hash-policy: "layer3+4"
|
||||||
|
vlans:
|
||||||
|
bond0.30:
|
||||||
|
id: 30
|
||||||
|
link: bond0
|
||||||
|
addresses:
|
||||||
|
- "192.168.3.3/24"
|
||||||
|
bond0.40:
|
||||||
|
id: 40
|
||||||
|
link: bond0
|
||||||
|
addresses:
|
||||||
|
- "192.168.4.3/24"
|
||||||
|
bridges:
|
||||||
|
br0:
|
||||||
|
interfaces:
|
||||||
|
- bond0
|
||||||
|
addresses:
|
||||||
|
- "192.168.1.13/24"
|
||||||
|
nameservers:
|
||||||
|
addresses:
|
||||||
|
- 192.168.1.1
|
||||||
|
- 1.1.1.1
|
||||||
|
- 8.8.8.8
|
||||||
|
search: []
|
||||||
|
routes:
|
||||||
|
- to: "default"
|
||||||
|
via: "192.168.1.1"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Preparación básica
|
||||||
|
|
||||||
|
En **todos los servidores**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt update && sudo apt upgrade -y
|
||||||
|
sudo apt install -y keepalived nfs-common
|
||||||
|
```
|
||||||
|
|
||||||
|
> Asegúrate de tener los manifiestos clonados desde Gitea o preparados localmente antes de empezar.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Preparación básica
|
||||||
|
|
||||||
|
En **todos los servidores**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt update && sudo apt upgrade -y
|
||||||
|
sudo apt install -y keepalived nfs-common
|
||||||
|
```
|
||||||
|
|
||||||
|
> Asegúrate de tener los manifiestos clonados desde Gitea o preparados localmente antes de empezar.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Configuración de ZFS en `niflheim`
|
||||||
|
|
||||||
|
1. Instalar ZFS:
|
||||||
|
|
||||||
|
sudo apt install -y zfsutils-linux
|
||||||
|
|
||||||
|
|
||||||
|
2. Crear el pool ZFS con los 4 discos Toshiba (RAID10 con 2 espejos):
|
||||||
|
|
||||||
|
sudo zpool create -o ashift=12 k8spool \
|
||||||
|
mirror /dev/sda /dev/sdb \
|
||||||
|
mirror /dev/sdc /dev/sde
|
||||||
|
|
||||||
|
3. Crear dataset:
|
||||||
|
|
||||||
|
sudo zfs create k8spool/k8s
|
||||||
|
sudo zfs set mountpoint=/mnt/storage/k8s k8spool/k8s
|
||||||
|
sudo zfs set compression=lz4 k8spool/k8s
|
||||||
|
sudo chown nobody:nogroup /mnt/storage/k8s
|
||||||
|
|
||||||
|
4. Verificar:
|
||||||
|
|
||||||
|
sudo zpool status
|
||||||
|
sudo zfs list
|
||||||
|
sudo zfs get compression k8spool/k8s
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Configuración de Keepalived
|
||||||
|
|
||||||
|
En tartaro (MASTER):
|
||||||
|
|
||||||
|
`sudo nano /etc/keepalived/keepalived.conf`
|
||||||
|
|
||||||
|
vrrp_instance VI_1 {
|
||||||
|
state MASTER
|
||||||
|
interface br0
|
||||||
|
virtual_router_id 51
|
||||||
|
priority 150
|
||||||
|
advert_int 1
|
||||||
|
authentication {
|
||||||
|
auth_type PASS
|
||||||
|
auth_pass 42manabo42
|
||||||
|
}
|
||||||
|
virtual_ipaddress {
|
||||||
|
192.168.1.10/24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
En styx (BACKUP):
|
||||||
|
|
||||||
|
`sudo nano /etc/keepalived/keepalived.conf`
|
||||||
|
|
||||||
|
vrrp_instance VI_1 {
|
||||||
|
state BACKUP
|
||||||
|
interface br0
|
||||||
|
virtual_router_id 51
|
||||||
|
priority 100
|
||||||
|
advert_int 1
|
||||||
|
authentication {
|
||||||
|
auth_type PASS
|
||||||
|
auth_pass 42manabo42
|
||||||
|
}
|
||||||
|
virtual_ipaddress {
|
||||||
|
192.168.1.10/24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Después en ambos:
|
||||||
|
|
||||||
|
sudo systemctl enable keepalived
|
||||||
|
sudo systemctl start keepalived
|
||||||
|
|
||||||
|
## 4. Instalar K3s
|
||||||
|
En `tartaro` (control plane principal):
|
||||||
|
|
||||||
|
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--cluster-init --disable traefik \
|
||||||
|
--node-name tartaro \
|
||||||
|
--node-ip 192.168.4.1 \
|
||||||
|
--advertise-address 192.168.4.1 \
|
||||||
|
--tls-san 192.168.1.10 \
|
||||||
|
--tls-san 192.168.1.11 \
|
||||||
|
--write-kubeconfig-mode 644" sh -
|
||||||
|
|
||||||
|
Obtener token:
|
||||||
|
|
||||||
|
sudo cat /var/lib/rancher/k3s/server/node-token
|
||||||
|
|
||||||
|
En `styx` (segundo nodo):
|
||||||
|
|
||||||
|
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --disable traefik \
|
||||||
|
--node-name styx \
|
||||||
|
--node-ip 192.168.4.2 \
|
||||||
|
--advertise-address 192.168.4.2 \
|
||||||
|
--tls-san 192.168.1.10 \
|
||||||
|
--tls-san 192.168.1.12" \
|
||||||
|
K3S_URL=https://192.168.1.10:6443 \
|
||||||
|
K3S_TOKEN="token" \
|
||||||
|
sh -
|
||||||
|
|
||||||
|
En `niflheim` (control plane adicional, dedicado exclusivamente a almacenamiento):
|
||||||
|
|
||||||
|
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --disable traefik \
|
||||||
|
--node-name niflheim \
|
||||||
|
--node-ip 192.168.4.3 \
|
||||||
|
--advertise-address 192.168.4.3 \
|
||||||
|
--tls-san 192.168.1.10 \
|
||||||
|
--tls-san 192.168.1.13 \
|
||||||
|
--node-taint storage=only:NoSchedule" \
|
||||||
|
K3S_URL=https://192.168.1.10:6443 \
|
||||||
|
K3S_TOKEN="token" \
|
||||||
|
sh -
|
||||||
|
|
||||||
|
### Verificar estado del clúster
|
||||||
|
|
||||||
|
Desde tartaro (o con el kubeconfig copiado):
|
||||||
|
|
||||||
|
kubectl get nodes
|
||||||
|
|
||||||
|
En styx, niflheim para permitir acceso al kubeconfig:
|
||||||
|
|
||||||
|
sudo chmod 644 /etc/rancher/k3s/k3s.yaml
|
||||||
|
|
||||||
|
## 5. Instalar driver de almacenamiento.
|
||||||
|
|
||||||
|
En **Tartaro** (o en el nodo donde previamente hayamos clonado los repositorios):
|
||||||
|
|
||||||
|
cd ~/k3s/k8s-storage/
|
||||||
|
kubectl apply -k .
|
||||||
|
|
||||||
|
Comprobar:
|
||||||
|
|
||||||
|
kubectl get pods -n nfs-provisioner
|
||||||
|
|
||||||
|
## 6. Desplegar sistema automatizado de Ingress
|
||||||
|
|
||||||
|
### Redirección de puertos desde el router
|
||||||
|
|
||||||
|
- Hay que hacer port forwarding de puertos externos 80 y 443 a la IP virtual de Keepalived (192.168.1.9)
|
||||||
|
- El `NodePort` está configurado en el manifiesto como:
|
||||||
|
- 30080 → 80 (HTTP)
|
||||||
|
- 30443 → 443 (HTTPS)
|
||||||
|
- Por lo tanto la redireccion sera:
|
||||||
|
- de 80 a 192.168.1.9:30080
|
||||||
|
- de 443 a 192.168.1.9:30443
|
||||||
|
|
||||||
|
>Si necesitamos ver los puertos en uso podemos listarlos por la via rapida con el comando:
|
||||||
|
|
||||||
|
kubectl get svc --all-namespaces -o jsonpath="{range .items[*]}{.metadata.namespace}:{.metadata.name} → {.spec.ports[*].nodePort}{'\n'}{end}" | grep -v "→ $"
|
||||||
|
|
||||||
|
### Desplegar cert-manager
|
||||||
|
|
||||||
|
cd ~/k3s/k8s-cert-manager/
|
||||||
|
kubectl apply -f namespace.yaml
|
||||||
|
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
|
||||||
|
kubectl apply -f clusterissuer-staging.yaml
|
||||||
|
kubectl apply -f clusterissuer-prod.yaml
|
||||||
|
|
||||||
|
### Desplegar ingress-controller
|
||||||
|
|
||||||
|
cd ~/k3s/k8s-ingress-controller/
|
||||||
|
kubectl apply -k .
|
||||||
|
|
||||||
|
## 7. Desplegar Gitea manualmente
|
||||||
|
|
||||||
|
### En Tartaro (o en el nodo donde hayas copiado los repositorios)
|
||||||
|
|
||||||
|
cd ~/k3s/k8s-gitea/
|
||||||
|
kubectl apply -k .
|
||||||
|
|
||||||
|
Comprueba que los pods estén en estado `Running`:
|
||||||
|
|
||||||
|
kubectl get pods -n gitea -w
|
||||||
|
|
||||||
|
>Con acceso ya a gitea, seria el momento de crear todos los repositorios remotos. Es una buena idea apoyarnos en [git-publish](herramienta%20git-publish.md).
|
||||||
|
>Si tambien te has hartado de teclear git-publish, tambien tenemos un script para ti: [publicar-todos](herramienta%20publicar-todos.md)
|
||||||
|
|
||||||
|
## 8. Instalar ArgoCD
|
||||||
|
|
||||||
|
### En Tartaro (o donde tengamos los manifiestos locales clonados de Gitea)
|
||||||
|
|
||||||
|
cd ~/k3s/k8s-argocd/
|
||||||
|
kubectl apply -f namespace.yaml
|
||||||
|
# Instalar ArgoCD desde manifiesto oficial (26000 líneas aprox)
|
||||||
|
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
|
||||||
|
kubectl apply -f services/argocd.yaml
|
||||||
|
kubectl apply -f ingress/ingress.yaml
|
||||||
|
|
||||||
|
### Acceder
|
||||||
|
>Crear acceso en NPM es lo mas adecuado.
|
||||||
|
|
||||||
|
Se puede obtener la contraseña de admin con:
|
||||||
|
|
||||||
|
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo
|
||||||
|
|
||||||
|
### Crear la App of Apps
|
||||||
|
En la interfaz web:
|
||||||
|
1. Name: app-of-apps (todo en minúsculas)
|
||||||
|
2. Project: default
|
||||||
|
3. Repository URL: el repositorio k8s-master en Gitea: https://git.manabo.org/xavor/k8s-master.git
|
||||||
|
4. Path: apps
|
||||||
|
5. Cluster URL: https://kubernetes.default.svc
|
||||||
|
6. Namespace: argocd
|
||||||
|
7. Sync policy: automática
|
||||||
|
8. Marca las casillas: `AUTO-CREATE NAMESPACE` `PRUNE` `SELF HEAL` `DIRECTORY RECURSE`
|
||||||
|
|
||||||
|
## 9. Instalar KubeVirt
|
||||||
|
|
||||||
|
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
|
||||||
|
kubectl apply -f https://raw.githubusercontent.com/k8snetworkplumbingwg/multus-cni/master/deployments/multus-daemonset.yml
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
### Comprobar despliegue
|
||||||
|
|
||||||
|
kubectl get pods -n kubevirt
|
||||||
|
|
||||||
|
### Instalar virtctl (herramienta de cliente)
|
||||||
|
|
||||||
|
export KUBEVIRT_VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases/latest | grep tag_name | cut -d '"' -f 4)
|
||||||
|
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/
|
||||||
|
|
||||||
|
### 9.1 Configurar Multus y las redes virtuales
|
||||||
|
En cada nodo:
|
||||||
|
|
||||||
|
sudo rm -f /etc/cni/net.d/*
|
||||||
|
sudo find /etc/cni/net.d/ -type f -exec rm {} \;
|
||||||
|
sudo cp /var/lib/rancher/k3s/agent/etc/cni/net.d/10-flannel.conflist /etc/cni/net.d/
|
||||||
|
|
||||||
|
y en tartaro (o cualquier nodo)
|
||||||
|
|
||||||
|
kubectl -n kube-system delete pod -l app=multus
|
||||||
|
|
||||||
|
## 10. Desplegar servidor HTTP para ISOs (KubeVirt ISO Server)
|
||||||
|
|
||||||
|
cd ~/k3s/k8s-kubevirt-isoserver/
|
||||||
|
kubectl apply -k .
|
||||||
|
|
||||||
|
## 11. Desplegar Apache Guacamole
|
||||||
|
|
||||||
|
cd ~/k3s/k8s-guacamole/
|
||||||
|
kubectl apply -k .
|
||||||
|
|
||||||
|
>⚠️ Es necesario inyectar manualmente el esquema SQL de la base de datos tras el despliegue.
|
||||||
|
|
||||||
|
## Inyectar full-schema.sql
|
||||||
|
|
||||||
|
cd ~/k3s/k8s-guacamole/
|
||||||
|
kubectl cp full-schema.sql -n guacamole \
|
||||||
|
$(kubectl get pod -n guacamole -l app=mysql -o jsonpath="{.items[0].metadata.name}"):/full-schema.sql
|
||||||
|
|
||||||
|
kubectl exec -n guacamole deploy/mysql -- \
|
||||||
|
bash -c "mysql -u root -pguacroot guacamole_db < /full-schema.sql"
|
||||||
|
|
||||||
|
## Comprobación
|
||||||
|
|
||||||
|
kubectl exec -n guacamole deploy/mysql -it -- \
|
||||||
|
mysql -uguacuser -pguacpass -D guacamole_db -e \
|
||||||
|
"SELECT name FROM guacamole_entity WHERE type='USER';"
|
||||||
|
|
||||||
|
>Usuario/pass por defecto: ```guacadmin/guacadmin```
|
||||||
52
docs/herramienta git-bajartodos.md
Normal file
52
docs/herramienta git-bajartodos.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# git-bajartodos
|
||||||
|
|
||||||
|
📥 Descarga (`git pull`) los últimos cambios de todos los repositorios `k8s-*`.
|
||||||
|
|
||||||
|
## ¿Qué hace?
|
||||||
|
|
||||||
|
Este script entra en cada carpeta que empieza por `k8s-` y ejecuta `git pull`, trayendo los cambios remotos a tu copia local.
|
||||||
|
|
||||||
|
## 1. Crea el script
|
||||||
|
Copia este contenido en ~/bin/git-publish (crea la carpeta ~/bin si no existe):
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
for dir in k8s-*; do
|
||||||
|
if [ -d "$dir/.git" ]; then
|
||||||
|
echo "📦 Entrando en $dir"
|
||||||
|
cd "$dir"
|
||||||
|
git pull
|
||||||
|
cd ..
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
Hazlo ejecutable:
|
||||||
|
|
||||||
|
chmod +x ~/bin/git-bajartodos
|
||||||
|
|
||||||
|
## 2. Añade ~/bin a tu PATH si no lo tienes
|
||||||
|
Edita ~/.bashrc (o ~/.zshrc si usas Zsh) y añade:
|
||||||
|
|
||||||
|
export PATH="$HOME/bin:$PATH"
|
||||||
|
|
||||||
|
Y recarga:
|
||||||
|
|
||||||
|
source ~/.bashrc
|
||||||
|
|
||||||
|
## Uso
|
||||||
|
|
||||||
|
./git-bajartodos
|
||||||
|
|
||||||
|
## Requisitos
|
||||||
|
|
||||||
|
- Tener acceso al remoto (vía SSH o HTTPS).
|
||||||
|
- No tener conflictos sin resolver en el repositorio local.
|
||||||
|
|
||||||
|
## Ejemplo de salida
|
||||||
|
|
||||||
|
📦 Entrando en k8s-npm
|
||||||
|
Already up to date.
|
||||||
|
|
||||||
|
## Notas
|
||||||
|
|
||||||
|
- Si hay conflictos al hacer `pull`, Git te lo indicará y deberás resolverlos manualmente.
|
||||||
|
- Este script no sube nada, solo sincroniza **desde** el remoto. Para subir cambios locales, usa `git-subirtodos`.
|
||||||
45
docs/herramienta git-chilremove.md
Normal file
45
docs/herramienta git-chilremove.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# 🛠️Creacion de herramienta git-childremove
|
||||||
|
|
||||||
|
Git-childremove es una herramienta para eliminar los git de las carpetas hijas
|
||||||
|
|
||||||
|
## 1. Crea el script
|
||||||
|
Copia este contenido en ~/bin/git-publish (crea la carpeta ~/bin si no existe):
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
ENV_FILE="${HOME}/.gitpublish.env"
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
echo "Falta archivo .env en $ENV_FILE"
|
||||||
|
exit 1# 🛠️Creacion de herramienta git-publish
|
||||||
|
|
||||||
|
Git-publish es una herramienta para automatizar la creacion y publicacion de repositorios
|
||||||
|
|
||||||
|
## 1. Crea el script
|
||||||
|
Copia este contenido en ~/bin/git-publish (crea la carpeta ~/bin si no existe):
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "🔍 Buscando carpetas .git en subdirectorios..."
|
||||||
|
|
||||||
|
find . -mindepth 2 -type d -name ".git" | while read gitdir; do
|
||||||
|
echo "🗑️ Eliminando $gitdir"
|
||||||
|
rm -rf "$gitdir"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "✅ Todas las carpetas .git han sido eliminadas."
|
||||||
|
|
||||||
|
Hazlo ejecutable:
|
||||||
|
|
||||||
|
chmod +x ~/bin/git-childremove
|
||||||
|
|
||||||
|
## 2. Añade ~/bin a tu PATH si no lo tienes
|
||||||
|
Edita ~/.bashrc (o ~/.zshrc si usas Zsh) y añade:
|
||||||
|
|
||||||
|
export PATH="$HOME/bin:$PATH"
|
||||||
|
|
||||||
|
Y recarga:
|
||||||
|
|
||||||
|
source ~/.bashrc
|
||||||
|
|
||||||
79
docs/herramienta git-publish.md
Normal file
79
docs/herramienta git-publish.md
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# 🛠️Creacion de herramienta git-publish
|
||||||
|
|
||||||
|
Git-publish es una herramienta para automatizar la creacion y publicacion de repositorios
|
||||||
|
|
||||||
|
## 1. Crea el script
|
||||||
|
Copia este contenido en ~/bin/git-publish (crea la carpeta ~/bin si no existe):
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
ENV_FILE="${HOME}/.gitpublish.env"
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
echo "Falta archivo .env en $ENV_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
source "$ENV_FILE"
|
||||||
|
|
||||||
|
REPO_NAME=$(basename "$(pwd)")
|
||||||
|
REPO_DESC="${1:-Repositorio publicado desde script}"
|
||||||
|
API_URL="$GITEA_URL/api/v1/user/repos"
|
||||||
|
|
||||||
|
echo "Inicializando git..."
|
||||||
|
git init
|
||||||
|
git checkout -b main 2>/dev/null || git checkout main
|
||||||
|
git add .
|
||||||
|
git commit -m "Primer commit" || echo "(commit ya hecho)"
|
||||||
|
|
||||||
|
echo "Creando repo remoto $REPO_NAME en Gitea..."
|
||||||
|
REPO_EXISTS=$(curl -s -H "Authorization: token $GITEA_TOKEN" "$GITEA_URL/api/v1/repos/$GITEA_USER/$REPO_NAME" | jq -r '.id // empty')
|
||||||
|
|
||||||
|
if [ -z "$REPO_EXISTS" ]; then
|
||||||
|
curl -s -X POST "$API_URL" \
|
||||||
|
-H "Authorization: token $GITEA_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"name\": \"$REPO_NAME\", \"description\": \"$REPO_DESC\", \"private\": false}" \
|
||||||
|
> /dev/null
|
||||||
|
echo "Repositorio remoto creado."
|
||||||
|
else
|
||||||
|
echo "Repositorio remoto ya existe."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Subiendo código..."
|
||||||
|
git remote add origin "$GITEA_URL/$GITEA_USER/$REPO_NAME.git" 2>/dev/null || true
|
||||||
|
git push -u origin main
|
||||||
|
|
||||||
|
echo "✔️ Repo $REPO_NAME publicado en $GITEA_URL/$GITEA_USER/$REPO_NAME"
|
||||||
|
|
||||||
|
Hazlo ejecutable:
|
||||||
|
|
||||||
|
chmod +x ~/bin/git-publish
|
||||||
|
|
||||||
|
## 2. Añade ~/bin a tu PATH si no lo tienes
|
||||||
|
Edita ~/.bashrc (o ~/.zshrc si usas Zsh) y añade:
|
||||||
|
|
||||||
|
export PATH="$HOME/bin:$PATH"
|
||||||
|
|
||||||
|
Y recarga:
|
||||||
|
|
||||||
|
source ~/.bashrc
|
||||||
|
|
||||||
|
## 3. Crea tu .env
|
||||||
|
Archivo ~/.gitpublish.env: (crea y copia tu token en gitea)
|
||||||
|
|
||||||
|
GITEA_URL=https://git.manabo.org
|
||||||
|
GITEA_USER=xavor
|
||||||
|
GITEA_TOKEN=61a7abcb33ad7bf92454dd5a85c7bfe4becc41eb
|
||||||
|
|
||||||
|
## 4. Inicializa valores globales
|
||||||
|
|
||||||
|
git config --global user.email "xavor@hotmail.es"
|
||||||
|
git config --global user.name "xavor"
|
||||||
|
git config --global credential.helper store
|
||||||
|
|
||||||
|
### ✅ Y ahora sí: úsalo
|
||||||
|
|
||||||
|
cd ~/k3s/k8s-gitea
|
||||||
|
git-publish "Manifiestos de Gitea"
|
||||||
67
docs/herramienta git-subirtodos.md
Normal file
67
docs/herramienta git-subirtodos.md
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# git-subirtodos
|
||||||
|
|
||||||
|
🚀 Sube automáticamente todos los cambios locales a los repositorios `git` dentro de carpetas `k8s-*`.
|
||||||
|
|
||||||
|
### ¿Qué hace?
|
||||||
|
|
||||||
|
Este script busca todas las carpetas que empiecen por `k8s-`, detecta si hay cambios locales sin commitear, y si los hay:
|
||||||
|
|
||||||
|
1. Añade todos los cambios (`git add .`)
|
||||||
|
2. Hace un commit con un mensaje genérico
|
||||||
|
3. Ejecuta `git push` al remoto
|
||||||
|
|
||||||
|
## 1. Crea el script
|
||||||
|
Copia este contenido en ~/bin/git-publish (crea la carpeta ~/bin si no existe):
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
for dir in k8s-*; do
|
||||||
|
if [ -d "$dir/.git" ]; then
|
||||||
|
echo "📦 Entrando en $dir"
|
||||||
|
cd "$dir"
|
||||||
|
|
||||||
|
if ! git diff --quiet || ! git diff --cached --quiet; then
|
||||||
|
echo "✅ Cambios detectados en $dir. Haciendo commit y push..."
|
||||||
|
git add .
|
||||||
|
git commit -m "Actualización automática desde git-subirtodos"
|
||||||
|
git push
|
||||||
|
else
|
||||||
|
echo "⚠️ No hay cambios en $dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
Hazlo ejecutable:
|
||||||
|
|
||||||
|
chmod +x ~/bin/git-subirtodos
|
||||||
|
|
||||||
|
## 2. Añade ~/bin a tu PATH si no lo tienes
|
||||||
|
Edita ~/.bashrc (o ~/.zshrc si usas Zsh) y añade:
|
||||||
|
|
||||||
|
export PATH="$HOME/bin:$PATH"
|
||||||
|
|
||||||
|
Y recarga:
|
||||||
|
|
||||||
|
source ~/.bashrc
|
||||||
|
|
||||||
|
## Uso
|
||||||
|
|
||||||
|
./git-subirtodos
|
||||||
|
|
||||||
|
## Requisitos
|
||||||
|
|
||||||
|
- Tener permisos de escritura en todos los repositorios `k8s-*`.
|
||||||
|
- Estar en una rama con remoto configurado (`origin`).
|
||||||
|
- Tener acceso por SSH o con credenciales ya configuradas.
|
||||||
|
|
||||||
|
## Ejemplo de salida
|
||||||
|
tree
|
||||||
|
📦 Entrando en k8s-gitea
|
||||||
|
✅ Cambios detectados en k8s-gitea. Haciendo commit y push...
|
||||||
|
|
||||||
|
## Notas
|
||||||
|
|
||||||
|
- Si no hay cambios, el script te lo indicará.
|
||||||
|
- No se realiza `pull`, solo subida. Usa `git-bajartodos` si quieres sincronizar desde remoto.
|
||||||
22
docs/herramienta publicar-todos.md
Normal file
22
docs/herramienta publicar-todos.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Script: publicar-todos.sh
|
||||||
|
Si no hay ganas de teclear todos los git-publish de todos los repositorios, guarda este script como ```publicar-todos.sh```
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Recorre todas las carpetas que empiecen por k8s-
|
||||||
|
for dir in k8s-*; do
|
||||||
|
if [ -d "$dir" ]; then
|
||||||
|
echo "📦 Entrando en $dir"
|
||||||
|
cd "$dir"
|
||||||
|
git-publish "Manifiestos de ${dir}"
|
||||||
|
cd ..
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
Y dale permisos de ejecucion
|
||||||
|
|
||||||
|
chmod +x publicar-todos.sh
|
||||||
|
|
||||||
|
Hazlo en la carpeta donde tengas los repositorios y subira todas las carpetas que empiecen por ```k8s-*``` con el comando:
|
||||||
|
|
||||||
|
./publicar-todos.sh
|
||||||
74
docs/herramientas-auxiliares.md
Normal file
74
docs/herramientas-auxiliares.md
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# 🛠️ Herramientas auxiliares
|
||||||
|
|
||||||
|
Esta sección recoge los scripts y utilidades que facilitan el trabajo con los repositorios Git del clúster, automatizando tareas como publicar, subir o clonar todos los manifiestos gestionados por Argo CD y Gitea.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `git-publish`
|
||||||
|
|
||||||
|
Publica un repositorio local en Gitea automáticamente.
|
||||||
|
Crea el repositorio remoto (si no existe), hace `init`, `add`, `commit`, crea la rama `main` y hace `push`.
|
||||||
|
|
||||||
|
📝 Documentación: [`herramienta git-publish.md`](herramienta%20git-publish.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `publicar-todos.sh`
|
||||||
|
|
||||||
|
Script que recorre todas las carpetas de servicios (`k8s-*`) y ejecuta `git-publish` en cada una de ellas.
|
||||||
|
|
||||||
|
Ideal para hacer el primer despliegue completo de manifiestos en Gitea.
|
||||||
|
|
||||||
|
📝 Documentación: [`herramienta publicar-todos.md`](herramienta%20publicar-todos.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `git-subirtodos`
|
||||||
|
|
||||||
|
Hace `git add`, `commit` y `push` en todos los subrepositorios del clúster.
|
||||||
|
|
||||||
|
Útil cuando se ha trabajado localmente en varias apps y se quiere subir todo de golpe.
|
||||||
|
|
||||||
|
📝 Documentación: [`herramienta git-subirtodos.md`](herramienta%20git-subirtodos.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `git-bajartodos`
|
||||||
|
|
||||||
|
Clona todos los repositorios hijos (servicios del clúster) desde Gitea.
|
||||||
|
|
||||||
|
Permite replicar rápidamente toda la estructura del clúster en un nuevo entorno de desarrollo.
|
||||||
|
|
||||||
|
📝 Documentación: [`herramienta git-bajartodos.md`](herramienta%20git-bajartodos.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `git-chilremove`
|
||||||
|
|
||||||
|
Elimina todos los subrepositorios Git de carpetas hijas (útil para limpiar y reestructurar).
|
||||||
|
|
||||||
|
Requiere confirmación para evitar errores destructivos.
|
||||||
|
|
||||||
|
📝 Documentación: [`herramienta git-chilremove.md`](herramienta%20git-chilremove.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Requisitos
|
||||||
|
|
||||||
|
- Token de Gitea guardado en `.env`
|
||||||
|
- Nombre de usuario y URL base configurados en los scripts
|
||||||
|
- Estructura de carpetas estándar (`k8s-*` con su `readme.md` y `kustomization.yaml`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ejemplo de uso rápido
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Publicar todos los manifiestos como repos en Gitea
|
||||||
|
./publicar-todos.sh
|
||||||
|
|
||||||
|
# Hacer commit y push masivo
|
||||||
|
./docs/git-subirtodos.sh
|
||||||
|
|
||||||
|
# Clonar todos los servicios desde Gitea
|
||||||
|
./docs/git-bajartodos.sh
|
||||||
83
docs/procedimientos-adicionales.md
Normal file
83
docs/procedimientos-adicionales.md
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# 📚 Procedimientos adicionales
|
||||||
|
|
||||||
|
Aquí se documentan acciones puntuales que pueden ser necesarias durante el mantenimiento o despliegue del clúster, incluyendo soluciones a errores frecuentes o tareas manuales especiales.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ Eliminar namespace atascado (en terminación)
|
||||||
|
|
||||||
|
### ✅ Diagnóstico confirmado
|
||||||
|
|
||||||
|
Si ves un error como este:
|
||||||
|
|
||||||
|
...is forbidden: unable to create new content in namespace kubevirt-manager because it is being terminated
|
||||||
|
|
||||||
|
Significa que el namespace está atascado en estado de terminación y Kubernetes no puede limpiarlo correctamente.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🧹 Solución forzada paso a paso
|
||||||
|
|
||||||
|
#### 1. Exporta el namespace a un archivo
|
||||||
|
|
||||||
|
kubectl get namespace kubevirt-manager -o json > ns.json
|
||||||
|
|
||||||
|
#### 2. Edita el archivo ns.json
|
||||||
|
Abre el archivo con tu editor (nano, vim, code, etc.) y elimina la sección finalizers dentro de spec.
|
||||||
|
|
||||||
|
Ejemplo original:
|
||||||
|
|
||||||
|
"spec": {
|
||||||
|
"finalizers": [
|
||||||
|
"kubernetes"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Debes dejarlo así:
|
||||||
|
|
||||||
|
"spec": {}
|
||||||
|
|
||||||
|
Guarda y cierra el archivo.
|
||||||
|
|
||||||
|
#### 3. Aplica la eliminación forzada
|
||||||
|
|
||||||
|
kubectl replace --raw "/api/v1/namespaces/kubevirt-manager/finalize" -f ./ns.json
|
||||||
|
|
||||||
|
✅ Resultado esperado
|
||||||
|
El namespace kubevirt-manager desaparecerá en unos segundos.
|
||||||
|
|
||||||
|
Verifícalo con:
|
||||||
|
|
||||||
|
kubectl get ns
|
||||||
|
|
||||||
|
#### 4. Vuelve a aplicar los manifiestos si es necesario
|
||||||
|
|
||||||
|
kubectl apply -k .
|
||||||
|
|
||||||
|
## 📥 Copiar manualmente una ISO al servidor HTTP de KubeVirt
|
||||||
|
|
||||||
|
Este procedimiento permite subir manualmente una imagen `.iso` al servidor HTTP que sirve las ISOs en el namespace `kubevirt-isoserver`, para que pueda ser utilizada desde una VM en KubeVirt.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ✅ 1. Identificar la ruta del PVC del servidor HTTP
|
||||||
|
|
||||||
|
Ejecuta:
|
||||||
|
|
||||||
|
kubectl -n kubevirt-isoserver get pvc
|
||||||
|
|
||||||
|
Salida
|
||||||
|
|
||||||
|
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
|
||||||
|
iso-pvc Bound pvc-169349e9-5e0c-4cb1-b7a5-8cd6ddc48be4 800Gi RWX nfs-manabo 17m
|
||||||
|
|
||||||
|
La carpeta real en el servidor de almacenamiento será algo como:
|
||||||
|
|
||||||
|
/mnt/storage/k8s/nfsshare/kubevirt-isoserver-iso-pvc-pvc-169349e9-5e0c-4cb1-b7a5-8cd6ddc48be4/
|
||||||
|
|
||||||
|
### 📤 2. Copiar la imagen desde el servidor origen
|
||||||
|
Estando en el servidor donde tienes la imagen .iso (ej. 192.168.1.3) y suponiendo que tienes acceso SSH al servidor de almacenamiento (192.168.1.10), ejecuta:
|
||||||
|
|
||||||
|
scp /mnt/Iso/Windows.iso xavor@192.168.1.10:/mnt/storage/k8s/nfsshare/kubevirt-isoserver-iso-pvc-pvc-169349e9-5e0c-4cb1-b7a5-8cd6ddc48be4/
|
||||||
|
|
||||||
|
Deberías ver el archivo Windows.iso.
|
||||||
28
k8s-argocd/ingress/ingress.yaml
Normal file
28
k8s-argocd/ingress/ingress.yaml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: argocd
|
||||||
|
namespace: argocd
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
|
||||||
|
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
|
||||||
|
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||||
|
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
||||||
|
spec:
|
||||||
|
ingressClassName: nginx
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- argo.manabo.org
|
||||||
|
secretName: argocd-tls
|
||||||
|
rules:
|
||||||
|
- host: argo.manabo.org
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: argocd-server
|
||||||
|
port:
|
||||||
|
number: 443
|
||||||
4
k8s-argocd/namespace.yaml
Normal file
4
k8s-argocd/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: argocd
|
||||||
14
k8s-argocd/readme.md
Normal file
14
k8s-argocd/readme.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Manifiestos para Argo CD
|
||||||
|
Este repositorio contiene los manifiestos necesarios para desplegar Argo CD, una herramienta de Continuous Delivery para Kubernetes basada en GitOps.
|
||||||
|
|
||||||
|
Se instala en el namespace argocd, utilizando los recursos oficiales del proyecto, y se expone al exterior mediante un servicio NodePort, permitiendo su acceso a través de Nginx Proxy Manager o directamente desde IP pública.
|
||||||
|
|
||||||
|
>Argo CD monitoriza los repositorios Git declarativos del clúster y sincroniza automáticamente el estado deseado con el real, facilitando el despliegue, control y actualización de aplicaciones en Kubernetes.
|
||||||
|
|
||||||
|
## Despliegue
|
||||||
|
|
||||||
|
kubectl apply -f namespace.yaml
|
||||||
|
# Instalar ArgoCD desde manifiesto oficial (26000 líneas aprox)
|
||||||
|
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
|
||||||
|
kubectl apply -f services/argocd.yaml
|
||||||
|
|
||||||
18
k8s-argocd/services/argocd.yaml
Normal file
18
k8s-argocd/services/argocd.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: argocd-server-nodeport
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
type: NodePort
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: argocd-server
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: 8080
|
||||||
|
nodePort: 32080
|
||||||
|
- name: https
|
||||||
|
port: 443
|
||||||
|
targetPort: 8080
|
||||||
|
nodePort: 32443
|
||||||
14
k8s-cert-manager/clusterissuer-prod.yaml
Normal file
14
k8s-cert-manager/clusterissuer-prod.yaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
apiVersion: cert-manager.io/v1
|
||||||
|
kind: ClusterIssuer
|
||||||
|
metadata:
|
||||||
|
name: letsencrypt-prod
|
||||||
|
spec:
|
||||||
|
acme:
|
||||||
|
email: xavor@hotmail.es
|
||||||
|
server: https://acme-v02.api.letsencrypt.org/directory
|
||||||
|
privateKeySecretRef:
|
||||||
|
name: letsencrypt-prod
|
||||||
|
solvers:
|
||||||
|
- http01:
|
||||||
|
ingress:
|
||||||
|
ingressClassName: nginx
|
||||||
14
k8s-cert-manager/clusterissuer-staging.yaml
Normal file
14
k8s-cert-manager/clusterissuer-staging.yaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
apiVersion: cert-manager.io/v1
|
||||||
|
kind: ClusterIssuer
|
||||||
|
metadata:
|
||||||
|
name: letsencrypt-staging
|
||||||
|
spec:
|
||||||
|
acme:
|
||||||
|
email: xavor@hotmail.es
|
||||||
|
server: https://acme-staging-v02.api.letsencrypt.org/directory
|
||||||
|
privateKeySecretRef:
|
||||||
|
name: letsencrypt-staging
|
||||||
|
solvers:
|
||||||
|
- http01:
|
||||||
|
ingress:
|
||||||
|
ingressClassName: nginx
|
||||||
5
k8s-cert-manager/kustomization.yaml
Normal file
5
k8s-cert-manager/kustomization.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
resources:
|
||||||
|
- clusterissuer-prod.yaml
|
||||||
|
- clusterissuer-staging.yaml
|
||||||
|
- namespace.yaml
|
||||||
|
|
||||||
4
k8s-cert-manager/namespace.yaml
Normal file
4
k8s-cert-manager/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: cert-manager
|
||||||
15
k8s-cert-manager/readme.md
Normal file
15
k8s-cert-manager/readme.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Cert Manager para Kubernetes
|
||||||
|
|
||||||
|
Este repositorio contiene los manifiestos necesarios para desplegar [cert-manager](https://cert-manager.io), una herramienta que automatiza la gestión y renovación de certificados TLS en Kubernetes.
|
||||||
|
|
||||||
|
Cert-manager se encarga de emitir y renovar automáticamente certificados mediante ACME (por ejemplo, Let's Encrypt), y es compatible con `Ingress` para habilitar TLS en tus servicios expuestos.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Despliegue
|
||||||
|
|
||||||
|
kubectl apply -f namespace.yaml
|
||||||
|
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
|
||||||
|
kubectl apply -f clusterissuer-staging.yaml
|
||||||
|
kubectl apply -f clusterissuer-prod.yaml
|
||||||
|
|
||||||
36
k8s-gitea/deployments/gitea-db.yaml
Normal file
36
k8s-gitea/deployments/gitea-db.yaml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: gitea-db
|
||||||
|
namespace: gitea
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: gitea-db
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: gitea-db
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: mysql
|
||||||
|
image: mysql:8
|
||||||
|
env:
|
||||||
|
- name: MYSQL_ROOT_PASSWORD
|
||||||
|
value: gitea123
|
||||||
|
- name: MYSQL_DATABASE
|
||||||
|
value: gitea
|
||||||
|
- name: MYSQL_USER
|
||||||
|
value: gitea
|
||||||
|
- name: MYSQL_PASSWORD
|
||||||
|
value: gitea123
|
||||||
|
ports:
|
||||||
|
- containerPort: 3306
|
||||||
|
volumeMounts:
|
||||||
|
- name: gitea-db
|
||||||
|
mountPath: /var/lib/mysql
|
||||||
|
volumes:
|
||||||
|
- name: gitea-db
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: gitea-db
|
||||||
42
k8s-gitea/deployments/gitea.yaml
Normal file
42
k8s-gitea/deployments/gitea.yaml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: gitea
|
||||||
|
namespace: gitea
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: gitea
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: gitea
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: gitea
|
||||||
|
image: gitea/gitea:latest
|
||||||
|
ports:
|
||||||
|
- containerPort: 3000
|
||||||
|
env:
|
||||||
|
- name: USER_UID
|
||||||
|
value: "1000"
|
||||||
|
- name: USER_GID
|
||||||
|
value: "1000"
|
||||||
|
- name: GITEA__database__DB_TYPE
|
||||||
|
value: "mysql"
|
||||||
|
- name: GITEA__database__HOST
|
||||||
|
value: "gitea-db:3306"
|
||||||
|
- name: GITEA__database__NAME
|
||||||
|
value: "gitea"
|
||||||
|
- name: GITEA__database__USER
|
||||||
|
value: "gitea"
|
||||||
|
- name: GITEA__database__PASSWD
|
||||||
|
value: "gitea123"
|
||||||
|
volumeMounts:
|
||||||
|
- name: gitea-data
|
||||||
|
mountPath: /data
|
||||||
|
volumes:
|
||||||
|
- name: gitea-data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: gitea-data
|
||||||
27
k8s-gitea/ingress/ingress.yaml
Normal file
27
k8s-gitea/ingress/ingress.yaml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: gitea
|
||||||
|
namespace: gitea
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
nginx.ingress.kubernetes.io/ssl-redirect: "false"
|
||||||
|
nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
|
||||||
|
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
|
||||||
|
spec:
|
||||||
|
ingressClassName: nginx
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- git.manabo.org
|
||||||
|
secretName: gitea-tls
|
||||||
|
rules:
|
||||||
|
- host: git.manabo.org
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: gitea
|
||||||
|
port:
|
||||||
|
number: 3000
|
||||||
9
k8s-gitea/kustomization.yaml
Normal file
9
k8s-gitea/kustomization.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- pvc/gitea-data.yaml
|
||||||
|
- pvc/gitea-db.yaml
|
||||||
|
- deployments/gitea.yaml
|
||||||
|
- deployments/gitea-db.yaml
|
||||||
|
- services/gitea.yaml
|
||||||
|
- services/gitea-db.yaml
|
||||||
|
- ingress/ingress.yaml
|
||||||
4
k8s-gitea/namespace.yaml
Normal file
4
k8s-gitea/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: gitea
|
||||||
12
k8s-gitea/pvc/gitea-data.yaml
Normal file
12
k8s-gitea/pvc/gitea-data.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: gitea-data
|
||||||
|
namespace: gitea
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteMany
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 5Gi
|
||||||
|
storageClassName: nfs-manabo
|
||||||
12
k8s-gitea/pvc/gitea-db.yaml
Normal file
12
k8s-gitea/pvc/gitea-db.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: gitea-db
|
||||||
|
namespace: gitea
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 2Gi
|
||||||
|
storageClassName: nfs-manabo
|
||||||
12
k8s-gitea/readme.md
Normal file
12
k8s-gitea/readme.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# Manifiestos para Gitea
|
||||||
|
Este repositorio contiene los manifiestos necesarios para desplegar Gitea, un servidor Git ligero, en el namespace gitea.
|
||||||
|
|
||||||
|
## Despliegue
|
||||||
|
|
||||||
|
kubectl apply -f namespace.yaml
|
||||||
|
kubectl apply -f pvc/gitea-data.yaml
|
||||||
|
kubectl apply -f pvc/gitea-db.yaml
|
||||||
|
kubectl apply -f deployments/gitea-db.yaml
|
||||||
|
kubectl apply -f services/gitea-db.yaml
|
||||||
|
kubectl apply -f deployments/gitea.yaml
|
||||||
|
kubectl apply -f services/gitea.yaml
|
||||||
11
k8s-gitea/services/gitea-db.yaml
Normal file
11
k8s-gitea/services/gitea-db.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: gitea-db
|
||||||
|
namespace: gitea
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: gitea-db
|
||||||
|
ports:
|
||||||
|
- port: 3306
|
||||||
14
k8s-gitea/services/gitea.yaml
Normal file
14
k8s-gitea/services/gitea.yaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: gitea
|
||||||
|
namespace: gitea
|
||||||
|
spec:
|
||||||
|
type: NodePort
|
||||||
|
selector:
|
||||||
|
app: gitea
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 3000
|
||||||
|
targetPort: 3000
|
||||||
|
nodePort: 30300
|
||||||
37
k8s-guacamole/deployments/guacamole-deployment.yaml
Normal file
37
k8s-guacamole/deployments/guacamole-deployment.yaml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: guacamole
|
||||||
|
namespace: guacamole
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: guacamole
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: guacamole
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: guacamole
|
||||||
|
image: guacamole/guacamole
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
env:
|
||||||
|
- name: MYSQL_HOSTNAME
|
||||||
|
value: mysql
|
||||||
|
- name: MYSQL_DATABASE
|
||||||
|
value: guacamole_db
|
||||||
|
- name: MYSQL_USER
|
||||||
|
value: guacuser
|
||||||
|
- name: MYSQL_PASSWORD
|
||||||
|
value: guacpass
|
||||||
|
- name: GUACD_HOSTNAME
|
||||||
|
value: localhost
|
||||||
|
- name: MYSQL_PORT
|
||||||
|
value: "3306"
|
||||||
|
- name: guacd
|
||||||
|
image: guacamole/guacd
|
||||||
|
ports:
|
||||||
|
- containerPort: 4822
|
||||||
35
k8s-guacamole/deployments/mysql-deployment.yaml
Normal file
35
k8s-guacamole/deployments/mysql-deployment.yaml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: mysql
|
||||||
|
namespace: guacamole
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: mysql
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: mysql
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: mysql
|
||||||
|
image: mysql:5.7
|
||||||
|
env:
|
||||||
|
- name: MYSQL_ROOT_PASSWORD
|
||||||
|
value: guacroot
|
||||||
|
- name: MYSQL_DATABASE
|
||||||
|
value: guacamole_db
|
||||||
|
- name: MYSQL_USER
|
||||||
|
value: guacuser
|
||||||
|
- name: MYSQL_PASSWORD
|
||||||
|
value: guacpass
|
||||||
|
ports:
|
||||||
|
- containerPort: 3306
|
||||||
|
volumeMounts:
|
||||||
|
- name: mysql-storage
|
||||||
|
mountPath: /var/lib/mysql
|
||||||
|
volumes:
|
||||||
|
- name: mysql-storage
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: mysql-pvc
|
||||||
666
k8s-guacamole/full-schema.sql
Normal file
666
k8s-guacamole/full-schema.sql
Normal file
@@ -0,0 +1,666 @@
|
|||||||
|
--
|
||||||
|
-- Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
-- or more contributor license agreements. See the NOTICE file
|
||||||
|
-- distributed with this work for additional information
|
||||||
|
-- regarding copyright ownership. The ASF licenses this file
|
||||||
|
-- to you under the Apache License, Version 2.0 (the
|
||||||
|
-- "License"); you may not use this file except in compliance
|
||||||
|
-- with the License. You may obtain a copy of the License at
|
||||||
|
--
|
||||||
|
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
--
|
||||||
|
-- Unless required by applicable law or agreed to in writing,
|
||||||
|
-- software distributed under the License is distributed on an
|
||||||
|
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
-- KIND, either express or implied. See the License for the
|
||||||
|
-- specific language governing permissions and limitations
|
||||||
|
-- under the License.
|
||||||
|
--
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of connection groups. Each connection group has a name.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_connection_group` (
|
||||||
|
|
||||||
|
`connection_group_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`parent_id` int(11),
|
||||||
|
`connection_group_name` varchar(128) NOT NULL,
|
||||||
|
`type` enum('ORGANIZATIONAL',
|
||||||
|
'BALANCING') NOT NULL DEFAULT 'ORGANIZATIONAL',
|
||||||
|
|
||||||
|
-- Concurrency limits
|
||||||
|
`max_connections` int(11),
|
||||||
|
`max_connections_per_user` int(11),
|
||||||
|
`enable_session_affinity` boolean NOT NULL DEFAULT 0,
|
||||||
|
|
||||||
|
PRIMARY KEY (`connection_group_id`),
|
||||||
|
UNIQUE KEY `connection_group_name_parent` (`connection_group_name`, `parent_id`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_connection_group_ibfk_1`
|
||||||
|
FOREIGN KEY (`parent_id`)
|
||||||
|
REFERENCES `guacamole_connection_group` (`connection_group_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of connections. Each connection has a name, protocol, and
|
||||||
|
-- associated set of parameters.
|
||||||
|
-- A connection may belong to a connection group.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_connection` (
|
||||||
|
|
||||||
|
`connection_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`connection_name` varchar(128) NOT NULL,
|
||||||
|
`parent_id` int(11),
|
||||||
|
`protocol` varchar(32) NOT NULL,
|
||||||
|
|
||||||
|
-- Guacamole proxy (guacd) overrides
|
||||||
|
`proxy_port` integer,
|
||||||
|
`proxy_hostname` varchar(512),
|
||||||
|
`proxy_encryption_method` enum('NONE', 'SSL'),
|
||||||
|
|
||||||
|
-- Concurrency limits
|
||||||
|
`max_connections` int(11),
|
||||||
|
`max_connections_per_user` int(11),
|
||||||
|
|
||||||
|
-- Load-balancing behavior
|
||||||
|
`connection_weight` int(11),
|
||||||
|
`failover_only` boolean NOT NULL DEFAULT 0,
|
||||||
|
|
||||||
|
PRIMARY KEY (`connection_id`),
|
||||||
|
UNIQUE KEY `connection_name_parent` (`connection_name`, `parent_id`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_connection_ibfk_1`
|
||||||
|
FOREIGN KEY (`parent_id`)
|
||||||
|
REFERENCES `guacamole_connection_group` (`connection_group_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of base entities which may each be either a user or user group. Other
|
||||||
|
-- tables which represent qualities shared by both users and groups will point
|
||||||
|
-- to guacamole_entity, while tables which represent qualities specific to
|
||||||
|
-- users or groups will point to guacamole_user or guacamole_user_group.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_entity` (
|
||||||
|
|
||||||
|
`entity_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(128) NOT NULL,
|
||||||
|
`type` enum('USER',
|
||||||
|
'USER_GROUP') NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`entity_id`),
|
||||||
|
UNIQUE KEY `guacamole_entity_name_scope` (`type`, `name`)
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of users. Each user has a unique username and a hashed password
|
||||||
|
-- with corresponding salt. Although the authentication system will always set
|
||||||
|
-- salted passwords, other systems may set unsalted passwords by simply not
|
||||||
|
-- providing the salt.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_user` (
|
||||||
|
|
||||||
|
`user_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`entity_id` int(11) NOT NULL,
|
||||||
|
|
||||||
|
-- Optionally-salted password
|
||||||
|
`password_hash` binary(32) NOT NULL,
|
||||||
|
`password_salt` binary(32),
|
||||||
|
`password_date` datetime NOT NULL,
|
||||||
|
|
||||||
|
-- Account disabled/expired status
|
||||||
|
`disabled` boolean NOT NULL DEFAULT 0,
|
||||||
|
`expired` boolean NOT NULL DEFAULT 0,
|
||||||
|
|
||||||
|
-- Time-based access restriction
|
||||||
|
`access_window_start` TIME,
|
||||||
|
`access_window_end` TIME,
|
||||||
|
|
||||||
|
-- Date-based access restriction
|
||||||
|
`valid_from` DATE,
|
||||||
|
`valid_until` DATE,
|
||||||
|
|
||||||
|
-- Timezone used for all date/time comparisons and interpretation
|
||||||
|
`timezone` VARCHAR(64),
|
||||||
|
|
||||||
|
-- Profile information
|
||||||
|
`full_name` VARCHAR(256),
|
||||||
|
`email_address` VARCHAR(256),
|
||||||
|
`organization` VARCHAR(256),
|
||||||
|
`organizational_role` VARCHAR(256),
|
||||||
|
|
||||||
|
PRIMARY KEY (`user_id`),
|
||||||
|
|
||||||
|
UNIQUE KEY `guacamole_user_single_entity` (`entity_id`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_user_entity`
|
||||||
|
FOREIGN KEY (`entity_id`)
|
||||||
|
REFERENCES `guacamole_entity` (`entity_id`)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of user groups. Each user group may have an arbitrary set of member
|
||||||
|
-- users and member groups, with those members inheriting the permissions
|
||||||
|
-- granted to that group.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_user_group` (
|
||||||
|
|
||||||
|
`user_group_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`entity_id` int(11) NOT NULL,
|
||||||
|
|
||||||
|
-- Group disabled status
|
||||||
|
`disabled` boolean NOT NULL DEFAULT 0,
|
||||||
|
|
||||||
|
PRIMARY KEY (`user_group_id`),
|
||||||
|
|
||||||
|
UNIQUE KEY `guacamole_user_group_single_entity` (`entity_id`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_user_group_entity`
|
||||||
|
FOREIGN KEY (`entity_id`)
|
||||||
|
REFERENCES `guacamole_entity` (`entity_id`)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of users which are members of given user groups.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_user_group_member` (
|
||||||
|
|
||||||
|
`user_group_id` int(11) NOT NULL,
|
||||||
|
`member_entity_id` int(11) NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`user_group_id`, `member_entity_id`),
|
||||||
|
|
||||||
|
-- Parent must be a user group
|
||||||
|
CONSTRAINT `guacamole_user_group_member_parent_id`
|
||||||
|
FOREIGN KEY (`user_group_id`)
|
||||||
|
REFERENCES `guacamole_user_group` (`user_group_id`) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
-- Member may be either a user or a user group (any entity)
|
||||||
|
CONSTRAINT `guacamole_user_group_member_entity_id`
|
||||||
|
FOREIGN KEY (`member_entity_id`)
|
||||||
|
REFERENCES `guacamole_entity` (`entity_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of sharing profiles. Each sharing profile has a name, associated set
|
||||||
|
-- of parameters, and a primary connection. The primary connection is the
|
||||||
|
-- connection that the sharing profile shares, and the parameters dictate the
|
||||||
|
-- restrictions/features which apply to the user joining the connection via the
|
||||||
|
-- sharing profile.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE guacamole_sharing_profile (
|
||||||
|
|
||||||
|
`sharing_profile_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`sharing_profile_name` varchar(128) NOT NULL,
|
||||||
|
`primary_connection_id` int(11) NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`sharing_profile_id`),
|
||||||
|
UNIQUE KEY `sharing_profile_name_primary` (sharing_profile_name, primary_connection_id),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_sharing_profile_ibfk_1`
|
||||||
|
FOREIGN KEY (`primary_connection_id`)
|
||||||
|
REFERENCES `guacamole_connection` (`connection_id`)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of connection parameters. Each parameter is simply a name/value pair
|
||||||
|
-- associated with a connection.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_connection_parameter` (
|
||||||
|
|
||||||
|
`connection_id` int(11) NOT NULL,
|
||||||
|
`parameter_name` varchar(128) NOT NULL,
|
||||||
|
`parameter_value` varchar(4096) NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`connection_id`,`parameter_name`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_connection_parameter_ibfk_1`
|
||||||
|
FOREIGN KEY (`connection_id`)
|
||||||
|
REFERENCES `guacamole_connection` (`connection_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of sharing profile parameters. Each parameter is simply
|
||||||
|
-- name/value pair associated with a sharing profile. These parameters dictate
|
||||||
|
-- the restrictions/features which apply to the user joining the associated
|
||||||
|
-- connection via the sharing profile.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE guacamole_sharing_profile_parameter (
|
||||||
|
|
||||||
|
`sharing_profile_id` integer NOT NULL,
|
||||||
|
`parameter_name` varchar(128) NOT NULL,
|
||||||
|
`parameter_value` varchar(4096) NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`sharing_profile_id`, `parameter_name`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_sharing_profile_parameter_ibfk_1`
|
||||||
|
FOREIGN KEY (`sharing_profile_id`)
|
||||||
|
REFERENCES `guacamole_sharing_profile` (`sharing_profile_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of arbitrary user attributes. Each attribute is simply a name/value
|
||||||
|
-- pair associated with a user. Arbitrary attributes are defined by other
|
||||||
|
-- extensions. Attributes defined by this extension will be mapped to
|
||||||
|
-- properly-typed columns of a specific table.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE guacamole_user_attribute (
|
||||||
|
|
||||||
|
`user_id` int(11) NOT NULL,
|
||||||
|
`attribute_name` varchar(128) NOT NULL,
|
||||||
|
`attribute_value` varchar(4096) NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (user_id, attribute_name),
|
||||||
|
KEY `user_id` (`user_id`),
|
||||||
|
|
||||||
|
CONSTRAINT guacamole_user_attribute_ibfk_1
|
||||||
|
FOREIGN KEY (user_id)
|
||||||
|
REFERENCES guacamole_user (user_id) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of arbitrary user group attributes. Each attribute is simply a
|
||||||
|
-- name/value pair associated with a user group. Arbitrary attributes are
|
||||||
|
-- defined by other extensions. Attributes defined by this extension will be
|
||||||
|
-- mapped to properly-typed columns of a specific table.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE guacamole_user_group_attribute (
|
||||||
|
|
||||||
|
`user_group_id` int(11) NOT NULL,
|
||||||
|
`attribute_name` varchar(128) NOT NULL,
|
||||||
|
`attribute_value` varchar(4096) NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`user_group_id`, `attribute_name`),
|
||||||
|
KEY `user_group_id` (`user_group_id`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_user_group_attribute_ibfk_1`
|
||||||
|
FOREIGN KEY (`user_group_id`)
|
||||||
|
REFERENCES `guacamole_user_group` (`user_group_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of arbitrary connection attributes. Each attribute is simply a
|
||||||
|
-- name/value pair associated with a connection. Arbitrary attributes are
|
||||||
|
-- defined by other extensions. Attributes defined by this extension will be
|
||||||
|
-- mapped to properly-typed columns of a specific table.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE guacamole_connection_attribute (
|
||||||
|
|
||||||
|
`connection_id` int(11) NOT NULL,
|
||||||
|
`attribute_name` varchar(128) NOT NULL,
|
||||||
|
`attribute_value` varchar(4096) NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (connection_id, attribute_name),
|
||||||
|
KEY `connection_id` (`connection_id`),
|
||||||
|
|
||||||
|
CONSTRAINT guacamole_connection_attribute_ibfk_1
|
||||||
|
FOREIGN KEY (connection_id)
|
||||||
|
REFERENCES guacamole_connection (connection_id) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of arbitrary connection group attributes. Each attribute is simply a
|
||||||
|
-- name/value pair associated with a connection group. Arbitrary attributes are
|
||||||
|
-- defined by other extensions. Attributes defined by this extension will be
|
||||||
|
-- mapped to properly-typed columns of a specific table.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE guacamole_connection_group_attribute (
|
||||||
|
|
||||||
|
`connection_group_id` int(11) NOT NULL,
|
||||||
|
`attribute_name` varchar(128) NOT NULL,
|
||||||
|
`attribute_value` varchar(4096) NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (connection_group_id, attribute_name),
|
||||||
|
KEY `connection_group_id` (`connection_group_id`),
|
||||||
|
|
||||||
|
CONSTRAINT guacamole_connection_group_attribute_ibfk_1
|
||||||
|
FOREIGN KEY (connection_group_id)
|
||||||
|
REFERENCES guacamole_connection_group (connection_group_id) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of arbitrary sharing profile attributes. Each attribute is simply a
|
||||||
|
-- name/value pair associated with a sharing profile. Arbitrary attributes are
|
||||||
|
-- defined by other extensions. Attributes defined by this extension will be
|
||||||
|
-- mapped to properly-typed columns of a specific table.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE guacamole_sharing_profile_attribute (
|
||||||
|
|
||||||
|
`sharing_profile_id` int(11) NOT NULL,
|
||||||
|
`attribute_name` varchar(128) NOT NULL,
|
||||||
|
`attribute_value` varchar(4096) NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (sharing_profile_id, attribute_name),
|
||||||
|
KEY `sharing_profile_id` (`sharing_profile_id`),
|
||||||
|
|
||||||
|
CONSTRAINT guacamole_sharing_profile_attribute_ibfk_1
|
||||||
|
FOREIGN KEY (sharing_profile_id)
|
||||||
|
REFERENCES guacamole_sharing_profile (sharing_profile_id) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of connection permissions. Each connection permission grants a user or
|
||||||
|
-- user group specific access to a connection.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_connection_permission` (
|
||||||
|
|
||||||
|
`entity_id` int(11) NOT NULL,
|
||||||
|
`connection_id` int(11) NOT NULL,
|
||||||
|
`permission` enum('READ',
|
||||||
|
'UPDATE',
|
||||||
|
'DELETE',
|
||||||
|
'ADMINISTER') NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`entity_id`,`connection_id`,`permission`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_connection_permission_ibfk_1`
|
||||||
|
FOREIGN KEY (`connection_id`)
|
||||||
|
REFERENCES `guacamole_connection` (`connection_id`) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_connection_permission_entity`
|
||||||
|
FOREIGN KEY (`entity_id`)
|
||||||
|
REFERENCES `guacamole_entity` (`entity_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of connection group permissions. Each group permission grants a user
|
||||||
|
-- or user group specific access to a connection group.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_connection_group_permission` (
|
||||||
|
|
||||||
|
`entity_id` int(11) NOT NULL,
|
||||||
|
`connection_group_id` int(11) NOT NULL,
|
||||||
|
`permission` enum('READ',
|
||||||
|
'UPDATE',
|
||||||
|
'DELETE',
|
||||||
|
'ADMINISTER') NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`entity_id`,`connection_group_id`,`permission`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_connection_group_permission_ibfk_1`
|
||||||
|
FOREIGN KEY (`connection_group_id`)
|
||||||
|
REFERENCES `guacamole_connection_group` (`connection_group_id`) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_connection_group_permission_entity`
|
||||||
|
FOREIGN KEY (`entity_id`)
|
||||||
|
REFERENCES `guacamole_entity` (`entity_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of sharing profile permissions. Each sharing profile permission grants
|
||||||
|
-- a user or user group specific access to a sharing profile.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE guacamole_sharing_profile_permission (
|
||||||
|
|
||||||
|
`entity_id` integer NOT NULL,
|
||||||
|
`sharing_profile_id` integer NOT NULL,
|
||||||
|
`permission` enum('READ',
|
||||||
|
'UPDATE',
|
||||||
|
'DELETE',
|
||||||
|
'ADMINISTER') NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`entity_id`, `sharing_profile_id`, `permission`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_sharing_profile_permission_ibfk_1`
|
||||||
|
FOREIGN KEY (`sharing_profile_id`)
|
||||||
|
REFERENCES `guacamole_sharing_profile` (`sharing_profile_id`) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_sharing_profile_permission_entity`
|
||||||
|
FOREIGN KEY (`entity_id`)
|
||||||
|
REFERENCES `guacamole_entity` (`entity_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of system permissions. Each system permission grants a user or user
|
||||||
|
-- group a system-level privilege of some kind.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_system_permission` (
|
||||||
|
|
||||||
|
`entity_id` int(11) NOT NULL,
|
||||||
|
`permission` enum('CREATE_CONNECTION',
|
||||||
|
'CREATE_CONNECTION_GROUP',
|
||||||
|
'CREATE_SHARING_PROFILE',
|
||||||
|
'CREATE_USER',
|
||||||
|
'CREATE_USER_GROUP',
|
||||||
|
'ADMINISTER') NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`entity_id`,`permission`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_system_permission_entity`
|
||||||
|
FOREIGN KEY (`entity_id`)
|
||||||
|
REFERENCES `guacamole_entity` (`entity_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of user permissions. Each user permission grants a user or user group
|
||||||
|
-- access to another user (the "affected" user) for a specific type of
|
||||||
|
-- operation.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_user_permission` (
|
||||||
|
|
||||||
|
`entity_id` int(11) NOT NULL,
|
||||||
|
`affected_user_id` int(11) NOT NULL,
|
||||||
|
`permission` enum('READ',
|
||||||
|
'UPDATE',
|
||||||
|
'DELETE',
|
||||||
|
'ADMINISTER') NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`entity_id`,`affected_user_id`,`permission`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_user_permission_ibfk_1`
|
||||||
|
FOREIGN KEY (`affected_user_id`)
|
||||||
|
REFERENCES `guacamole_user` (`user_id`) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_user_permission_entity`
|
||||||
|
FOREIGN KEY (`entity_id`)
|
||||||
|
REFERENCES `guacamole_entity` (`entity_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of user group permissions. Each user group permission grants a user
|
||||||
|
-- or user group access to a another user group (the "affected" user group) for
|
||||||
|
-- a specific type of operation.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_user_group_permission` (
|
||||||
|
|
||||||
|
`entity_id` int(11) NOT NULL,
|
||||||
|
`affected_user_group_id` int(11) NOT NULL,
|
||||||
|
`permission` enum('READ',
|
||||||
|
'UPDATE',
|
||||||
|
'DELETE',
|
||||||
|
'ADMINISTER') NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`entity_id`, `affected_user_group_id`, `permission`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_user_group_permission_affected_user_group`
|
||||||
|
FOREIGN KEY (`affected_user_group_id`)
|
||||||
|
REFERENCES `guacamole_user_group` (`user_group_id`) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_user_group_permission_entity`
|
||||||
|
FOREIGN KEY (`entity_id`)
|
||||||
|
REFERENCES `guacamole_entity` (`entity_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of connection history records. Each record defines a specific user's
|
||||||
|
-- session, including the connection used, the start time, and the end time
|
||||||
|
-- (if any).
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_connection_history` (
|
||||||
|
|
||||||
|
`history_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_id` int(11) DEFAULT NULL,
|
||||||
|
`username` varchar(128) NOT NULL,
|
||||||
|
`remote_host` varchar(256) DEFAULT NULL,
|
||||||
|
`connection_id` int(11) DEFAULT NULL,
|
||||||
|
`connection_name` varchar(128) NOT NULL,
|
||||||
|
`sharing_profile_id` int(11) DEFAULT NULL,
|
||||||
|
`sharing_profile_name` varchar(128) DEFAULT NULL,
|
||||||
|
`start_date` datetime NOT NULL,
|
||||||
|
`end_date` datetime DEFAULT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`history_id`),
|
||||||
|
KEY `user_id` (`user_id`),
|
||||||
|
KEY `connection_id` (`connection_id`),
|
||||||
|
KEY `sharing_profile_id` (`sharing_profile_id`),
|
||||||
|
KEY `start_date` (`start_date`),
|
||||||
|
KEY `end_date` (`end_date`),
|
||||||
|
KEY `connection_start_date` (`connection_id`, `start_date`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_connection_history_ibfk_1`
|
||||||
|
FOREIGN KEY (`user_id`)
|
||||||
|
REFERENCES `guacamole_user` (`user_id`) ON DELETE SET NULL,
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_connection_history_ibfk_2`
|
||||||
|
FOREIGN KEY (`connection_id`)
|
||||||
|
REFERENCES `guacamole_connection` (`connection_id`) ON DELETE SET NULL,
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_connection_history_ibfk_3`
|
||||||
|
FOREIGN KEY (`sharing_profile_id`)
|
||||||
|
REFERENCES `guacamole_sharing_profile` (`sharing_profile_id`) ON DELETE SET NULL
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- User login/logout history
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE guacamole_user_history (
|
||||||
|
|
||||||
|
`history_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_id` int(11) DEFAULT NULL,
|
||||||
|
`username` varchar(128) NOT NULL,
|
||||||
|
`remote_host` varchar(256) DEFAULT NULL,
|
||||||
|
`start_date` datetime NOT NULL,
|
||||||
|
`end_date` datetime DEFAULT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (history_id),
|
||||||
|
KEY `user_id` (`user_id`),
|
||||||
|
KEY `start_date` (`start_date`),
|
||||||
|
KEY `end_date` (`end_date`),
|
||||||
|
KEY `user_start_date` (`user_id`, `start_date`),
|
||||||
|
|
||||||
|
CONSTRAINT guacamole_user_history_ibfk_1
|
||||||
|
FOREIGN KEY (user_id)
|
||||||
|
REFERENCES guacamole_user (user_id) ON DELETE SET NULL
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- User password history
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE guacamole_user_password_history (
|
||||||
|
|
||||||
|
`password_history_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_id` int(11) NOT NULL,
|
||||||
|
|
||||||
|
-- Salted password
|
||||||
|
`password_hash` binary(32) NOT NULL,
|
||||||
|
`password_salt` binary(32),
|
||||||
|
`password_date` datetime NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`password_history_id`),
|
||||||
|
KEY `user_id` (`user_id`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_user_password_history_ibfk_1`
|
||||||
|
FOREIGN KEY (`user_id`)
|
||||||
|
REFERENCES `guacamole_user` (`user_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
--
|
||||||
|
-- Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
-- or more contributor license agreements. See the NOTICE file
|
||||||
|
-- distributed with this work for additional information
|
||||||
|
-- regarding copyright ownership. The ASF licenses this file
|
||||||
|
-- to you under the Apache License, Version 2.0 (the
|
||||||
|
-- "License"); you may not use this file except in compliance
|
||||||
|
-- with the License. You may obtain a copy of the License at
|
||||||
|
--
|
||||||
|
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
--
|
||||||
|
-- Unless required by applicable law or agreed to in writing,
|
||||||
|
-- software distributed under the License is distributed on an
|
||||||
|
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
-- KIND, either express or implied. See the License for the
|
||||||
|
-- specific language governing permissions and limitations
|
||||||
|
-- under the License.
|
||||||
|
--
|
||||||
|
|
||||||
|
-- Create default user "guacadmin" with password "guacadmin"
|
||||||
|
INSERT INTO guacamole_entity (name, type) VALUES ('guacadmin', 'USER');
|
||||||
|
INSERT INTO guacamole_user (entity_id, password_hash, password_salt, password_date)
|
||||||
|
SELECT
|
||||||
|
entity_id,
|
||||||
|
x'CA458A7D494E3BE824F5E1E175A1556C0F8EEF2C2D7DF3633BEC4A29C4411960', -- 'guacadmin'
|
||||||
|
x'FE24ADC5E11E2B25288D1704ABE67A79E342ECC26064CE69C5B3177795A82264',
|
||||||
|
NOW()
|
||||||
|
FROM guacamole_entity WHERE name = 'guacadmin';
|
||||||
|
|
||||||
|
-- Grant this user all system permissions
|
||||||
|
INSERT INTO guacamole_system_permission (entity_id, permission)
|
||||||
|
SELECT entity_id, permission
|
||||||
|
FROM (
|
||||||
|
SELECT 'guacadmin' AS username, 'CREATE_CONNECTION' AS permission
|
||||||
|
UNION SELECT 'guacadmin' AS username, 'CREATE_CONNECTION_GROUP' AS permission
|
||||||
|
UNION SELECT 'guacadmin' AS username, 'CREATE_SHARING_PROFILE' AS permission
|
||||||
|
UNION SELECT 'guacadmin' AS username, 'CREATE_USER' AS permission
|
||||||
|
UNION SELECT 'guacadmin' AS username, 'CREATE_USER_GROUP' AS permission
|
||||||
|
UNION SELECT 'guacadmin' AS username, 'ADMINISTER' AS permission
|
||||||
|
) permissions
|
||||||
|
JOIN guacamole_entity ON permissions.username = guacamole_entity.name AND guacamole_entity.type = 'USER';
|
||||||
|
|
||||||
|
-- Grant admin permission to read/update/administer self
|
||||||
|
INSERT INTO guacamole_user_permission (entity_id, affected_user_id, permission)
|
||||||
|
SELECT guacamole_entity.entity_id, guacamole_user.user_id, permission
|
||||||
|
FROM (
|
||||||
|
SELECT 'guacadmin' AS username, 'guacadmin' AS affected_username, 'READ' AS permission
|
||||||
|
UNION SELECT 'guacadmin' AS username, 'guacadmin' AS affected_username, 'UPDATE' AS permission
|
||||||
|
UNION SELECT 'guacadmin' AS username, 'guacadmin' AS affected_username, 'ADMINISTER' AS permission
|
||||||
|
) permissions
|
||||||
|
JOIN guacamole_entity ON permissions.username = guacamole_entity.name AND guacamole_entity.type = 'USER'
|
||||||
|
JOIN guacamole_entity affected ON permissions.affected_username = affected.name AND guacamole_entity.type = 'USER'
|
||||||
|
JOIN guacamole_user ON guacamole_user.entity_id = affected.entity_id;
|
||||||
28
k8s-guacamole/ingress/ingress.yaml
Normal file
28
k8s-guacamole/ingress/ingress.yaml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: guacamole
|
||||||
|
namespace: guacamole
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
|
||||||
|
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
|
||||||
|
nginx.ingress.kubernetes.io/enable-websockets: "true"
|
||||||
|
spec:
|
||||||
|
ingressClassName: nginx
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- gua.manabo.org
|
||||||
|
secretName: guacamole-tls
|
||||||
|
rules:
|
||||||
|
- host: gua.manabo.org
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: guacamole
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
12
k8s-guacamole/kustomization.yaml
Normal file
12
k8s-guacamole/kustomization.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- deployments/guacamole-deployment.yaml
|
||||||
|
- deployments/mysql-deployment.yaml
|
||||||
|
- pvc/mysql-pvc.yaml
|
||||||
|
- services/guacamole-service.yaml
|
||||||
|
- services/mysql-service.yaml
|
||||||
|
- ingress/ingress.yaml
|
||||||
|
|
||||||
4
k8s-guacamole/namespace.yaml
Normal file
4
k8s-guacamole/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: guacamole
|
||||||
12
k8s-guacamole/pvc/mysql-pvc.yaml
Normal file
12
k8s-guacamole/pvc/mysql-pvc.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: mysql-pvc
|
||||||
|
namespace: guacamole
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
storageClassName: nfs-manabo
|
||||||
31
k8s-guacamole/readme.md
Normal file
31
k8s-guacamole/readme.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Manifiestos para Guacamole
|
||||||
|
|
||||||
|
Este repositorio contiene los manifiestos necesarios para desplegar [Apache Guacamole](https://guacamole.apache.org/) en un clúster Kubernetes. El despliegue incluye:
|
||||||
|
|
||||||
|
- Guacamole + Guacd (como contenedores en el mismo `Deployment`)
|
||||||
|
- MySQL 5.7 como backend de autenticación
|
||||||
|
- Ingreso expuesto mediante Ingress y cert-manager
|
||||||
|
- Inyección automatizada del esquema `full-schema.sql` usando un `initContainer` y un `ConfigMap`
|
||||||
|
|
||||||
|
> Apache Guacamole es un cliente remoto sin necesidad de plugins, accesible desde navegador, compatible con protocolos como VNC, RDP y SSH.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Despliegue
|
||||||
|
Aplica todos los manifiestos usando kustomize:
|
||||||
|
|
||||||
|
kubectl apply -k .
|
||||||
|
|
||||||
|
>Usuario/pass por defecto: ```guacadmin/guacadmin```
|
||||||
|
|
||||||
|
## Reinyectar full-schema.sql (por si no sale el configmap)
|
||||||
|
|
||||||
|
kubectl cp full-schema.sql -n guacamole $(kubectl get pod -n guacamole -l app=mysql -o jsonpath="{.items[0].metadata.name}"):/full-schema.sql
|
||||||
|
kubectl exec -n guacamole deploy/mysql -- bash -c "mysql -u root -pguacroot guacamole_db < /full-schema.sql"
|
||||||
|
|
||||||
|
## Comprobación
|
||||||
|
Para verificar que el usuario guacadmin ha sido creado correctamente:
|
||||||
|
|
||||||
|
kubectl exec -n guacamole deploy/mysql -it -- \
|
||||||
|
mysql -uguacuser -pguacpass -D guacamole_db -e \
|
||||||
|
"SELECT name FROM guacamole_entity WHERE type='USER';"
|
||||||
12
k8s-guacamole/services/guacamole-service.yaml
Normal file
12
k8s-guacamole/services/guacamole-service.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: guacamole
|
||||||
|
namespace: guacamole
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: guacamole
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 8080
|
||||||
10
k8s-guacamole/services/mysql-service.yaml
Normal file
10
k8s-guacamole/services/mysql-service.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: mysql
|
||||||
|
namespace: guacamole
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 3306
|
||||||
|
selector:
|
||||||
|
app: mysql
|
||||||
11
k8s-ingress-controller/configmap/configmap.yaml
Normal file
11
k8s-ingress-controller/configmap/configmap.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: ingress-nginx-controller
|
||||||
|
namespace: ingress-nginx
|
||||||
|
data:
|
||||||
|
allow-snippet-annotations: "true"
|
||||||
|
enable-ssl-passthrough: "false"
|
||||||
|
proxy-read-timeout: "3600"
|
||||||
|
proxy-send-timeout: "3600"
|
||||||
|
use-forwarded-headers: "true"
|
||||||
59
k8s-ingress-controller/deployments/deployment.yaml
Normal file
59
k8s-ingress-controller/deployments/deployment.yaml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: DaemonSet
|
||||||
|
metadata:
|
||||||
|
name: ingress-nginx-controller
|
||||||
|
namespace: ingress-nginx
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: ingress-nginx
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: ingress-nginx
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: ingress-nginx
|
||||||
|
spec:
|
||||||
|
serviceAccountName: ingress-nginx
|
||||||
|
containers:
|
||||||
|
- name: controller
|
||||||
|
image: registry.k8s.io/ingress-nginx/controller:v1.9.4
|
||||||
|
args:
|
||||||
|
- /nginx-ingress-controller
|
||||||
|
- --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
|
||||||
|
- --election-id=ingress-controller-leader
|
||||||
|
- --controller-class=k8s.io/ingress-nginx
|
||||||
|
- --ingress-class=nginx
|
||||||
|
env:
|
||||||
|
- name: POD_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.name
|
||||||
|
- name: POD_NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
name: http
|
||||||
|
protocol: TCP
|
||||||
|
- containerPort: 443
|
||||||
|
name: https
|
||||||
|
protocol: TCP
|
||||||
|
- containerPort: 10254
|
||||||
|
name: metrics
|
||||||
|
protocol: TCP
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 10254
|
||||||
|
scheme: HTTP
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 10254
|
||||||
|
scheme: HTTP
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
6
k8s-ingress-controller/ingressclass/ingressclass.yaml
Normal file
6
k8s-ingress-controller/ingressclass/ingressclass.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: IngressClass
|
||||||
|
metadata:
|
||||||
|
name: nginx
|
||||||
|
spec:
|
||||||
|
controller: k8s.io/ingress-nginx
|
||||||
9
k8s-ingress-controller/kustomization.yaml
Normal file
9
k8s-ingress-controller/kustomization.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- rbac/clusterrole.yaml
|
||||||
|
- rbac/clusterrolebinding.yaml
|
||||||
|
- rbac/serviceaccount.yaml
|
||||||
|
- configmap/configmap.yaml
|
||||||
|
- deployments/deployment.yaml
|
||||||
|
- services/service.yaml
|
||||||
|
- ingressclass/ingressclass.yaml
|
||||||
4
k8s-ingress-controller/namespace.yaml
Normal file
4
k8s-ingress-controller/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: ingress-nginx
|
||||||
62
k8s-ingress-controller/rbac/clusterrole.yaml
Normal file
62
k8s-ingress-controller/rbac/clusterrole.yaml
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: ingress-nginx
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
- endpoints
|
||||||
|
- nodes
|
||||||
|
- pods
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- nodes
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- services
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- networking.k8s.io
|
||||||
|
resources:
|
||||||
|
- ingresses
|
||||||
|
- ingressclasses
|
||||||
|
- ingresses/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- coordination.k8s.io
|
||||||
|
resources:
|
||||||
|
- leases
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- create
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- pods
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- apiGroups:
|
||||||
|
- discovery.k8s.io
|
||||||
|
resources:
|
||||||
|
- endpointslices
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
12
k8s-ingress-controller/rbac/clusterrolebinding.yaml
Normal file
12
k8s-ingress-controller/rbac/clusterrolebinding.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: ingress-nginx
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: ingress-nginx
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: ingress-nginx
|
||||||
|
namespace: ingress-nginx
|
||||||
5
k8s-ingress-controller/rbac/serviceaccount.yaml
Normal file
5
k8s-ingress-controller/rbac/serviceaccount.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: ingress-nginx
|
||||||
|
namespace: ingress-nginx
|
||||||
18
k8s-ingress-controller/services/service.yaml
Normal file
18
k8s-ingress-controller/services/service.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: ingress-nginx-controller
|
||||||
|
namespace: ingress-nginx
|
||||||
|
spec:
|
||||||
|
type: NodePort
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: ingress-nginx
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
|
nodePort: 30080
|
||||||
|
- name: https
|
||||||
|
port: 443
|
||||||
|
targetPort: 443
|
||||||
|
nodePort: 30443
|
||||||
37
k8s-kubevirt-isoserver/deployments/isoserver.yaml
Normal file
37
k8s-kubevirt-isoserver/deployments/isoserver.yaml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: iso-server
|
||||||
|
namespace: kubevirt
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: iso-server
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: iso-server
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: httpd
|
||||||
|
image: httpd:2.4
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
volumeMounts:
|
||||||
|
- name: iso-storage
|
||||||
|
mountPath: /usr/local/apache2/htdocs
|
||||||
|
- name: samba
|
||||||
|
image: dperson/samba
|
||||||
|
args: ["-p", "-s", "isos;/share;yes;no"]
|
||||||
|
ports:
|
||||||
|
- containerPort: 445
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 0
|
||||||
|
volumeMounts:
|
||||||
|
- name: iso-storage
|
||||||
|
mountPath: /share
|
||||||
|
volumes:
|
||||||
|
- name: iso-storage
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: iso-pvc
|
||||||
25
k8s-kubevirt-isoserver/ingress/ingress.yaml
Normal file
25
k8s-kubevirt-isoserver/ingress/ingress.yaml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: iso-server
|
||||||
|
namespace: kubevirt
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
# nginx.ingress.kubernetes.io/whitelist-source-range: "192.168.1.0/24"
|
||||||
|
spec:
|
||||||
|
ingressClassName: nginx
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- isoserver.manabo.org
|
||||||
|
secretName: isoserver-tls
|
||||||
|
rules:
|
||||||
|
- host: isoserver.manabo.org
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: iso-server
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
6
k8s-kubevirt-isoserver/kustomization.yaml
Normal file
6
k8s-kubevirt-isoserver/kustomization.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- pvc/iso-pvc.yaml
|
||||||
|
- deployments/isoserver.yaml
|
||||||
|
- services/service.yaml
|
||||||
|
- ingress/ingress.yaml
|
||||||
4
k8s-kubevirt-isoserver/namespace.yaml
Normal file
4
k8s-kubevirt-isoserver/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: kubevirt
|
||||||
12
k8s-kubevirt-isoserver/pvc/iso-pvc.yaml
Normal file
12
k8s-kubevirt-isoserver/pvc/iso-pvc.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: iso-pvc
|
||||||
|
namespace: kubevirt
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteMany
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 800Gi
|
||||||
|
storageClassName: nfs-manabo
|
||||||
34
k8s-kubevirt-isoserver/readme.md
Normal file
34
k8s-kubevirt-isoserver/readme.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Manifiestos para servidor HTTP de imágenes ISO (KubeVirt ISO Server)
|
||||||
|
|
||||||
|
Este repositorio contiene los manifiestos necesarios para desplegar un servidor HTTP basado en Apache (httpd:2.4) que sirve una carpeta compartida con archivos ISO, accesible por KubeVirt para instalar sistemas operativos en máquinas virtuales.
|
||||||
|
|
||||||
|
>El almacenamiento se expone desde un servidor externo NFS (por ejemplo, niflheim) con las imágenes ISO ubicadas en /mnt/Iso.
|
||||||
|
|
||||||
|
## Requisitos:
|
||||||
|
|
||||||
|
- El servidor NFS debe exportar la ruta /mnt/Iso con permisos RO (solo lectura) para la red del clúster.
|
||||||
|
- Las ISOs deben estar copiadas dentro de /mnt/Iso.
|
||||||
|
- Debes tener configurado nfs-common en todos los nodos del clúster.
|
||||||
|
|
||||||
|
### Despliegue manual:
|
||||||
|
Entra al repositorio:
|
||||||
|
|
||||||
|
cd ~/k3s/k8s-kubevirt-isoserver
|
||||||
|
|
||||||
|
Aplica los manifiestos en orden:
|
||||||
|
|
||||||
|
kubectl apply -f namespace.yaml
|
||||||
|
kubectl apply -f pv/iso-pv.yaml
|
||||||
|
kubectl apply -f pv/iso-pvc.yaml
|
||||||
|
kubectl apply -f deployments/httpd.yaml
|
||||||
|
kubectl apply -f services/httpd.yaml
|
||||||
|
|
||||||
|
### Acceso:
|
||||||
|
|
||||||
|
El servicio httpd queda expuesto por un NodePort que puedes consultar con:
|
||||||
|
|
||||||
|
kubectl get svc -n iso-server
|
||||||
|
|
||||||
|
>Despues de pasarlo por npm, puedes montar esta URL como cdrom o disk en tus VirtualMachine (VM) manifests, usando por ejemplo:
|
||||||
|
|
||||||
|
http://iso-server.manabo.org/windows.iso
|
||||||
20
k8s-kubevirt-isoserver/services/service.yaml
Normal file
20
k8s-kubevirt-isoserver/services/service.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: iso-server
|
||||||
|
namespace: kubevirt
|
||||||
|
spec:
|
||||||
|
type: NodePort
|
||||||
|
selector:
|
||||||
|
app: iso-server
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
|
nodePort: 30088 # Puerto externo HTTP
|
||||||
|
- name: samba
|
||||||
|
port: 445
|
||||||
|
targetPort: 445
|
||||||
|
nodePort: 30445 # Puerto externo Samba
|
||||||
|
externalIPs:
|
||||||
|
- 192.168.1.9
|
||||||
24
k8s-kubevirt-manager/deployments/deployment.yaml
Normal file
24
k8s-kubevirt-manager/deployments/deployment.yaml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: kubevirt-manager
|
||||||
|
namespace: kubevirt-manager
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: kubevirt-manager
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: kubevirt-manager
|
||||||
|
spec:
|
||||||
|
serviceAccountName: kubevirt-manager
|
||||||
|
containers:
|
||||||
|
- name: kubevirt-manager
|
||||||
|
image: kubevirtmanager/kubevirt-manager:1.4.0
|
||||||
|
ports:
|
||||||
|
- containerPort: 8001
|
||||||
|
env:
|
||||||
|
- name: BACKEND_URL
|
||||||
|
value: "http://localhost:8080"
|
||||||
26
k8s-kubevirt-manager/ingress/ingress.yaml
Normal file
26
k8s-kubevirt-manager/ingress/ingress.yaml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: kubevirt-manager
|
||||||
|
namespace: kubevirt-manager
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
||||||
|
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
|
||||||
|
spec:
|
||||||
|
ingressClassName: nginx
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- kubevirt.manabo.org
|
||||||
|
secretName: kubevirt-manager-tls
|
||||||
|
rules:
|
||||||
|
- host: kubevirt.manabo.org
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: kubevirt-manager
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
7
k8s-kubevirt-manager/kustomization.yaml
Normal file
7
k8s-kubevirt-manager/kustomization.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- deployments/deployment.yaml
|
||||||
|
- services/service.yaml
|
||||||
|
- ingress/ingress.yaml
|
||||||
|
- rbac/serviceaccount.yaml
|
||||||
|
- rbac/clusterrolebinding.yaml
|
||||||
4
k8s-kubevirt-manager/namespace.yaml
Normal file
4
k8s-kubevirt-manager/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: kubevirt-manager
|
||||||
12
k8s-kubevirt-manager/rbac/clusterrolebinding.yaml
Normal file
12
k8s-kubevirt-manager/rbac/clusterrolebinding.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: kubevirt-manager
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: cluster-admin
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: kubevirt-manager
|
||||||
|
namespace: kubevirt-manager
|
||||||
6
k8s-kubevirt-manager/rbac/serviceaccount.yaml
Normal file
6
k8s-kubevirt-manager/rbac/serviceaccount.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: kubevirt-manager
|
||||||
|
namespace: kubevirt-manager
|
||||||
|
|
||||||
13
k8s-kubevirt-manager/services/service.yaml
Normal file
13
k8s-kubevirt-manager/services/service.yaml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: kubevirt-manager
|
||||||
|
namespace: kubevirt-manager
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: kubevirt-manager
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 8001
|
||||||
|
protocol: TCP
|
||||||
|
type: ClusterIP
|
||||||
20
k8s-master/apps/external-router.yaml.pause
Normal file
20
k8s-master/apps/external-router.yaml.pause
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: k8s-external-router
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'http://192.168.1.9:30300/xavor/k8s-external-router.git' # ← ajusta si hace falta
|
||||||
|
targetRevision: HEAD
|
||||||
|
path: .
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: external-router
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
20
k8s-master/apps/gitea.yaml
Normal file
20
k8s-master/apps/gitea.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: gitea
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'http://192.168.1.9:30300/xavor/k8s-gitea.git'
|
||||||
|
targetRevision: HEAD
|
||||||
|
path: .
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: gitea
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
20
k8s-master/apps/guacamole.yaml
Normal file
20
k8s-master/apps/guacamole.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: guacamole
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'http://192.168.1.9:30300/xavor/k8s-guacamole.git'
|
||||||
|
targetRevision: HEAD
|
||||||
|
path: .
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: guacamole
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
20
k8s-master/apps/ingress-controller.yaml
Normal file
20
k8s-master/apps/ingress-controller.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: ingress-controller
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'http://192.168.1.9:30300/xavor/k8s-ingress-controller.git'
|
||||||
|
targetRevision: HEAD
|
||||||
|
path: .
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: ingress-nginx
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
20
k8s-master/apps/kubevirt-isoserver.yaml
Normal file
20
k8s-master/apps/kubevirt-isoserver.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: kubevirt-isoserver
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'http://192.168.1.9:30300/xavor/k8s-kubevirt-isoserver.git'
|
||||||
|
targetRevision: HEAD
|
||||||
|
path: .
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: kubevirt
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
20
k8s-master/apps/storage.yaml
Normal file
20
k8s-master/apps/storage.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: storage
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'http://192.168.1.9:30300/xavor/k8s-storage.git'
|
||||||
|
targetRevision: HEAD
|
||||||
|
path: .
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: storage
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
20
k8s-master/apps/vm-windows-demo.yaml
Normal file
20
k8s-master/apps/vm-windows-demo.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: k8s-vm-windows-demo
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'http://192.168.1.9:30300/xavor/k8s-vm-windows-demo.git'
|
||||||
|
targetRevision: HEAD
|
||||||
|
path: .
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: k8s-vm-windows-demo
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
20
k8s-master/apps/vscode.yaml
Normal file
20
k8s-master/apps/vscode.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: vscode
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: 'http://192.168.1.9:30300/xavor/k8s-vscode.git'
|
||||||
|
targetRevision: HEAD
|
||||||
|
path: .
|
||||||
|
destination:
|
||||||
|
server: 'https://kubernetes.default.svc'
|
||||||
|
namespace: vscode
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
4
k8s-master/readme.md
Normal file
4
k8s-master/readme.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Manifiestos para K8S-Master
|
||||||
|
Este repositorio define una "App de apps" para Argo CD. Actúa como punto central de sincronización del clúster, permitiendo desplegar automáticamente cada aplicación (como Gitea o NPM) de forma desacoplada mediante repositorios independientes.
|
||||||
|
|
||||||
|
>No contiene recursos a aplicar directamente con kubectl, sino que se utiliza desde la interfaz o los manifiestos de Argo CD como raíz de sincronización.
|
||||||
41
k8s-storage/deployments/nfs-client-provisioner.yaml
Normal file
41
k8s-storage/deployments/nfs-client-provisioner.yaml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nfs-client-provisioner
|
||||||
|
namespace: nfs-provisioner
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: nfs-client-provisioner
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nfs-client-provisioner
|
||||||
|
spec:
|
||||||
|
serviceAccountName: nfs-client-provisioner
|
||||||
|
containers:
|
||||||
|
- name: nfs-client-provisioner
|
||||||
|
image: k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
|
||||||
|
volumeMounts:
|
||||||
|
- name: nfs-client-root
|
||||||
|
mountPath: /persistentvolumes
|
||||||
|
env:
|
||||||
|
- name: PROVISIONER_NAME
|
||||||
|
value: k8s-sigs.io/nfs-subdir-external-provisioner
|
||||||
|
- name: NFS_SERVER
|
||||||
|
value: 192.168.3.3 # VLAN 30 IP de niflheim
|
||||||
|
- name: NFS_PATH
|
||||||
|
value: /
|
||||||
|
- name: LABELS
|
||||||
|
value: "namespace,pvcName"
|
||||||
|
volumes:
|
||||||
|
- name: nfs-client-root
|
||||||
|
nfs:
|
||||||
|
server: 192.168.3.3
|
||||||
|
path: /
|
||||||
|
tolerations:
|
||||||
|
- key: "storage"
|
||||||
|
operator: "Equal"
|
||||||
|
value: "only"
|
||||||
|
effect: "NoSchedule"
|
||||||
43
k8s-storage/deployments/nfs-server.yaml
Normal file
43
k8s-storage/deployments/nfs-server.yaml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nfs-server
|
||||||
|
namespace: nfs-provisioner
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: nfs-server
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nfs-server
|
||||||
|
spec:
|
||||||
|
hostNetwork: true
|
||||||
|
containers:
|
||||||
|
- name: nfs-server
|
||||||
|
image: itsthenetwork/nfs-server-alpine:latest
|
||||||
|
ports:
|
||||||
|
- name: nfs
|
||||||
|
containerPort: 2049
|
||||||
|
protocol: TCP
|
||||||
|
securityContext:
|
||||||
|
privileged: true
|
||||||
|
env:
|
||||||
|
- name: SHARED_DIRECTORY
|
||||||
|
value: /nfsshare
|
||||||
|
volumeMounts:
|
||||||
|
- name: nfs-data
|
||||||
|
mountPath: /nfsshare
|
||||||
|
volumes:
|
||||||
|
- name: nfs-data
|
||||||
|
hostPath:
|
||||||
|
path: /mnt/storage/k8s/nfsshare
|
||||||
|
type: Directory
|
||||||
|
tolerations:
|
||||||
|
- key: "storage"
|
||||||
|
operator: "Equal"
|
||||||
|
value: "only"
|
||||||
|
effect: "NoSchedule"
|
||||||
|
nodeSelector:
|
||||||
|
kubernetes.io/hostname: niflheim
|
||||||
8
k8s-storage/kustomization.yaml
Normal file
8
k8s-storage/kustomization.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- rbac/clusterrolebinding.yaml
|
||||||
|
- rbac/clusterrole.yaml
|
||||||
|
- rbac/serviceaccount.yaml
|
||||||
|
- deployments/nfs-server.yaml
|
||||||
|
- deployments/nfs-client-provisioner.yaml
|
||||||
|
- storageclass/storageclass.yaml
|
||||||
4
k8s-storage/namespace.yaml
Normal file
4
k8s-storage/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: nfs-provisioner
|
||||||
20
k8s-storage/rbac/clusterrole.yaml
Normal file
20
k8s-storage/rbac/clusterrole.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
kind: ClusterRole
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: nfs-client-provisioner-runner
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["persistentvolumes"]
|
||||||
|
verbs: ["get", "list", "watch", "create", "delete"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["persistentvolumeclaims"]
|
||||||
|
verbs: ["get", "list", "watch", "update"]
|
||||||
|
- apiGroups: ["storage.k8s.io"]
|
||||||
|
resources: ["storageclasses"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["events"]
|
||||||
|
verbs: ["create", "update", "patch"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["endpoints"]
|
||||||
|
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||||
12
k8s-storage/rbac/clusterrolebinding.yaml
Normal file
12
k8s-storage/rbac/clusterrolebinding.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: run-nfs-client-provisioner
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: nfs-client-provisioner
|
||||||
|
namespace: nfs-provisioner
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: nfs-client-provisioner-runner
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
5
k8s-storage/rbac/serviceaccount.yaml
Normal file
5
k8s-storage/rbac/serviceaccount.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: nfs-client-provisioner
|
||||||
|
namespace: nfs-provisioner
|
||||||
17
k8s-storage/readme.md
Normal file
17
k8s-storage/readme.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# k8s-storage
|
||||||
|
|
||||||
|
Este m<>dulo despliega un driver de almacenamiento din<69>mico basado en NFS, apuntando a un servidor ZFS (`niflheim`, 192.168.1.10) con la ruta `/mnt/storage/k8s`.
|
||||||
|
|
||||||
|
## Componentes incluidos
|
||||||
|
|
||||||
|
- Namespace `nfs-provisioner`
|
||||||
|
- RBAC necesario
|
||||||
|
- Deployment del provisioner din<69>mico
|
||||||
|
- StorageClass predeterminado `nfs-manabo`
|
||||||
|
|
||||||
|
## C<>mo aplicar
|
||||||
|
|
||||||
|
kubectl apply -f namespace.yaml
|
||||||
|
kubectl apply -f rbac/
|
||||||
|
kubectl apply -f deployment/
|
||||||
|
kubectl apply -f storageclass/
|
||||||
9
k8s-storage/storageclass/storageclass.yaml
Normal file
9
k8s-storage/storageclass/storageclass.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
apiVersion: storage.k8s.io/v1
|
||||||
|
kind: StorageClass
|
||||||
|
metadata:
|
||||||
|
name: nfs-manabo
|
||||||
|
annotations:
|
||||||
|
storageclass.kubernetes.io/is-default-class: "true"
|
||||||
|
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
|
||||||
|
reclaimPolicy: Retain
|
||||||
|
volumeBindingMode: Immediate
|
||||||
16
k8s-vm-windows-demo/data-volume.yaml
Normal file
16
k8s-vm-windows-demo/data-volume.yaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
apiVersion: cdi.kubevirt.io/v1beta1
|
||||||
|
kind: DataVolume
|
||||||
|
metadata:
|
||||||
|
name: windows-disk
|
||||||
|
namespace: k8s-vm-windows-demo
|
||||||
|
spec:
|
||||||
|
source:
|
||||||
|
http:
|
||||||
|
url: "https://isoserver.manabo.org/Windows.iso"
|
||||||
|
pvc:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 60Gi
|
||||||
|
storageClassName: nfs-manabo
|
||||||
6
k8s-vm-windows-demo/kustomization.yaml
Normal file
6
k8s-vm-windows-demo/kustomization.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- virtual-machine.yaml
|
||||||
|
- data-volume.yaml
|
||||||
4
k8s-vm-windows-demo/namespace.yaml
Normal file
4
k8s-vm-windows-demo/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: k8s-vm-windows-demo
|
||||||
50
k8s-vm-windows-demo/virtual-machine.yaml
Normal file
50
k8s-vm-windows-demo/virtual-machine.yaml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
apiVersion: kubevirt.io/v1
|
||||||
|
kind: VirtualMachine
|
||||||
|
metadata:
|
||||||
|
name: windows-demo
|
||||||
|
namespace: k8s-vm-windows-demo
|
||||||
|
spec:
|
||||||
|
running: true
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
kubevirt.io/domain: windows-demo
|
||||||
|
spec:
|
||||||
|
domain:
|
||||||
|
cpu:
|
||||||
|
cores: 2
|
||||||
|
devices:
|
||||||
|
disks:
|
||||||
|
- name: cdromiso
|
||||||
|
cdrom:
|
||||||
|
bus: sata
|
||||||
|
- name: harddrive
|
||||||
|
disk:
|
||||||
|
bus: virtio
|
||||||
|
- disk:
|
||||||
|
bus: virtio
|
||||||
|
name: cloudinitdisk
|
||||||
|
interfaces:
|
||||||
|
- name: default
|
||||||
|
masquerade: {}
|
||||||
|
machine:
|
||||||
|
type: q35
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: 4Gi
|
||||||
|
volumes:
|
||||||
|
- name: cdromiso
|
||||||
|
containerDisk:
|
||||||
|
image: kubevirt/cirros-container-disk-demo # se reemplazará en DataVolume
|
||||||
|
- name: harddrive
|
||||||
|
dataVolume:
|
||||||
|
name: windows-disk
|
||||||
|
- name: cloudinitdisk
|
||||||
|
cloudInitNoCloud:
|
||||||
|
userData: |
|
||||||
|
#cloud-config
|
||||||
|
password: "Windows1234"
|
||||||
|
chpasswd: { expire: False }
|
||||||
|
networks:
|
||||||
|
- name: default
|
||||||
|
pod: {}
|
||||||
30
k8s-vscode/deployments/vscode.yaml
Normal file
30
k8s-vscode/deployments/vscode.yaml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: vscode
|
||||||
|
namespace: vscode
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: vscode
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: vscode
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: vscode
|
||||||
|
image: xavor/vscode-custom:latest
|
||||||
|
ports:
|
||||||
|
- containerPort: 8443
|
||||||
|
env:
|
||||||
|
- name: PASSWORD
|
||||||
|
value: "M@nabo2025"
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /home/coder/project
|
||||||
|
name: vscode-data
|
||||||
|
volumes:
|
||||||
|
- name: vscode-data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: vscode-data
|
||||||
25
k8s-vscode/ingress/ingress.yaml
Normal file
25
k8s-vscode/ingress/ingress.yaml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: vscode
|
||||||
|
namespace: vscode
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
|
||||||
|
spec:
|
||||||
|
ingressClassName: nginx
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- vscode.manabo.org
|
||||||
|
secretName: vscode-tls
|
||||||
|
rules:
|
||||||
|
- host: vscode.manabo.org
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: vscode
|
||||||
|
port:
|
||||||
|
number: 8080
|
||||||
6
k8s-vscode/kustomization.yaml
Normal file
6
k8s-vscode/kustomization.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- pvc/vscode-pvc.yaml
|
||||||
|
- deployments/vscode.yaml
|
||||||
|
- services/vscode.yaml
|
||||||
|
- ingress/ingress.yaml
|
||||||
4
k8s-vscode/namespace.yaml
Normal file
4
k8s-vscode/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: vscode
|
||||||
12
k8s-vscode/pvc/vscode-pvc.yaml
Normal file
12
k8s-vscode/pvc/vscode-pvc.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: vscode-data
|
||||||
|
namespace: vscode
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 5Gi
|
||||||
|
storageClassName: nfs-manabo
|
||||||
263
k8s-vscode/readme.md
Normal file
263
k8s-vscode/readme.md
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
# 🚀 Virtualización Next-Gen: Clúster K3s con DevOps: manual de instalacion
|
||||||
|
|
||||||
|
## 1. Instalar el sistema operativo en ambos servidores
|
||||||
|
|
||||||
|
Configurar bonding (bond0) en ambos servidores como interfaz principal.
|
||||||
|
- Configurar IP fija de la red (ejemplo):
|
||||||
|
|
||||||
|
- tartaro: 192.168.1.7
|
||||||
|
- styx: 192.168.1.8
|
||||||
|
- niflheim: 192.168.1.10
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Preparación básica del sistema
|
||||||
|
|
||||||
|
En **todos los servidores**:
|
||||||
|
|
||||||
|
sudo apt update && sudo apt upgrade -y
|
||||||
|
sudo apt install -y keepalived nfs-common
|
||||||
|
|
||||||
|
> Asegúrate de tener los manifiestos clonados desde Gitea o preparados localmente antes de empezar.
|
||||||
|
|
||||||
|
### Configuración de ZFS en `niflheim`
|
||||||
|
|
||||||
|
1. Instalar ZFS:
|
||||||
|
|
||||||
|
sudo apt install -y zfsutils-linux
|
||||||
|
|
||||||
|
|
||||||
|
2. Crear el pool ZFS con los 4 discos Toshiba (RAID10 con 2 espejos):
|
||||||
|
|
||||||
|
sudo zpool create -o ashift=12 k8spool mirror /dev/sda /dev/sdb mirror /dev/sdc /dev/sde
|
||||||
|
|
||||||
|
3. Crear dataset:
|
||||||
|
|
||||||
|
sudo zfs create k8spool/k8s
|
||||||
|
sudo zfs set mountpoint=/mnt/storage/k8s k8spool/k8s
|
||||||
|
sudo zfs set compression=lz4 k8spool/k8s
|
||||||
|
sudo chown nobody:nogroup /mnt/storage/k8s
|
||||||
|
|
||||||
|
4. Verificar:
|
||||||
|
|
||||||
|
sudo zpool status
|
||||||
|
sudo zfs list
|
||||||
|
sudo zfs get compression k8spool/k8s
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Configuración de Keepalived
|
||||||
|
|
||||||
|
En tartaro (MASTER):
|
||||||
|
|
||||||
|
`sudo nano /etc/keepalived/keepalived.conf`
|
||||||
|
|
||||||
|
vrrp_instance VI_1 {
|
||||||
|
state MASTER
|
||||||
|
interface bond0
|
||||||
|
virtual_router_id 51
|
||||||
|
priority 150
|
||||||
|
advert_int 1
|
||||||
|
authentication {
|
||||||
|
auth_type PASS
|
||||||
|
auth_pass 42manabo42
|
||||||
|
}
|
||||||
|
virtual_ipaddress {
|
||||||
|
192.168.1.9/24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
En styx (BACKUP):
|
||||||
|
|
||||||
|
`sudo nano /etc/keepalived/keepalived.conf`
|
||||||
|
|
||||||
|
vrrp_instance VI_1 {
|
||||||
|
state BACKUP
|
||||||
|
interface bond0
|
||||||
|
virtual_router_id 51
|
||||||
|
priority 100
|
||||||
|
advert_int 1
|
||||||
|
authentication {
|
||||||
|
auth_type PASS
|
||||||
|
auth_pass 42manabo42
|
||||||
|
}
|
||||||
|
virtual_ipaddress {
|
||||||
|
192.168.1.9/24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Después en ambos:
|
||||||
|
|
||||||
|
sudo systemctl enable keepalived
|
||||||
|
sudo systemctl start keepalived
|
||||||
|
|
||||||
|
## 4. Instalar K3s
|
||||||
|
En `tartaro` (control plane principal):
|
||||||
|
|
||||||
|
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--cluster-init --disable traefik --write-kubeconfig-mode 644 --node-name tartaro --tls-san 192.168.1.7 --tls-san 192.168.1.9" sh -
|
||||||
|
|
||||||
|
Obtener token:
|
||||||
|
|
||||||
|
sudo cat /var/lib/rancher/k3s/server/node-token
|
||||||
|
|
||||||
|
En `styx` (segundo nodo):
|
||||||
|
|
||||||
|
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --node-name styx --disable traefik" \
|
||||||
|
K3S_URL=https://192.168.1.7:6443 \
|
||||||
|
K3S_TOKEN="token" \
|
||||||
|
sh -
|
||||||
|
|
||||||
|
En `niflheim` (control plane adicional, dedicado exclusivamente a almacenamiento):
|
||||||
|
|
||||||
|
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --node-name niflheim --disable traefik --node-taint storage=only:NoSchedule" \
|
||||||
|
K3S_URL=https://192.168.1.7:6443 \
|
||||||
|
K3S_TOKEN="token" \
|
||||||
|
sh -
|
||||||
|
|
||||||
|
### Verificar estado del clúster
|
||||||
|
|
||||||
|
Desde tartaro (o con el kubeconfig copiado):
|
||||||
|
|
||||||
|
kubectl get nodes
|
||||||
|
|
||||||
|
En styx, niflheim para permitir acceso al kubeconfig:
|
||||||
|
|
||||||
|
sudo chmod 644 /etc/rancher/k3s/k3s.yaml
|
||||||
|
|
||||||
|
## 5. Instalar driver de almacenamiento.
|
||||||
|
|
||||||
|
En **Tartaro** (o en el nodo donde previamente hayamos clonado los repositorios):
|
||||||
|
|
||||||
|
cd ~/k3s/k8s-storage/
|
||||||
|
kubectl apply -k .
|
||||||
|
|
||||||
|
Comprobar:
|
||||||
|
|
||||||
|
kubectl get pods -n nfs-provisioner
|
||||||
|
|
||||||
|
## 6. Desplegar sistema automatizado de Ingress
|
||||||
|
|
||||||
|
### Redirección de puertos desde el router
|
||||||
|
|
||||||
|
- Hay que hacer port forwarding de puertos externos 80 y 443 a la IP virtual de Keepalived (192.168.1.9)
|
||||||
|
- El `NodePort` está configurado en el manifiesto como:
|
||||||
|
- 30080 → 80 (HTTP)
|
||||||
|
- 30443 → 443 (HTTPS)
|
||||||
|
- Por lo tanto la redireccion sera:
|
||||||
|
- de 80 a 192.168.1.9:30080
|
||||||
|
- de 443 a 192.168.1.9:30443
|
||||||
|
|
||||||
|
>Si necesitamos ver los puertos en uso podemos listarlos por la via rapida con el comando:
|
||||||
|
|
||||||
|
kubectl get svc --all-namespaces -o jsonpath="{range .items[*]}{.metadata.namespace}:{.metadata.name} → {.spec.ports[*].nodePort}{'\n'}{end}" | grep -v "→ $"
|
||||||
|
|
||||||
|
### Desplegar cert-manager
|
||||||
|
|
||||||
|
cd ~/k3s/k8s-cert-manager/
|
||||||
|
kubectl apply -f namespace.yaml
|
||||||
|
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
|
||||||
|
kubectl apply -f clusterissuer-staging.yaml
|
||||||
|
kubectl apply -f clusterissuer-prod.yaml
|
||||||
|
|
||||||
|
### Desplegar ingress-controller
|
||||||
|
|
||||||
|
cd ~/k3s/k8s-ingress-controller/
|
||||||
|
kubectl apply -k .
|
||||||
|
|
||||||
|
## 7. Desplegar Gitea manualmente
|
||||||
|
|
||||||
|
### En Tartaro (o en el nodo donde hayas copiado los repositorios)
|
||||||
|
|
||||||
|
cd ~/k3s/k8s-gitea/
|
||||||
|
kubectl apply -k .
|
||||||
|
|
||||||
|
Comprueba que los pods estén en estado `Running`:
|
||||||
|
|
||||||
|
kubectl get pods -n gitea -w
|
||||||
|
|
||||||
|
>Con acceso ya a gitea, seria el momento de crear todos los repositorios remotos. Es una buena idea apoyarnos en [git-publish](herramienta%20git-publish.md).
|
||||||
|
>Si tambien te has hartado de teclear git-publish, tambien tenemos un script para ti: [publicar-todos](herramienta%20publicar-todos.md)
|
||||||
|
|
||||||
|
## 8. Instalar ArgoCD
|
||||||
|
|
||||||
|
### En Tartaro (o donde tengamos los manifiestos locales clonados de Gitea)
|
||||||
|
|
||||||
|
cd ~/k3s/k8s-argocd/
|
||||||
|
kubectl apply -f namespace.yaml
|
||||||
|
# Instalar ArgoCD desde manifiesto oficial (26000 líneas aprox)
|
||||||
|
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
|
||||||
|
kubectl apply -f services/argocd.yaml
|
||||||
|
kubectl apply -f ingress/ingress.yaml
|
||||||
|
|
||||||
|
### Acceder
|
||||||
|
>Crear acceso en NPM es lo mas adecuado.
|
||||||
|
|
||||||
|
Se puede obtener la contraseña de admin con:
|
||||||
|
|
||||||
|
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo
|
||||||
|
|
||||||
|
### Crear la App of Apps
|
||||||
|
En la interfaz web:
|
||||||
|
1. Name: app-of-apps (todo en minúsculas)
|
||||||
|
2. Project: default
|
||||||
|
3. Repository URL: el repositorio k8s-master en Gitea: https://git.manabo.org/xavor/k8s-master.git
|
||||||
|
4. Path: apps
|
||||||
|
5. Cluster URL: https://kubernetes.default.svc
|
||||||
|
6. Namespace: argocd
|
||||||
|
7. Sync policy: automática
|
||||||
|
8. Marca las casillas: `AUTO-CREATE NAMESPACE` `PRUNE` `SELF HEAL` `DIRECTORY RECURSE`
|
||||||
|
|
||||||
|
## 9. Instalar KubeVirt
|
||||||
|
KubeVirt permite crear y gestionar máquinas virtuales dentro de Kubernetes. Es compatible con el entorno actual y se integra fácilmente con el resto de recursos.
|
||||||
|
|
||||||
|
### Instalación manual del operador y CR
|
||||||
|
Desde cualquier nodo con kubectl configurado, ejecutar:
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
### Comprobar despliegue
|
||||||
|
|
||||||
|
kubectl get pods -n kubevirt
|
||||||
|
|
||||||
|
### Instalar virtctl (herramienta de cliente)
|
||||||
|
Virtctl es una herramienta de línea de comandos para gestionar máquinas virtuales con KubeVirt
|
||||||
|
|
||||||
|
export KUBEVIRT_VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases/latest | grep tag_name | cut -d '"' -f 4)
|
||||||
|
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/
|
||||||
|
|
||||||
|
## 10. Desplegar servidor HTTP para ISOs (KubeVirt ISO Server)
|
||||||
|
|
||||||
|
El servidor de ISOs se encarga de exponer vía HTTP las imágenes necesarias para el despliegue de sistemas operativos en máquinas virtuales con KubeVirt.
|
||||||
|
|
||||||
|
## 11. Desplegar Apache Guacamole
|
||||||
|
|
||||||
|
Guacamole permite conectarse desde el navegador a escritorios remotos a través de protocolos como VNC, RDP o SSH, sin necesidad de plugins. Se despliega con autenticación MySQL y se expone mediante Ingress con TLS automatizado por cert-manager.
|
||||||
|
>⚠️ Es necesario inyectar manualmente el esquema SQL de la base de datos tras el despliegue.
|
||||||
|
|
||||||
|
## Inyectar full-schema.sql
|
||||||
|
|
||||||
|
cd ~/k3s/k8s-guacamole/
|
||||||
|
kubectl cp full-schema.sql -n guacamole \
|
||||||
|
$(kubectl get pod -n guacamole -l app=mysql -o jsonpath="{.items[0].metadata.name}"):/full-schema.sql
|
||||||
|
|
||||||
|
kubectl exec -n guacamole deploy/mysql -- \
|
||||||
|
bash -c "mysql -u root -pguacroot guacamole_db < /full-schema.sql"
|
||||||
|
|
||||||
|
## Comprobación
|
||||||
|
Para verificar que el usuario guacadmin ha sido creado correctamente:
|
||||||
|
|
||||||
|
kubectl exec -n guacamole deploy/mysql -it -- \
|
||||||
|
mysql -uguacuser -pguacpass -D guacamole_db -e \
|
||||||
|
"SELECT name FROM guacamole_entity WHERE type='USER';"
|
||||||
|
|
||||||
|
>Usuario/pass por defecto: ```guacadmin/guacadmin```
|
||||||
12
k8s-vscode/services/vscode.yaml
Normal file
12
k8s-vscode/services/vscode.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: vscode
|
||||||
|
namespace: vscode
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: vscode
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
targetPort: 8080
|
||||||
11
publicar-todos.sh
Normal file
11
publicar-todos.sh
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Recorre todas las carpetas que empiecen por k8s-
|
||||||
|
for dir in k8s-*; do
|
||||||
|
if [ -d "$dir" ]; then
|
||||||
|
echo "📦 Entrando en $dir"
|
||||||
|
cd "$dir"
|
||||||
|
git-publish "Manifiestos de ${dir}"
|
||||||
|
cd ..
|
||||||
|
fi
|
||||||
|
done
|
||||||
98
readme.md
Normal file
98
readme.md
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
# 🚀 Virtualización Next-Gen: Clúster K3s con DevOps
|
||||||
|
|
||||||
|
Bienvenido a **Virtualización Next-Gen**, una guía práctica y modular para desplegar un clúster Kubernetes con [K3s](https://k3s.io/), alta disponibilidad, almacenamiento centralizado, ingress con TLS automático y soporte para máquinas virtuales con KubeVirt. Todo está versionado en Git y gestionado con Argo CD.
|
||||||
|
|
||||||
|
Este repositorio está orientado tanto a **homelabs avanzados** como a entornos **profesionales** que buscan una infraestructura reproducible, automatizada y documentada.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧭 Tabla de contenidos
|
||||||
|
|
||||||
|
| Sección | Descripción |
|
||||||
|
|--------|-------------|
|
||||||
|
| [📘 Guía de instalación](docs/guia-instalacion.md) | Paso a paso para desplegar el clúster completo. |
|
||||||
|
| [🏗️ Arquitectura del clúster](docs/arquitectura.md) | Estructura lógica, roles de nodos y servicios desplegados. |
|
||||||
|
| [🛠️ Herramientas auxiliares](docs/herramientas-auxiliares.md) | Scripts para automatizar tareas como publicar, clonar o subir repos. |
|
||||||
|
| [📚 Procedimientos adicionales](docs/procedimientos-adicionales.md) | Tareas puntuales como eliminar namespaces atascados o cargas manuales. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙️ Componentes clave del clúster
|
||||||
|
|
||||||
|
- **Alta disponibilidad** con IP flotante (`keepalived`) y bonding de red (`bond0`)
|
||||||
|
- **K3s cluster** en `tartaro`, `styx` y `niflheim` (dedicado a almacenamiento)
|
||||||
|
- **ZFS + NFS** como backend de almacenamiento
|
||||||
|
- **Ingress TLS automatizado** con cert-manager + ingress-nginx
|
||||||
|
- **Gitea** como Git server para los manifiestos
|
||||||
|
- **Argo CD** para despliegue GitOps (App of Apps)
|
||||||
|
- **KubeVirt** para gestionar VMs dentro de Kubernetes
|
||||||
|
- **Apache Guacamole** para acceso remoto a escritorios vía navegador
|
||||||
|
- **VS Code Server** desplegado como pod accesible por Ingress
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📂 Estructura del repositorio
|
||||||
|
|
||||||
|
Estructura del repositorio:
|
||||||
|
- docs/: Carpeta de documentación con guías y herramientas auxiliares.
|
||||||
|
- guia-instalacion.md: Manual paso a paso para desplegar todo el clúster.
|
||||||
|
- herramienta git-publish.md: Explica el script para publicar repositorios individuales en Gitea.
|
||||||
|
- herramienta publicar-todos.md: Script para publicar todos los manifiestos del clúster de forma masiva.
|
||||||
|
- herramienta git-subirtodos.md: Sube todos los cambios a los repositorios remotos.
|
||||||
|
- herramienta git-bajartodos.md: Clona todos los repositorios configurados.
|
||||||
|
- herramienta git-chilremove.md: Elimina subrepositorios integrados.
|
||||||
|
- k8s-argocd/: Manifiestos para desplegar Argo CD, incluyendo Ingress y servicios personalizados.
|
||||||
|
- k8s-cert-manager/: Manifiestos para instalar cert-manager, incluyendo ClusterIssuer de staging y producción.
|
||||||
|
- k8s-gitea/: Manifiestos para desplegar Gitea y su base de datos con almacenamiento persistente y acceso externo.
|
||||||
|
- k8s-guacamole/: Manifiestos para desplegar Apache Guacamole con autenticación MySQL y acceso vía Ingress.
|
||||||
|
- k8s-ingress-controller/: Despliegue de ingress-nginx como DaemonSet con configuración personalizada, RBAC, y service.
|
||||||
|
- k8s-kubevirt-isoserver/: Servidor HTTP que expone imágenes ISO para KubeVirt, con su PVC y despliegue.
|
||||||
|
- k8s-kubevirt-manager/: Despliegue opcional del panel web de KubeVirt con su acceso Ingress y RBAC.
|
||||||
|
- k8s-master/: Repositorio central con la definición App of Apps de Argo CD (apps/*.yaml para cada servicio).
|
||||||
|
- k8s-storage/: Despliegue del NFS server y del NFS client provisioner, con su StorageClass y permisos.
|
||||||
|
- k8s-vm-windows-demo/: Ejemplo de despliegue de una máquina virtual Windows usando KubeVirt.
|
||||||
|
- k8s-vscode/: Pod de Visual Studio Code Server accesible vía navegador y gestionado por Kubernetes.
|
||||||
|
- publicar-todos.sh: Script shell para publicar automáticamente todos los manifiestos locales a sus repos Gitea.
|
||||||
|
- readme.md: Documento principal del repositorio con introducción, tabla de contenidos y enlaces.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ Herramientas auxiliares
|
||||||
|
|
||||||
|
En la carpeta `docs/` tienes scripts útiles para trabajar con Gitea:
|
||||||
|
|
||||||
|
- [`herramienta git-publish.md`](docs/herramienta%20git-publish.md): Publica un repo local en Gitea automáticamente.
|
||||||
|
- [`herramienta publicar-todos.md`](docs/herramienta%20publicar-todos.md): Publica todos los servicios con un solo comando.
|
||||||
|
- [`herramienta git-subirtodos.md`](docs/herramienta%20git-subirtodos.md): Hace `push` de todos los repositorios hijos.
|
||||||
|
- [`herramienta git-bajartodos.md`](docs/herramienta%20git-bajartodos.md): Clona todos los repos del clúster.
|
||||||
|
- [`herramienta git-chilremove.md`](docs/herramienta%20git-chilremove.md): Limpia todos los subrepos.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Procedimientos adicionales
|
||||||
|
|
||||||
|
Ejemplos:
|
||||||
|
|
||||||
|
- Inyectar el esquema SQL de Guacamole: ver sección correspondiente en la [guía de instalación](docs/guia-instalacion.md)
|
||||||
|
- Crear y gestionar volúmenes o VMs de prueba con KubeVirt
|
||||||
|
- Publicar todos los manifiestos desde local con [`publicar-todos.sh`](publicar-todos.sh)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🙌 Autor
|
||||||
|
|
||||||
|
**Xavor - Manabo Inc**
|
||||||
|
Proyecto autogestionado y mantenido para homelab y formación profesional.
|
||||||
|
Repositorio privado/documentado en [https://git.manabo.org](https://git.manabo.org)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧪 Estado actual
|
||||||
|
|
||||||
|
✅ Clúster en funcionamiento
|
||||||
|
✅ Ingress con TLS
|
||||||
|
✅ Almacenamiento replicado
|
||||||
|
✅ App of Apps en Argo CD
|
||||||
|
✅ Acceso remoto vía Guacamole
|
||||||
|
☑️ Próximos pasos: integración con FreeIPA, backups, y monitorización
|
||||||
|
|
||||||
Reference in New Issue
Block a user