Mascota Jacar — leyendo contigo Un portátil cuyos ojos siguen el cursor mientras lees.
Arquitectura Tecnología

gVisor: sandboxing para contenedores multi-tenant

gVisor: sandboxing para contenedores multi-tenant

Actualizado: 2026-05-03

Los contenedores comparten el kernel del anfitrión y esa propiedad, que explica buena parte de su ligereza, también marca su techo en entornos multi-tenant donde la confianza entre cargas es baja. gVisor nació dentro de Google precisamente para resolver ese techo: interponer un kernel escrito en Go entre el proceso del contenedor y el kernel real del anfitrión, reduciendo la superficie de llamadas al sistema expuesta y ofreciendo una forma de aislamiento intermedia entre el contenedor tradicional y la máquina virtual ligera.

Puntos clave

  • gVisor implementa el runtime runsc, compatible con OCI, que sustituye a runc interponiendo un kernel en espacio de usuario llamado Sentry.
  • El modo systrap (disponible desde 2024) es la opción por defecto recomendada: buen rendimiento, portable, sin requisitos especiales de hardware.
  • Para cargas de CPU el coste es del 5–10 %; para cargas de E/S intensiva el impacto puede llegar al 20–50 %.
  • Integrar gVisor en un clúster Kubernetes existente requiere instalar runsc y declarar una RuntimeClass; el resto de pods siguen con runc.
  • Tiene sentido para cargas multi-tenant, funciones serverless y ejecución de código de terceros; no para bases de datos pesadas o cargas con alto IOPS.

Qué es gVisor y por qué se construyó

gVisor implementa un runtime compatible con OCI llamado runsc que sustituye a runc. La diferencia decisiva es que runsc no deja al proceso del contenedor hablar con el kernel del anfitrión directamente. En su lugar, un componente llamado Sentry, un kernel de Linux reimplementado en Go en espacio de usuario, intercepta esas llamadas y responde a la mayoría por sí mismo, hablando con el anfitrión solo cuando no queda otra opción y siempre a través de un perímetro muy acotado.

El resultado es que un exploit del kernel que normalmente escalaría del contenedor al anfitrión tiene que atravesar primero la implementación de Sentry, que es mucho más pequeña y está escrita en un lenguaje con seguridad de memoria. Google abrió el código en 2018 y lo usa en producción para ejecutar código de clientes en App Engine, Cloud Run y Cloud Functions.

Arquitectura: Sentry, Gofer y modos de plataforma

Cuando un contenedor arranca con runsc, el runtime crea dos procesos principales en el anfitrión:

  • Sentry: el kernel en espacio de usuario que ejecuta el código del contenedor.
  • Gofer: proceso separado que actúa como intermediario para el acceso al sistema de archivos.

Esta separación es deliberada: incluso si un atacante compromete Sentry, todavía tiene que atravesar Gofer para tocar el disco, y ninguno de los dos tiene capacidades privilegiadas más allá de lo estrictamente necesario.

La intercepción de llamadas al sistema usa dos modos principales:

  • ptrace: portable pero lento, rara vez usado en producción.
  • KVM: aprovecha extensiones de virtualización de hardware para rendimiento notablemente mejor, pero requiere /dev/kvm.
  • systrap (recomendado desde 2024): usa seccomp con filtros de notificación para interceptar llamadas sin depender de KVM ni de ptrace. Buen rendimiento, portable y sin requisitos especiales de hardware.

Un detalle importante: Sentry no implementa todas las llamadas al sistema de Linux. Cubre la mayoría de lo que un programa típico necesita, pero hay llamadas oscuras que fallarán si el contenedor intenta usarlas. Esto es deliberado: cada llamada implementada es superficie de ataque potencial.

Rendimiento: dónde gana y dónde pierde

Para cargas con uso intenso de CPU y poco contacto con el kernel, gVisor está muy cerca de un contenedor nativo. Las diferencias son del orden del 5–10 % en cargas puras de cálculo sobre systrap.

