Puede preguntar, ¿por qué lidiar con la terminología si el concepto de contenedores parece bastante simple y directo? Sin embargo, con frecuencia el uso incorrecto de los términos crea obstáculos para el desarrollo de contenedores. Por ejemplo, las personas a menudo piensan que los términos "contenedores" e "imágenes" se usan indistintamente, aunque en realidad existen importantes diferencias conceptuales entre ellos. Otro ejemplo: en el mundo de los contenedores, un "repositorio" no significa lo que piensas. Además, la tecnología de contenedores es mucho más que solo docker.

Entonces, sin conocer la terminología, será difícil entender cómo Docker difiere de CRI-O, rkt o lxc / lxd; o evaluar el papel de Open Container Initiative en la estandarización de tecnologías de contenedores.
Introduccion
Comenzar con los contenedores de Linux es muy simple, pero pronto resulta que esta simplicidad es engañosa. Esto suele suceder así: después de pasar solo un par de minutos instalando un acoplador u otro motor de contenedor, ya ingresas tus primeros comandos. Solo un par de minutos, y ya creó su primera imagen del contenedor y la puso en el dominio público. Luego, habitualmente, se pasa a la arquitectura del entorno de producción y, de repente, se da cuenta de que para esto primero necesita lidiar con la gran cantidad de términos y tecnologías que están detrás de todo esto. Peor aún, muchos de los términos enumerados a continuación se usan indistintamente, lo que crea mucha confusión para los principiantes.
- Contenedor
- Imagen
- Imagen de contenedor
- Capa de imagen
- Registro
- Repositorio
- Etiqueta
- Imagen base
- Imagen de plataforma
- Capa
Una vez que domine la terminología establecida en este documento, comprenderá mejor la base tecnológica de los contenedores. Además, lo ayudará a usted y a sus colegas a hablar el mismo idioma, así como a diseñar consciente y resueltamente la arquitectura de los entornos de contenedores de acuerdo con los detalles de las tareas que se resuelven. A su vez, desde el punto de vista de la comunidad de TI y la industria en general, un aumento general en la comprensión de las tecnologías de contenedores contribuye a la aparición de nuevas arquitecturas y soluciones. Tenga en cuenta que este artículo está destinado a un lector que ya tiene una idea de cómo ejecutar contenedores.
Contenedores: básicos
Antes de continuar con la terminología de los contenedores, determinaremos qué es, de hecho, el contenedor en sí. El término "contenedor" significa dos cosas a la vez. Al igual que un programa Linux normal, un contenedor puede estar en uno de dos estados: en funcionamiento y no en funcionamiento. En el estado inactivo, el contenedor es un archivo o un conjunto de archivos almacenados en el disco. A este estado se refieren los términos Imagen de contenedor y Repositorio de contenedor. Cuando ingresa el comando de inicio del contenedor, el motor del contenedor desempaqueta los archivos y metadatos necesarios y los transfiere al kernel de Linux. Iniciar un contenedor es muy similar a iniciar un proceso normal de Linux y requiere una llamada API al kernel de Linux. Esta llamada a la API generalmente inicia un aislamiento adicional y monta una copia de los archivos que están en la imagen del contenedor. Una vez que se inicia el contenedor, es solo un proceso de Linux. El procedimiento para lanzar contenedores, así como el formato de las imágenes de los contenedores almacenados en el disco, están definidos y regulados por estándares.
Existen varios formatos para imágenes de contenedor (
Docker ,
Appc ,
LXD ), pero la industria se está moviendo gradualmente hacia un único estándar de
Open Container Initiative , a veces llamado Open Containers o simplemente OCI. Este estándar define la
especificación del formato de la imagen del contenedor , que define el formato de disco para almacenar imágenes del contenedor, así como los metadatos, que, a su vez, define elementos tales como la arquitectura del hardware y el sistema operativo (Linux, Windows, etc.). Un único formato de imagen para toda la industria es la clave para crear un ecosistema de software que permita a los desarrolladores, proyectos de código abierto y proveedores de software crear imágenes compatibles y diversas herramientas, como firma electrónica, escaneo, ensamblaje, lanzamiento, movimiento y administración de imágenes de contenedores.
Además, hay varios motores de contenedores, como
Docker ,
CRI-O ,
Railcar ,
RKT ,
LXC . El motor del contenedor toma una imagen del contenedor y lo convierte en un contenedor (es decir, un proceso en ejecución). El proceso de conversión también está definido por el estándar OCI, que incluye una especificación de tiempo de ejecución de contenedor y una implementación de referencia de tiempo de ejecución llamada RunC, que es un modelo de código abierto que está regulado por la comunidad de desarrollo apropiada. Muchos motores de contenedores utilizan este modelo para interactuar con el núcleo del host al crear contenedores.
Las herramientas que admiten las especificaciones del
formato de imagen del contenedor y
el entorno de ejecución del contenedor del estándar OCI proporcionan portabilidad dentro del ecosistema de varias plataformas de contenedores, motores de contenedores y herramientas de soporte en varias plataformas de nube y arquitecturas locales. Comprender la terminología, los estándares y la arquitectura de los sistemas de contenedores le permitirá comunicarse fructíferamente con otros especialistas y diseñar aplicaciones y entornos en contenedores escalables y compatibles que garanticen el uso eficiente de contenedores en los años venideros.
Vocabulario básico
Imagen del contenedor
En su definición más simple, una imagen de contenedor es un archivo que se descarga del servidor de registro y se usa localmente como punto de montaje cuando se inicia el contenedor. A pesar de que el término "imagen contenedor" se usa con bastante frecuencia, puede significar cosas diferentes. El hecho es que, aunque Docker, RKT e incluso LXD funcionan de acuerdo con el principio que se acaba de describir, es decir, descargan archivos eliminados y los ejecutan como contenedores, cada una de estas tecnologías interpreta la imagen del contenedor a su manera. LXD funciona con imágenes monolíticas (una capa), mientras que Docker y RKT usan imágenes OCI, que pueden contener varias capas.
Estrictamente hablando, una imagen de contenedor en un servidor de registro está lejos de ser un solo archivo. Cuando las personas usan el término "imagen del contenedor", a menudo se refieren al repositorio y a un conjunto de varias capas de la imagen del contenedor, así como a los metadatos que contienen información adicional sobre estas capas.
Además, el concepto de una imagen contenedor implica implícitamente la existencia de un formato para dicha imagen.
Formato de imagen de contenedor
Inicialmente, cada motor de contenedor, incluidos LXD, RKT y Docker, tenía su propio formato de imagen. Algunos de estos formatos permiten solo una capa, mientras que otros admiten una estructura de árbol de varias capas. Hoy, casi todas las herramientas y motores principales del contenedor han cambiado al formato
OCI , que determina cómo deben organizarse las capas y los metadatos en la imagen del contenedor. En esencia, el formato OCI define una imagen de contenedor que consta de archivos tar separados para cada capa y un archivo manifest.json común que contiene metadatos.
El estándar
Open Container Initiative (OCI) , que se basó originalmente en
el formato de imagen Docker V2 , ha combinado con éxito un gran ecosistema de motores de contenedores, plataformas y herramientas en la nube (escáneres de seguridad, herramientas de firma, creación y movimiento de contenedores) y le permite proteger su inversión en conocimiento y herramientas
Motor de contenedores
El motor de contenedor es esa parte del software que acepta las solicitudes de los usuarios, incluidos los parámetros de la línea de comandos, descarga imágenes y, desde la perspectiva del usuario final, lanza contenedores. Hay muchos motores de contenedores, incluidos docker, RKT, CRI-O y LXD. Además, muchas plataformas en la nube, servicios de PaaS y plataformas de contenedores tienen sus propios motores que entienden las imágenes en formato Docker u OCI. Tener un estándar de la industria para el formato de imagen garantiza la interoperabilidad de todas estas plataformas.
Al bajar un nivel, podemos decir que la mayoría de los motores de contenedores no inician los contenedores en sí, sino a través de un tiempo de ejecución compatible con OCI, como runc. Normalmente, un tiempo de ejecución de contenedor hace lo siguiente:
- Maneja parámetros, entrada del usuario
- Maneja los parámetros pasados a través de la API (más a menudo el sistema de orquestación de contenedores)
- Descargar imágenes del contenedor desde el servidor de registro
- Desempaqueta y guarda la imagen del contenedor en el disco usando Graph Driver (bloque o archivo, dependiendo del controlador)
- Prepara un punto de montaje para el contenedor, generalmente en almacenamiento de copia en escritura (nuevamente, bloque o archivo, dependiendo del controlador)
- Prepara metadatos que se pasarán al tiempo de ejecución para ejecutar el contenedor correctamente usando:
- Configuraciones predeterminadas específicas que están implícitas para la imagen del contenedor (por ejemplo, ArchX86 )
- Entrada del usuario para anular los valores predeterminados contenidos en la imagen del contenedor (por ejemplo, CMD, ENTRYPOINT)
- Parámetros predeterminados especificados por la imagen del contenedor (por ejemplo, reglas SECCOM )
- Invoca el tiempo de ejecución del contenedor
Contenedor
Los contenedores han existido en los sistemas operativos durante bastante tiempo, porque de hecho esto es solo una instancia en ejecución de una imagen de contenedor. Un contenedor es un proceso estándar de Linux que generalmente se crea usando la llamada al sistema clone () en lugar de fork () o exec (). Además, a menudo se aplican medidas de aislamiento adicionales a los contenedores que usan
cgroups ,
SELinux o
AppArmor .
Host de contenedores
Un host de contenedor es un sistema en el que se ejecutan procesos en contenedor, que a menudo se denominan contenedores por simplicidad. Esto puede ser, por ejemplo, una máquina virtual
RHEL Atomic Host ubicada en una nube pública o que se ejecuta en el metal desnudo en un centro de datos corporativo. Cuando la imagen del contenedor (en otras palabras, el repositorio) del servidor de registro se descarga al host del contenedor local, dicen que cae en el caché local.
Puede determinar qué repositorios se sincronizan con la memoria caché local utilizando el siguiente comando:
[root @ rhel7 ~] # imágenes acoplables -a
ID DE IMAGEN DE ETIQUETA DE REPOSITORIO TAMAÑO VIRTUAL CREADO
Registry.access.redhat.com/rhel7 última 6883d5422f4e Hace 3 semanas 201.7 MB
Servidor de registro
Un servidor de registro es esencialmente un servidor de archivos que se utiliza para almacenar repositorios de acopladores. Como regla general, el servidor de registro se especifica mediante el nombre DNS y, opcionalmente, el número de puerto. La mayoría de los beneficios del ecosistema docker están impulsados por la capacidad de descargar y cargar repositorios en los servidores de registro.
Si el dacker de Docker no encuentra una copia del repositorio en la memoria caché local, la descarga automáticamente del servidor de registro. En la mayoría de las distribuciones de Linux, el docker daemon usará el sitio docker.io para esto, pero en algunas distribuciones se puede configurar a su manera. Por ejemplo, Red Hat Enterprise Linux primero intenta descargar desde Registry.access.redhat.com, y solo luego desde docker.io (Docker Hub).
Debe enfatizarse aquí que el servidor de registro se considera implícitamente como confiable. Por lo tanto, debe decidir cuánto confía en el contenido de un registro y, respectivamente, permitirlo o denegarlo. Además de la seguridad, hay otros aspectos que deben abordarse de antemano, por ejemplo, problemas de licencias de software o monitoreo de cumplimiento. La simplicidad con la que Docker permite a los usuarios descargar software hace que el tema de la confianza sea extremadamente importante.
Red Hat Enterprise Linux le permite configurar el registro docker predeterminado. Además, RHEL7 y RHEL7 Atomic le permiten agregar o bloquear servidores de registro a través del
archivo de configuración :
vi / etc / sysconfig / docker
RHEL7 y RHEL 7 Atomic utilizan el servidor de registro de Red Hat de manera predeterminada:
ADD_REGISTRY = '- agregar registro-registro.access.redhat.com'
En algunos casos, por razones de seguridad, tiene sentido bloquear los registros de acopladores públicos, como DockerHub:
# BLOCK_REGISTRY = '- bloque-registro'
Red Hat también ofrece su servidor de registro integrado como parte de
OpenShift Container Platform , así como el servidor de registro corporativo independiente
Quay Enterprise y los repositorios en la nube, privados y públicos
Quay.io.Orquestación de contenedores
Las personas generalmente comienzan instalando un host contenedor y primero simplemente descargando las imágenes de contenedor que necesitan. Luego proceden a crear sus propias imágenes y las suben al servidor de registro para ponerlas a disposición del resto del equipo. Después de algún tiempo, es necesario combinar varios contenedores para que puedan desplegarse como una sola unidad. Y finalmente, en algún momento, estas unidades deben formar parte del transportador de producción (desarrollo-control de calidad-producción). Así es como las personas suelen darse cuenta de que necesitan un sistema de orquestación.
El sistema de orquestación de contenedores implementa solo dos cosas:- Despacha dinámicamente cargas de contenedores a través de equipos de clúster (esto a menudo se conoce como "computación distribuida")
- Proporciona un archivo de descripción de aplicación estándar (kube yaml, docker compose, etc.)
Estas dos cosas realmente ofrecen una variedad de beneficios:
- La capacidad de administrar los contenedores que componen la aplicación, independientemente uno del otro, lo que le permite resolver de manera efectiva las siguientes tareas:
- Eliminación de grandes grupos de hosts de contenedores.
- Falla a nivel de contenedores individuales (ya no responden procesos, agotamiento de memoria)
- Conmutación por error en el nivel de host del contenedor (unidades, red, reinicio)
- Conmutación por error en el nivel del motor del contenedor (daño, reinicio)
- Escalado individual de contenedores hacia arriba y hacia abajo
- Fácil de implementar nuevas instancias de la misma aplicación en nuevos entornos, tanto en la nube como tradicionales, por ejemplo:
- En máquinas desarrolladoras controladas por un sistema de orquestación
- En un entorno de desarrollo compartido en un espacio de nombres privado
- En un entorno de desarrollo común en un espacio de nombres público interno para garantizar la visibilidad y probar el rendimiento
- En el ambiente interno de QA
- En un entorno de carga de prueba proporcionado dinámicamente y revocado en la nube
- En un entorno de referencia para verificar la compatibilidad con el entorno de producción.
- En ambiente de producción
- En un entorno de recuperación ante desastres.
- En un nuevo entorno de producción que contiene hosts de contenedores actualizados, motores de contenedores o herramientas de orquestación
- En el nuevo entorno de producción, que no es diferente del principal, sino que se encuentra en una región diferente
Las comunidades de código abierto y los proveedores de software ofrecen muchas herramientas de orquestación diferentes. Inicialmente, las tres grandes herramientas incluían
Swarm ,
Mesos y
Kubernetes , pero hoy Kubernetes se ha convertido en el estándar de la industria, porque incluso
Docker y
Mesosphere han anunciado su apoyo, sin mencionar a casi todos los principales proveedores de servicios. Sin embargo, si está buscando un sistema de orquestación corporativa, le recomendamos que eche un vistazo más de cerca a
Red Hat OpenShift .
Diccionario avanzado
Tiempo de ejecución del contenedor
El tiempo de ejecución del contenedor es un componente de bajo nivel que generalmente se usa como parte de un motor de contenedor, pero también se puede usar manualmente para probar los contenedores.
El estándar OCI define una implementación de referencia del tiempo de ejecución conocido como
runc . Esta es la implementación más utilizada, pero hay otros
tiempos de ejecución compatibles con OCI como
crun ,
railcar y
katacontainers . Docker, CRI-O y muchos otros motores de contenedor usan runc.
El tiempo de ejecución del contenedor es responsable de lo siguiente:
- Obtiene el punto de montaje del contenedor proporcionado por el motor del contenedor (para la prueba, podría ser solo un directorio)
- Obtiene los metadatos del contenedor proporcionados por el motor del contenedor (durante la prueba, este puede ser un archivo config.json ensamblado manualmente)
- Se comunica con el núcleo del sistema operativo para iniciar procesos en contenedores (a través de la llamada al sistema de clonación)
- Configura cgroups
- Configura la política de SELinux
- Configura las reglas de la armadura de la aplicación
Una pequeña digresión histórica: cuando apareció por primera vez el motor Docker, utilizaba el LXC como un entorno de tiempo de ejecución. Los desarrolladores de Docker escribieron su propia biblioteca para ejecutar contenedores llamados libcontainer. Fue escrito en el idioma Golang y se convirtió en parte del motor Docker. Después del establecimiento de la organización OCI, Docker introdujo el código fuente libcontainer en este proyecto y lanzó esta biblioteca como una utilidad separada llamada runc, que luego se convirtió en la implementación de referencia del tiempo de ejecución del contenedor dentro del estándar OCI y se usa en otros motores de contenedor, como CRI-O . Runc es una utilidad muy simple que solo espera que se le pase un punto de montaje (directorio) y metadatos (config.json). Puede encontrar más información sobre runc
aquí .
Para una comprensión más profunda, vea
Comprensión de los estándares de contenedores y el
tiempo de ejecución de contenedores .
Capas de imagen
Los repositorios a menudo se denominan imágenes o imágenes de contenedores, aunque de hecho los repositorios consisten en una o más capas. Las capas de imagen en el repositorio están interconectadas por las relaciones padre-hijo, y cada capa de imagen contiene diferencias de la capa padre.
Veamos las capas del repositorio en el host del contenedor local. Desde que comenzó
con la versión 1.7, Docker no tiene una herramienta integrada para ver las capas de imágenes en el repositorio local (pero hay herramientas para registros en línea), utilizaremos la utilidad
Dockviz . Tenga en cuenta que cada capa tiene una etiqueta y un
identificador único universal (UUID) . Para ver los UUID abreviados que generalmente son únicos dentro de la misma máquina, utilizamos el siguiente comando (si necesita un UUID completo, use el mismo comando con la opción -no-trunc):
docker run --rm --privileged -v /var/run/docker.sock:/var/run/docker.sock nate / dockviz images -t
322332d8973c93 Tamaño virtual: 187.7 MB
Virtual └─ea358092da77 Tamaño virtual: 187.9 MB
Virtual └─a467a7c6794f Tamaño virtual: 187.9 MB
Virtual └─ca4d7b1b9a51 Tamaño virtual: 187.9 MB
Virtual └─4084976dd96d Tamaño virtual: 384.2 MB
Virtual └─943128b20e28 Tamaño virtual: 386.7 MB
Virtual └─db20cc018f56 Tamaño virtual: 386.7 MB
Virtual └─45b3c59b9130 Tamaño virtual: 398.2 MB
Virtual └─91275de1a5d7 Tamaño virtual: 422.8 MB
Virtual └─e7a97058d51f Tamaño virtual: 422.8 MB
Virtual └─d5c963edfcb2 Tamaño virtual: 422.8 MB
Virtual └─5cfc0ce98e02 Tamaño virtual: 422.8 MB
Virtual └─7728f71a4bcd Tamaño virtual: 422.8 MB
Virtual └─0542f67da01b Tamaño virtual: 422.8 MB Etiquetas: docker.io/registry:latest
Como puede ver, el repositorio docker.io/registry en realidad consta de muchas capas. Sin embargo, lo que es más importante, el usuario puede, en principio, "iniciar" el contenedor desde cualquier paso de esta escalera de pasos, por ejemplo, ingresando el comando a continuación (es completamente correcto, pero nadie puede garantizar que se haya probado o funcionará correctamente). Como regla general, el colector de imágenes etiqueta (crea nombres) aquellas capas que deben usarse como punto de partida:
docker run -it 45b3c59b9130 bash
Los repositorios se organizan de manera similar porque cada vez que el recopilador crea una nueva imagen, las diferencias se guardan como otra capa. Hay dos formas principales de crear nuevas capas en el repositorio. Primero, al crear una imagen manualmente, cada confirmación de cambio crea una nueva capa. Si el recopilador crea una imagen utilizando un archivo Docker, cada directiva del archivo crea una nueva capa. Por lo tanto, siempre es útil poder ver qué ha cambiado en el repositorio entre capas.
Etiquetas
Aunque el usuario mismo puede especificar la capa de inicio para montar e iniciar el contenedor en el repositorio, no tiene que hacer esto en absoluto. Cuando el recopilador de imágenes crea un nuevo repositorio, generalmente marcan las capas más adecuadas para este rol. Estos marcadores se denominan etiquetas y representan una herramienta con la que el recopilador de imágenes puede decirle al consumidor de imágenes qué capas se utilizan mejor. Normalmente, las etiquetas se usan para indicar versiones de software dentro de un repositorio. OCI, - , . , .
, – latest, , . , , .
, (
jq ):
curl -s registry.access.redhat.com/v1/repositories/rhel7/tags | jq
{
"7.0-21": "e1f5733f050b2488a17b7630cb038bfbea8b7bdfa9bdfb99e63a33117e28d02f",
"7.0-23": "bef54b8f8a2fdd221734f1da404d4c0a7d07ee9169b1443a338ab54236c8c91a",
"7.0-27": "8e6704f39a3d4a0c82ec7262ad683a9d1d9a281e3c1ebbb64c045b9af39b3940",
"7.1-11": "d0a516b529ab1adda28429cae5985cab9db93bfd8d301b3a94d22299af72914b",
"7.1-12": "275be1d3d0709a06ff1ae38d0d5402bc8f0eeac44812e5ec1df4a9e99214eb9a",
"7.1-16": "82ad5fa11820c2889c60f7f748d67aab04400700c581843db0d1e68735327443",
"7.1-24": "c4f590bbcbe329a77c00fea33a3a960063072041489012061ec3a134baba50d6",
"7.1-4": "10acc31def5d6f249b548e01e8ffbaccfd61af0240c17315a7ad393d022c5ca2",
"7.1-6": "65de4a13fc7cf28b4376e65efa31c5c3805e18da4eb01ad0c8b8801f4a10bc16",
"7.1-9": "e3c92c6cff3543d19d0c9a24c72cd3840f8ba3ee00357f997b786e8939efef2f",
"7.2": "6c3a84d798dc449313787502060b6d5b4694d7527d64a7c99ba199e3b2df834e",
"7.2-2": "58958c7fafb7e1a71650bc7bdbb9f5fd634f3545b00ec7d390b2075db511327d",
"7.2-35": "6883d5422f4ec2810e1312c0e3e5a902142e2a8185cd3a1124b459a7c38dc55b",
"7.2-38": "6c3a84d798dc449313787502060b6d5b4694d7527d64a7c99ba199e3b2df834e",
"latest": "6c3a84d798dc449313787502060b6d5b4694d7527d64a7c99ba199e3b2df834e"
}
docker , . , «rhel7» – .
docker pull rhel7
:
docker pull registry.access.redhat.com/rhel7:latest
, . , , , docker images. , , , «» (manifest.json):
docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
registry.access.redhat.com/rhel7 latest 6883d5422f4e 4 weeks ago 201.7 MB
registry.access.redhat.com/rhel latest 6883d5422f4e 4 weeks ago 201.7 MB
registry.access.redhat.com/rhel6 latest 05c3d56ba777 4 weeks ago 166.1 MB
registry.access.redhat.com/rhel6/rhel latest 05c3d56ba777 4 weeks ago 166.1 MB
...
, . docker ( , ) , «rhel7» .
, docker URL. , , URL .
, :
REGISTRY/NAMESPACE/REPOSITORY[:TAG]
URL , , , . URL , docker , . , : :
docker pull registry.access.redhat.com/rhel7/rhel:latest
docker pull registry.access.redhat.com/rhel7/rhel
docker pull registry.access.redhat.com/rhel7
docker pull rhel7/rhel:latest
– .
DockerHub , , .
Red Hat ,
Red Hat Federated Registry . registry.access.redhat.com . , . , Red Hat , - :
registry.access.redhat.com/rhel7/rhel
registry.access.redhat.com/openshift3/mongodb-24-rhel7
registry.access.redhat.com/rhscl/mongodb-26-rhel7
registry.access.redhat.com/rhscl_beta/mongodb-26-rhel7
registry-mariadbcorp.rhcloud.com/rhel7/mariadb-enterprise-server:10.0
, URL . . fedora, latest. :
docker pull fedora
docker pull docker.io/fedora
docker pull docker.io/library/fedora:latest
, , . , , , , , . , , , . .
Bash Enter, Bash Linux-
exec() . , , docker, docker ,
clone() . clone () , , , , , ..
, Linux - , clone ().
…