MicroK8s¶
MicroK8s es una distribución ligera de Kubernetes desarrollada por Canonical (la empresa detrás de Ubuntu), diseñada para ser fácil de instalar, mantener y ejecutar en:
- Desarrolladores locales (portátiles o sobremesa)
- Sistemas edge o embebidos
- Entornos de pruebas
- Entornos de producción pequeños o medianos
Introducción¶
MicroK8s - Zero-ops Kubernetes for developers, edge and IoT
MicroK8s - MicroK8s documentation - home
Características¶
| Característica | Detalle |
|---|---|
| 🧩 Instalación sencilla | Un solo comando: sudo snap install microk8s --classic |
| 📦 Todo en uno | Incluye kubectl, containerd, kubelet, kube-apiserver, etc. |
| 🚀 Autoconfigurado | No necesitas configurar certificados, flannel, DNS, etc. |
| 🔌 Addons activables | Como ingress, dns, helm, prometheus, istio, etc. |
| 🧱 Soporte de clúster | Puedes unir varios nodos y crear un clúster HA |
| 📉 Bajo consumo de recursos | Ideal para dispositivos edge (Raspberry Pi, Intel NUC, etc.) |
| ✅ Certificado CNCF | Es una distribución Kubernetes 100% certificada |
Manifiesto¶

Un manifiesto en Kubernetes es simplemente otra forma de llamar a un archivo declarativo YAML que describe la configuración de un recurso en el clúster.
En otras palabras:
👉 "manifiesto" = archivo YAML que define un recurso de Kubernetes
Se le dice manifiesto porque "declara" de manera formal el estado deseado de un recurso dentro de Kubernetes. Es como una "declaración oficial" de cómo debe ser un Deployment, un Pod, un Service, etc.
Elementos¶
Un manifiesto en Kubernetes siempre tendrá al menos estas secciones:
-
apiVersion: La versión de la API de Kubernetes que se usará.
-
kind: El tipo de recurso que quieres crear (Pod, Deployment, Service, etc.).
-
metadata: Información como el nombre del recurso y etiquetas.
-
spec: La especificación detallada de cómo debe comportarse ese recurso.
📝 Ejemplo de un manifiesto¶
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Este sería un manifiesto de Pod que puedes aplicar en Kubernetes.
Contenido¶
Un YAML de Kubernetes describe recursos como:
- Pods
- Deployments
- Services
- ConfigMaps
- Secrets
- Ingress, etc.
Puedes tener múltiples manifiestos en un solo archivo YAML, separados con ---, alternativamente puedes tener un manifiesto por archivo si prefieres mantener todo modular.
Aplicación de un manifiesto¶
Kubernetes toma este manifiesto y se asegura de crear el recurso exactamente como lo describes. si el recurso ya está creado, Kubernetes lee el archivo, compara el estado deseado con el estado actual y concilia la diferencia para que tu aplicación quede como tú la definiste en el YAML.
POD¶

Un Pod en Kubernetes es la unidad más pequeña de despliegue y ejecución dentro del clúster. Un pod encapsula uno o más contenedores que comparten el mismo entorno de red, almacenamiento y configuración.
Características principales de un pod:¶
- Uno o varios contenedores: Aunque lo más común es que un pod contenga un solo contenedor, puede tener varios (por ejemplo, un contenedor principal y un "sidecar" para tareas auxiliares).
- Red compartida: Todos los contenedores dentro del pod comparten la misma dirección IP, el mismo puerto de red y las mismas interfaces de red.
- Volúmenes compartidos: Los contenedores dentro del pod pueden compartir volúmenes para intercambiar datos entre ellos.
- Ciclo de vida conjunto: Los contenedores dentro de un pod siempre se ejecutan juntos en el mismo nodo y se gestionan como una unidad. Si el pod muere, todos los contenedores dentro de él también se detienen.
📝 Manifiesto de Pod:¶
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: httpd:latest
ports:
- containerPort: 80
🔧 Comandos para PODs¶
# despliegue del Pod
kubectl apply -f myapp.yaml
# Eliminar el Pod
kubectl delete -f myapp.yaml
# Devuelve el listado de pods
kubectl get pods
# Describe un pod
kubectl describe pod <name>
# Devuelve el consumo de recursos de un nodo
kubectl top pod <name>
# Ejecutar un comando sobre un contenedor
kubectl exec <pod> -c <contenedor> <comando>
# Copia un fichero en un contenedor
kubectl cp /tmp/foo <pod-name>:/tmp/bar -c <container-name>
# Consulta de los de un contenedor
kubectl logs <pod-name> -c <container-name>
# Port forwarding
kubectl port-forward --address 0.0.0.0 pod/<pod-name> <host-port>:<pod-port>
Namespace¶

