コンテナで使用される技術要素

を今更ながら勉強しました。

## はじめに

本記事は、コンテナ技術のベースとなるLinuxカーネルやそれに付随する機能を紹介するものです。

## Namespace

Namespace とは、Linuxカーネルが持つ機能でホストから隔離された空間を作成する機能です。Namespace を作成することでホストからリソースやプロセスが分離されます。

Namespace には以下のような種類があります。これらの Namespace と後述の cgroup、pivot_root、bind mount、OverlayFS ...の機能を連携させることで、コンテナ環境が構成されています。

       Namespace   Flag              Page                    Isolates
       ───────────────────────────────────────────────────────────────────
       Cgroup      CLONE_NEWCGROUP   cgroup_namespaces(7)    Cgroup root directory
       IPC         CLONE_NEWIPC      ipc_namespaces(7)       System VIPC, POSIX message queues
       Network     CLONE_NEWNET      network_namespaces(7)   Network devices, stacks, ports, etc.
       Mount       CLONE_NEWNS       mount_namespaces(7)     Mount points
       PID         CLONE_NEWPID      pid_namespaces(7)       Process IDs
       Time        CLONE_NEWTIME     time_namespaces(7)      Boot and monotonic clocks
       User        CLONE_NEWUSER     user_namespaces(7)      User and group IDs
       UTS         CLONE_NEWUTS      uts_namespaces(7)       Hostname and NIS domain name

https://man7.org/linux/man-pages/man7/namespaces.7.html

## cgroup

cgroup とは、OS上で起動したプロセスに物理的なリソースを制限する機能です。Namespaceで隔離したプロセス(=コンテナ)に対しても同様に、リソースの制限をかけることができます。制限可能なリソースにCPU、メモリ、ネットワークI/O、ディスクI/Oがあります。リソース毎にコントローラーが実装されています。また、非特権ユーザでも cgroup を操作できるように権限を委譲する仕組みが用意されています。

https://man7.org/linux/man-pages/man7/cgroups.7.html

https://speakerdeck.com/tenforward/techfeed-experts-night-number-28

## chroot

chroot とは、プロセスのルートディレクトリーを変更する機能です。chroot でルートディレクトリを変更すると、変更したディレクトリがルートディレクトリとして認識されます。変更後のルートディレクトリより上位のファイルシステムにはアクセスできなくなります。

特権ユーザーは chroot した環境から更に chroot することでコンテナ(Namespace)から脱出してホストに侵入できるため、主要なコンテナランタイムは chroot ではなく後述の pivot_root を採用しています。

https://man7.org/linux/man-pages/man2/chroot.2.html

## pivot_root

pivot_root とは、ルートファイルシステムを変更する機能です。pivot_root でルートファイルシステムを切り替えると、新しいルートファイルシステムしか参照できなくなります。別のファイルシステムとなるため、元のファイルシステムに脱出することができません。

pivot_root を実行するには条件があるようです。この条件を満たすために、後述の bind mount を利用します。

https://manpages.debian.org/unstable/manpages-ja-dev/pivot_root.2.ja.html

## bind mount

bind mount とは、任意のファイル/ディレクトリを別のファイル/ディレクトリにマウントする機能です。
バインドマウントでホストのディレクトリを自分自身にマウントすることで、システムは自分自身にマウントしたディレクトリを独立したファイルシステムがマウントされた(マウントポイント)かのように扱います。
bind mount でマウントしたディレクトリに pivot_root を実行することで、任意のディレクトリをコンテナのファイルシステムとしてホストから隔離することができます。

https://man7.org/linux/man-pages/man8/mount.8.html

## ホスト・コンテナ間のUID、GIDマッピング

User Namespaceを作成すると、ホストから隔離された空間にUID、GIDを保持します。ホストと作成したUser Namespace間でUID、GIDを適切にマッピングすることで、セキュアなコンテナ環境を提供できるようになります。具体的に、コンテナの root ユーザをホストの一般ユーザにマッピングすることで、ホストから見ると一般ユーザの権限しか保持していない状態となります。この仕組みを利用すると、一般ユーザ(ルートレスユーザ)がコンテナを起動することが可能となります。

https://man7.org/linux/man-pages/man7/user_namespaces.7.html

https://manpages.debian.org/testing/uidmap/newuidmap.1.en.html

https://man7.org/linux/man-pages/man1/newgidmap.1.html

https://manpages.ubuntu.com/manpages/focal/ja/man7/user_namespaces.7.html

複数のIDをマッピングするケースでは、subuid と subgid を利用します。コンテナ内で複数のユーザを作成するとサブIDの範囲からIPがマッピングされます。

https://man7.org/linux/man-pages/man5/subuid.5.html

https://man7.org/linux/man-pages/man5/subgid.5.html

bind mount の項で記載したとおり、コンテナはホストのディレクトリをマウントしています。ホスト・コンテナ間のディレクトリ所有権も同様にマッピングする必要があります。このマッピングする機能がID mapped マウントです。具体的に、mount コマンドの `--map-users`, `--map-groups`オプションで所有権のマッピングを指定します。

