GNU/Linux >> Linux Esercitazione >  >> Linux

Una cronologia dei runtime di container Linux di basso livello

In Red Hat ci piace dire:"I container sono Linux—Linux è container". Ecco cosa significa. I container tradizionali sono processi su un sistema che di solito hanno le seguenti tre caratteristiche:

1. Vincoli di risorse

Contenitori Linux

  • Cosa sono i container Linux?
  • Un'introduzione alla terminologia dei contenitori
  • Download:Primer sui contenitori
  • Operatori Kubernetes:automatizzare la piattaforma di orchestrazione dei container
  • eBook:modelli Kubernetes per la progettazione di app cloud native
  • Cos'è Kubernetes?

Quando esegui molti container su un sistema, non vuoi che nessun container monopolizzi il sistema operativo, quindi utilizziamo i vincoli delle risorse per controllare cose come CPU, memoria, larghezza di banda di rete, ecc. Il kernel Linux fornisce la funzione cgroups, che può essere configurato per controllare le risorse di processo del contenitore.

2. Vincoli di sicurezza

Di solito, non vuoi che i tuoi container possano attaccarsi a vicenda o attaccare il sistema host. Sfruttiamo diverse funzionalità del kernel Linux per impostare la separazione della sicurezza, come SELinux, seccomp, capacità, ecc.

3. Separazione virtuale

I processi del contenitore non dovrebbero avere una vista di alcun processo al di fuori del contenitore. Dovrebbero essere sulla propria rete. I processi di container devono essere in grado di collegarsi alla porta 80 in container diversi. Ogni contenitore ha bisogno di una vista diversa della sua immagine, ha bisogno del proprio filesystem di root (rootfs). In Linux utilizziamo gli spazi dei nomi del kernel per fornire la separazione virtuale.

Pertanto, un processo che viene eseguito in un cgroup, dispone di impostazioni di sicurezza e viene eseguito in spazi dei nomi può essere chiamato contenitore. Osservando il PID 1, systemd, su un sistema Red Hat Enterprise Linux 7, si vede che systemd viene eseguito in un cgroup.

# tail -1 /proc/1/cgroup
1:name=systemd:/

Il ps comando mostra che il processo di sistema ha un'etichetta SELinux ...

# ps -eZ | grep systemd
system_u:system_r:init_t:s0             1 ?     00:00:48 systemd

e capacità.

# grep Cap /proc/1/status
...
CapEff: 0000001fffffffff
CapBnd: 0000001fffffffff
CapBnd:    0000003fffffffff

Infine, se guardi il /proc/1/ns subdir, vedrai lo spazio dei nomi in cui viene eseguito systemd.

ls -l /proc/1/ns
lrwxrwxrwx. 1 root root 0 Jan 11 11:46 mnt -> mnt:[4026531840]
lrwxrwxrwx. 1 root root 0 Jan 11 11:46 net -> net:[4026532009]
lrwxrwxrwx. 1 root root 0 Jan 11 11:46 pid -> pid:[4026531836]
...

Se il PID 1 (e in realtà ogni altro processo sul sistema) ha vincoli di risorse, impostazioni di sicurezza e spazi dei nomi, sostengo che ogni processo sul sistema è in un contenitore.

Gli strumenti di runtime del contenitore modificano semplicemente questi vincoli di risorse, impostazioni di sicurezza e spazi dei nomi. Quindi il kernel Linux esegue i processi. Dopo l'avvio del contenitore, il runtime del contenitore può monitorare il PID 1 all'interno del contenitore o il stdin del contenitore /stdout —il runtime del contenitore gestisce i cicli di vita di questi processi.

Tempi di esecuzione del contenitore

Potresti dire a te stesso, ben systemd suona abbastanza simile a un runtime di container. Bene, dopo aver avuto diverse discussioni via e-mail sul motivo per cui i runtime del contenitore non utilizzano systemd-nspawn come strumento per il lancio di container, ho deciso che sarebbe valsa la pena discutere i runtime dei container e fornire un contesto storico.

Docker è spesso chiamato runtime del contenitore, ma "runtime del contenitore" è un termine sovraccaricato. Quando le persone parlano di un "runtime di container", stanno davvero parlando di strumenti di livello superiore come Docker, CRI-O e RKT che vengono forniti con funzionalità di sviluppo. Sono guidati da API. Includono concetti come l'estrazione dell'immagine del contenitore dal registro del contenitore, la configurazione dell'archiviazione e infine l'avvio del contenitore. L'avvio del contenitore spesso implica l'esecuzione di uno strumento specializzato che configuri il kernel per eseguire il contenitore e questi sono anche indicati come "runtime del contenitore". Li chiamerò "runtime di container di basso livello". Demoni come Docker e CRI-O, così come strumenti da riga di comando come Podman e Buildah, dovrebbero probabilmente essere chiamati "gestori di container".

