352.1 Container Virtualization Concepts
Weight 7
Description: Candidates should understand the concept of container virtualization. This includes understanding the Linux components used to implement container virtualization as well as using standard Linux tools to troubleshoot these components.
Key Knowledge Areas:
Understand the concepts of system and application container
Understand and analyze kernel namespaces
Understand and analyze control groups
Understand and analyze capabilities
Understand the role of seccomp, SELinux and AppArmor for container virtualization
Understand how LXC and Docker leverage namespaces, cgroups, capabilities, seccomp and MAC
Understand the principle of runc
Understand the principle of CRI-O and containerd
Awareness of the OCI runtime and image specifications
Awareness of the Kubernetes Container Runtime Interface (CRI)
Awareness of podman, buildah and skopeo
Awareness of other container virtualization approaches in Linux and other free operating systems, such as rkt, OpenVZ, systemd-nspawn or BSD Jails
The following is a partial list of the used files, terms and utilities:
nsenter
unshare
ip (including relevant subcommands)
capsh
/sys/fs/cgroups
/proc/[0-9]+/ns
/proc/[0-9]+/status
Un contenedor son instancias aisladas en ejecución en un SO, y estan basados en grupos de control y espacios de nombres
Espacios de nombres
Es una caracteristica del kernel que particiona los recursos del sistema de tal forma que un proceso determinado solo vea los recursos "asignados" y no el resto.
Tipos de recursos
- mount
- Process ID (pid)
- Network (net)
- Inter process communication (ipc)
- UTS (unix time sharing)
- User ID (user)
- cgroup namespace
- Time namespace
Ver espacios de nombres
lsns
espacios de nombres associados a un proceso
lsns -p numero-de-proceso
ls -l /proc/numero-de-proceso/ns
unshare
El comando Unshare crea nuevos espacios de nombres y luego ejecuta el programa especificado.
tipos de espacis de nombre:
unshare [options] [program [arguments]]
options:
-m, --mount[=<fichero>] deja de compartir el espacio de nombre de los montajes
-u, --uts[=<fichero>] deja de compartir el espacio de nombres UTS (nombre de máquina, etc.)
-i, --ipc[=<fichero>] deja de compartir el espacio de nombres del System V IPC
-n, --net[=<fichero>] deja de compartir el espacio de nombres de red
-p, --pid[=<fichero>] deja de compartir el espacio de nombres de pid
-U, --user[=<fichero>] deja de compartir el espacio de nombres de usuario
-C, --cgroup[=<fichero>] deja de compartir el espacio de nombres de cgroup
-T, --time[=<fichero>] deja de compartir el espacio de nombres de la hora
crea un espacio de nombres tipo mount ejecutando un shell bash, dentro de esta shell estara aislados los montajes que se hagan
unshare -m bash
lsns -p $$
unshare -p -f --mount-proc bash
unshare --pid --fork --mount-proc bash
unhare -r bash # asocia el usuario actual a root
unshare --map-root-user bash
root@pc02:~# whoami
root
unshare -m -u -p -f -r --mount-proc bash
hostname paprica
mount -t tmpfs tmpfs /mnt
echo hola > /mnt/saludo
nsenter
nsenter corre un programa dentro de otro espacio de nombres, como su propio nombre muestra
nsenter [options] [program [arguments]]
nsenter -a -t 141954
nsenter --all --target 141954
netns
espacio de nombres de red
ip netns ls
# crear espacio de nombres de red
ip netns add aislado
ip netns del aislado
# se crea la interfaz que comunicara el espacio de nmbre
ip link add dev veth0 type veth peer name veth1
# se assigna interfaz al espacio de nombre
ip link set veth1 netns aislado
# mostrar
ip netns exec aislado ip link
# assignar ip al espacio de nombres
ip netns exec aislado ip address add dev veth1 10.7.7.1/24
ip netns exec aislado ip link set dev veth1 up
ip netns exec aislado ip a
# assignar ip al espacio de nombres default del host
ip address add dev veth0 10.7.7.2/24
ip link set dev veth0 up
grupos de control (cgroups)
Ofrece limitación de recursos, establecimiento de prioridades, contabilización y control
cgroup opera en el directorio /sys/fs/cgroup
donde almacena diferentes archivos que gestionan limites, minimos y diferentes opciones assignadas a procesos.
Capabilities
Proporcionan subconjuntos de los privilegios disponibles para root
sus tres categorias son:
- heredadad(i)
- permitidas(p)
- efectivas(e)
Ver capabilities associados al un usuario actual
capsh --print
cat /proc/$$/status
...
CapInh: 0000000000000000
CapPrm: 000001ffffffffff
CapEff: 000001ffffffffff
...
capsh --decode=000001ffffffffff
agregar y quitar capabilities
En man capabilities
podemos ver todas las capabilities disponibles
getcap /usr/bin/python3.9
setcap cap_net_bind_service+ep /usr/bin/python3.9
setcap -r /usr/bin/python3.9
Seccomp
Es una funcionalidad del kernel que permite a un proceso pasar a un estado en el que unicamente puede hacer un conjunto reducido de llamadas al sistema
Open container Initiative runtime (OCI)
La Open Container Initiative, también conocida por sus siglas OCI, es un proyecto de la Linux Foundation para diseñar un estándar abierto para virtualización a nivel de sistema operativo.
El objetivo con estos estándares es asegurar que las plataformas de contenedores no estén vinculadas a ninguna empresa o proyecto concreto.
Sus especificaciones son:
- Espcifcación del motor de ejecución (runtime): Describe cómo debe proceder un OCI Runtime para ejecutar una imagen que cumple especificación correspondiente OCI.
- Especificación de imagen: Determina el formato para empaquetar la imagen del contenedor de software
- especificación de distribución: Su objetivo es estandarizar la distribución de imágenes de contenedores facilitando así la interoperabilidad entre las nubes nativas y los ecosistemas de contenedores
runc
El tiempo de ejecución de contenedores "runC" es una implementación ligera y portátil de la especificación de tiempo de ejecución de contenedores de la Iniciativa de Contenedores Abiertos (OCI). El runC reúne muchas de las características de bajo nivel que hacen posible la ejecución de contenedores. Comparte mucho código de bajo nivel con Docker, pero no depende de ninguno de los componentes de la plataforma Docker.
runc es compatible con los espacios de nombres de Linux, la migración en vivo, y tiene perfiles de rendimiento portátiles. También proporciona soporte completo para las características de seguridad de Linux como SELinux, grupos de control (cgroups), seccomp, y otros. Puedes construir y ejecutar imágenes con runc, o puedes ejecutar imágenes compatibles con OCI con runc.
Containerd
containerd es un tiempo de ejecución de contenedor estándar de la industria con énfasis en la simplicidad, la solidez y la portabilidad.
Está disponible como un demonio para Linux y Windows, que puede administrar el ciclo de vida completo del contenedor de su sistema host: transferencia y almacenamiento de imágenes, ejecución y supervisión del contenedor, almacenamiento de bajo nivel y archivos adjuntos de red, etc.
containerd está diseñado para integrarse en un sistema más grande, en lugar de ser utilizado directamente por desarrolladores o usuarios finales.
El entorno de ejecución de contenedores es el software responsable de administrar los contenedores y las imágenes de contenedor en un nodo de Kubernetes. containerd es un entorno de ejecución de contenedores graduado de CNCF (Cloud Native Cloud Foundation). Es compatible con Kubernetes de forma nativa y se considera más seguro y eficiente en cuanto a recursos que Docker Engine para Kubernetes.
una abstracción de las características del kernel que proporciona una interfaz de contenedor de nivel relativamente alto. Otros proyectos de software pueden usar esto para ejecutar contenedores y administrar imágenes de contenedores.
CRI-O
CRI-O es una implementación de Kubernetes CRI (Container Runtime Interface) para habilitar el uso de tiempos de ejecución compatibles con OCI (Open Container Initiative). Es una alternativa liviana al uso de Docker como tiempo de ejecución para kubernetes. Permite a Kubernetes usar cualquier tiempo de ejecución compatible con OCI como tiempo de ejecución del contenedor para ejecutar pods. Actualmente admite runc y Kata Containers como tiempos de ejecución de contenedores, pero en principio se puede conectar cualquier tiempo de ejecución compatible con OCI.
CRI-O admite imágenes de contenedor OCI y puede extraerlas de cualquier registro de contenedor. Es una alternativa liviana al uso de Docker, Moby o rkt como tiempo de ejecución para Kubernetes.
Los componentes arquitectónicos son los siguientes:
- Kubernetes se pone en contacto con el kubelet para lanzar un pod.
- Los pods son un concepto de kubernetes que consta de uno o más contenedores que comparten los mismos espacios de nombres IPC, NET y PID y que viven en el mismo cgroup.
- El kubelet reenvía la solicitud al demonio CRI-O a través de kubernetes CRI (interfaz de tiempo de ejecución del contenedor) para lanzar el nuevo POD.
- CRI-O utiliza la biblioteca de contenedores/imágenes para extraer la imagen de un registro de contenedor.
- La imagen descargada se desempaqueta en los sistemas de archivos raíz del contenedor, se almacena en los sistemas de archivos COW, utilizando contenedores/biblioteca de almacenamiento.
- Una vez que se ha creado rootfs para el contenedor, CRI-O genera un archivo json de especificación de tiempo de ejecución de OCI que describe cómo ejecutar el contenedor con las herramientas de OCI Generate.
- Luego, CRI-O lanza un tiempo de ejecución compatible con OCI utilizando la especificación para ejecutar los procesos del contenedor. El tiempo de ejecución de OCI predeterminado es runc.
- Cada contenedor es monitoreado por un proceso común separado. El proceso común contiene el pty del PID1 del proceso contenedor. Maneja el registro del contenedor y registra el código de salida para el proceso del contenedor.
- La red para el pod se configura mediante el uso de CNI, por lo que cualquier complemento de CNI se puede usar con CRI-O.
CRI-O está compuesto por varios componentes que se encuentran en diferentes repositorios de GitHub.
- Tiempo de ejecución compatible con OCI
- contenedores/almacenamiento
- contenedores/imagen
- redes (CNI)
- monitoreo de contenedores (conmon)
- la seguridad es proporcionada por varias capacidades básicas de Linux
Podman,buildah,skopeo
En pocas palabras, Podman se utiliza para ejecutar los contenedores; Buildah, para diseñarlos; y Skopeo, para transportarlos, entre otras tareas. Imagínese que estas herramientas son una especie de navaja suiza para el entorno de contenedores: Skopeo sería una cuchilla ágil y versátil.
Podman
Es un motor de contenedores
- compatible con OCI
- no requiere un servicio en ejecucion para funcionar, a diferencia de lo que sucede con docker/dockerd
Archivos de configuración:
/etc/containers/registries.conf
es el archivo de configuración que especifica qué registros de contenedor deben consultarse al completar los nombres de imágenes que no incluyen una porción de registro o dominio.
mounts.conf
especifican directorios de montaje de volumen que se montan automáticamente dentro de contenedores al ejecutar los comandos podman run o podman build. El proceso del contenedor puede usar este contenido. El contenido del montaje del volumen no se compromete con la imagen final. /usr/share/containers/mounts.conf and optionally /etc/containers/mounts.conf
/usr/share/containers/seccomp.json
contiene la lista blanca de reglas seccomp que se permiten dentro de los contenedores. Este archivo generalmente lo proporciona el paquete container-common.
/etc/containers/policy.json
Los archivos de políticas de verificación de firmas se utilizan para especificar políticas,
Podman cuando se ejecuta como usuario non-root crea un directorio en el directorio home del usuario y almacena allí toda la información de las imágenes y contenedores que tiene este usuario
Ademas tiene una interfaz grafica bastante chula
flatpak install flathub io.podman_desktop.PodmanDesktop
Las ordenes de podman son identicas a las de docker, a sido creado así para facilitar su migración.
Buildah
Buildah es una herramienta para gestión de imágenes que está muy ligada al uso de Podman. Entre sus características nos permite manipular una imagen o un contenedor corriendo para crear nuevas imágenes, montar el directorio raíz de un contenedor para su manipulación o crear nuevas imágenes en formato tradicional o OCI.
Buildah se especializa en la creación de imágenes OCI. Los comandos de Buildah replican todos los comandos que se encuentran en un Dockerfile. Esto permite crear imágenes con y sin Dockerfiles sin necesidad de privilegios de root.
Podman permite a los usuarios crear 'contenedores tradicionales' en los que la intención de estos contenedores es que duren mucho tiempo. Mientras que los contenedores Buildah en realidad se crean para permitir que el contenido se vuelva a agregar a la imagen del contenedor
Ejemplo:
Containerfile/Dockerfile
# Base on the most recently released Fedora
FROM fedora:latest
MAINTAINER ipbabble email buildahboy@redhat.com # not a real email
# Install updates and httpd
RUN echo "Updating all fedora packages"; dnf -y update; dnf -y clean all
RUN echo "Installing httpd"; dnf -y install httpd && dnf -y clean all
# Expose the default httpd port 80
EXPOSE 80
# Run the httpd
CMD ["/usr/sbin/httpd", "-DFOREGROUND"]
construir
buildah build -f Dockerfile -t fedora-httpd .
# ejecutar
podman run --rm -p 8123:80 fedora-httpd
Skopeo
Es una herramienta para gestionar, analizar, firmar y transferir imágenes de contenedores y repositorios de imágenes
Skopeo le permite analizar las imágenes en un registro remoto sin necesidad de descargarla con todas sus capas, lo cual la convierte en una solución ligera y de estructura modular para trabajar con las imágenes de contenedores en diferentes formatos, como las de Docker y las que cumplen con los estándares de la Open Container Initiative (OCI).
Una de las ventajas de Skopeo es que no requiere que el usuario que se ejecute sea root, al igual que podman, para realizar así la mayoría de sus operaciones.
Las operaciones que puede realizar son:
- Copiar una imagen desde y hacia varios mecanismos de almacenamiento. Por ejemplo, podemos copiar imágenes de un registro a otro, sin necesidad de privilegios.
- Inspeccionar una imagen remota para que muestre sus propiedades, incluidas sus capas, sin que sea necesario que se descargue la imagen
- Eliminar una imagen de un repositorio dado.
- Sincronizar un repositorio de imágenes externo con un registro interno.
-
Cuando lo requiera el repositorio, Skopeo puede pasar las credenciales y certificados apropiados para la autentificación.
inspeccionar imagen
skopeo inspect docker://docker.io/library/centos
copiar imagenes entre diferentes repositorios
skopeo copy docker://quay.io/buildah/stable docker://registry.internal.company.com/buildah
mkdir -p /var/lib/images/busybox skopeo copy docker://busybox:latest dir:/var/lib/images/busybox
Para borrar imagenes
skopeo delete docker://localhost:5000/imagename:latest skopeo delete docker://registry.example.com/example/pause:latest
Sincronizar entre repositorios
skopeo sync --src docker --dest dir registry.example.com/busybox /media/usb skopeo sync --src dir --dest docker /media/usb/busybox:1-glibc my-registry.local.lan/test/
Otros enfoques de virtualización de contenedores
jaulas
BSD jail
FreeBSD jail es una implementación de virtualización a nivel de sistema operativo que tiene disponible el sistema operativo FreeBSD. Permite particionar una computadora con FreeBSD en varios minisistemas, llamados jaulas, que comparten el kernel del sistema operativo, con una pequeña sobrecarga
Las jaulas, citadas con frecuencia como la nueva generación de entornos chroot, son una herramienta muy poderosa que se ha puesto al servicio de los administradores de sistemas, aunque su uso más básico puede ser también de suma utilidad para usuarios avanzados.
jailkit
Jailkit es una herramienta para crear jaulas chroot
Crear directorio jaula y todas las opciones de ordenes permitidas
mkdir /opt/chroots
jk_init -v /opt/chroots basicshell jk_lsh openvpn ssh sftp git scp rsync extendedshell netutils
En el archivo
/etc/jailkit/jk_init.ini
esta la lista completa de ordenes que se pueden pasar a la jaula
crear usuario y añadirlo a la jaula
useradd -m enjaulado
passwd enjaulado
jk_jailuser -m -j /opt/chroots -s /usr/bin/bash enjaulado
Asegurarse que se crea bien la shel predeterminada para acceder por ssh
grep enjaulado /etc/passwd
...
#enjaulado:x:1001:1001:,,,:/home/enjaulado:/usr/sbin/jk_lsh
enjaulado:x:1001:1001:,,,:/home/enjaulado:/usr/bin/bash
Acceder por ssh
ssh enjaulado@192.168.0.100
systemd-nspawn
systemd-nspawn
es parecido al comando chroot, pero es un chroot en esteroides.
systemd-nspawn
puede ser usado para ejecutar un comando o un sistema operativo en contenedor de namespace muy ligero. Es mas poderoso que chroot ya que virtualiza toda estructura del sistema de archivos, así como el árbol de procesos, los sub sistemas IPC y los nombres de dominio y del servidor.
systemd-nspawn -M mycontainer -U -b -D ~/MyContainer
-b
arranca el contenedor (v.g. ejecuta systemd como PID=1), en lugar de simplemente iniciar una shell,-D
especifica el directorio que se usara como directorio raíz del contenedor.-M
asigna un nombre al contenedor
los contenedores de
systemd-nspawn
se pueden controlar con la herramientamachinectl
.
Crear un contenedor de debian
Descargar archivos esenciales
# debootstrap [options] <distribucion> myContainer [url-repositorio]
debootstrap --include=systemd,dbus stable /var/lib/machines/debian
Crear/arancar contenedor
systemd-nspawn -D /var/lib/machines/debian -U --machine debian
En nel primer inicio añadir contraseña
root@debian:~# passwd
New password:
Retype new password:
passwd: password updated successfully
Diferentes formas de arrancar un contenedor
systemctl start systemd-nspawn@debian
machinectl start debian
systemd-nspawn --boot -U -D /var/lib/machines/debian
Download a Fedora image and start a shell in it
# machinectl pull-raw --verify=no \
https://download.fedoraproject.org/pub/fedora/linux/releases/36/Cloud/x86_64/images/Fedora-Cloud-Base-36-1.5.x86_64.raw.xz \
Fedora-Cloud-Base-36-1.5.x86-64
# systemd-nspawn -M Fedora-Cloud-Base-36-1.5.x86-64
This downloads an image using machinectl(1) and opens a shell in it.
Build and boot a minimal Fedora distribution in a container
# dnf -y --releasever=36 --installroot=/var/lib/machines/f36 \
--repo=fedora --repo=updates --setopt=install_weak_deps=False install \
passwd dnf fedora-release vim-minimal systemd systemd-networkd
# systemd-nspawn -bD /var/lib/machines/f36
This installs a minimal Fedora distribution into the directory /var/lib/machines/f36
and then boots that OS in a namespace container.
Because the installation is located underneath the standard /var/lib/machines/
directory, it is also possible to start the machine using systemd-nspawn -M f36
.
Activar inicio automático de los contenedores
Al usar un contenedor frecuentemente, seria deseable iniciarlo al arrancar el sistema anfitrión.
Active el target machines.target
, después ejecute systemd-nspawn@myContainer.service
, donde myContainer es un contenedor de nspawn ubicado en /var/lib/machines
.
Sugerencia: Para personalizar el arranque de los contenedores, edite
/etc/systemd/nspawn/myContainer.nspawn
. Vea systemd.nspawn(5) para todas las opciones.
machinectl
los contenedores de systemd-nspawn
se pueden controlar con la herramienta machinectl
.
$ machinectl list
MACHINE CLASS SERVICE OS VERSION ADDRESSES
debian container systemd-nspawn debian 12 -
ordenes basicas
machinectl login MyContainer # iniciar una shell
machinectl shell root@debian [command]
machinectl status|show MyContainer # Mostrar informacion detallada
machinectl reboot|start|poweroff MyContainer
machinectl enable|disable MyContainer
machinectl remove MyImage
machinectl clean # borrar todas las imagenes
algunos mas de utilidad
journalctl -M MyContainer # logs del container
systemd-cgls -M MyContainer # Mostrar el contenido del grupo de control
systemd-analyze -M MyContainer # Mostrar el tiempo de arranque
systemd-cgtop # recursos usados
RKT
Se trata de un motor de contenedores de aplicaciones desarrollado para los entornos de producción modernos de la nube, el cual se integra a la perfección con otros sistemas, ya que cuenta con un enfoque basado en los pods, un entorno de ejecución al que se pueden agregar diferentes elementos y una superficie bien definida.
Algunos comandos basicos
rkt run docker://nginx --name=nginx
rkt run --insecure-options=image docker://hello-world
rkt list
rkt list --full
rkt image list
rkt gc
rkt image gc
rkt run coreos.com/etcd:v2.0.0 --cpu=750m --memory=128M
rkt run --volume logs,kind=host,source=/srv/logs \
example.com/app1 --mount volume=logs,target=/var/log
OpenVZ
OpenVZ es una tecnología de virtualización en el nivel de sistema operativo para Linux. OpenVZ permite que un servidor físico ejecute múltiples instancias de sistemas operativos aislados, conocidos como Servidores Privados Virtuales (SPV o VPS en inglés) o Entornos Virtuales (EV).
OpenVZ es una base de Virtuozzo que es un software comercial desarrollado por SWsoft, Inc., OpenVZ es un producto de software libre y licenciado bajo los términos de la licencia GNU GPL versión 2.