Container Runtimes para proyectos Cloud Native
Hola, lectores. En esta ocasión quiero mostrarles diferentes herramientas que pueden usar para crear contenedores. Exploraremos Podman, Containerd y Youki, algunos proyectos de la CNCF. El objetivo de esta publicación es ayudarles a elegir la mejor herramienta para contenedores según sus necesidades y compartir algunos conceptos básicos sobre cómo usar estas herramientas en sus proyectos nativos de la nube.
Esta publicación se centrará en:
- Entornos de ejecución de contenedores, incluyendo Podman, Containerd y Youki.
- Introducción a Container Runtimes
- Instalación de Containerd
- Creación de un contenedor con el SDK de Go para containerd
- Instalación de nerdctl
- Uso de Compose con nerdctl
- Trabajo con Podman
- Podman Compose
- Ejecución de contenedores con youki
Introducción a Container Runtimes
Para muchos desarrolladores, Docker es sinónimo de contenedores. Ofrece una excelente experiencia de desarrollo al combinar la gestión de imágenes, la ejecución de contenedores, la conectividad en red y una interfaz de línea de comandos familiar en una sola herramienta.
Sin embargo, las plataformas modernas nativas de la nube, especialmente Kubernetes, han evolucionado más allá de Docker como su entorno de ejecución predeterminado. Hoy en día, la mayoría de las distribuciones de Kubernetes dependen de containerd, mientras que herramientas alternativas como Podman y nerdctl ofrecen diferentes maneras de crear y administrar contenedores. Detrás de todas ellas, los entornos de ejecución de OCI, como runc y youki, son los responsables de crear y ejecutar los contenedores.
Comprender cómo funcionan estas tecnologías en conjunto es una habilidad importante para cualquier persona que trabaje con Kubernetes, DevOps o ingeniería de plataformas.
A continuación, resumimos algunas herramientas para contenedores:
- containerd: el entorno de ejecución de contenedores utilizado por la mayoría de las distribuciones de Kubernetes.
- nerdctl: una interfaz de línea de comandos compatible con Docker para containerd.
- Podman: un motor de contenedores sin demonio con soporte de primera clase para usuarios sin privilegios de administrador.
- youki: un entorno de ejecución OCI moderno escrito en Rust.
Veamos cómo se distribuyen estas herramientas en diferentes capas de abstracción:
Container CLI
Docker CLI | nerdctl | Podman
│
Container Engine
Docker Engine | containerd
│
OCI Runtime
runc | youki
│
Linux Kernel
Cada capa tiene una responsabilidad diferente:
- Container Engine: gestiona las imágenes, la red y el ciclo de vida de los contenedores.
- OCI Runtime: crea e inicia contenedores Linux.
- Container CLI: Las herramientas de línea de comandos proporcionan una interfaz fácil de usar.
Instalación de Containerd
Supongamos que estamos usando Alpine, tienes que activar los repositorios de la comunidad para poder instalar containerd. Para ello, sigue los siguientes pasos:
1. Edita /etc/apk/repositories para descomentar el repositorio de la comunidad
vi /etc/apk/repositories # Uncomment the community repo for example the line will look like this # http://dl-cdn.alpinelinux.org/alpine/v3.23/community
2. Actualiza los repositorios
apk update
3. Instala containerd
apk add containerd
4. Inicia containerd
service containerd start containerd --version
Create a container with the containerd Go SDK
1. Instala Go en Alpine
apk add git apk add go
2. Crea un directorio para crear el código de Go
cd $HOME mkdir containerd-example cd containerd-example go mod init containerd/example
3. Instala las librerías de Containerd para compilar el ejemplo
go get github.com/containerd/containerd go get github.com/containerd/containerd/cio go get github.com/containerd/containerd/oci go get github.com/containerd/containerd/namespaces
4. Crea el código en un archivo llamado main.go usando el siguiente contenido
package main
import (
"context"
"fmt"
"log"
"syscall"
"time"
"github.com/containerd/containerd"
"github.com/containerd/containerd/cio"
"github.com/containerd/containerd/oci"
"github.com/containerd/containerd/namespaces"
)
func main() {
if err := redisExample(); err != nil {
log.Fatal(err)
}
}
func redisExample() error {
// create a new client connected to the default socket path for containerd
client, err := containerd.New("/run/containerd/containerd.sock")
if err != nil {
return err
}
defer client.Close()
// create a new context with an "example" namespace
ctx := namespaces.WithNamespace(context.Background(), "example")
// pull the redis image from DockerHub
image, err := client.Pull(ctx, "docker.io/library/redis:alpine", containerd.WithPullUnpack)
if err != nil {
return err
}
// create a container
container, err := client.NewContainer(
ctx,
"redis-server",
containerd.WithImage(image),
containerd.WithNewSnapshot("redis-server-snapshot", image),
containerd.WithNewSpec(oci.WithImageConfig(image)),
)
if err != nil {
return err
}
defer container.Delete(ctx, containerd.WithSnapshotCleanup)
// create a task from the container
task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStdio))
if err != nil {
return err
}
defer task.Delete(ctx)
// make sure we wait before calling start
exitStatusC, err := task.Wait(ctx)
if err != nil {
fmt.Println(err)
}
// call start on the task to execute the redis server
if err := task.Start(ctx); err != nil {
return err
}
// sleep for a lil bit to see the logs
time.Sleep(3 * time.Second)
// kill the process and get the exit status
if err := task.Kill(ctx, syscall.SIGTERM); err != nil {
return err
}
// wait for the process to fully exit and print out the exit status
status := <-exitStatusC
code, _, err := status.Result()
if err != nil {
return err
}
fmt.Printf("redis-server exited with status: %d\n", code)
return nil
}
Instala nerdctl
1. Instala nerdctl para usar containerd
apk add nerdctl nerdctl --version
2. Usa nerdctl para crear un container de nginx
nerdctl run -d nginx
Usando Compose con nerdctl
nerdctl compose up -d nerdctl compose ps nerdctl compose logs -f nerdctl compose build nerdctl compose down
Trabajand con Podman
1. Instala Podman
apk add podman
2. Crea un container de Redis usando Podman
podman run -it -d redis
3. Lista los container creados con Podman
podman ps
Podman Compose
podman compose up -d podman compose ps podman compose logs -f podman compose down
Corriendo Containers con youki
1. Instala las dependencias de youki
apk add libseccomp curl curl -sSfL https://github.com/youki-dev/youki/releases/download/v0.6.0/youki-0.6.0-$(uname -m)-musl.tar.gz | tar -xzvC /usr/bin/ youki youki --version # Test youki installation
2. Lista containers creados con youki (En este caso con podman)
podman run --runtime /usr/bin/youki -d -p 8080:80 nginx youki list
Conclusión sobre Container Runtimes
¡Gracias por leer! Nos vemos en mi próxima publicación del blog.
Sígueme
Estas son mis redes sociales:
- https://www.linkedin.com/in/sergioarmgpl
- https://sergiops.xyz
- https://x.com/sergioarmgpl
- https://www.instagram.com/sergioarmgpl/
Contribuye a estos proyectos: