Slide 1

Slide 1 text

コンテナ IBUFOBJOUFSO !

Slide 2

Slide 2 text

⾃⼰紹介 • id: SlashNephy • ねふぃー と呼んでくださいね • 職種 • Web アプリケーションエンジニア • 所属 • 東京オフィス • テクノロジーソリューション本部ゲームチー ム • 兼組織‧基盤開発本部サービスプラットフォ ームチーム IBUFOBJOUFSO !

Slide 3

Slide 3 text

⾃⼰紹介 • 趣味 • クロスバイク、SF ⼩説、PC ゲーム、お酒 IBUFOBJOUFSO !

Slide 4

Slide 4 text

この講義のゴール • コンテナ技術がどのように実現されているかを理解する • 普段私たちが利⽤しているコンテナがどう動いているか想像できるよ うになる • コンテナ技術を活⽤できるようになる • コンテナを利⽤するにあたり、どのような点に注意すべきか判断でき るようになる • コンテナ技術の発展を学ぶ IBUFOBJOUFSO !

Slide 5

Slide 5 text

コンテナとは? IBUFOBJOUFSO !

Slide 6

Slide 6 text

コンテナで実現したいこと • 仮想化 • 可搬性 (portability) を⾼く保つこと • ⾼速‧低コストであること これらを実現するのが、プロセスの隔離とコンテナイメージによ る環境の構築です。 IBUFOBJOUFSO !

Slide 7

Slide 7 text

プロセスの隔離 • コンテナ技術の根幹となる概念の1つ • あるプロセスから⾒えるリソース‧利⽤可能なリソースを制限 する • プロセス間の⼲渉がなくなり、複数のプロセスを安定して稼 働させられる • 不要なリソースを利⽤させないことで、安全性を⾼められる IBUFOBJOUFSO !

Slide 8

Slide 8 text

コンテナイメージ • 隔離されたプロセスの実⾏環境 • 次のようなものが含まれる • プロセスが動作するために必要なライブラリ等をまとめたフ ァイルシステム • 環境変数など実⾏時の設定 • その他のメタ情報 IBUFOBJOUFSO !

Slide 9

Slide 9 text

コンテナを実現する技術 IBUFOBJOUFSO !

Slide 10

Slide 10 text

コンテナを実現するプロダクト • 2000年: FreeBSD jails • 2008年: Linux Containers (LXC) • 2013年: Docker • 2019年: Podman これらのプロダクトも、概ね以降で紹介する技術 (や、相当の機 能) を組み合わせて実現されています。 IBUFOBJOUFSO !"

Slide 11

Slide 11 text

リソースの制限 • コンテナはプロセスが利⽤できるリソースを制限する技術を組 み合わせて実現されている • 何を制限するかによって複数の要素技術がある • リソースの可視性: Namespace (PID, Mount, User, ...) • リソースの利⽤上限: Namespace (cgroup) • 特権‧システムコール等: capability, seccomp, ... IBUFOBJOUFSO !!

Slide 12

Slide 12 text

Namespace • Linux Kernel の持つ機能 • Namespace ごとにリソースを隔離して、Namespace 内のプロセ スに対して独⽴した環境に⾒せる • それぞれのプロセスが⼲渉することがなくなる • どのリソースを隔離するかによって様々な Namespace が存在する • PID, Mount, User, Network, IPC, UTS, Time, cgroup IBUFOBJOUFSO !"

Slide 13

Slide 13 text

Namespace PID • プロセス ID 番号空間の隔離 • 名前空間内で最初のプロセスは PID 8 ubuntu@utm:~$ ps PID TTY TIME CMD 1889 pts/0 00:00:00 bash 2711 pts/0 00:00:00 ps ubuntu@utm:~$ sudo unshare "#pid "#fork "#mount-proc ps PID TTY TIME CMD 1 pts/0 00:00:00 ps IBUFOBJOUFSO !"

Slide 14

Slide 14 text

