Skip to content
Naoya Tech
Go back

How Container Isolation Works: Linux Namespaces, cgroups, Capabilities and seccomp

16:46 OS & Low-level

Overview

A container started with docker run shows up in the host’s ps as an ordinary process, right next to everything else. It still cannot see the outside because Docker wraps it in several layers of Linux features: namespaces, capabilities, cgroups, AppArmor or SELinux, and seccomp. This video goes through the layers from the inside out and looks into each one with standard Linux commands instead of the docker command.

Note that the steps can’t be followed as is on Docker Desktop for Mac or Windows, where containers run inside a Linux virtual machine.

Key Points

Chapters

概要

docker runで起動したコンテナは、ホストのpsで見ると、ほかのプロセスと同じ一覧に並ぶ普通のプロセスです。それでも中から外が見えないのは、Dockerが名前空間、ケーパビリティ、cgroups、AppArmorやSELinux、seccompといったLinuxの機能を何重にもかぶせているからです。この動画では、内側から順にそれぞれの層を、dockerコマンドではなくLinuxの標準のコマンドで覗いていきます。

なお、MacやWindowsのDocker Desktopではコンテナが裏で動くLinuxの仮想マシンの中にあるため、この手順はそのままでは試せません。

ポイント

  • nginxのコンテナは、ホストからはマスターと4つのワーカーとして見え、containerd-shimを経てsystemd(PID 1)につながる同じプロセスの木にぶら下がっています。ホストからは/proc/<PID>/rootでコンテナの中のファイルまで読めます。全部のコンテナの中身は/var/lib/dockerの下にあるので、このディレクトリに触れる人を絞り、アクセスを監査しておくべきです。
  • Linuxの名前空間は8種類あり、Dockerは最初からそのうち6つ(マウント、PID、ネットワーク、IPC、UTS、cgroup)をコンテナごとに分けます。lsnsで一覧でき、nsenterを使えばホストから名前空間に入れます。ネットワークの名前空間にだけ入れば、ipコマンドの入っていない小さなイメージでもホストのipを持ち込んで調べられます。--pid=container:や--network=container:で名前空間を共有すれば、デバッグ用のコンテナやkubectl debugから対象を調べられます。
  • ユーザーの名前空間を使うと、中ではrootでもホストでは普通のユーザーのままという状態を作れます。Dockerのuserns-remapでは、中のrootがホストではUID 100000になります。ただし、普通のユーザーがユーザーの名前空間を自由に作れる設定では、本来rootしか使えないカーネルの機能に手が届き、そこにある脆弱性で実際に権限昇格が起きています。
  • ケーパビリティはrootの権限を41種類に分けたものです。コンテナのrootが持つのは既定で14個だけなので、dateで時刻を変えようとしても断られます。--cap-drop ALLで全部外しても多くのアプリは動きます。Dockerはコンテナの中で特権なしのpingや1024番より下のポートでの待ち受けを許しているので、net_rawとnet_bind_serviceもたいてい外せます。
  • cgroupsは資源の量を制限します。2コアを使い切るストレステストを--cpus 0.5で半コアに抑え、--pids-limit 10でフォーク爆弾を止めている間もホストは普通に応答しました。Dockerはどちらも既定では制限しません。
  • AppArmorのdocker-defaultプロファイルは全部のコンテナに当たり、自作のプロファイルを使えばrootでも/etcに書き込めなくできます。seccompはプロセスが呼べるシステムコールを絞る仕組みで、Dockerの既定の許可リストはunshareを止めます。一方Kubernetesでは標準でseccompが外れているので、seccompProfileにRuntimeDefaultを指定し、アプリが止まらないかテストで確かめます。
  • 途中で、ソロモン・ハイクス、エリック・ビーダーマン、マイケル・ケリスク、クリスピン・コーワン、スティーブン・スモーリー、アンドレア・アルカンジェリ、キース・クック、ジェシー・フラゼルといった、これらの機能に関わった人たちも紹介します。

チャプター

Watch on YouTube

Share this post on:

Next Video
How Speech Recognition Works: Turning Speech into Text