Graba microvirtuales de petardos. Tomamos dos métodos populares para aislar cargas de trabajo multiusuario: máquinas virtuales y contenedores. Exprimimos lo mejor de ambos enfoques, simplificamos lo más posible, probamos con una carga real. Como resultado, obtenemos un aislamiento impenetrable de las computadoras virtuales que se pueden iniciar en cientos de milisegundos. Esta solución funciona bajo el capó de AWS Lambda y Fargate, ejecutando millones de funciones y contenedores sin servidor en la nube cada segundo. Se llama petardo.
Esta herramienta de microvirtualización está disponible en
OpenSource . Si sus tareas requieren aislamiento de múltiples inquilinos (bueno, por ejemplo, decide crear su propia nube), Firecracker es lo que necesita.
Vasily Pantyukhin , arquitecto de Amazon Web Services, habla sobre la arquitectura Firecracker, cómo la utiliza AWS Lambda, la compara con soluciones alternativas y da ejemplos de integración.
Descargo de responsabilidad: todo lo que sigue es la opinión personal de Vasily, y puede no coincidir con la posición de los servicios web de Amazon.Características naturales de las nubes públicas.
Una de las propiedades fundamentales de las nubes públicas es la tenencia múltiple.
Alguien traduce este término como "multicliente" o "entorno multiusuario". Pero desde mi punto de vista, esto no refleja la esencia. El arrendamiento múltiple es cuando diferentes usuarios y sus cargas viven en la misma infraestructura física, la comparten entre ellos, pero no se conocen entre sí. De las cargas de trabajo de múltiples usuarios, la tenencia múltiple se distingue por requisitos fundamentalmente más estrictos para el aislamiento de recursos y el acceso a ellos.
Otra propiedad inherente a las nubes públicas es la alta carga.
¡Créame, en el caso de AWS, esta es una carga enorme! La captura de pantalla es un ejemplo de datos reales. No diré durante cuánto tiempo y en qué región se midieron estos millones de "loros", pero este no es un tipo de emergencia, sino el modo de funcionamiento habitual para nosotros.

Resulta una cierta contradicción. Por un lado, necesitamos mantener a los usuarios lo más aislados posible. Por otro lado, debemos garantizar un nivel muy alto de productividad y utilización de recursos. Mejorar uno a menudo conduce a las limitaciones del otro. ¿Cómo encontrar un compromiso, y aún mejor, para obtener el máximo en todos los frentes?
Máquinas virtuales o contenedores?
Hay dos enfoques básicos que podrían ayudar. Estas son máquinas virtuales y contenedores. Cada uno tiene sus pros y sus contras.
La principal desventaja de las máquinas virtuales es que tardan
mucho en cargarse . Por lo general, toma decenas de segundos, o incluso minutos, arrancar la máquina. Pero los virtualoks tienen una virtud:
aíslan las cargas de
hormigón entre sí. Y desde ambos puntos de vista:
- seguridad cuando una máquina virtual no puede acceder a datos en otra máquina;
- recursos , cuando pedí 8 GB de memoria, espero que esta RAM sea mía y nadie pueda reclamar el recurso por el que pagué.
Lo contrario es el caso de los contenedores: son livianos y, por lo tanto, se
cargan muy rápido. Se pueden escalar fácilmente horizontalmente. Pero hay una característica con la que nosotros, como proveedor de nube pública, no podemos vivir. Utilizan un
núcleo compartido: el núcleo del sistema operativo se comparte entre todos los contenedores .