Namespace User • UID/GID を分離する • capability (後述) を分離する • 異なる Namespace で同じ UID のユーザを作成できる • ホストからは⼀般ユーザ、コンテナ内では root というユーザが作成できる • マッピング IBUFOBJOUFSO !"

Slide 15

Slide 15 text

Namespace cgroup (Control Group) • コンテナ内のプロセスの集合に対してリソース使⽤量を制限す る仕組み • CPU 使⽤量、メモリ使⽤量、プロセス数など • 監視も⾏うことができ、docker top はこれを利⽤している IBUFOBJOUFSO !"

Slide 16

Slide 16 text

Namespace • そのほか • Mount: マウントポイントを分離する • Network: ネットワークデバイス、ルーティングテーブル、IP アドレス、 ポート番号などを隔離する • Time: ホストとコンテナの時間を分離する • IPC: 共有メモリを分離する • UTS: ホスト名とドメイン名を分離する IBUFOBJOUFSO !"

Slide 17

Slide 17 text

capability • ネットワーク操作など、特定の操作を⾏うために特権が必要と なることがある • 特定の操作のためにあらゆる特権を取得するのは過剰 • 例: ping コマンドの実⾏のために特権を取得した。ping コマ ンドを実⾏する特権で PC の再起動までできるようになって しまった。 IBUFOBJOUFSO !"

Slide 18

Slide 18 text

capability • Linux Kernel では操作の種類に応じた権限として、capability とい う概念があり、プロセスに対して許可する権限を個別に選択できる • 先程の例では CAP_NET_RAW と CAP_SYS_BOOT を分離している • ping コマンドには CAP_NET_RAW のみを付与することで、特権処 理の1つである RAW ソケットの利⽤を許可しながら、PC の再起 動は許可しない • capability の⼀覧は man capabilities(7) で確認できる IBUFOBJOUFSO !"

Slide 19

Slide 19 text

capability • 特権操作を必要とするプロセスに対しても、特権を渡すのではなく capability を 付与する • capability によって許可される操作は Namespace で隔離された範囲に閉じな いことがあるので注意する必要がある • コンテナランタイムはコンテナで実⾏するプロセスに対していくつかの capability をデフォルトで付与する • 設定によって追加の capability を付与することもできる • Docker の場合 !"cap-add, !"cap-drop, !"priviledged オプションがある IBUFOBJOUFSO !"

Slide 20

Slide 20 text

seccomp • システムコールの中には Namespace で分離されていないリソースに⼲渉するもの もあり、コンテナ内のプロセスから呼び出されると仮想化が崩れてしまう • seccomp はプロセスの発⾏できるシステムコールを制限する仕組みで、コンテナラ ンタイムは seccomp を利⽤してコンテナ内のプロセスがこれらのシステムコールを 呼び出すことを防ぐ • Docker でデフォルトで制限されているシステムコールは公式ドキュメントに⼀覧さ れている • 設定でプロファイルを渡すことによって呼び出しを制限するシステムコールを制御 できる IBUFOBJOUFSO !"

Slide 21

Slide 21 text

seccomp Docker で kill というシステムコールを制限してみる。 seccomp.json { "defaultAction": "SCMP_ACT_ALLOW", "syscalls": [ { "name": "kill", "action": "SCMP_ACT_ERRNO" } ] } slashnephy@Macbook $ docker run !"name ubuntu_bash \ !"rm -it !"security-opt seccomp=seccomp.json ubuntu bash root@f9d4b6ac2a8a:/# sleep 100 & [1] 10 root@f9d4b6ac2a8a:/# kill 10 bash: kill: (10) - Operation not permitted IBUFOBJOUFSO !"

Slide 22

Slide 22 text

その他の機能 これまで紹介してきた機能以外にもコンテナの可搬性‧安全性に寄与する技術が提案‧利⽤されていま す。 • AppArmor / SELinux • ポリシーに基づいてさらに強固にプロセスの挙動を制約する • gVisor • ユーザ空間カーネルを実装し、システムコール呼び出しをホストマシンに伝搬させないことで隔離 性能を⾼める • Kata Containers • コンテナを qemu, Firecracker などで⽣成した仮想マシン内で実⾏する IBUFOBJOUFSO !!

