Uno degli argomenti più richiesti alle persone che lavorano su tecnologie di container a monte è l'esecuzione di Podman all'interno di un container. La maggior parte di questo è stata storicamente correlata a Docker in Docker (DIND), ma ora le persone vogliono anche eseguire Podman in Podman (PINP) o Podman in Docker (PIND).
Ma Podman può essere eseguito in più modi, rootful e rootless. Finiamo con le persone che vogliono eseguire varie combinazioni di Podman rootful e rootless:
- Podman radicato in Podman radicato
- Podman senza radice in Podman radicato
- Podman Rootful in Podman senza radici
- Podman senza radici in Podman senza radici
Ottieni l'immagine.
Questo blog tenterà di coprire ogni combinazione, iniziando con una discussione sui privilegi. Inizieremo con lo scenario PINP qui nella prima parte. Nella seconda parte della serie tratteremo un terreno simile, ma lo faremo nel contesto di Kubernetes. Assicurati di leggere entrambi gli articoli per un quadro completo.
I motori container richiedono privilegi
Per eseguire un motore di container come Podman all'interno di un container, la prima cosa che devi capire è che hai bisogno di una discreta quantità di privilegi.
- I contenitori richiedono più UID. La maggior parte delle immagini del contenitore richiede più di un UID per funzionare. Ad esempio, potresti avere un'immagine con la maggior parte dei file di proprietà di root, ma alcuni di proprietà dell'utente apache (UID=60).
- I motori container montano i file system e utilizzano il clone della chiamata di sistema per creare spazi dei nomi utente.
Nota:potrebbe essere necessaria una versione più recente di Podman. Gli esempi in questo blog sono stati eseguiti con Podman 3.2.
La nostra immagine di prova
Per gli esempi in questo blog, utilizzeremo quay.io/podman/stable
image, che è stato creato con l'idea di trovare il modo migliore per eseguire Podman all'interno di un container. Puoi esaminare come costruiamo questa immagine dal Dockerfile e da containers.conf
immagine nel repository github.com.
# stable/Dockerfile
#
# Build a Podman container image from the latest
# stable version of Podman on the Fedoras Updates System.
# https://bodhi.fedoraproject.org/updates/?search=podman
# This image can be used to create a secured container
# that runs safely with privileges within the container.
#
FROM registry.fedoraproject.org/fedora:latest
# Don't include container-selinux and remove
# directories used by yum that are just taking
# up space.
RUN dnf -y update; yum -y reinstall shadow-utils; \
yum -y install podman fuse-overlayfs --exclude container-selinux; \
rm -rf /var/cache /var/log/dnf* /var/log/yum.*
RUN useradd podman; \
echo podman:10000:5000 > /etc/subuid; \
echo podman:10000:5000 > /etc/subgid;
VOLUME /var/lib/containers
VOLUME /home/podman/.local/share/containers
ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf
ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/podman-containers.conf /home/podman/.config/containers/containers.conf
RUN chown podman:podman -R /home/podman
# chmod containers.conf and adjust storage.conf to enable Fuse storage.
RUN chmod 644 /etc/containers/containers.conf; sed -i -e 's|^#mount_program|mount_program|g' -e '/additionalimage.*/a "/var/lib/shared",' -e 's|^mountopt[[:space:]]*=.*$|mountopt = "nodev,fsync=0"|g' /etc/containers/storage.conf
RUN mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers /var/lib/shared/vfs-images /var/lib/shared/vfs-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock; touch /var/lib/shared/vfs-images/images.lock; touch /var/lib/shared/vfs-layers/layers.lock
ENV _CONTAINERS_USERNS_CONFIGURED=""
Esaminiamo il Dockerfile.
FROM registry.fedoraproject.org/fedora:latest
# Don't include container-selinux and remove
# directories used by yum that are just taking
# up space.
RUN dnf -y update; yum -y reinstall shadow-utils; \
yum -y install podman fuse-overlayfs --exclude container-selinux; \
rm -rf /var/cache /var/log/dnf* /var/log/yum.*
Prima l'ultima versione di fedora, quindi l'aggiornamento agli ultimi pacchetti. Nota che reinstalla shadow-utils
, poiché esiste un problema noto in shadow-utils
installa sull'immagine Fedora dove filecaps
su newsubuid
e newsubgid
non sono impostati. Reinstallazione di shadow-utils
risolve il problema. Quindi, installa Podman e fuse-overlayfs
. Non installiamo container-selinux
perché non è necessario all'interno del contenitore.
RUN useradd podman; \
echo podman:10000:5000 > /etc/subuid; \
echo podman:10000:5000 > /etc/subgid;
Quindi creo un utente podman
e imposta il /etc/subuid
e /etc/subgid
file per utilizzare 5000 UID. Viene utilizzato per configurare lo spazio dei nomi utente all'interno del contenitore. 5000 è un numero arbitrario e potenzialmente troppo piccolo. Abbiamo scelto questo numero perché è inferiore ai 65.000 assegnati agli utenti rootless. Se avessi eseguito il container solo come root, 65k sarebbe stato un numero migliore.
VOLUME /var/lib/containers
VOLUME /home/podman/.local/share/containers
Poiché possiamo eseguire container rootfull e rootless con questa immagine, creiamo due volumi. Rootfull Podman usa /var/lib/containers
per lo storage di container e gli usi rootless /home/podman/.local/share/containers
. L'overlay overlay è spesso negato dal kernel, quindi questo crea volumi non overlay da utilizzare all'interno del contenitore.
ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf
ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/podman-containers.conf /home/podman/.config/containers/containers.conf
Ho preconfigurato due containers.conf
file per assicurarsi che i contenitori vengano eseguiti più facilmente in ciascuna modalità.
L'immagine è impostata per funzionare con fuse-overlayfs per impostazione predefinita. In alcuni casi, potresti eseguire il file system di overlay del kernel per la modalità rootful e presto sarai in grado di farlo in modalità rootless. Tuttavia, per ora, utilizziamo fuse-overlayfs come spazio di archiviazione del contenitore all'interno del contenitore. Altre persone hanno utilizzato il driver di archiviazione VFS, ma non è così efficiente.
Il flag --privileged
Il modo più semplice per eseguire Podman all'interno di un container è utilizzare --privileged
bandiera.
Rootful Podman in Rootful Podman con --privileged
# podman run --privileged quay.io/podman/stable podman run ubi8 echo hello
Resolved "ubi8-minimal" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
Trying to pull registry.access.redhat.com/ubi8:latest...
Getting image source signatures
Copying blob sha256:a591faa84ab05242a17131e396a336da172b0e1ec66d921c9f130b7c4c24586d
Copying blob sha256:76b9354adec626b01ffb0faae4a217cebd616661fd90c4b54ba4415f53392fb8
Copying config sha256:dc080723f596f2407300cca2c19a17accad89edcf39f7b8b33e6472dd41e30f1
Writing manifest to image destination
Storing signatures
hello
Per risparmiare tempo, dato che farò molti esperimenti, ho creato una directory sul mio host ./mycontainers
, che monterò del volume nel contenitore da utilizzare e non dovrò estrarre l'immagine ogni volta.
# podman run --privileged -v ./mycontainers:/var/lib/containers quay.io/podman/stable podman run ubi8 echo hello
hello
Podman senza radice in Podman radicato con --privileged
Il quay.io/podman/stable
l'immagine è impostata con un podman utente che puoi utilizzare per eseguire container senza root.
# podman run --user podman --privileged quay.io/podman/stable podman run ubi8 echo hello
Resolved "ubi8" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
...
hello
Nota in questo caso, il Podman in esecuzione all'interno del contenitore è in esecuzione come utente podman . Questo perché il Podman containerizzato utilizza lo spazio dei nomi utente per creare un container confinato all'interno del container privilegiato.
Esegui Podman senza root in Docker con --privileged
Simile a Podman rootful, puoi anche eseguire Podman rootless all'interno di Docker con il --privileged
opzione.
# docker run --privileged quay.io/podman/stable podman run ubi8 echo hello
Podman senza radici con Docker
# docker run --user podman --privileged quay.io/podman/stable podman run ubi8 echo hello
Resolved "ubi8" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
...
hello
Possiamo farlo in modo più sicuro?
Nota che anche se abbiamo eseguito i contenitori esterni --privileged
sopra, i contenitori interni funzionano in modalità bloccata. Il Podman senza radici in esecuzione all'interno del container è davvero bloccato e avrebbe difficoltà a scappare. Detto questo, non sono un fan dell'utilizzo di --privileged
bandiera. Credo che possiamo fare di meglio dal punto di vista della sicurezza.
In esecuzione senza il flag --privileged
Diamo un'occhiata a come rimuovere il --privileged
flag per una maggiore sicurezza.
Rootful Podman in Rootful Podman senza --privileged
# podman run --cap-add=sys_admin,mknod --device=/dev/fuse --security-opt label=disable quay.io/podman/stable podman run ubi8-minimal echo hello
hello
Possiamo eliminare il --privileged
flag da Podman rootful ma devi comunque disabilitare alcune funzionalità di sicurezza per far funzionare Podman rootful all'interno del contenitore.
- Funzionalità:
--cap-add=sys_admin,mknod
Dobbiamo aggiungere due funzionalità Linux.- CAP_SYS_ADMIN è necessario per il Podman in esecuzione come root all'interno del contenitore per montare i file system richiesti.
- CAP_MKNOD è necessario affinché Podman venga eseguito come root all'interno del contenitore per creare i dispositivi in
/dev
. (Nota che Docker lo consente per impostazione predefinita).
- Dispositivi:il
--device /dev/fuse
flag deve utilizzare fuse-overlayfs all'interno del contenitore. Questa opzione dice a Podman sull'host di aggiungere/dev/fuse
al container in modo che Podman containerizzato possa usarlo. - Disabilita SELinux:il
--security-opt label=disable
opzione dice al Podman dell'host di disabilitare la separazione di SElinux per il contenitore. SELinux non consente ai processi containerizzati di montare tutti i file system necessari per essere eseguiti all'interno di un container.
Rootful Podman in Docker senza --privileged
# docker run --cap-add=sys_admin --cap-add mknod --device=/dev/fuse --security-opt seccomp=unconfined --security-opt label=disable quay.io/podman/stable podman run ubi8-minimal echo hello
hello
- Nota Docker non supporta la virgola separata
--cap-add
comando, quindi ho dovuto aggiungere sys_admin e mknod separatamente - Ancora necessario
--device /dev/fuse
, poiché per impostazione predefinita il contenitore è/dev/fuse
- Docker crea sempre volumi incorporati di proprietà di root:root, quindi dobbiamo creare un volume da montare per Podman nel contenitore per poterlo utilizzare per l'archiviazione.
- Come sempre, devo disabilitare la separazione di SELinux
- Devi anche disabilitare
seccomp
, poiché Docker ha unseccomp
leggermente più rigido politica rispetto a Podman. Potresti semplicemente usare una politica di sicurezza Podman usando--seccomp=/usr/share/containers/seccomp.json
# docker run --cap-add=sys_admin --cap-add mknod --device=/dev/fuse --security-opt seccomp=/usr/share/containers/seccomp.json --security-opt label=disable quay.io/podman/stable podman run ubi8-minimal echo hello
hello
Podman senza radice in Podman radicato senza --privileged
Esegui non -contenitore privilegiato con Podman all'interno utilizzando un utente non root utilizzando lo spazio dei nomi utente.
# podman run --user podman --security-opt label=disable --security-opt unmask=ALL --device /dev/fuse -ti quay.io/podman/stable podman run -ti docker.io/busybox echo hello
hello
- Nota che, a differenza del rooful all'interno del caso rootful prima, non dobbiamo aggiungere le pericolose funzionalità di sicurezza sys_admin e mknod
- In questo caso, sto utilizzando
--user podman
, che fa in modo che Podman all'interno del contenitore venga eseguito automaticamente all'interno dello spazio dei nomi utente - Ancora disabilitando SELinux poiché blocca il montaggio
- Servo ancora
--device /dev/fuse
per utilizzare i fusibili di sovrapposizione all'interno del contenitore
Podman-remote in Podman rootful con una presa Podman trapelata dall'host
# podman run -v /run:/run --security-opt label=disable quay.io/podman/stable podman --remote run busybox echo hi
hi
In questo caso, stiamo perdendo il /run
directory dall'host nel contenitore. Ciò consente a podman --remote
per comunicare con il socket Podman sull'host e avviare il contenitore sul sistema operativo host. Questo è spesso il modo in cui le persone eseguono Docker In Docker, in particolare le build Docker. Puoi anche eseguire le build Podman in questo modo e sfruttare le immagini precedentemente importate nel sistema.
Nota, tuttavia, questo è estremamente insicuro. I processi all'interno del container possono assumere totalmente il controllo della macchina host.
- Devi comunque disabilitare la separazione di SELinux perché SELinux bloccherebbe i processi del contenitore dall'uso di socket trapelati in
/run
. - Il
podman --remote
viene aggiunto il flag per dire a Podman di lavorare in modalità remota. Nota che potresti anche installare ilpodman-remote
eseguibile in un contenitore e usalo.
[ Iniziare con i container? Dai un'occhiata a questo corso gratuito. Distribuzione di applicazioni containerizzate:una panoramica tecnica. ]
Telecomando Podman in Docker con una presa Podman trapelata dall'host
# docker run -v /run:/run --security-opt label=disable quay.io/podman/stable podman --remote run busybox echo hi
hi
Lo stesso esempio funziona per un contenitore Docker.
Questo esempio mostra un contenitore completamente bloccato, diverso da SELinux disabilitato, con il socket Podman trapelato nel contenitore. SELinux bloccherebbe questo accesso, come dovrebbe.
# /bin/podman run --security-opt=label=disable -v /run/podman:/run/podman quay.io/podman/stable podman --remote run alpine echo hi
hi
Podman senza radice con Podman pieno di radici containerizzato
$ podman run --privileged quay.io/podman/stable podman run ubi8 echo hello
Resolved "ubi8" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
..
hello
Podman senza radice che esegue Podman senza radice
$ podman run --security-opt label=disable --user podman --device /dev/fuse quay.io/podman/stable podman run alpine echo hello
Pensieri finali
Ora hai un po' di contesto per Podman nelle opzioni Podman, usando sia le modalità rootful che rootless. in varie combinazioni. Hai anche un'idea migliore dei privilegi necessari e delle considerazioni che circondano il --privileged
bandiera.
La seconda parte di questa serie esamina l'uso di Podman e Kubernetes. L'articolo copre un territorio simile ma nel contesto di Kubernetes.
[ Vuoi testare le tue capacità di amministratore di sistema? Fai una valutazione delle abilità oggi. ]