kubestronautへの道 ~CKS編 その12 killer coda「Container Namespaces Docker」~

tech article

今日覚えて帰ること

PID名前空間

一群のプロセスが他の名前空間のPIDとは別に独自の一意のPIDセットを持つことができる名前空間のこと。
各コンテナは通常独自のPID名前空間を持つ。

コンテナを立ち上げる際、–pid=<resistory:tag> というオプションをつけると、指定したコンテナと同じ名前空間にコンテナを立ち上げることが出来る。

Container Namespaces Docker

Create two Docker containers sharing the same PID namespace

Run two Docker containers app1 and app2 with the following attributes:

  • they should run image nginx:alpine
  • they should share the same PID kernel namespace
  • they should run command sleep infinity
  • they should run in the background (detached)

Then check which container sees which processes and make sense of why.

2つのコンテナを指定した条件で立ち上げろ、と言っています。

ここでそもそもコンテナの立ち上げ方を正しく認識していなかったのでメモしておきます。
このブログでは今まで

docker run <containerID>

で立ち上げていました。

これでも問題はないのですが、このような立ち上げ方以外にも以下のようにレポジトリとタグを指定することでコンテナを立ち上げることが出来ます。

docker run <repositoryName>:<tag>

例えばローカルに以下のようなイメージがあるとします。

$ docker image ls

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               alpine              21f5eb7b4eec        2 weeks ago         22.9MB
nginx               latest              5578ee0b9347        2 weeks ago         133MB

この場合、

docker run nginx:alpine

で一つ目に記載されているコンテナを立ち上げることが出来ます。

デフォルトのタグは「latest」なので、

docker run nginx

というコマンドを打てば2つ目のコンテナが立ち上がります。

また、コマンドで指定したイメージがローカルに存在しない場合、docker hubからコンテナイメージを取得してコンテナを立ち上げます。

閑話休題。(脱線でもなかったけどね。)

まずはapp1を立ち上げます。

controlplane $ docker run --name app1 -d nginx:alpine sleep infinity

Unable to find image 'nginx:alpine' locally
alpine: Pulling from library/nginx
46b060cc2620: Pull complete 
21af147d2ad5: Pull complete 
b3ee43e51ca6: Pull complete 
b17a9d410da1: Pull complete 
542e3e75411d: Pull complete 
2b2faad386df: Pull complete 
a5e22afba545: Pull complete 
fb923a41dc10: Pull complete 
Digest: sha256:208b70eefac13ee9be00e486f79c695b15cef861c680527171a27d253d834be9
Status: Downloaded newer image for nginx:alpine
e8db81b6bfc13b0ccba497dee35d642bd62bd6b49246aac95c1ebf77c04b34ca
docker run --name <container name> -d(optioin) <repository>:<tag> <command> 

という形で立ち上げています。

今回はローカルにイメージがなかったのでpullしてきているみたいですね。

Unable to find image 'nginx:alpine' locally

どのユーザーがプロセスを立ち上げているか確認します。

controlplane $ docker exec app1 ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 sleep infinity
    6 root      0:00 ps aux

rootでした。

次に app1 が存在するPID名前空間に 同じ中身のコンテナ app2 を立てます。
が、PID名前空間が良くわからないので調べてみます。

PID(プロセス識別子)名前空間は、Linuxカーネルの機能であり、プロセスの隔離を提供します。これにより、一群のプロセスが他の名前空間のPIDとは別に独自の一意のPIDセットを持つことができます。これは、プロセスの隔離がセキュリティとリソース管理に不可欠なコンテナ化に特に役立ちます。

PID Namespace | HackTricks

必要な情報を箇条書きにすると、

  • Linuxカーネルの機能
  • プロセスの隔離を提供(別の名前空間のプロセスを参照できない)
  • プロセスが他の名前空間のPIDとは別に独自の一意のPIDセットを持てるようになる
  • コンテナ化に必要

ってなところでしょうか。
コンテナって言っちゃえば隔離されたプロセスの塊で、PID名前空間の分離はコンテナを構成する技術の一つですね。

今回は2つのコンテナでそのPID名前空間を共有しよう、ということです。
疎通できるコンテナってなんとなく聞き覚えがありませんか?
そうです!今回はpodのようなものを作ろうとしているのです。

詳しく知りたい方は以下の記事が参考になります

では進めていきます。

controlplane $ docker run --name app2 --pid=container:app1 -d nginx:alpine sleep infinity
015766188c859aa80f64ddc5fd1cd9dcef0ff4aa04d7cc9e1e50e6c26273517d

イメージが既にローカルに存在するため各レイヤーをpullする必要がなくなっています。

そして –pid=<resistory:tag> オプションで既存のコンテナとPID名前空間を共有することが出来ます。

docker exec でコンテナに入って参照できるpsを確認します。

controlplane $ docker exec app1 ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 sleep infinity
   11 root      0:00 sleep infinity
   16 root      0:00 ps aux
controlplane $ docker exec app2 ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 sleep infinity
   11 root      0:00 sleep infinity
   21 root      0:00 ps aux

どちらのコンテナでも sleep infinity は一度しか実行していないにもかかわらず、2つのプロセスが表示されています。
これは app1, app2がPID名前空間を共有しており、各コンテナ内に存在するプロセスを相互に確認できるからです。

次のシナリオである Container Namespaces Podman は、今回のシナリオのコマンドを docker から podman に変更しただけで全く同じなので、省略します。

タイトルとURLをコピーしました