コンテナ技術が利用しているカーネル機能の一つpid namespaceを知ることでコンテナ技術についての知識を深める
namespaceとは?
名前空間(namespace)は任意の識別子を使ってユニークな値を複数のグループに分離するために使われます。
例としては住所で、同じ中央区1-1でも北海道札幌市中央区と福岡県福岡市中央区では別の地図の場所を指し示すように、北海道と福岡とで別々の名前空間に属しているので別のユニークな値を示します。
pid namespace
lsns -t pid
でプロセスのネームスペースを表示することができます。
コンテナを起動していない状態のネームスペースを確認
# lsns -t pid
NS TYPE NPROCS PID USER COMMAND
4026531836 pid 155 1 root /sbin/init fixrtc splash
名前空間は4026531836の一つだけ
コンテナ起動後に確認
postgresのコンテナを立ち上げてから確認すると2つのnamespaceが確認できる
##---docker psコマンドでコンテナの起動を確認---
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c39561a2af03 postgres:13-alpine "docker-entrypoint.s…" 5 months ago Up 1 second 5432/tcp docker-postgres-1
###---lsnsでネームスペースを確認
# lsns -t pid
NS TYPE NPROCS PID USER COMMAND
4026531836 pid 157 1 root /sbin/init fixrtc splash
4026532369 pid 7 2923124 70 postgres
ネームスペースの親子関係
プロセスと同じようにプロセスのネームスペースにも親子関係がある。
lsnsで確認した時に上のPIDネームスペース4026531836はPIDが1になっている。これが親です。
一方でpostgres(コンテナ)のNSのPIDは304612で子の関係にあります。
# lsns -t pid
NS TYPE NPROCS PID USER COMMAND
4026531836 pid 167 1 root /sbin/init fixrtc splash
4026532369 pid 7 3034612 70 postgres
新しい世代のLinuxはsystemdを採用しているので、PID1のinitプロセスはsystemdになっているはずです。
上の例のOSはubuntuですが、なぜか/sbin/initとなっています。この詳細をlsで確認すると/lib/systemd/systemdへのシンボリックリンクになっていることが確認できるので実質これはsystemdということがわかります。
# cat /etc/os-release | grep PRETTY
PRETTY_NAME="Ubuntu 22.04.1 LTS"
# ls -al /sbin/init
lrwxrwxrwx 1 root root 20 Sep 10 03:47 /sbin/init -> /lib/systemd/systemd
https://bugs.launchpad.net/ubuntu/+source/init-system-helpers/+bug/1457886
systemdでは全てのプロセスはsystemdの子プロセスとして起動します。
systemdとは?systemctlコマンドとは親側であるホストOSからは子側(コンテナ)のプロセスを確認することができる。
# ps -e -o pid,ipcns,args | sort -nk2 | tail -10
2941085 4026531839 ps -e -o pid,ipcns,args
2941086 4026531839 sort -nk2
2941087 4026531839 tail -10
2923124 4026532368 postgres
2923195 4026532368 postgres: checkpointer
2923196 4026532368 postgres: background writer
2923197 4026532368 postgres: walwriter
2923198 4026532368 postgres: autovacuum launcher
2923199 4026532368 postgres: stats collector
2923200 4026532368 postgres: logical replication launcher
ホスト側でプロセスを確認するとdockerで立ち上げているpostgresのプロセスがホストとは別のnamespaceで上がっている。
docker側から確認しようとしてもホスト側のプロセスは確認できない
# ps aux
PID USER TIME COMMAND
1 postgres 0:00 postgres
23 postgres 0:00 postgres: checkpointer
24 postgres 0:00 postgres: background writer
25 postgres 0:00 postgres: walwriter
26 postgres 0:00 postgres: autovacuum launcher
27 postgres 0:00 postgres: stats collector
28 postgres 0:00 postgres: logical replication launcher
153 root 0:00 /bin/bash
162 root 0:00 ps aux
コンテナ内ではPID1はpostgresになっている。
ホストのsystemdのPID1と被ってしまうように感じるが、ホストとコンテナでは別々のnamespaceに属しているので同じPID1でも別物である。
ネームスペースを分離することでプロセスをホストとは別のグループに分離できる。
このカーネルの機能がdockerなどのコンテナ技術で利用されている。