Los namespaces en Kubernetes son una forma de aislar y organizar recursos dentro de un mismo clúster.
Piensa en ellos como "espacios de trabajo" o "compartimentos" virtuales donde puedes tener recursos que no interfieren entre sí, aunque tengan el mismo nombre.
Utilidad¶
- Separar entornos: Puedes tener un
namespacepara desarrollo, otro para testing y otro para producción dentro del mismo clúster. - Evitar conflictos de nombres: Puedes tener un Deployment llamado
web-appen dos namespaces diferentes sin que choquen entre ellos. -
Aplicar políticas y límites:
- Puedes aplicar quotas de recursos por namespace (CPU, memoria).
- Puedes definir reglas de seguridad o control de acceso (RBAC) por namespace.
- Facilitar la administración: En clústeres grandes, los namespaces ayudan a que los equipos trabajen de manera aislada y organizada.
Namespaces por defecto¶
- default: Namespace por defecto donde se crean los recursos si no especificas otro.
- kube-system: Recursos internos del sistema de Kubernetes (DNS, kube-proxy, etc.).
- kube-public: Datos accesibles de forma pública dentro del clúster (rara vez se usa directamente).
- kube-node-lease: Namespace para gestionar heartbeats de los nodos (para detectar si un nodo está vivo).
🔧 Comandos para trabajar con Namespaces:¶
# Devuelve el listado de namespaces
kubectl get namespaces
# Crea un namespace
kubectl create namespace <nombre>
# Especifical el namespace en el cliente kubectl
kubectl apply -f pod.yaml --namespace=<nombre>
# Establecer un determinado namespace como predeterminado
kubectl config set-context --current -–namespace=<nombre>
Definir un namespace dentro de un YAML
Service¶

Un Service en Kubernetes es un recurso que proporciona una abstracción para exponer y acceder a un conjunto de pods de manera estable y confiable. Los pods son efímeros y sus IPs pueden cambiar, por lo que un Service actúa como un punto fijo de entrada que redirige el tráfico a los pods correctos, incluso si estos son recreados o se mueven a otro nodo.
Funciones principales de un servicio:¶
-
Descubrimiento y balanceo de carga:
- Distribuye automáticamente el tráfico entre los pods que coincidan con el selector definido.
-
Dirección IP estable:
-
Mientras que los pods tienen IPs dinámicas, el Service proporciona una IP virtual estable (ClusterIP) o un nombre DNS interno.
-
Exposición de la aplicación:
-
Puede exponer una aplicación internamente dentro del clúster o externamente hacia internet.
Tipos de servicios en Kubernetes:¶
-
ClusterIP (por defecto):
- Expone el servicio internamente dentro del clúster. No es accesible desde fuera.
-
NodePort:
-
Abre un puerto en cada nodo del clúster y redirige el tráfico a los pods.
-
LoadBalancer:
-
Crea un balanceador de carga externo (si el clúster está en una nube como AWS, GCP, Azure) y lo conecta al servicio.
-
ExternalName:
-
No redirige tráfico, pero mapea un nombre DNS interno a un nombre DNS externo.
📝 Manifiesto de "Service" tipo NodePort¶
---
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
type: NodePort
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 80
Funcionamiento¶
- El selector
app: myapphace que este Service envíe tráfico a todos los pods que tengan la etiquetaapp=myapp. - El puerto
80del Service se mapea al puerto80del pod (targetPort).
🔧 Comandos¶
# Aplica el manifiesto o los cambios
kubectl apply -f myapp.yaml
# Elimina el manifiesto
kubectl delete -f myapp.yaml
# Comprueba
kubectl get all
NAME READY STATUS RESTARTS AGE
pod/myapp 1/1 Running 0 15m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 44h
service/service1 NodePort 10.96.146.193 <none> 80:31926/TCP 15m
Deployment
¶
Un deployment en Kubernetes es un recurso que gestiona y mantiene el ciclo de vida de un conjunto de réplicas de un pod de manera declarativa. Es uno de los objetos más utilizados en Kubernetes, ya que te permite:
- Desplegar una aplicación: Define qué imagen de contenedor se debe usar, cuántas réplicas deben ejecutarse y cómo deben exponerse.
- Actualizar la aplicación sin tiempo de inactividad: Permite hacer rolling updates (actualizaciones progresivas) de los pods, minimizando la posibilidad de interrupciones.
- Gestionar el estado deseado: Kubernetes se asegura de que siempre haya el número de réplicas especificadas corriendo; si un pod falla, automáticamente se crea uno nuevo.
- Rollback: Puedes revertir a una versión anterior si una actualización falla.
📝 Manifiesto de "Deployment"¶
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: httpd:latest
ports:
- containerPort: 80
✅ Conceptos clave:¶
- replicas: número de instancias de un pod.
- selector: cómo Kubernetes identifica los pods que pertenecen a este deployment.
- template: especifica la plantilla de los pods (contenedores, puertos, variables de entorno, etc.).
- strategy: (opcional) puedes definir estrategias de despliegue como RollingUpdate o Recreate.
🔧 Comandos para deployments¶
# Aplica el manifiesto o los cambios
kubectl apply -f myapp.yaml
# Elimina el manifiesto
kubectl delete -f myapp.yaml
# Comprueba deployments
kubectl get deployments
# Escala el despliegue
kubectl scale --replicas 2 deployment/myapp
Despliegue¶

