上流のコンテナ技術に取り組んでいる人々に最もよく聞かれるトピックの1つは、コンテナ内でPodmanを実行することです。これらのほとんどは、歴史的にDocker in Docker(DIND)に関連していましたが、今では、Podman in Podman(PINP)またはPodman in Docker(PIND)も実行したいと考えています。
しかし、Podmanは、ルートフルとルートレスの複数の方法で実行できます。根っからのPodmanと根のないPodmanのさまざまな組み合わせを実行したいと思う人が出てきます:
- ルートフルポッドマンのルートフルポッドマン
- ルートフルポッドマンのルートレスポッドマン
- ルートレスポッドマンのルートフルポッドマン
- ルートレスポッドマンのルートレスポッドマン
あなたは写真を手に入れます。
このブログでは、特権の説明から始めて、各組み合わせについて説明します。ここでは、パート1のPINPシナリオから始めます。シリーズのパート2では、同様の根拠について説明しますが、Kubernetesのコンテキスト内で行います。全体像については、必ず両方の記事をお読みください。
コンテナエンジンには特権が必要です
コンテナ内でPodmanのようなコンテナエンジンを実行するには、最初に理解する必要があるのは、かなりの量の特権が必要であるということです。
- コンテナには複数のUIDが必要です。ほとんどのコンテナイメージが機能するには、複数のUIDが必要です。たとえば、ほとんどのファイルがrootによって所有されているが、一部はapacheユーザー(UID =60)によって所有されているイメージがあるとします。
- コンテナエンジンはファイルシステムをマウントし、システムコールのクローンを使用してユーザーの名前空間を作成します。
注:Podmanの新しいバージョンが必要になる場合があります。このブログの例は、Podman3.2で実行されました。
テスト画像
このブログの例では、quay.io/podman/stable
を使用します コンテナ内でPodmanを実行するための最良の方法を見つけるというアイデアで作成された画像。 Dockerfileとcontainers.conf
からこのイメージを構築する方法を調べることができます 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=""
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.*
最初にfedoraを最新にプルし、次に最新のパッケージに更新します。 shadow-utils
を再インストールすることに注意してください 、shadow-utils
に既知の問題があるため filecaps
があるFedoraイメージにインストールします newsubuid
で およびnewsubgid
設定されていません。 shadow-utils
を再インストールします 問題を修正します。次に、Podmanとfuse-overlayfs
をインストールします 。 container-selinux
はインストールしません コンテナ内では必要ないためです。
RUN useradd podman; \
echo podman:10000:5000 > /etc/subuid; \
echo podman:10000:5000 > /etc/subgid;
次に、ユーザーpodman
を作成します /etc/subuid
を設定します および/etc/subgid
5000のUIDを使用するファイル。これは、コンテナ内にユーザー名前空間を設定するために使用されます。 5000は任意の数であり、小さすぎる可能性があります。ルートレスユーザーに割り当てられた65kよりも小さいため、この数を選択しました。コンテナをrootとしてのみ実行している場合は、65kの方が適切な数値でした。
VOLUME /var/lib/containers
VOLUME /home/podman/.local/share/containers
このイメージでルートフルコンテナとルートレスコンテナを実行できるため、2つのボリュームを作成します。 RootfullPodmanは/var/lib/containers
を使用します コンテナストレージとルートレスの使用/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
2つのcontainers.conf
を事前設定しました コンテナが各モードでより簡単に実行できるようにするためのファイル。
イメージは、デフォルトでfuse-overlayfsで実行するように設定されています。場合によっては、カーネルのオーバーレイファイルシステムをルートフルモードで実行でき、すぐにルートレスモードで実行できるようになります。ただし、現時点では、コンテナー内のコンテナーストレージとしてfuse-overlayfsを使用しています。他の人はVFSストレージドライバーを使用していますが、これはそれほど効率的ではありません。
--特権フラグ
コンテナ内でPodmanを実行する最も簡単な方法は、--privileged
を使用することです。 フラグ。
--privilegedを使用したrootfulPodmanのRootfulPodman
# 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
時間を節約するために、多くの実験を行うため、ホスト./mycontainers
にディレクトリを作成しました。 、使用するコンテナにボリュームマウントし、毎回イメージをプルする必要はありません。
# podman run --privileged -v ./mycontainers:/var/lib/containers quay.io/podman/stable podman run ubi8 echo hello
hello
--privilegedを使用したrootfulPodmanのRootlessPodman
quay.io/podman/stable
画像はpodmanで設定されています ルートレスコンテナの実行に使用できるユーザー。
# 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
この場合、コンテナ内で実行されているPodmanは、ユーザー podmanとして実行されていることに注意してください。 。これは、コンテナ化されたPodmanがユーザー名前空間を使用して、特権コンテナ内に制限されたコンテナを作成するためです。
--privilegedを使用してDockerでrootlessPodmanを実行する
ルートフルPodmanと同様に、Docker内で--privileged
を使用してルートレスPodmanを実行することもできます。 オプション。
# docker run --privileged quay.io/podman/stable podman run ubi8 echo hello
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
これをより安全に行うことができますか?
外側のコンテナを実行したにもかかわらず、--privileged
上記では、内部コンテナはロックダウンモードで実行されています。コンテナ内で実行されているルートレスのPodmanは実際にロックダウンされており、エスケープするのは非常に困難です。それを考えると、私は--privileged
を使用するのが好きではありません 国旗。セキュリティの観点から、もっとうまくやれると思います。
--privilegedフラグなしで実行
--privileged
を削除する方法を見てみましょう セキュリティを強化するためのフラグ。
--privilegedのないrootfulPodmanのRootfulPodman
# 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
--privileged
を排除できます ルートフルポッドマンからフラグを立てますが、コンテナ内のルートフルポッドマンを機能させるには、いくつかのセキュリティ機能を無効にする必要があります。
- 機能:
--cap-add=sys_admin,mknod
2つのLinux機能を追加する必要があります。- CAP_SYS_ADMIN コンテナ内でrootとして実行されているPodmanが、必要なファイルシステムをマウントするために必要です。
- CAP_MKNOD コンテナ内でrootとして実行されているPodmanが、
/dev
にデバイスを作成するために必要です。 。 (Dockerはデフォルトでこれを許可していることに注意してください。)
- デバイス:
--device /dev/fuse
フラグは、コンテナ内でfuse-overlayfsを使用する必要があります。このオプションは、ホスト上のPodmanに/dev/fuse
を追加するように指示します コンテナ化されたPodmanが使用できるようにコンテナに追加します。 - SELinuxを無効にする:
--security-opt label=disable
オプションは、ホストのPodmanにコンテナのSElinux分離を無効にするように指示します。 SELinuxでは、コンテナ化されたプロセスが、コンテナ内で実行するために必要なすべてのファイルシステムをマウントすることはできません。
--privilegedを使用しないDockerのRootfulPodman
# 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
- 注Dockerはコンマ区切りの
--cap-add
をサポートしていません コマンドなので、 sys_adminを追加する必要がありました およびmknod 個別に - まだ必要な
--device /dev/fuse
、コンテナのデフォルトは/dev/fuse
であるため - Dockerは常にroot:rootが所有する組み込みボリュームを作成するため、ストレージに使用できるように、Podman用にコンテナーにマウントするボリュームを作成する必要があります。
- いつものように、SELinux分離を無効にする必要があります
-
seccomp
も無効にする必要があります 、Dockerのseccomp
は少し厳しいため Podmanよりもポリシー。--seccomp=/usr/share/containers/seccomp.json
を使用すると、Podmanセキュリティポリシーを使用できます。
# 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
--privilegedのないrootfulPodmanのRootlessPodman
nonを実行します -ユーザー名前空間を使用する非rootユーザーを使用するPodmanを内部に持つ特権コンテナ。
# 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
- 以前の根強いケースのroofulとは異なり、危険なセキュリティ機能を追加する必要がないことに注意してください sys_admin およびmknod
- この場合、私は
--user podman
で実行しています。 、これにより、コンテナ内のPodmanがユーザー名前空間内で自動的に実行されます - マウントをブロックするため、SELinuxを引き続き無効にします
- まだ
--device /dev/fuse
が必要です コンテナ内でfuse-overlayfsを使用するには
Podman-ホストからPodmanソケットがリークされたルートフルPodmanでリモート
# podman run -v /run:/run --security-opt label=disable quay.io/podman/stable podman --remote run busybox echo hi
hi
この場合、/run
がリークしています。 ホストからコンテナへのディレクトリ。これにより、podman --remote
が可能になります ホストのPodmanソケットと通信し、ホストOSでコンテナを起動します。これは多くの場合、Docker In Docker、特にDockerビルドを実行する方法です。この方法でPodmanビルドを実行し、以前にシステムにプルされたイメージを利用することもできます。
ただし、これは非常に安全ではないことに注意してください。コンテナ内のプロセスは、ホストマシンを完全に引き継ぐことができます。
- SELinuxは、コンテナプロセスが
/run
でリークされたソケットを使用するのをブロックするため、SELinux分離を無効にする必要があります。 。 -
podman --remote
Podmanにリモートモードで動作するように指示するフラグが追加されました。podman-remote
をインストールすることもできます。 実行可能ファイルをコンテナに入れて使用します。
[コンテナを使い始めますか?この無料コースをチェックしてください。コンテナ化されたアプリケーションのデプロイ:技術的な概要。 ]
Podman-ホストからPodmanソケットがリークされたDockerでリモート
# docker run -v /run:/run --security-opt label=disable quay.io/podman/stable podman --remote run busybox echo hi
hi
同じ例がDockerコンテナでも機能します。
この例は、Podmanソケットがコンテナーにリークされた状態で、完全にロックダウンされたコンテナー(SELinuxが無効になっている場合を除く)を示しています。 SELinuxは、必要に応じてこのアクセスをブロックします。
# /bin/podman run --security-opt=label=disable -v /run/podman:/run/podman quay.io/podman/stable podman --remote run alpine echo hi
hi
コンテナ化されたルートフルポッドマンを備えたルートレスポッドマン
$ 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 run --security-opt label=disable --user podman --device /dev/fuse quay.io/podman/stable podman run alpine echo hello
最終的な考え
これで、ルートフルモードとルートレスモードの両方を使用して、PodmanオプションでPodmanのコンテキストを取得できます。さまざまな組み合わせで。また、--privileged
を取り巻く必要な特権と考慮事項についてもよく理解できます。 フラグ。
このシリーズのパート2では、PodmanとKubernetesの使用について説明します。この記事は同様の領域をカバーしていますが、Kubernetesのコンテキスト内にあります。
[システム管理者のスキルをテストしたいですか?今日、スキル評価を受けてください。 ]