¿Se puede decir que los contenedores son inseguros? No, a pesar de que existen serias vulnerabilidades.
Creo que hoy un contenedor debidamente "soldado" proporciona un nivel suficiente de seguridad.
El problema es diferente: un núcleo compartido no garantiza fundamentalmente que en el futuro no aparezcan vulnerabilidades que rompan el aislamiento de los inquilinos. La nube pública no puede permitírselo ni siquiera en teoría.
Hay otra contradicción más, y se debe buscar una solución. La forma más fácil es sacar lo mejor de mamá, una máquina virtual y de papá, un contenedor, una cruz y obtener algo
convergente . En realidad lo hicimos. Resultó petardo.
Petardo ya está en producción. En la misma gran carga de servicios críticos, por ejemplo, AWS Lambda (funciones sin servidor) y AWS Fargate (contenedores sin servidor).
Problemas de la antigua AWS Lambda
AWS Lambda es un servicio de características sin servidor. Tomamos la función en Java, Go, Python u otro lenguaje, la lanzamos en Lambda y se ejecuta mágicamente. No es necesario asignar y administrar recursos. ¿Cómo se implementó esto antes?

Para cada cuenta de AWS, se asignaron una o más máquinas virtuales EC2 separadas para aislar funciones que pertenecen a diferentes inquilinos. Tal máquina virtual consume recursos, incluso cuando no hace nada. Supongamos que ejecutamos una función una vez cada 10 minutos, y se ejecuta en 200 ms como un Lambda normal. Resulta que en una hora la máquina EC2 se usa solo unos segundos. Además, incluso en tiempo de ejecución, no consume todos los recursos disponibles: eliminación por debajo de la placa base. Esto es furiosamente inútil.

¿Cómo resolvió el problema del reciclaje?
Desarrolló desde cero su propia solución de Firecracker. Esto es obvio por el título del informe :)
Para comenzar a desarrollar un nuevo producto, necesita una tarea técnica. Tiene mucho texto, pero si selecciona solo el significado, obtendrá lo siguiente.
- Desarrollado por KVM como hipervisor. Quien trabaja con AWS sabe que tenemos dos hipervisores favoritos. Las máquinas virtuales heredadas se ejecutan en Xen. Desde finales de 2017, KVM ha estado viviendo bajo el capó de todos los automóviles.
- Comienza lo más rápido posible. En el hardware de referencia, el requisito era una carga completa del microvirtual en 125 ms.
- Mínima sobrecarga de virtualización . En la arquitectura de referencia, una sola máquina micro-virtual Firecracker consume además solo 5 MB de memoria.
- La posibilidad del comienzo más denso . Parámetros de diseño: carga completa de 5 microvirtuales por núcleo por segundo. Este requisito es fundamental para servicios como AWS Lambda. Las funciones deben despegar, trabajar y morir rápidamente, liberando recursos para el próximo.
- La posibilidad de volver a suscribirse . Es una oportunidad, no es necesario usarla. De hecho, esta es la asignación de recursos virtuales en mayor medida de lo que están físicamente disponibles. Esto significa que el servidor tiene 16 GB de RAM, y simultáneamente ejecuta 4 máquinas virtuales, cada una de las cuales está segura de que tiene 8 GB de memoria.
AWS Lambda con petardo debajo del capó
¿Qué ha cambiado en la nueva versión de AWS Lambda? Desde el punto de vista del usuario final, nada ha cambiado. La migración a una arquitectura actualizada en producción fue completamente transparente e invisible para los consumidores. Las características de Lambda son de corta duración: fue fácil de hacer.
¿Cómo es la arquitectura moderna?
En el nivel más bajo ahora no hay una máquina virtual, sino un físico físico.
Dichos servidores permiten el uso completo de todas las funciones de la CPU, por ejemplo, Intel VT. Esto proporciona beneficios adicionales cuando se utiliza la virtualización en niveles superiores.

Encima de la pieza de hierro se encuentra el
sistema operativo host con el módulo KVM en el núcleo.
Los microvirtuales
Firecracker con sus propios
SO invitados se lanzan arriba. Bueno, ya implementaron componentes del servicio AWS Lambda.
Anteriormente, para cada cliente que usa las características de Lambda, asignamos máquinas virtuales EC2 separadas con baja utilización. El nuevo enfoque le permite ejecutar un microvirtual ligero solo cuando realmente lo necesita. Aislar los recursos de Firecracker entre sí nos permite hacer esto en un hardware común con la máxima densidad. La utilización de los recursos ha mejorado fundamentalmente.
¿Qué hay en la caja?
Prometí un anboxing, así que repasemos los componentes principales de Firecracker, consideremos cada uno de ellos por separado, y luego póngalos juntos.