https://man7.org/linux/man-pages/man8/mount.8.html

## OverlayFS

OverlayFS とは、複数のファイルシステムが持つディレクトリを重ね合わせて、あたかも1つのディレクトリツリーとして構成するユニオンファイルシステムです。コンテナファイルの`FROM`キーワードが下層レイヤー、`RUN`キーワードが上層レイヤーとなり、OverlayFS の各レイヤーにアーカイブファイルを展開します。

https://docs.kernel.org/filesystems/overlayfs.html

https://zenn.dev/tenforward/articles/35fccf15b4f83cad7d66

## コンテナのネットワーク

コンテナに隔離されたネットワーク機能を提供するために、レイヤー2の仮想ネットワークインターフェースである veth (Virtual Ethernet Device) が利用されています。
veth は常にペアで作成され、それぞれが異なる Network Namespace に配置されます。具体的に、veth ペアの一方はホストのデフォルト Network Namespace に配置され、もう一方はコンテナの Network Namespace 内に移動されます。veth ペアの内のホスト側は、ホストに作成された仮想ブリッジへ接続されます。これにより、仮想ブリッジを介してホストとコンテナ間の通信が可能になります。

レイヤー2はOSI参照モデルのデータリンク層にあたります。veth はMACアドレスを介して同一ネットワーク内(仮装ブリッジ)にパケットを転送し、仮想ブリッジに接続された veth ペアへパケットを転送します。

veth 以外にも、ホストのネットワークスタックを直接共有したり、macvlan でコンテナのネットワークを構成することができます。

https://man7.org/linux/man-pages/man4/veth.4.html

https://man7.org/linux/man-pages/man8/ip-link.8.html

## capabilities

capabilities とは、root が持つ特権を細分化して、必要な権限のみを一般ユーザに付与する機能です。capabilities の設定で、コンテナに必要な権限のみを付与する運用が可能となります。

https://man7.org/linux/man-pages/man7/capabilities.7.html

https://github.com/torvalds/linux/blob/master/include/uapi/linux/capability.h

## seccomp

seccomp (Secure Computing Mode) とは、プロセスから発行されるシステムコールをフィルタリングする機能です。システムコールをフィルタリングするためにBPF(Berkeley Packet Filter)が利用されています。

https://man7.org/linux/man-pages/man2/seccomp.2.html

https://man7.org/linux/man-pages/man2/bpf.2.html

コンテナはホストのカーネルを共有するため、コンテナ内から自由にシステムコールを使用すると他のコンテナやホストに影響が出てしまいます。コンテナが発行するシステムコールを制限する目的で seccomp が利用されています。
制限する内容は seccomp プロファイルで定義することができます。

https://github.com/containers/common/blob/main/pkg/seccomp/seccomp.json

https://kubernetes.io/docs/tutorials/security/seccomp/

## SELinux

SELinux (Security-Enhanced Linux) とは、Linuxカーネルに組み込まれたセキュリティ機能で、システムリソースへのアクセスをより詳細に制御するための仕組みです。ホスト上のユーザとプロセス、ファイル、NWなどの各種リソースにLabelを付与し、そのLabelの組み合わせでアクセス可能なリソースを制限するPolicyを定義します。SELinux のルールを適切に設定することにより、権限昇格による被害を軽減できます。

https://man7.org/linux/man-pages/man8/selinux.8.html

https://moriya.hatenadiary.com/entry/2024/07/20/164632

## AppArmor

AppArmor とは、Linuxカーネルに統合された[セキュリティモジュール](https://www.kernel.org/doc/html/v4.19/admin-guide/LSM/index.html)です。プログラムからのファイルやデバイス、ネットワークへのアクセスを制限することができます。任意のファイルパスを対象にセキュリティ制御が可能という特徴があります。

https://gitlab.com/apparmor/apparmor/-/wikis/manpage_apparmor.d.5

https://manual.geeko.jp/ja/cha.apparmor.profiles.html

https://cloud.google.com/container-optimized-os/docs/how-to/secure-apparmor?hl=ja

## まとめ

この記事では、コンテナ技術を支えるLinuxカーネルの主要な機能について解説しました。
複数のLinuxカーネルの機能が複雑に連携することで、隔離性と効率性、セキュリティを確保したコンテナ環境が構築されています。

## 参考リンク

- [Container Security Book](https://container-security.dev/)
- [tenforward.hatenablog.com](https://tenforward.hatenablog.com/archive)
- [LXCで学ぶコンテナ入門 －軽量仮想化環境を実現する技術 記事一覧](https://gihyo.jp/list/group/LXC%E3%81%A7%E5%AD%A6%E3%81%B6%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E5%85%A5%E9%96%80-%E8%BB%BD%E9%87%8F%E4%BB%AE%E6%83%B3%E5%8C%96%E7%92%B0%E5%A2%83%E3%82%92%E5%AE%9F%E7%8F%BE%E3%81%99%E3%82%8B%E6%8A%80%E8%A1%93)