Slide 23

Slide 23 text

コンテナイメージ IBUFOBJOUFSO !"

Slide 24

Slide 24 text

プロセスの実⾏環境 • プロセスが利⽤するライブラリや読み書きするファイルも独⽴ していたい • スケーラビリティを確保するためにはこれらが素早く、再現性 を持って準備されていたい • これを実現するのがコンテナイメージ IBUFOBJOUFSO !"

Slide 25

Slide 25 text

コンテナイメージ • コンテナ化された環境で利⽤するファイルシステムなどをまと めたもの • 主な内容物はコンテナ化されるプロセスから参照される Mount Namespace にマウントされるファイル群の tar アーカイブ • この tar アーカイブの root を隔離したプロセスに対するルー トファイルシステムとして pivot_root する IBUFOBJOUFSO !"

Slide 26

Slide 26 text

Union ファイルシステム • 複数の異なるファイルシステムを重ね合わせて利⽤できる仕組 み • OverlayFS などの実装がある IBUFOBJOUFSO !"

Slide 27

Slide 27 text

Union ファイルシステム • ベースとなる下位ディレクトリ (Lower Dir) に対し、差分を上位ディレクト リ (Upper Dir) として重ね合わせる • コンテナイメージに含まれるファイルシステムは Lower Dir、コンテナ上で 変更されるファイルシステムを Upper Dir とする • Lower Dir は変更されないので1つのコンテナイメージを複数のコンテナ インスタンスで共有できる • 変更を個々のコンテナインスタンス毎の Copy on Write レイヤー (Upper Dir) に適⽤する IBUFOBJOUFSO !"

Slide 28

Slide 28 text

Dockerfile # syntax=docker/dockerfile:1 FROM golang:1.23-bookworm AS builder WORKDIR /services/blog COPY go.mod go.sum ./ RUN go mod download COPY . . RUN !"mount=type=cache,target=/root/.cache/go-build \ make build FROM debian:bookworm COPY !"from=builder \ /services/blog/bin/server \ /services/blog/bin/server RUN adduser -D -u 1000 app USER 1000 ENTRYPOINT ["/services/blog/bin/server"] • 単純なテキストベースのスクリプ トファイル • コンテナイメージを⽣成するため の命令が記述されている • イメージビルダによって Dockerfile がコンテナイメージへ と変換される IBUFOBJOUFSO !"

Slide 29

Slide 29 text

コンテナイメージの構造を覗く 以下の Dockerfile をビルドしてイメージを作成する FROM ubuntu RUN echo "hoge" > hoge.txt RUN rm hoge.txt 作成したイメージを出⼒して解凍する docker save $CID > image.tar tar xf image.tar IBUFOBJOUFSO !"

Slide 30

Slide 30 text

イメージレイヤー Dockerfile の命令毎にレイヤーが分かれている。 . ├── 3fe352f27d6d9b899da69b9799728c4492690186797a106cbfa029264b6ebcf7 │ ├── VERSION │ ├── json │ └── layer.tar ├── aa8c0471e58774435617a2efb80b963d0288bdbdfdd7ded778776c3051664569.json ├── af197d5ca08b03ffdfd8c1285260360fbbc237328d421b73c2abc3f07bb054d9 │ ├── VERSION │ ├── json │ └── layer.tar ├── b3ea71bd7712c8534c4e3440a02a2217d0049fc8acacac191cf875bc21ab9f6a │ ├── VERSION │ ├── json │ └── layer.tar └── manifest.json IBUFOBJOUFSO !"

Slide 31

Slide 31 text

layer.tar • 下位のレイヤーに対しての差分がまとめられている b3ea71bd7712c8534c4e3!!" 以下の layer.tar の中⾝を⾒てみる % tar xf layer.tar -C ./tmp % ls ./tmp hoge.txt % cat ./tmp/hoge.txt hoge IBUFOBJOUFSO !"