Quando Docker è stato originariamente scritto, ha avviato i container utilizzando lxc set di strumenti, precedente a systemd-nspawn . Il lavoro originale di Red Hat con Docker consisteva nel cercare di integrare libvirt (libvirt-lxc ) in Docker come alternativa a lxc strumenti, che non erano supportati in RHEL. libvirt-lxc inoltre non utilizzava systemd-nspawn . A quel tempo, il team di systemd diceva che systemd-nspawn era solo uno strumento per il test, non per la produzione.

Allo stesso tempo, gli sviluppatori Docker a monte, inclusi alcuni membri del mio team Red Hat, hanno deciso di volere un modo nativo per il golang per lanciare i container, piuttosto che lanciare un'applicazione separata. Il lavoro è iniziato su libcontainer, come libreria golang nativa per l'avvio di container. L'ingegneria di Red Hat ha deciso che questa era la strada migliore e ha abbandonato libvirt-lxc .

Successivamente, è stata costituita la Open Container Initiative (OCI), festa perché le persone volevano essere in grado di lanciare container in modi aggiuntivi. I contenitori tradizionali separati dallo spazio dei nomi erano popolari, ma le persone desideravano anche l'isolamento a livello di macchina virtuale. Intel e Hyper.sh stavano lavorando su contenitori separati da KVM e Microsoft stava lavorando su contenitori basati su Windows. L'OCI voleva una specifica standard che definisse cos'è un contenitore, quindi è nata la specifica di runtime OCI.

La specifica di runtime OCI definisce un formato di file JSON che descrive quale binario deve essere eseguito, come deve essere contenuto e la posizione dei rootfs del contenitore. Gli strumenti possono generare questo file JSON. Quindi altri strumenti possono leggere questo file JSON ed eseguire un contenitore su rootfs. Le parti libcontainer di Docker sono state estratte e donate all'OCI. Gli ingegneri Docker a monte e i nostri ingegneri hanno contribuito a creare un nuovo strumento frontend per leggere il file JSON delle specifiche di runtime OCI e interagire con libcontainer per eseguire il container. Questo strumento, chiamato runc , è stato anche donato all'OCI. Mentre runc può leggere il file JSON OCI, gli utenti sono lasciati a generarlo da soli. runc da allora è diventato il runtime di container di basso livello più popolare. Quasi tutti gli strumenti di gestione dei container supportano runc , inclusi CRI-O, Docker, Buildah, Podman e Cloud Foundry Garden. Da allora, anche altri strumenti hanno implementato OCI Runtime Spec per eseguire container conformi a OCI.

Sia Clear Containers che runV di Hyper.sh sono stati creati strumenti per utilizzare la specifica di runtime OCI per eseguire container basati su KVM e stanno combinando i loro sforzi in un nuovo progetto chiamato Kata. L'anno scorso, Oracle ha creato una versione dimostrativa di uno strumento di runtime OCI chiamato RailCar, scritto in Rust. Sono trascorsi due mesi dall'aggiornamento del progetto GitHub, quindi non è chiaro se sia ancora in fase di sviluppo. Un paio di anni fa, Vincent Batts ha lavorato all'aggiunta di uno strumento, nspawn-oci , che ha interpretato un file di specifica del runtime OCI e lanciato systemd-nspawn , ma nessuno se ne è accorto e non era un'implementazione nativa.

Se qualcuno vuole implementare un systemd-nspawn --oci OCI-SPEC.json nativo e farlo accettare dal team di systemd per il supporto, quindi CRI-O, Docker e infine Podman potrebbero usarlo oltre a runc  e Cancella contenitore/runV (Kata). (Nessuno nel mio team ci sta lavorando.)

La conclusione è che, indietro di tre o quattro anni, gli sviluppatori a monte volevano scrivere uno strumento golang di basso livello per il lancio di container e questo strumento ha finito per diventare runc . Quegli sviluppatori all'epoca avevano uno strumento basato su C per farlo chiamato lxc e si allontanò da esso. Sono abbastanza sicuro che nel momento in cui hanno deciso di costruire libcontainer, non sarebbero stati interessati a systemd-nspawn o qualsiasi altro modo non nativo (golang) per eseguire contenitori separati dallo "spazio dei nomi".


Linux
  1. Spiegazione approfondita del comando della cronologia in Linux

  2. 5 motivi per cui dovresti sviluppare una strategia di container Linux

  3. 7 divertenti contenitori Linux/caratteristiche di trasporto di immagini

  4. Qual è la differenza tra un container Linux e un'immagine?

  5. Le mie 5 immagini di container Linux preferite

Comando della cronologia in Linux (Cronologia di Bash)

Comando della cronologia in Linux con esempi

Introduzione alla gestione dei container Linux

Come installare Mcfly su Linux.

Comando cronologia in Linux:visualizza la cronologia del terminale Linux

Come gestire i container Docker