Principios de diseño
Cuando comenzamos a discutir el desarrollo de Firecracker, acordamos adherirnos a dos principios.
Deshazte de todo lo innecesario. ¿Por qué las máquinas virtuales clásicas se cargan lentamente? En particular, porque el código está sobrecargado. Tienen que soportar una gran cantidad de dispositivos heredados. Pero, ¿por qué emular un dispositivo que nadie más usaba hace 10 años? No hay necesidad, por lo tanto, nos deshacemos de todo lo que es superfluo. Resolvemos una tarea estrecha específica y cualquier funcionalidad que no ayude a resolver este problema se considera innecesaria.
Deshágase de todo lo superfluo y concéntrese en una tarea.
Simplifica lo que queda. Incluso lo que queda debe ser lo más simple posible.
¿Sobre qué escribieron?
Firecracker está escrito en moda Rust porque:
- le permite escribir código más seguro , en particular, en términos de memoria;
- El rendimiento y la sobrecarga son comparables a los modernos C ++;
- Rust se ha utilizado durante mucho tiempo, desde 2015 ha escrito muchas soluciones geniales de alta carga.
Hierro
Repito: Firecracker requiere instalación en hardware real. Como configuración de referencia, se eligió la máquina de metal desnudo i3.metal.
Nota: el informe fue a principios de abril de 2019. En ese momento, solo se admitía la plataforma Intel. En mayo, agregaron soporte alfa para AMD, y en junio ARM. AMD puede ser un poco más barato que Intel, y el soporte ARM ofrece oportunidades interesantes para trabajar con IoT de múltiples inquilinos.Si solicita una máquina i3.metal u otra máquina de metal desnudo en AWS, entonces para los experimentos será una configuración demasiado potente y costosa. Por lo tanto, si decide instalar Firecracker en ellos, no olvide pagar estas máquinas después de los experimentos. De lo contrario, se obtendrá un puntaje decente a fin de mes.
¿Hay una opción más barata? Sí, puede iniciar Firecracker en un entorno virtual. Pero ya no está en AWS: básicamente no admitimos la virtualización anidada en EC2. Pero puede hacerlo en GCP, Azure, DigitalOcean o usar Proxmox, Parallels, VMware Fusion. Todo funcionará si cumple con los requisitos, en particular, de acuerdo con la versión del kernel del sistema operativo invitado.
El núcleo
El elemento fundamental de la solución es el módulo del núcleo KVM.
Por si acaso, describiré como una digresión lo que es KVM. Este no es el hipervisor completo, sino solo una parte de él. Sus tareas principales son
configurar un procesador virtual (vCPU) e
iniciar una máquina virtual .

Pero esto no es suficiente para un trabajo completo. Además del procesador, se necesitan algunos otros dispositivos. Su emulación ocurre en el espacio del usuario.
VMM
Para que aparezcan al menos dispositivos básicos, necesita otro componente: Virtual Machine Manager (VMM). Antes de Firecracker, la opción principal de VMM era QEMU.

Consideramos seriamente la posibilidad de usar QEMU, pero decidimos desarrollar nuestra propia "bicicleta". Hubo varias razones para esto.
Gestión del desarrollo . QEMU es un producto grande y maduro con más de un millón de líneas de código. Para realizar cambios, debe ver demasiados códigos fuente. Mucha gente participa en el desarrollo y la toma de decisiones sobre el desarrollo.
Seguridad QEMU puede emular muchos dispositivos. Es por eso que tiene una superficie de ataque bastante grande. Nuestra tarea es hacer un microvirtual. Desde un punto de vista de seguridad, debemos minimizar la superficie de ataque.
La necesidad de implementar nuevas características. QEMU tiene buen código. Este es un producto maduro en el que todos los errores obvios ya están atrapados. Pero en su forma actual, la funcionalidad QEMU aún no nos convenía, tendríamos que agregar mucho. Desde este punto de vista, el nuevo código en QEMU y en el nuevo producto tendría la misma calidad. Por lo tanto, una victoria especial no funcionaría.
Dispositivos
Firecracker implementa VMM, que se utiliza para emular dispositivos. Emulamos los siguientes dispositivos:
- Consola Una cosa útil y necesaria, aunque se puede desactivar.
- Teclado Creamos un teclado complicado, con solo un botón "Restablecer". Simplemente no confiamos en el software "Reset" de aquellos sistemas operativos que potencialmente podrían ejecutarse en Firecracker. Por lo tanto, hicieron hierro.
- Controladores Virtio para disco y red . Virtio es un dispositivo muy primitivo. En esencia, este es un "anillo de amortiguación". El sistema invitado escribió algo en el búfer, hizo clic en la llamada y el sistema host leyó los datos de este búfer a través de un archivo.
En algunos casos, por ejemplo, para la integración con contenedores, todavía necesitamos un dispositivo de red que represente la funcionalidad básica de una tarjeta de red normal. Virtio no encaja aquí, demasiado simple. Por lo tanto, para la red usamos otro dispositivo:
Vsock .
Bueno, también necesitamos la capacidad de controlar el consumo de recursos. El
limitador de velocidad es responsable de esto.
Hay dispositivos Pero, ¿cómo gestionar y configurar microvirtuales? La API de gestión nos ayudará aquí.
Gestión
Amazon tiene varios principios fundamentales irrompibles. Uno de ellos es que cualquier servicio se comunica entre sí solo a través de la API. No importa si se trata de servicios externos que utiliza como usuario o nuestros servicios internos. No sucede que un servicio vaya directamente a la base de datos de otro servicio; está prohibido y se castiga. El hilo API Firecracker solo se usa para acceder a la configuración y funcionalidad de los microvirtuales a través de la API REST.

Nos adherimos a la especificación Open API, por lo que puede usar Swagger.
Metadatos
Existe tal maldad: codificación difícil. Esto es cuando algunos datos se cosen directamente en el código, por ejemplo, el inicio de sesión y la contraseña de acceso a otro recurso. Esto, por supuesto, no está permitido. Periódicamente, necesitamos transferir algunos datos dentro del microvirtual. Esto se hace a través del
servicio de metadatos .

Pasamos la información requerida a través del socket al comercio de metadatos IMDS. Para obtener esta información dentro del microvirtual, debe solicitar
http://169.254.169.254/latest/meta-data utilizando la API REST. Los usuarios de AWS ya conocen esta IP mágica. Del mismo modo, los microvirtuales pueden obtener información detallada sobre su propia configuración.
Registros
Es imperativo poder arrojar troncos de microvirtuales al mundo exterior antes de que ella muera. Esto se hace a través de un Unix
FIFO regular.

Aislamiento adicional
La principal ventaja de la máquina virtual de forma aislada. Parece que esto debería ser suficiente, pero fuimos más allá. Por si acaso, para ejecutar la producción, se recomienda colocar una capa adicional de aislamiento llamada
Jailer .

Estas son precauciones estándar:
- cgroups para limitar los recursos;
- espacio de nombres para aislar procesos;
- seccomp : un análogo del firewall para llamadas al sistema;
- y, por supuesto, el chroot favorito de todos .
Integración con otros servicios.
¿Hay alguna solución preparada basada en Firecracker? Por supuesto que si.
OSV
Este sistema operativo está diseñado para ejecutar solo una aplicación. Debido a esto, ella simplemente ha organizado el trabajo con memoria y un planificador. Un sistema operativo potente y fácil de administrar ahora
funciona sobre Firecracker .
Contenedor
También hicimos integración con containerd. Si ya trabaja con él, necesita un mínimo esfuerzo para lanzar contenedores envueltos en Firecracker para su aislamiento.