Slide 32

Slide 32 text

layer.tar whiteout • ファイルの削除は whiteout file によって表現される • ファイルを削除したときは .wh. から始まる空のファイルが作られる • 特定のディレクトリの全てのファイルを削除した場合はそのディレクトリに opaque whiteout file .wh!"wh!"opq が作られる af197d5ca08b03ffdfd8c!!" 以下の layer.tar の中⾝を⾒てみる % tar tvf af197d5ca08b03ffdfd8c!!"/layer.tar -rw------- 0 0 0 0 7 31 19:35 .wh.hoge.txt IBUFOBJOUFSO !"

Slide 33

Slide 33 text

レイヤーキャッシュ # syntax=docker/dockerfile:1 FROM golang:1.23-bookworm AS builder WORKDIR /services/blog COPY go.mod go.sum ./ # ͕͜͜มߋ͞Εͨ৔߹͸ ↓ ͷ෦෼Λ࠶࣮ߦ RUN go mod download COPY . . RUN "#mount=type=cache,target=/root/.cache/go-build \ make build • コンテナイメージのビルド時に は Lower Dir に対する変更を Upper Dir として新しいレイヤー ⽤の tar アーカイブを作成する • ⼀度実⾏した命令は Lower Dir として残っているので、Upper Dir による変更だけを⾏えばよ く、レイヤーキャッシュが利⽤ できる IBUFOBJOUFSO !!

Slide 34

Slide 34 text

イメージのビルド • Dockerfile からコンテナイメージを作成するにはビルダーを利 ⽤する • BuildKit, Kaniko, Buildah などのツールがある • ビルダーは Dockerfile に記述されている命令に従ってイメージ レイヤーを積み重ねてコンテナイメージを作る IBUFOBJOUFSO !"

Slide 35

Slide 35 text

BuildKit • Docker Engine -..0 から docker build で使われているビル ダ • buildctl という CLI ツールからも利⽤できる • イメージの並列ビルドやマルチプラットフォーム対応イメージ のビルドが可能 • Dockerfile の最新の構⽂に対応している IBUFOBJOUFSO !"

Slide 36

Slide 36 text

BuildKit SBOM (Software Bill of Materials) • 利⽤しているソフトウェアを管理できるフ ォーマット • ライセンス管理や脆弱性管理に使われる • BuildKit では Syft scanner というプラグ インを利⽤してコンテナイメージに SBOM を追加できる • SBOM からコンテナイメージ内に存在 するソフトウェアの脆弱性を検出できる $ buildctl build \ !"frontend dockerfile.v0 !"local context=. !"local dockerfile=. \ !"opt attest:sbom=generator=docker/buildkit-syft-scanner \ !"output type=image,name=hatena/intern2023 [+] Building 16.7s (23/23) FINISHED !# [internal] load build definition from Dockerfile 0.0s !# !# transferring dockerfile: 844B 0.0s !!$ !# !# resolve docker.io/docker/buildkit-syft-scanner:latest 0.3s !# [linux/arm64] generating sbom using docker.io/docker/buildkit-syft-sc 0.1s !# exporting to image 0.5s !# !# exporting layers 0.4s !# !# exporting manifest sha256:d6e8bd451e080886f0b7a764e731347bd4b22cdd 0.0s !# !# exporting config sha256:0941190ee8cb0d7b70ecfba24f8281dde9497012c1 0.0s !# !# exporting attestation manifest sha256:677397d604ce5507cd5b54c79838 0.0s !# !# exporting manifest list sha256:c032b2a13f1de13780312229b9ba5bca0ce 0.0s IBUFOBJOUFSO !"

Slide 37

Slide 37 text

コンテナランタイムのアーキテクチ ャと標準 IBUFOBJOUFSO !"

Slide 38

Slide 38 text