Kubernetes de alta disponibilidad, con gestión de operaciones totalmente automatizada y sin interrupciones, desde estaciones de trabajo de desarrolladores hasta producción.
Entorno¶
-----------+-----------------------------+-----------------------------+------------
| | |
192.168.1.251 192.168.1.252 192.168.1.253
+----------+------------+ +-----------+------------+ +------------+------------+
| [k8s1.cluster.local] | | [k8s2.cluster.local] | | [k8s3.cluster.local] |
| Control Plane | | Worker Node | | Worker Node |
+------------------ ----+ +------------------------+ +-------------------------+
3 x servidores ubuntu 26.04
El dominio estándar en Kubernetes es <em>cluster.local</em>. Funciona bien en la mayoría de los casos y es importante para la resolución de nombres entre servicios.
Adicionalmente puedes añadir al fichero de resolución local de cada host /etc/hosts las siguientes lineas:
192.168.1.251 k8s1.cluster.local k8s1
192.168.1.252 k8s2.cluster.local k8s2
192.168.1.253 k8s3.cluster.local k8s3
Instalación¶
MicroK8s instalará un Kubernetes minimalista y ligero que podrás ejecutar y usar en prácticamente cualquier máquina. Se instala en un instante:
# Instala la versión mas reciente estable de Microk8s
sudo snap install microk8s --classic
# Evita auto-actualizaciones de Microk8s
sudo snap refresh --hold microk8s
MicroK8s crea un grupo para permitir el uso sin problemas de comandos que requieren privilegios de administrador. Para agregar su usuario actual al grupo y obtener acceso al directorio de caché .kube, ejecute los siguientes comandos:
sudo usermod -a -G microk8s $USER
mkdir -p ~/.kube
chmod 0700 ~/.kube
# Volver a ingresar a la sesión para que se aplique
su - $USER
Comandos¶
# Comprobar estado
microk8s status --wait-ready
# Ver nodos
microk8s kubectl get nodes
# Ver servicios
microk8s kubectl get services
Para usar solo el comando kubectl añadir al fichero ~/.bash_aliases la linea
Clúster¶
Añadir nodos¶
Para crear un clúster a partir de dos o más instancias de MicroK8s en ejecución, utilice el comando microk8s add-node. La instancia de MicroK8s en la que se ejecuta este comando será un nodo master alojará el "control plane" de Kubernetes:
El comando devolverá algunas instrucciones de unión que deben ejecutarse en la instancia de MicroK8s que desea unir al clúster:
Eliminar nodos¶
# En el nodo a eliminar
microk8s leave
# En el nodo master
microk8s remove-node <IP_nodo_a_eliminar>
Addons¶

MicroK8s utiliza el mínimo de componentes para un Kubernetes puro y ligero. Sin embargo, hay muchas funciones adicionales disponibles "addons" que son componentes preconfigurados que proporcionarán capacidades adicionales.
Puedes consultar la lista de complementos disponibles e instalados en cualquier momento ejecutando:
El complemento «hostpath-storage» proporciona espacio de directorio en el host. No se usa en cluster
Dashboard¶