La historia cambia con cargas pesadas en E/S:

  • Redis sufre poco porque sus operaciones tocan poco el sistema de archivos.
  • Postgres o MySQL con escritura constante muestran penalizaciones del 20–50 % en transacciones por segundo.
  • La red también tiene impacto: gVisor trae su propia pila TCP en Go que no iguala al kernel Linux en rendimiento bruto.

La lección operativa: gVisor es buena opción para APIs HTTP, funciones serverless cortas, trabajos por lotes y ejecución de código no confiable. Es mala opción para bases de datos pesadas, sistemas de archivos distribuidos o cualquier carga cuya métrica principal sea IOPS.

Comparación con Kata Containers y microVMs

La comparación obvia es con Kata Containers, que también busca aislamiento reforzado pero arrancando una máquina virtual pequeña con Firecracker o QEMU. Los modelos de amenaza son distintos:

  • Kata apuesta por la barrera de hardware del hipervisor.
  • gVisor apuesta por la reducción de superficie en espacio de usuario.

Kata tiende a mejor compatibilidad con cargas de E/S intensiva porque dentro de la VM corre un kernel Linux completo. gVisor tiende a arrancar más rápido y consumir menos memoria fija por contenedor porque no hay hipervisor completo que cargar. En Cloud Run, donde el arranque en frío importa, la elección de gVisor tiene sentido.

Firecracker por sí solo es un ladrillo de construcción distinto: modelo de amenaza fuerte por la separación de hipervisor, pero operar Firecracker puro implica mucha más integración con el orquestador que runsc, que se enchufa en containerd con pocas líneas de configuración.

Operación y despliegue

Integrar gVisor en un clúster existente es relativamente sencillo:

bash
# Instalación típica en un nodo Debian
curl -fsSL https://gvisor.dev/archive.key | sudo gpg --dearmor 
  -o /usr/share/keyrings/gvisor-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) 
  signed-by=/usr/share/keyrings/gvisor-archive-keyring.gpg] 
  https://storage.googleapis.com/gvisor/releases release main" 
  | sudo tee /etc/apt/sources.list.d/gvisor.list
sudo apt update && sudo apt install -y runsc
sudo runsc install   # añade runsc a containerd
sudo systemctl restart containerd

Después se declara una RuntimeClass en Kubernetes y los Pods que la referencien arrancan con Sentry y Gofer; el resto sigue con runc. Esto permite aplicar gVisor solo a las cargas que lo necesitan sin imponer su coste a todo el clúster. Este patrón de runtime mixto encaja bien con el modelo de containerd con Wasm, donde también se conviven varios runtimes en el mismo nodo.

runsc exporta métricas en formato Prometheus con información de CPU y memoria, y los registros se integran con el stack habitual de logs. El diagnóstico cuando algo falla es más complicado que con runc porque los mensajes pueden venir de Sentry, pero la documentación ha mejorado mucho y hay una comunidad activa.

Cuándo compensa

gVisor tiene un sitio claro: cargas multi-tenant donde el aislamiento importa y el patrón de uso es intensivo en CPU y ligero en E/S.

  • Plataformas que ejecutan código de terceros.
  • Funciones serverless.
  • Entornos de pruebas donde usuarios distintos comparten nodos.
  • Clústeres educativos y laboratorios de análisis de malware.

En todos esos casos la reducción de superficie de ataque compensa de largo el 5–10 % de rendimiento que se pierde. Muchos operadores usan gVisor para una fracción del clúster, Kata para otra y runc para el resto, eligiendo la barrera que mejor encaja con el nivel de confianza y el perfil de rendimiento de cada carga. Esta heterogeneidad es la respuesta madura a cómo aislar contenedores en entornos con muchos actores. Donde no compensa es en cargas propias de una organización que confía en su propio código: si todos los pods los despliega el mismo equipo con el mismo pipeline, el sandbox extra rara vez justifica el coste operativo. Para esas cargas, las herramientas de observabilidad 2026 y Kubernetes 1.35 ofrecen mejoras de seguridad sin el sobrecoste de sandbox adicional.

¿Te ha resultado útil?
[Total: 12 · Media: 4.6]

Escrito por

CEO - Jacar Systems

Apasionado de la tecnología, la infraestructura cloud y la inteligencia artificial. Escribe sobre DevOps, IA, plataformas y software desde Madrid.