コンテナランタイムを構成するコンポーネン ト • 低レベルランタイム: プロセスを隔離して実⾏する • ⾼レベルランタイム: コンテナイメージやコンテナの管理 • CLI/デーモンなど: ユーザにインタフェースを提供し、⾼レベルランタイムを操作する IBUFOBJOUFSO !"

Slide 39

Slide 39 text

⾼レベルランタイム • containerd, CRI-O など • コンテナイメージや複数台のコンテナを管理する • ユーザインタフェースとなるツールや、コンテナオーケストレーションツールと通信 する • CRI (Container Runtime Interface) という規格がある • 低レベルランタイムと通信してコンテナを起動する‧低レベルランタイムにコンテ ナ環境の設定を送信する • Docker は低レベルランタイムとの通信に containerd を利⽤している IBUFOBJOUFSO !"

Slide 40

Slide 40 text

低レベルランタイム • runc, gVisor など • 個々のプロセスを起動し、Namespace を隔離してコンテナと して実⾏する • OCI Runtime Spec (Open Container Initiative Runtime Specification) によって標準的な仕様‧挙動が定義されている IBUFOBJOUFSO !"

Slide 41

Slide 41 text

Open Container Initiative (OCI) • コンテナの業界標準を定める団体 • 現在 Runtime Spec, Image Spec, Distribution Spec が定義さ れている IBUFOBJOUFSO !"

Slide 42

Slide 42 text

Open Container Initiative (OCI) Runtime Specification • コンテナランタイムの実現すべき挙動が主に定義されている • コンテナの原則 (The C principles of Standard Containers) • コンテナのライフサイクルや、コンテナに対して実⾏可能な操作 • 付与する capability, Namespace, cgroup によるリソースの制 限の指定⽅法など IBUFOBJOUFSO !"

Slide 43

Slide 43 text

Open Container Initiative(OCI) The % principles of Standard Containers • ". Standard operations • 起動‧停⽌‧削除やスナップショットの取得などの基本的な操作が可能 • L. Content-agnostic • コンテナに対する操作はコンテナの内容によらず同じ結果になる • b. Infrastructure-agnostic • OCI に準拠しているコンテナランタイム上で動くコンテナは、どのような場所やアーキテクチャの上でも同様に動作する • . Designed for automation • Ç. Industrial-grade delivery IBUFOBJOUFSO !"

Slide 44

Slide 44 text

Open Container Initiative (OCI) Image Specification • コンテナイメージに含まれるデータの種類や、その配置について定義 されている • 主たるデータは Filesystem Layer, Image Index, Image Configuration。他にも Image Manifest などが含まれる • Image Manifest ごとの Filesystem Layer や Image Configuration が含まれており、それらの配置が Image Index に記載されている IBUFOBJOUFSO !!

Slide 45

Slide 45 text

実践的なコンテナイメージの作成 IBUFOBJOUFSO !"

Slide 46

Slide 46 text

1コンテナ 1プロセス • 単⼀の機能として分離して⽔平スケールしやすくするため • 再利⽤性、透明性を⾼める • 依存関係を減らす IBUFOBJOUFSO !"

Slide 47

Slide 47 text

ステートレスでイミュータブルにする • 状態を持たず、不変 • 実⾏しているコンテナ内でアプリケーションを変更しない • 永続データはコンテナ外部のコンポーネントに任せる • ログは stdout/stderr に出⼒する • ログをファイルに書き出さない IBUFOBJOUFSO !"

Slide 48

Slide 48 text

イメージは軽量にする • 実⾏に必要な依存関係のみを持つイメージを作成する • 軽量なので実⾏までのコストが⼩さくなる。依存関係が減ると攻撃されうる対象 も減る。 • 軽量なベースイメージを選択する • -slim な flavor や distroless をベースとして、必要なランタイムとアプリケーシ ョンだけインストールする • SlimToolkitで軽量化する • 軽量化にこだわりすぎず、Seekable OCI でイメージを遅延読み込みするのも⼿ IBUFOBJOUFSO !"

Slide 49