El repositorio oficial fue movido a **`kubernetes-retired/dashboard`** y está **archivado (read-only) desde el 21 de enero de 2026**, indicando explícitamente que **no se mantiene** y recomendando [**Headlamp**](https://bookstack.ictiberia.com/books/ubuntu/page/headlamp "Headlamp") como alternativa.
Ingress¶

Este complemento añade un controlador de entrada NGINX para MicroK8. Se habilita ejecutando el comando:
Con Ingress habilitado, se puede crear una regla de tipo "ingress" HTTP/HTTPS. por ejemplo:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: http-ingress
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: some-service
port:
number: 80
Cert-Manager¶

Cert-Manager es la solución estándar para la gestión de certificados en clústeres de Kubernetes. Se habilita ejecutando el comando:
ClusterIssuer¶
Se utiliza un recurso ClusterIssuer para configurar una cuenta con Let's Encrypt. Solo necesita una dirección de correo electrónico (asegúrese de usar una válida).Global -> para todo el clúster
- Se aplica una sola vez y puedes usarlo en cualquier namespace.
- Ideal para producción cuando quieres certificados automáticos a nivel de clúster.
Manifiesto "letsencrypt-staging*.yaml*"
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
# The ACME server URL
server: https://acme-staging-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: user@example.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-staging
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: public
Manifiesto "letsencrypt-prod*.yaml*":
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: user@example.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-prod
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: public
# ClusterIssuer test
kubectl apply -f letsencrypt-staging.yaml
# ClusterIssuer Producción
kubectl apply -f letsencrypt-prod.yaml
Comprobación¶
# Lista ClusterIssuers
kubectl get clusterissuer
# Obtener detalles del ClusterIssuer
kubectl describe clusterissuer letsencrypt-staging
kubectl describe clusterissuer letsencrypt-prod
Persistent Volumes¶
Si se utiliza el almacenamiento simple proporcionado por el complemento de almacenamiento hostpath, hay que tener en cuenta que solo estará disponible para los nodos en los que se haya habilitado. Para el almacenamiento en clúster, se debe configurar un almacenamiento alternativo.
NFS¶

CSI driver para NFS¶
En la práctica debes instalar `nfs-common` en **todos los nodos worker/control-plane donde puedan ejecutarse pods que monten PVCs NFS**.
# instala nfs-common en todos los nodos del cluster
sudo apt update
sudo apt install -y nfs-common
# comprueba cambiando la IP del NFS server
which mount.nfs
showmount -e 10.0.0.42
Habilite el complemento Helm3 (si aún no está habilitado) y agregue el repositorio para el controlador NFS CSI:
microk8s enable helm3
microk8s helm3 repo add csi-driver-nfs https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/master/charts
microk8s helm3 repo update
Instalar el driver de Helm en el espacio de nombres kube-system:
microk8s helm3 install csi-driver-nfs csi-driver-nfs/csi-driver-nfs \
--namespace kube-system \
--set kubeletDir=/var/snap/microk8s/common/var/lib/kubelet
En este punto, se pueden listar los controladores CSI disponibles en el clúster de Kubernetes.
microk8s kubectl get csidrivers
NAME ATTACHREQUIRED PODINFOONMOUNT STORAGECAPACITY TOKENREQUESTS REQUIRESREPUBLISH MODES AGE
nfs.csi.k8s.io false false false
StorageClass para NFS¶
Crear una clase de almacenamiento de Kubernetes que utilice el controlador CSI nfs.csi.k8s.io. Suponiendo que haya configurado un recurso compartido NFS /volume1/k8s y que la dirección de su servidor NFS sea 10.0.0.42
# sc-nfs.yaml
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-csi
provisioner: nfs.csi.k8s.io
parameters:
server: 10.0.0.42
share: /volume1/k8s
subDir: "${pvc.metadata.namespace}/${pvc.metadata.name}"
onDelete: retain
reclaimPolicy: Retain
allowVolumeExpansion: true
volumeBindingMode: Immediate
mountOptions:
- hard
- nfsvers=4.0
Cada PVC queda ordenado por namespace y nombre dentro del NFS. El CSI NFS soporta sustitución con `${pvc.metadata.name}`, `${pvc.metadata.namespace}` y `${pv.metadata.name}`
# aplica el maniefiesto creado
kubectl apply -f sc-nfs.yaml
# Comprueba
kubectl get storageclass
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-csi nfs.csi.k8s.io Retain Immediate true 17s
PersistentVolumeClaim¶
El último paso consiste en crear un nuevo PersistentVolumeClaim utilizando la clase de almacenamiento nfs-csi. Esto es tan sencillo como especificar storageClassName: nfs-csi en la definición del PVC.
# pvc-nfs.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
storageClassName: nfs-csi
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 5Gi
# aplica el maniefiesto creado
kubectl apply -f pvc-nfs.yaml
# Comprueba
kubectl describe pvc my-pvc
Headlamp¶
Headlamp es una interfaz de usuario de Kubernetes fácil de usar centrada en la extensibilidad
# 1) Añadir repo Helm de Headlamp
microk8s helm3 repo add headlamp https://kubernetes-sigs.github.io/headlamp/
microk8s helm3 repo update
# 2) Instalar en kube-system (o crea un namespace propio si prefieres)
microk8s helm3 install headlamp headlamp/headlamp -n kube-system
Acceso rápido (sin Ingress): port-forward¶
microk8s kubectl -n kube-system get svc | grep headlamp
microk8s kubectl -n kube-system port-forward svc/headlamp 8080:80 --address 0.0.0.0
Abres http://<IP-del-nodo>:8080.
Inicio de sesión¶
Headlamp permite login con bearer token (ServiceAccount) o con certificado cliente; lo habitual es token + RBAC.
Service Account token¶
#Create a Service Account:
kubectl -n kube-system create serviceaccount headlamp-admin
# Give admin rights to the account
kubectl create clusterrolebinding headlamp-admin \
--serviceaccount=kube-system:headlamp-admin \
--clusterrole=cluster-admin
# Create the token
kubectl create token headlamp-admin -n kube-system
Argo CD¶

Instalación¶
kubectl create namespace argocd
kubectl apply -n argocd --server-side --force-conflicts \
-f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
kubectl -n argocd get pods -o wide
kubectl -n argocd rollout status deploy/argocd-server
Instalar Argo CD CLI¶
VERSION=$(curl -L -s https://raw.githubusercontent.com/argoproj/argo-cd/stable/VERSION)
curl -sSL -o argocd-linux-amd64 \
"https://github.com/argoproj/argo-cd/releases/download/v${VERSION}/argocd-linux-amd64"
sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd
rm argocd-linux-amd64
argocd version --client
En microk8s puede aparecer el error: `"invalid configuration: no configuration has been provided, try setting KUBERNETES_MASTER environment variable"`. Significa que el binario `argocd` no está encontrando configuración de Kubernetes. Es típico en MicroK8s cuando `kubectl` funciona porque es alias/wrapper de `microk8s kubectl`, pero no existe un `~/.kube/config` estándar para otras herramientas.
Para corregirlo:
echo 'export KUBECONFIG=/var/snap/microk8s/current/credentials/client.config' >> ~/.bashrc
source ~/.bashrc
Iniciar sesión mediante la CLI¶
Una vez que haya cambiado la contraseña, debe eliminar el secreto argocd-initial-admin-secret del espacio de nombres de Argo CD. Este secreto solo sirve para almacenar la contraseña generada inicialmente en texto plano y puede eliminarse sin problemas en cualquier momento.
Acceder a la UI de Argo CD¶
Mediante port-forward
k9s¶

- K9s es una herramienta de línea de comandos interactiva para Kubernetes.
- Te permite navegar, monitorizar y gestionar clústeres de K8s desde la terminal.
Características¶
-
Navegación rápida
- Pulsa
:y escribe recursos (pods,deployments,svc,ingress, etc.) y navega entre ellos. - Usa
arrow keyspara moverte,enterpara abrir detalles de un pod o contenedor. -
Logs en tiempo real
-
Selecciona un pod y pulsa
lpara ver logs. - Puedes seguir logs de todos los contenedores de un pod o filtrarlos.
-
Acciones sobre pods y recursos
-
Reiniciar (
r), borrar (d), escalar (s) deployments directamente desde la UI de terminal. -
Filtrado y búsqueda
-
Ctrl+fpara buscar pods por nombre, label o status. - Filtrar por namespace:
:ns <nombre_namespace>. -
Soporte multi-clúster
-
Detecta todos los contextos de tu
kubeconfig. - Cambia rápidamente de un clúster a otro (
:ctx <context>). -
Temas y colores
-
Muestra pods en verde/amarillo/rojo según estado, con alertas visuales.
- Personalizable mediante config file.
- Pulsa
Ventajas¶
- Muy rápido, todo en terminal.
- Ideal para operaciones de emergencia sin abrir UI web.
- Compatible con cualquier clúster K8s (MicroK8s, k3s, EKS, AKS, GKE…).
- Ligero, no necesita navegador ni plugins externos.
Instalación¶
Windows¶
1️⃣ Instalar¶
Usando un terminal en modo administrador de PowerShell
# Install chocolatey
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
# instala via chocolatey
choco install k9s
# Ejecuta k9s
k9s
2️⃣ Exportar kubeconfig de MicroK8s¶
MicroK8s guarda su configuración dentro del nodo Linux. Necesitas copiarla a Windows.
En el nodo <span class="hljs-comment">MicroK8s</span>
Esto imprime el contenido del kubeconfig.
- Copia todo el contenido a un archivo
microk8s-config.yamlen tu máquina Windows, por ejemplo:
3️⃣ Conectar K9s al clúster MicroK8s¶
No olvides especificar tu usuario y cierra y abre PowerShell de nuevo para que se aplique.
2. Abre K9s:
Comandos básicos¶
How to install a Windows 11 VM using LXD | Ubuntu
IA¶
Conceptos¶

La IA (Inteligencia Artificial) es una rama de la informática que busca crear máquinas o programas capaces de realizar tareas que normalmente requieren inteligencia humana.
Estas tareas incluyen cosas como:
- Reconocimiento de voz o imágenes (por ejemplo, cuando tu teléfono entiende lo que dices).
- Toma de decisiones (como los sistemas que recomiendan películas o rutas de viaje).
- Aprendizaje automático (machine learning), donde las máquinas aprenden de los datos sin ser programadas explícitamente para cada tarea.
- Procesamiento del lenguaje natural, que permite a los sistemas entender y responder en lenguaje humano (como yo 😊).
En resumen, la IA trata de imitar la forma en que las personas piensan, aprenden y resuelven problemas, pero usando algoritmos y datos.
Arquitectura¶
┌───────────────────────────────────────────────────────────────┐
│ USUARIO │
│───────────────────────────────────────────────────────────────│
│ 💬 Usa navegador web (Chrome, Firefox, etc.) │
│ 🌐 Accede a http://tu-servidor:3000 │
└───────────────┬───────────────────────────────────────────────┘
│ 1️⃣ Escribe / envía prompt
▼
┌──────────────────────────────────────────────────────────────────────┐
│ 🖥️ Open WebUI (contenedor Docker) │
│──────────────────────────────────────────────────────────────────────│
│ - Interfaz tipo ChatGPT │
│ - Guarda historiales de chat (persistencia) │
│ - Tiene “Knowledge Base” (memoria larga / aprendizaje) │
│ - Llama al modelo LLM a través de API local │
└───────────────┬──────────────────────────────────────────────────────┘
│ 2️⃣ Envía prompt al motor de IA local (Ollama)
▼
┌──────────────────────────────────────────────────────────────────────┐
│ 🧠 Ollama (host, fuera del contenedor) │
│──────────────────────────────────────────────────────────────────────│
│ - Maneja modelos LLM (Llama 3, Mistral, Phi-3, etc.) │
│ - Usa GPU vía CUDA para acelerar inferencia │
│ - Expone API local http://localhost:11434 │
│ - Compatible con múltiples modelos y embeddings │
└───────────────┬──────────────────────────────────────────────────────┘
│ 3️⃣ Llama a la GPU para procesar el modelo
▼
┌──────────────────────────────────────────────────────────────────────┐
│ ⚙️ NVIDIA Container Toolkit + Drivers CUDA │
│──────────────────────────────────────────────────────────────────────│
│ - “Puentea” la GPU física hacia los contenedores │
│ - Permite ejecutar CUDA/Tensor ops dentro de Docker │
│ - Asegura compatibilidad entre driver y librerías del contenedor │
└───────────────┬──────────────────────────────────────────────────────┘
│ 4️⃣ Acceso a la GPU física
▼
┌──────────────────────────────────────────────────────────────────────┐
│ 💻 GPU Física (RTX, CUDA cores, VRAM) │
│──────────────────────────────────────────────────────────────────────│
│ - Ejecuta el modelo LLM en paralelo masivo │
│ - Usa librerías CUDA/cuDNN/TensorRT instaladas en Ubuntu │
│ - Devuelve resultados procesados a Ollama │
└──────────────────────────────────────────────────────────────────────┘
Modelos¶

Un modelo de inteligencia artificial es un programa entrenado para aprender patrones a partir de datos (como texto, imágenes o sonidos), y luego usar esos patrones para hacer tareas “inteligentes”, por ejemplo:
- Entender preguntas
- Escribir texto
- Traducir
- Reconocer imágenes o voz
🔹 Un modelo de IA aprende de muchos ejemplos y luego predice o genera cosas nuevas que tienen sentido.
🔹Un modelo de IA es un sistema entrenado para hacer una tarea específica.
🔹 Cada tipo de modelo de IA se especializa en un tipo de información.
🔹 Algunos (como los multimodales) combinan varios tipos a la vez.
🔹 Los modelos de lenguaje grandes (LLMs) son los más usados hoy por su versatilidad (chat, análisis, generación, etc.).
Tipos¶
Los tipos de modelos se diferencian por el tipo de datos que usan (texto, imagen, sonido, etc.) y lo que saben hacer (predecir, clasificar, generar, etc.).
Modelos populares por tipo¶
Terminología¶
Parámetros¶
Son las “conexiones internas” del cerebro del modelo. Cada parámetro guarda un número que el modelo ajustó mientras aprendía. Un modelo tiene capas de redes neuronales con miles de millones de parámetros (sus “neuronas”). Durante el entrenamiento, el modelo ajusta esos parámetros para aprender relaciones entre los datos.
- El número define el tamaño: Un modelo de
8B(como Llama 3.1) tiene 8.000 millones de parámetros. - Regla física: A más parámetros, la IA es más inteligente, pero requiere más memoria VRAM en GPU para funcionar.
Por ejemplo:
- llama3.1:70b tiene 70 mil millones de parámetros.(ocupa decenas de GB).
- Esos son los “pesos” de una red neuronal, como las sinapsis de un cerebro.
- Cuantos más parámetros, más conocimiento y más capacidad de razonamiento.
🔹 “B” = *billones de parámetros* 🔹 Más parámetros = más inteligencia, más tamaño, más consumo 🔹 “70B” = modelo muy grande, con calidad similar a ChatGPT avanzado
Tokens¶
Los tokens son las unidades de texto que el modelo procesa o genera. No son palabras exactamente, sino pedacitos de palabras.
Los tokens son las piezas del texto que entran o salen del modelo cuando conversas.
Cuando tú hablas con él, el modelo usa lo que aprendió para procesar tus tokens (las partes de texto que le mandas) y generar una respuesta.
Cuantización (Quantization)¶
- El beneficio: Reduce el peso del modelo a la cuarta parte (de 32 GB a solo 8 GB de VRAM) perdiendo menos del 1% de inteligencia. Es lo que permite que tu GPU L4 rinda al máximo.
Ventana de Contexto (Context Window)¶
- Los modelos modernos tienen ventanas enormes (ej. Llama 3.1 soporta 128.000 tokens).
- Impacto: Aunque el modelo soporte mucho, a mayor contexto usado por un usuario, más VRAM consume.
Temperatura (Temperature)¶
0.0 a 1.0 (o a veces hasta 2.0):- Temperatura baja (0.0 - 0.2): Respuestas lógicas, precisas y repetitivas. Ideal para programación, matemáticas o análisis de datos.
- Temperatura alta (0.7 - 1.0): Respuestas creativas, variadas y fluidas. Ideal para lluvia de ideas o redacción de textos.
Prompt del Sistema (System Prompt)¶
Resumen¶
Ollama¶

Ollama es una herramienta y plataforma diseñada para ejecutar modelos de lenguaje grandes (LLMs) de manera local en tu computadora, sin depender de servidores en la nube.
En términos simples, es una forma de usar modelos tipo ChatGPT o LLaMA directamente en tu máquina.
- Permite descargar y correr modelos de IA (como LLaMA 2, Mistral, Gemma, Phi-3, etc.) en tu propio equipo.
- Proporciona una interfaz de línea de comandos (CLI) y una API local, con la que puedes integrar los modelos en tus propias aplicaciones.
- Se encarga de gestionar la descarga, ejecución y optimización del modelo, para que no tengas que configurar manualmente entornos complejos.
Enlaces¶
Características¶
- Ejecución local: todos los cálculos se hacen en tu computadora (no se envían datos a la nube).
- Compatibilidad multiplataforma: disponible para macOS, Windows y Linux.
- Modelos variados: soporta modelos de código abierto como LLaMA 2, Mistral, Gemma, Phi-3, Command-R, entre otros.
- Integración sencilla: se puede usar desde terminal o con peticiones HTTP a
http://localhost:11434. - Privacidad y control: ideal si quieres mantener tus datos en local o experimentar con IA sin depender de OpenAI, Anthropic, etc.
Requisitos¶
- Servidor local con GPU
- Ubuntu 24.04 o superior instalado
- Drivers Nvidia instalados
- Docker Instalado (opcional)
Instalación¶
Baremetal¶
curl -fsSL https://ollama.com/install.sh | sh
# Arranca el servicio (si no arrancó solo):
sudo systemctl enable --now ollama
Docker¶
Creando el directorio para los servicios
compose.yaml
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
ports:
- "11434:11434"
volumes:
- ollama:/root/.ollama
environment:
- OLLAMA_NUM_PARALLEL=4 # Permite procesar hasta 4 peticiones simultáneas en la GPU L4
- OLLAMA_MAX_LOADED_MODELS=1 # Mantiene un solo modelo en VRAM para evitar saturación
restart: unless-stopped
# ===== Recursos y GPU NVIDIA ===== (requiere nvidia-container-toolkit en el host)
deploy:
resources:
reservations:
devices:
- driver: nvidia
capabilities: ["gpu"]
count: all
limits: # Control de recursos para Ollama
cpus: '10.0' # Máximo 10 cores lógicos simultáneos
memory: 24gb # Espacio de sobra para Llama 3.1 8B y picos de contexto
# ===========================
volumes:
ollama:
CLI¶
# Arranca el stack
sudo docker compose up -d
# Comprueba los logs de ollama
sudo docker logs -n 200 -f ollama
# apaga el stack
sudo docker compose down
# Conectar al shell del contenedor ollama
sudo docker exec -it ollama bash
# Lista los modelos instalados
ollama list
# Descarga un modelo sin ejecutarlo
ollama pull phi3
# Muestra información de un modelo
ollama show llama3.1
# ejecuta un modelo
ollama run llama3.1
# Elimina un modelo
ollama rm mistral
Open WebUI¶

Open WebUI (antes conocida como Ollama WebUI) es una interfaz gráfica web de código abierto que te permite usar modelos de lenguaje locales (como los de Ollama, LM Studio, o incluso GPTs remotos) desde una experiencia parecida a ChatGPT — pero en tu propia computadora o servidor, sin depender de la nube.
En pocas palabras:
Convierte Ollama en un ChatGPT local.
Con Open WebUI, obtienes una interfaz moderna (accesible desde tu navegador) donde puedes:
- Chatear con modelos locales como Mistral, LLaMA 3, Phi-3, etc.
- Crear y guardar “personas” o prompts personalizados (como GPTs locales).
- Subir archivos y pedirle al modelo que los analice.
- Administrar varios modelos desde un mismo panel.
- Integrar extensiones o conectarlo con APIs externas.
Open WebUI corre dentro de Docker y usa Ollama o PyTorch como backend IA.
Funciones¶
| Función | Descripción |
|---|---|
| 💬 Chat multihilo | Guarda y organiza tus conversaciones. |
| 🧠 Compatibilidad con Ollama | Usa modelos locales fácilmente. |
| 🌍 Integración con OpenAI y otros backends | También puede conectarse a GPT-4, Claude, etc. |
| 🧩 Soporte para plugins y herramientas | Puedes ampliar sus funciones (por ejemplo, para buscar en la web o ejecutar código). |
| 📄 Análisis de archivos | Puedes subir PDFs, TXT o CSV y hacerle preguntas al modelo. |
| 🛡️ Privacidad total | Todos los datos se quedan en tu equipo si solo usas Ollama. |
Instalar¶
Después de instalar Ollama, puedes desplegar Open WebUI como contenedor docker ampliando el fichero compose.yaml con el contenido:
---
open-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-webui
deploy:
resources:
limits:
cpus: '2.0' # La interfaz web es ligera, 2 cores bastan
memory: 2gb
volumes:
- open_webui:/app/backend/data
ports:
- "3000:8080"
environment:
- OLLAMA_BASE_URL=http://ollama:11434
- WEBUI_SECRET_KEY=${WEBUI_SECRET_KEY}
- ENABLE_SIGNUP=false
- DEFAULT_USER_ROLE=user
# ===== CONFIGURACIÓN DE BÚSQUEDA WEB AUTOMÁTICA =====
- ENABLE_RAG_WEB_SEARCH=True # Activa la búsqueda web de forma global al iniciar
- RAG_WEB_SEARCH_ENGINE=ddgs # Selecciona DuckDuckGo (Gratis y sin requerir APIs externas)
- WEB_SEARCH_CONCURRENT_REQUESTS=1 # Crítico multiusuario: Encola las búsquedas para evitar bloqueos por IP
depends_on:
- ollama
restart: unless-stopped
networks:
- default
- proxy
volumes:
open_webui:
networks:
default:
proxy:
external: true
Comandos:
# Arranca el stack
sudo docker compose up -d
# Comprueba los logs de open-webui
sudo docker logs -n 200 -f open-webui
# apaga el stack
sudo docker compose down
Ahora ya puedes acceder a Open WebUI en http://IP-Host:8080
Personalización¶
Entra ID¶
🌍 Microsoft Environment Variable Configuration | Open WebUI
Añade a docker-compose.yaml en la sección de variables:
# SSO Microsoft Entra ID (OIDC)
- ENABLE_OAUTH_SIGNUP=true
- MICROSOFT_CLIENT_ID=${CLIENT_ID}
- MICROSOFT_CLIENT_SECRET=${CLIENT_SECRET}
- MICROSOFT_CLIENT_TENANT_ID=${TENANT_ID}
- MICROSOFT_OAUTH_SCOPE=openid email profile
- MICROSOFT_REDIRECT_URI=https://${FQDN}/oauth/microsoft/callback
- OPENID_PROVIDER_URL=https://login.microsoftonline.com/${TENANT_ID}/v2.0/.well-known/openid-configuration
fichero .env
FQDN="ia.dominio.com"
TENANT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
CLIENT_SECRET=xxxxx~xxxxxxxxxxxxxxxxxxxxxxxxxx