En lugar de la cuña habitual, containerd se refiere a la cuña Firecracker. Ya administra runc, a través de un agente que está instalado dentro del microvirtual.
A cuadros, funciona .
Contenedores Kata
Cuando anunciamos Firecracker por primera vez, una de las preguntas más populares de los clientes fue:
- El mecanismo para aislar contenedores ya se ha inventado: se trata de Kata Containers. ¿Por qué no los usaste? ¿Por qué desarrollar el tuyo?- Kata trabaja con QEMU, pero no queremos trabajar con QEMU. Por lo tanto, decidimos cocinar la nuestra.Pero resultó interesante. Los desarrolladores de Kata se reunieron con los desarrolladores de Firecracker y acordaron integrarse. Porque todos ven esto como una gran ventaja.
Kata Containers v1.5 ya es compatible con QEMU y Firecracker.
Resulta que no competimos, sino que nos complementamos armoniosamente. En Kubernetes con v1.12, puede definir runtimeClassName como Kata FC o Kata QEMU, y ejecutar sus contenedores en el aislamiento adecuado.
¿Cómo elegir el aislamiento que se adapte a su aplicación: Firecracker o QEMU? Mi opinión personal es que lo que
importa es si su aplicación es
mascotas o ganado .
Kata con QEMU es una solución para mascotas. QEMU es un sistema grande y multifuncional. Potencialmente, ofrece más opciones de soporte y tratamiento para sus mascotas favoritas.
El petardo es adecuado cuando la carga es ganado. En el caso de que su aplicación sin estado se haya diseñado originalmente para un escalado horizontal flexible y la falla de uno o más contenedores no es crítica. Proporcionando un aislamiento confiable, le permite cargar rápidamente la cantidad requerida de contenedores nuevos para reemplazar los fallidos.
Cual es el resultado?
Comenzamos con contradicciones. Parece que resolver la contradicción es un enfoque "nuestro y tuyo", algo intermedio que satisfará a todos. Pero la experiencia dice que el compromiso no es necesario.
Nos propusimos el objetivo de desarrollar una nueva solución en la que no habrá nada superfluo que no sea necesario para resolver una tarea estrecha. También era importante simplificar todo lo que usamos tanto como sea posible. Me gustaría creer que no obtuvimos un compromiso, sino una solución sólida que le permite lanzar de forma rápida y densa miles de microvirtuales sin sacrificar su aislamiento.
Ya usamos Firecracker en la producción de varios de nuestros servicios. La principal ventaja que obtuvimos es la mejora de la utilización del servicio. Esto permitió ahorrar significativamente. Parte de este ahorro lo compartimos con los clientes. Por ejemplo, después de la introducción de Firecracker, los precios de los contenedores sin servidor AWS Fargate en enero de 2019 cayeron en un 35-50%. El beneficio es visible a simple vista, por lo que no hay duda de que continuaremos desarrollando este producto y compartiendo nuestras mejores prácticas con Open Source. El hecho de que Firecracker ya haya comenzado a integrarse con otras soluciones indica un interés creciente por parte de la comunidad.
Si tiene una idea o un producto terminado en cuya descripción están las palabras "aislamiento multiinquilino", este es un claro indicador de lo que vale la pena experimentar con los microvirtuales Firecracker.
Este informe ilustra perfectamente el principio al que estamos intentando adherirnos en las conferencias de Ontiko : recibir experiencia mundial de expertos de habla rusa. Y el punto no es solo una posible barrera del idioma, sino que en la cultura estamos acostumbrados a compartir detalles técnicos. En noviembre, Vasily actuará nuevamente en HighLoad ++ , y se le unirá , por ejemplo, Artemy Kolesnikov de Facebook, Vittorio Cioe de Oracle y, por supuesto, Petr Zaitsev de Percona. También tendremos informes en inglés, suscríbase al boletín informativo: le informaremos cuándo se agregarán nuevos a los cuarenta informes aceptados.