Slide 49 text

適切なベースイメージを選択する • イメージを作成する上で、ベースイメージを正しく選択することは重要 • 開発元の公式イメージや、コンテナレジストリで verified となっているイメージを選択すべき • Alpine Linux を避ける • glibc を採⽤していないので互換性やパフォーマンスの問題が起こることがある IBUFOBJOUFSO !"

Slide 50

Slide 50 text

コンテナのユーザーは⼀般ユーザーにする • User namespace の分離と適切なマッピングを指定しない場 合、コンテナの root はホストの root に対応する • コンテナ内の脆弱性で root 権限を取得された場合、影響がホス トの root にまで及んでしまうことも • Dockerfile の USER 命令でコンテナを実⾏するユーザを指定す る IBUFOBJOUFSO !"

Slide 51

Slide 51 text

設定値を環境変数に格納する • コンテナイメージを作り直すことなく動作を変更できる • デリバリータイムの削減 • 複数の環境で同じ Docker イメージが使える • The Twelve-Factor App で提唱されている IBUFOBJOUFSO !"

Slide 52

Slide 52 text

シークレット値をコンテナイメージに含めな い • コンテナイメージ経由でシークレットが漏洩する可能性がある • シークレットの更新のためにコンテナイメージを再度⽣成する必要がある • 代わりに以下のような⽅法をとる • コンテナ起動後にネットワーク経由で取得する • 環境変数経由でコンテナにシークレットを渡す • The Twelve-Factor App ではこの⽅法を推奨している • コンテナがマウントされるボリュームに書き込む IBUFOBJOUFSO !"

Slide 53

Slide 53 text

イメージのスキャン • Dockerfile の書き⽅の不備や、イメージ内に含まれるファイル‧パッケ ージに含まれる脆弱性をスキャンできるツールが存在する • Trivy, Claier, Anchore などのツールや、AWS ECR, Docker Hub の機 能、docker scout sves コマンドが利⽤できる 脆弱性の発⾒されているソフトウェアが Docker イメージの中に⼊ってい ないか、スキャンします。 イメージをスキャンするには、そのためのツールやサービスを利⽤した り、レジストリが脆弱性スキャンを実施してくれるものもあります。 IBUFOBJOUFSO !"

Slide 54

Slide 54 text

イメージのスキャン Trivy • https://github.com/aquasecurity/trivy • Docker イメージ、ファイルシステム、Git リポジトリに対してスキャンができる • イメージの SBOM からも脆弱性をスキャンできる $ trivy image !"severity HIGH hatena/apply-for-internship-2020:latest 2020-08-05T08:44:37.496+0900 WARN You should avoid using the :latest tag as it is cached. You need to specify '!"clear-cache' option when :latest image is changed 2020-08-05T08:44:40.616+0900 INFO Detecting Debian vulnerabilities!!$ hatena/apply-for-internship-2020:latest (debian 10.4) ===================================================== Total: 1 (HIGH: 1) +-----------+------------------+----------+-------------------+------------------+--------------------------------+ | LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION | TITLE | +-----------+------------------+----------+-------------------+------------------+--------------------------------+ | perl-base | CVE-2020-10878 | HIGH | 5.28.1-6 | 5.28.1-6+deb10u1 | perl: corruption of | | | | | | | intermediate language state | | | | | | | of compiled regular expression | | | | | | | due to!!$ | +-----------+------------------+----------+-------------------+------------------+--------------------------------+ IBUFOBJOUFSO !"

Slide 55

Slide 55 text

まとめ • コンテナはプロセスを隔離し、コンテナイメージをもとに実⾏して実現されています • Namespace, seccomp, OverlayFS など • コンテナランタイムの挙動は標準化されています • CRI, OCI (Runtime Spec, Image Spec) など • コンテナを軽量かつステートレスに設計することでスケールしやすくなります • ! 詳しくは次の「コンテナオーケストレーション」講義で! ご清聴ありがとうございました IBUFOBJOUFSO !!