Slide 1

Slide 1 text

コンテナ コンテナオーケストレーション IBUFOBJOUFSO !

Slide 2

Slide 2 text

この講義で学んでほしいこと • コンテナの概要 • コンテナオーケストレーションの概要 • コンテナオーケストレーションのデファクトスタンダードであ るKubernetesの特徴と機能 • インターンの中でKubernetesを使うために最低限の操作⽅法 IBUFOBJOUFSO !

Slide 3

Slide 3 text

コンテナ IBUFOBJOUFSO !

Slide 4

Slide 4 text

世はまさに⼤コンテナ時代 • ここ数年でエンタープライズの環境でもコンテナが利⽤されて いる • はてなでもほとんどのアプリケーションがコンテナで動いて いる(ECS) • コンテナオーケストレーションとしてはKubernetesがデファク トスタンダードで、各クラウドがKubernetesサービスを提供し ている IBUFOBJOUFSO !

Slide 5

Slide 5 text

なぜコンテナ環境が採⽤されるのか • ポータビリティ(可搬性)の向上と環境再現性 • Build once, Run anywhere • コンテナじゃないときは、⾃分の環境では動くのに...とか、 テスト環境では動くのに...というのが起きやすい • 確実な環境分離と依存関係の明確化 IBUFOBJOUFSO !

Slide 6

Slide 6 text

なぜコンテナ環境が採⽤されるのか • 開発者の⽣産性向上 • ⾼速な開発サイクル • 環境構築の簡素化 • アプリケーション運⽤の効率化 • コンテナオーケストレーションとしての役割 現代のアプリケーション開発でコンテナは⽋かせないものになっている IBUFOBJOUFSO !

Slide 7

Slide 7 text

コンテナとは IBUFOBJOUFSO !

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

cgroup • cgroupは、プロセスグループに対してCPU、メモリ、ディスクI/Oなど のリソースの使⽤量を制限、監視、優先順位付けをするLinuxカーネル の機能 • 階層構造を持っており、各ノード(cgroupの階層)がリソースグループ を表す • cgroup Namespaceにより、コンテナ内のプロセスはホストOS全体の cgroup階層を⾒るのではなく、⾃⾝に割り当てられたcgroup階層のサ ブツリーをルートとして認識する IBUFOBJOUFSO !"

Slide 19

Slide 19 text

Capability • 特権の細分化 • ネットワーク操作など、特定の操作を⾏うために特権が必要となることがある • 特定の操作のためにあらゆる特権を取得するのは過剰 • pingバイナリに CAP_SYS_BOOT(システムの再起動)を付与してしまった • pingコマンドの実⾏のために特権を取得すると、この特権で PC の再起動までで きるようになってしまった • もちろんping コマンドの中に再起動処理のロジックが⼊っていなければできな いけれど、権限としてはできる IBUFOBJOUFSO !"

Slide 20

Slide 20 text

Capability • Linux Kernel では操作の種類に応じた権限として、Capability という概念があり、プロセスに対して許可 する権限を個別に選択できる • Capabillityは"鍵"のようなもので、実装という"ドア"とセットで機能する • pingは、ICMPパケットを直接送受信するために、rootでしか使えないRAWソケットを利⽤する • pingバイナリに、この特権処理を許可するCAP_NET_RAWというCapabilityのみを付与し、pingは⼀般 ユーザでも実⾏可能になる • pingバイナリにはシステムを再起動する権限であるCAP_SYS_BOOTのような他の強⼒な権限は付与しな い • pingコマンドに脆弱性があっても、システム全体に影響が及ぶリスクを最⼩限に抑えることができる • Capability の⼀覧は man capabilities(7) で確認できる IBUFOBJOUFSO !"

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

seccomp • システムコールの中には、Linux Namespaceでは⼗分に分離できない、あるいはホストシステム 全体に影響を及ぼす可能性のあるリソースに⼲渉するものがある • コンテナ内のプロセスからこれらのシステムコールが呼び出されると、コンテナの分離性が損な われ、ホストシステムにセキュリティ上の影響が及ぶリスクがある • seccomp はプロセスの発⾏できるシステムコールを制限する仕組みで、コンテナランタイムは seccomp を利⽤してコンテナ内のプロセスがこれらのシステムコールを呼び出すことを防ぐ • Docker でデフォルトで制限されているシステムコールは公式ドキュメントに⼀覧されている • 設定でプロファイルを渡すことによって呼び出しを制限するシステムコールを制御できる • プロファイルとは、許可するシステムコールと拒否するシステムコールを定義したルールセット IBUFOBJOUFSO !!

Slide 23

Slide 23 text

コンテナイメージ IBUFOBJOUFSO !"

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

コンテナイメージ • コンテナ化された環境で利⽤するファイルシステムなどをまと めたもの • 主な内容物はコンテナ化されるプロセスから参照される Mount Namespace にマウントされるファイル群の tar アーカイブ • コンテナ化されるプロセスにとって、この tar アーカイブが/ (ルートディレクトリ)となるようにコンテナランタイムは 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

コンテナイメージの構造を覗く FROM ubuntu RUN echo "hoge" > hoge.txt RUN rm hoge.txt $ docker build . -t sample 作成したイメージを出⼒して解凍する $ docker save sample > image.tar $ mkdir /tmp/images $ tar xf image.tar -C /tmp/images $ ls -l /tmp/images total 32 drwxr-xr-x@ 3 rskmm0chang wheel 96 7 14 12:54 blobs -rw-r"#r"#@ 1 rskmm0chang wheel 362 1 1 1970 index.json -rw-r"#r"#@ 1 rskmm0chang wheel 1067 1 1 1970 manifest.json -rw-r"#r"#@ 1 rskmm0chang wheel 31 1 1 1970 oci-layout -rw-r"#r"#@ 1 rskmm0chang wheel 89 1 1 1970 repositories IBUFOBJOUFSO !"

Slide 29

Slide 29 text

イメージレイヤー blobs以下にDockerfile の命令毎にレイヤーが分かれている $ tree /tmp/images/ /tmp/images/ ├── blobs │ └── sha256 │ ├── 081fb1efc91eea477727e7966405f2e3038e2f283672dda79108e305e1d14e09 │ ├── 176b61970a68fab10ed0567af1cb59479f6d50436043cf533b123ad1e485e5c9 │ ├── 520724c855391393f7903c957f7a8d4c363fb6c216f53374f69f55c338e46aca │ ├── 7e06715b212add1e8fab9603a4c3954986ea7f8a5b20a83a559af215c16e8766 │ ├── 88d4446cbfd41e9e3e5225c78c6e068d3104726e320b92ec1d62d81fd3641b4e │ ├── 961ef2cb6a6eec47b257f88e92a47dcabb5df1b010acc4cd41bc153c3fe6c98a │ ├── a353043666c367fcf0ccba8b0a0dc23b4bd9625ea7ceefeb8dbc0917d9b4061e │ └── fcecd6f30cfb23f719076bb2bae17b876968f9bebcc1821d5f54cf594c9f63b5 ├── index.json ├── manifest.json ├── oci-layout └── repositories IBUFOBJOUFSO !"

Slide 30

Slide 30 text

blobs • 下位のレイヤーに対しての差分がまとめられている • 以下のblobsの中⾝を⾒てみる # vΛ͚ͭͯల։ $ tar xvf blobs/sha256/081fb1efc91eea477727e7966405f2e3038e2f283672dda79108e305e1d14e09 -C /tmp/layer_content x hoge.txt IBUFOBJOUFSO !"

Slide 31

Slide 31 text

blobs whiteout • ファイルの削除は whiteout file によって表現される • ファイルを削除したときは .wh.(ϑΝΠϧ໊) という空ファイルが作られる • ディレクトリを削除したときは .wh.(σΟϨΫτϦ໊) という空ファイルが作 られる • ディレクトリの内容をすべて削除した場合、そのディレクトリ全体を不透明 (opaque)にするためにopaque whiteout file(.wh!"wh!"opq)が作成される IBUFOBJOUFSO !"

Slide 32

Slide 32 text

whiteout # vΛ͚ͭͯల։ $ tar xvf blobs/sha256/a353043666c367fcf0ccba8b0a0dc23b4bd9625ea7ceefeb8dbc0917d9b4061e -C /tmp/layer_content x .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

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

ランタイム IBUFOBJOUFSO !"

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

1コンテナ 1プロセス • 単⼀の機能として分離して⽔平スケールしやすくするため • 再利⽤性、透明性を⾼める • 依存関係を減らす • PID 1問題への対策にもなる • PID Namespaceのところで話した話題 • LinuxにおいてPID eは特殊な役割がある • 通常ではinitや、systemdなどが担っている IBUFOBJOUFSO !"

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

Graceful Shutdown コンテナに限らないけれど、コンテナ環境ではアプリケーションのライフサイクルが短くなりやすい • アプリケーションを適切に終了させる • データの不整合が起きないように、など、アプリケーションをきちんと⽌める • SIGTERMに対応させる • コンテナオーケストレーションでのオートスケールへの対応にもなる • アプリケーションの中にはSIGTERM以外のときがあるので注意 • nginxとかphp-fpmはSIGQUIT • DockerfileのSTOPSIGNALでGraceful Shutdownのシグナルを変えることも可能 • https://github.com/nginx/docker-nginx/blob/master/Dockerfile-debian.template#LÇÉÉ IBUFOBJOUFSO !"

Slide 46

Slide 46 text

コンテナを動かす環境 • Dockerの登場でコンテナが簡単に使えるようになった • 本番環境で扱うにはオペレーションが⾜りない • デプロイ • 復旧⼿段 • スケール IBUFOBJOUFSO !"

Slide 47

Slide 47 text

コンテナオーケストレーション登場 IBUFOBJOUFSO !"

Slide 48

Slide 48 text

...休憩... IBUFOBJOUFSO !"

Slide 49

Slide 49 text

コンテナオーケストレーションとは IBUFOBJOUFSO !"

Slide 50

Slide 50 text

コンテナオーケストレーションの⽬的 • ⾃動化による管理コスト削減 • コンテナのライフサイクルを⾃動化し、⼿間とコストを削減する • コンテナ環境の⾼い可⽤性を維持 • コンテナやノードの障害発⽣時に、アプリケーションの継続的な稼働を可能にす る • コンテナ同⼠の接続 • 複数のコンテナが協調して動作するために必要なネットワークを⾃動的に設定 し、コンテナ同⼠が安全かつ効率的に通信できるようにする IBUFOBJOUFSO !"

Slide 51

Slide 51 text

コンテナオーケストレーションツールが持つ 主な機能 • コンテナ配置のスケジューリング • コンテナをどのノードに配置するか • 負荷分散/サービスディスカバリー • クラスタ内のコンテナ間の負荷分散 • セルフヒーリング/ヘルスチェック • コンテナのヘルスチェックと問題発⽣時への⾃動復旧 • オートスケーリング • 負荷に応じたコンテナのスケールイン‧アウト IBUFOBJOUFSO !"

Slide 52

Slide 52 text

コンテナ配置のスケジューリング • コンテナの起動数を指定し、その数だけコンテナを⽴てる • システムの負荷やコンテナの起動条件をみて、どのマシンにコ ンテナを⽴てるかを⾃動で選択する • フィルターとスコアリング IBUFOBJOUFSO !"

Slide 53

Slide 53 text

負荷分散/サービスディスカバリー • 複数のコンテナに負荷を分散して可⽤性を⾼める • サービスディスカバリー • 動的にコンテナが⼊れ替わるクラスター内で特定のコンテナ を⾒つけて通信するための仕組み • コンテナは⽣存期間が⽐較的短く、IPアドレスも頻繁に変わ る IBUFOBJOUFSO !"

Slide 54

Slide 54 text

セルフヒーリング • マシンに障害が発⽣した場合 • 正常なマシンにコンテナを配置し直す • コンテナに障害が発⽣した場合 • 必要な分だけコンテナを⽴て直す • コンテナ障害を検知するためのヘルスチェック IBUFOBJOUFSO !"

Slide 55

Slide 55 text

オートスケーリング 複数のコンテナのスケーリングを、負荷状況に応じて⾃動で⾏う 仕組み • コンテナのスケールイン‧スケールアウト(コンテナ数の増 減) • コンテナのスケールアップ‧スケールダウン(CPUやメモリの 割り当ての増減) IBUFOBJOUFSO !!

Slide 56

Slide 56 text

コンテナオーケストレーションたち • Docker Swarm • Apache Mesos • Kubernetes • Amazon Elastic Container Service(ECS) AWSの優位性をベースにECSも使われているが、商⽤環境(オンプ レ含む)ではKubernetesがデファクトスタンダード IBUFOBJOUFSO !"

Slide 57

Slide 57 text

Kubernetesとは IBUFOBJOUFSO !"

Slide 58

Slide 58 text

Kubernetesとは • Kubernetes, K,s • Googleの内製コンテナ管理ツールBorgをOSS化したもの • OSSになる前からGoogleの⼤規模環境で利⽤されていたので、概念が洗練されていた • パブリッククラウドでサービスが提供されている • Amazon Elastic Kubernetes Service(EKS) • Google Kubernetes Engine (GKE) • Azure Kubernetes Service (AKS) • ⾼い拡張性、エコシステムが充実 • コントローラ作成やAdmission Webhookなど IBUFOBJOUFSO !"

Slide 59

Slide 59 text

Kubernetesで何ができるのか? コンテナオーケストレーションツールとして持つべき機能を⼀通り兼ね備えている • 宣⾔的な構成管理 • コンテナ配置のスケジューリング • 負荷分散/サービスディスカバリー • セルフヒーリング/ヘルスチェック • オートスケーリング ここからはKubernetesの⾔葉でこれらを説明していく IBUFOBJOUFSO !"

Slide 60

Slide 60 text

宣⾔的な構成管理 Kubernetesは宣⾔的な構成管理を実現している • 期待する状態を設定ファイル(Manifest)に記述する • 設定ファイルを適⽤すると、以前の状態に依存せずに宣⾔した状態にな る • 設定ファイルの内容と現状に差分があるかどうかを⾒て、差分があれ ば、その状態にする • Reconciliation Loop IBUFOBJOUFSO !"

Slide 61

Slide 61 text

Kubernetesの構成 IBUFOBJOUFSO !"

Slide 62

Slide 62 text

Cluster 引⽤元: https://kubernetes.io/docs/concepts/overview/components/ IBUFOBJOUFSO !"

Slide 63

Slide 63 text

Cluster • control PlaneとNodeで構成 • control Plane • kube-apiserver • etcd • kube-scheduler • kube-controller-manager • Node • kubeletがkube-apiserverとやり取り • コンテナを実⾏するためのコンピューティングリソースの集まり • Data Planeと⾔ったりもする • 詳細は後述 IBUFOBJOUFSO !"

Slide 64

Slide 64 text

control Plane • Kubernetesの中枢となるコンポーネント • 各クラウドのマネージドサービスでは、まさにマネージドなと ころ • kube-apiserverを介して、各コンポーネントが機能する IBUFOBJOUFSO !"

Slide 65

Slide 65 text

Node • Data Plane • 複数のPod(コンテナの集まり)を実⾏するためのコンピューティングリソー ス • 物理 or 仮想のサーバー • ノードでkubeletが起動し、API Serverとやりとりをする • K`s⾃体にはノードをスケールさせる仕組みはない • サードパーティ(cluster-autoscaler, Karpenter)を利⽤する IBUFOBJOUFSO !"

Slide 66

Slide 66 text

Pod • デプロイの最⼩単位 • Podは1つ以上のコンテナから構成される • ストレージとネットワークを共有する • Network Namespace • Mount Namespace IBUFOBJOUFSO !!

Slide 67

Slide 67 text

複数のコンテナ • Podは1つ以上のコンテナ群 • 1コンテナ1プロセス • ひとつのPodに複数のコンテナ • メインのコンテナとそれを⽀えるコンテ ナ • (例) Proxy, ログ転送, 監視エージェント • 内部的にpauseコンテナが動いていて、 Namespaceの共有などを⾏う • PodのStatusとして⾒えないが、ノードか らは⾒える特殊なコンテナ 引⽤元: https://www.ianlewis.org/en/ almighty-pause-container IBUFOBJOUFSO !"

Slide 68

Slide 68 text

Kubernetesのリソース IBUFOBJOUFSO !"

Slide 69

Slide 69 text

リソースのカテゴリ あまりカテゴリを意識することはないけれど、説明しやすいので、いったん分けて話していきます • Workloads コンテナの実⾏に関するリソース • Service コンテナを外部公開するようなエンドポイントを提供するリソース • Config&Storage 設定‧機密情報‧永続化ボリュームなどに関するリソース • Cluster セキュリティやクォータなどに関するリソース • Metadata クラスタ内の他のリソースを操作するためのリソース Namespaceという仮想的なクラスタの分離機能 IBUFOBJOUFSO !"

Slide 70

Slide 70 text

Workloadsカテゴリ コンテナの実⾏に関するリソース • Pod 1つ以上のコンテナから構成されている Pod内に含まれるコンテナは同じネットワーク内に存在し同⼀IPを持つ コンテナ同⼠はlocalhostで通信可能 • ReplicaSet Podのレプリカを作成して指定した数のPodを維持する 同じコンテナイメージのコンテナが複数がPodが展開される IBUFOBJOUFSO !"

Slide 71

Slide 71 text

Workloadsカテゴリ • Deployment 複数のReplicaSetを管理してローリン グアップデートやロールバックなどを 可能にする Deploymentの機能としてローリング アップデートやロールバックを⾏う この機能があることで、K,sだけでもデ プロイ管理しやすい IBUFOBJOUFSO !"

Slide 72

Slide 72 text

Workloadsカテゴリ • Statefulset Volumeを扱いやすくしたり、Pod名を固定したりして、ステートフルなアプリケー ションを動かしやすくしたリソース • DaemonSet すべてのノードにPodを配置させるためのリソース • Job コンテナを利⽤してワンオフの処理を実⾏させるリソース • CronJob スケジュールされた時間にjobを実⾏するリソース IBUFOBJOUFSO !"

Slide 73

Slide 73 text

Serviceカテゴリ コンテナを外部(クラスタ内外)開するようなエンドポイントを提供するリソース 受信したトラフィックを複数のPodにロードバランシングする • Service • L)ロードバランサ • サービスディスカバリ • Ingress • L;ロードバランサ IBUFOBJOUFSO !"

Slide 74

Slide 74 text

ConfigMap/Secret アプリケーションの設定をリソースとして管理でき、アプリケーションと設定を分離できる • ConfigMap • 機密性のないデータをキーと値のペアで保存する • 環境変数の管理もできる • Secret • ConfigMapと機能はほぼ同じ • 機密性のあるデータをキーと値のペアで保存する • といっても実はただのBaseYZなので、丸⾒えに近い • secretは使わずに、Podにmountさせるのがベストではあるが、やや⼿間 • https://github.com/aws/secrets-store-csi-driver-provider-aws IBUFOBJOUFSO !"

Slide 75

Slide 75 text

Kubernetesクラスタ内の通信 少しServiceまわりを掘り下げていきます • 同じPod内のコンテナに通信する場合はlocalhost宛に通信する • 別のPodに通信する場合はPodのIP宛に通信する • PodのIP宛の通信は可能だがアプリケーションからIPを指定すると実運⽤上で課題が発⽣する • PodのIPはPodが⼊れ替わる度に異なるIPが割り当てられる • Podが停⽌した場合にサービス断が発⽣する • オートスケールなどPodの数が流動的な場合に破綻する これらを解決するのがServiceリソース IBUFOBJOUFSO !"

Slide 76

Slide 76 text

Service ロードバランサ • kube-proxyというコンポーネントの機能 • iptablesで実現している • 他の実装もあるが、デフォルトはiptables • 複数のPodに対するトラフィックのロードバランシング(負荷分散)を⾏う • ロードバランシングの⼊り⼝となるエンドポイントを提供 • エンドポイントには単⼀の仮想IPが割り当てられる • エンドポイントの種類は⽤途によって様々 • ClusterIP (内部向け) • NodePort (外部向け) • LoadBalancer(外部向け) IBUFOBJOUFSO !"

Slide 77

Slide 77 text

Service サービスディスカバリ • 動的にPodが⼊れ替わるクラスター内で情報を登録、発 ⾒するための仕組み • クラスタ内DNSの利⽤が推奨されている • ロードバランシングの⼊り⼝となるエンドポイントがク ラスタ内DNSに⾃動的に登録される • [SERVICE_NAME]. [NAMESPACE].svc.cluster.localという形式で DNS Aレコードに割り当てられる • (例) account.hatena- intern.svc.cluster.local • 同じNamespace内であれば、account、違う Namespaceの場合はaccount.hatena-internで も名前解決できる IBUFOBJOUFSO !!

Slide 78

Slide 78 text

Ingress • Ingress • L)のロードバランサ • Kubernetes⾃体にはIngressの実装がなく、インターフェイスのみ • aws-load-balancer-controller, ingress-nginx, etc • HTTPSの終端として証明書を指定可能 • Secretは証明書も管理でき、それを指定できる IBUFOBJOUFSO !"

Slide 79

Slide 79 text

リソース管理 IBUFOBJOUFSO !"

Slide 80

Slide 80 text

Manifest • リソース定義ファイル • yamlで書くことが多いがjsonでも可能 • kubectl apply -f によってK=sクラスタに適⽤ • コントローラがリソースの状態を⾃律的にマニフェストの内容に 近づける • Reconciliation Loop IBUFOBJOUFSO !"

Slide 81

Slide 81 text

Manifestのサンプル(Deployment) apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 IBUFOBJOUFSO !"

Slide 82

Slide 82 text

Manifestのサンプル(Service) apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 80 IBUFOBJOUFSO !"

Slide 83

Slide 83 text

リソース制限 • Podに対して割り当てるCPUやメモリの制限 を⾏うことができる • cgroup • 要求と制限 • requests(要求)とlimits(制限)を指定でき る • ノードにPodを配置する際に考慮される • requestsの指定がない場合は判断のしよ うがないので、どこかのノードに詰め込ま れる spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" IBUFOBJOUFSO !"

Slide 84

Slide 84 text

ヘルスチェック • Podが正しく動作しているか確認するための仕組み • Liveness Probe • アプリケーションが起動し、コンテナが正しく動作しているかどうか • チェックが通らなかったときはPodを再起動する • Readiness Probe • Podがリクエストを受け付ける準備ができているかどうか • チェックが通らなかったときにはServiceのendpointのリストから当該Podが削除される • Startup Probe • 起動時にしか実⾏されない • Podの起動に時間がかかるような場合に、Liveness Probeの前に実⾏される • Podが正常に起動したことを確認するチェック IBUFOBJOUFSO !"

Slide 85

Slide 85 text

可⽤性と拡張性 IBUFOBJOUFSO !"

Slide 86

Slide 86 text

可⽤性(Availability) • セルフヒーリング • ReplicaSetがコンテナのプロセス監視を⾏う • チェックに失敗するとManifestで設定したレ プリカ数を維持するように働く • Node障害時にもPodを正常なNodeにスケジ ュールし直す IBUFOBJOUFSO !"

Slide 87

Slide 87 text

負荷に対する拡張性(Scalability) • ⽔平オートスケール • Horizontal Pod Autoscaler (HPA) • CPU等のメトリクスを参照してPodのレプリカを⾃動で追加する • 垂直オートスケール • Vertical Pod Autoscaler (VPA) • Kubernetesの内部リソースではなく、個別に対応は必要 • CPU, メモリの使⽤量を分析してリクエスト値を提案したり⾃動的に更新したりする • Kvsの内部リソースではないので注意 IBUFOBJOUFSO !"

Slide 88

Slide 88 text

ハンズオンで利⽤するツール紹介 IBUFOBJOUFSO !!

Slide 89

Slide 89 text

Minikube • ローカル環境でKubernetesのクラスターを⽴ち上げるのにオスス メ https://minikube.sigs.kHs.io/docs/start/ • Kubernetesのバージョンを指定してクラスターを構築できる • 他にもkindといったツールなどでもローカルでクラスター構築が 可能 • kindは軽量なのでCIでも使われる IBUFOBJOUFSO !"

Slide 90

Slide 90 text

Kustomize • https://github.com/kubernetes-sigs/kustomize • K7sのマニフェストの構成をカスタマイズするためのツール • Dev, Stg, Prd等の複数の環境分Manifestを書くのは冗⻑なので、 共通のベースとなるマニフェストを作りつつ環境毎の差分をパッ チファイルとして管理できるようになる • kustomization.yaml にどのマニフェストを使うか、secretや configの設定などを記述する IBUFOBJOUFSO !"

Slide 91

Slide 91 text

Skaffold • https://skaffold.dev/ • ファイルの変更を検知してコンテナイメージのビルド、KHs環 境へ反映するツール • skaffold.yaml に対象となるファイル、dockerイメージ、 マニフェストを記述する IBUFOBJOUFSO !"

Slide 92

Slide 92 text

Kubernetesハンズオン IBUFOBJOUFSO !"

Slide 93

Slide 93 text

アジェンダ • 第1部 Hatena-Intern-./.0環境で遊ぼう • 第2部 記法変換サービスの追加 IBUFOBJOUFSO !"

Slide 94

Slide 94 text

第1部 Hatena-Intern-)*)+環境で遊ぼう IBUFOBJOUFSO !"

Slide 95

Slide 95 text

この時間はハンズオンです • ⼀緒に⼿を動かして⼿元のKubenetes環境を触ってみましょう • codespaces環境を使います IBUFOBJOUFSO !"

Slide 96

Slide 96 text

サービスの構成 IBUFOBJOUFSO !"

Slide 97

Slide 97 text

マニフェストの構成 k8s ├── account │ ├── app.yaml │ ├── config │ │ └── schema.sql │ ├── db.yaml │ ├── kustomization.yaml │ ├── secret │ │ └── ecdsa-private.pem │ └── test.yaml ├── blog │ ├── app.yaml │ ├── config │ │ └── schema.sql │ ├── db.yaml │ ├── kustomization.yaml │ ├── secret │ │ └── account-ecdsa-public.pem │ └── test.yaml ├── kustomization.yaml ├── namespace.yaml ├── renderer-go │ ├── app.yaml │ └── kustomization.yaml └── system └── sa.yaml • k8s ディレクトリがマニフェスト置き場 • account/blog/renderer-goとマイクロサービスごとにディレクト リを分ける • kustomization.yaml がkustomizeの設定ファイル IBUFOBJOUFSO !"

Slide 98

Slide 98 text

k"s/blog/kustomization.yaml apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - app.yaml - db.yaml - test.yaml secretGenerator: - name: blog-app-secret files: - secret/account-ecdsa-public.pem configMapGenerator: - name: blog-app-env-vars literals: - MODE=development - DATABASE_DSN=root@(blog-db:3306)/intern_2025_blog?time_zone=UTC&parseTime=true&loc=UTC - ACCOUNT_ADDR=account:50051 - RENDERER_ADDR=renderer-go:50051 - name: blog-test-env-vars literals: - TEST_DATABASE_DSN=root@(blog-db:3306)/intern_2025_blog_test?time_zone=UTC&parseTime=true&loc=UTC - name: blog-db-schema-config files: - config/schema.sql IBUFOBJOUFSO !"

Slide 99

Slide 99 text

確認 % make up • 8080番ポートは⾃動でポートフォワードされるようになっていますが、ポートフォワードされてい ない場合、別のターミナルを開き、以下のコマンドでポートフォワードできます。 % kubectl port-forward service/blog 8080:8080 # ϩʔΧϧͷ8080ϙʔτ΁ͷ௨৴Λ blog service ͔Βෛՙ෼ࢄ͞Ε͍ͯΔpodͷ8080ϙʔτʹసૹ͢Δ もしくは再度make upしてください。 Podが起動すると、⾃動でブラウザが開くので開いてブログを作成してみましょう。 開かない場合、vscodeのterminalのPORTSタブから8080ポートを追加してあげてください。 IBUFOBJOUFSO !!

Slide 100

Slide 100 text

サービスが起動していることを確認する contextの切り替え % kubectl config use-context hatena-intern-2025 % kubectl get pods IBUFOBJOUFSO !""

Slide 101

Slide 101 text

Podが起動する様⼦を⾒よう • services/blog/templates/index.html を書き換えると Skaffoldが反応するはず 別の端末で実⾏してPodの状態を⾒る % kubectl get pods -w % kubectl describe pods IBUFOBJOUFSO !"!

Slide 102

Slide 102 text

デバッグ # Podͷৄࡉ৘ใͷදࣔɻpod͕ىಈ͠ͳ͍৔߹͸ಛʹ"Events:"ཝʹ஫໨ % kubectl describe pod blog # ωʔϜεϖʔε্ʹ͋ΔϦιʔεͷ৘ใΛදࣔ % kubectl get all # ىಈ͍ͯ͠ΔPodͰγΣϧΛىಈ͢Δ % kubectl exec -it svc/account -c account !" /bin/sh Pod(コンテナ)に⼊ったら - 起動しているプロセスは? ! ps - blogサービスにアクセス ! wget -q -O - blog:8080 - ! nslookup blog IBUFOBJOUFSO !"#

Slide 103

Slide 103 text

第2部 記法変換サービスの追加 IBUFOBJOUFSO !"#

Slide 104

Slide 104 text

記法変換サービス renderer • services/renderer-ts にある実装をK*s上で動かす • デフォルトでは services/renderer-go が動いている • k8s/renderer-go を参考に、k8s/renderer-ts を追加 IBUFOBJOUFSO !"#

Slide 105

Slide 105 text

対応するファイル • 追加するファイル • k8s/renderer-ts/kustomization.yaml • k8s/renderer-ts/app.yaml • 編集するファイル • skaffold.yaml • k8s/kustomization.yaml • k8s/blog/kustomization.yaml IBUFOBJOUFSO !"#

Slide 106

Slide 106 text

ファイルの追加 % cp -R k8s/renderer-go k8s/renderer-ts % sed -i -e 's/renderer-go/renderer-ts/g' k8s/renderer-ts/*.yaml • k8s/renderer-go ディレクトリをコピーして k8s/ renderer-ts を作成 • マニフェスト内の renderer-go を renderer-ts に置き換え IBUFOBJOUFSO !"#

Slide 107

Slide 107 text

skaffoldの編集 skaffold.yaml apiVersion: skaffold/v4beta13 kind: Config metadata: name: hatena-intern-2025 build: artifacts: # (snip) - image: hatena-intern-2025-renderer-go context: services/renderer-go - image: hatena-intern-2025-renderer-ts # ! context: services/renderer-ts # ! local: # (snip) • services/renderer-ts のdockerイメージのビルドとk2sクラスタへの反映がされるようにする IBUFOBJOUFSO !"#

Slide 108

Slide 108 text

マニフェストの編集 k"s/kustomization.yaml apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: hatena-intern-2025 resources: - namespace.yaml - account - blog - renderer-go - renderer-ts # ! IBUFOBJOUFSO !"#

Slide 109

Slide 109 text

マニフェストの編集 k"s/blog/kustomization.yaml apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization # (snip) configMapGenerator: - name: blog-app-env-vars literals: - MODE=development - DATABASE_DSN=root@(blog-db:3306)/intern_2025_blog?time_zone=UTC&parseTime=true&loc=UTC - ACCOUNT_ADDR=account:50051 - RENDERER_ADDR=renderer-ts:50051 # ! - name: blog-test-env-vars # (snip) • blogサービスの記法変換サービスへの向き先をrenderer-goからrenderer-tsに変える IBUFOBJOUFSO !"#

Slide 110

Slide 110 text

Podが正常に起動しない場合 • kubectl get pods を実⾏して各Podが正しく起動している かどうか確認する • kubectl describe pod renderer-ts で詳細情報を確認 • なぜ正常に起動しないか原因を探ろう IBUFOBJOUFSO !!"

Slide 111

Slide 111 text

実際にrenderer-tsが動くことを確認する • kubectl get pods よりすべてのPodが正常に起動しているこ とを確認 • ブログにアクセスし、記事を作成し renderer-ts サービスが 動くことを確認 IBUFOBJOUFSO !!!

Slide 112

Slide 112 text

変更点をpushしておく ここらへんはご⾃由にという感じですが、今回の変更点をコミットしてpushしておき、 いつでもtypescript実装に変更可能にしておくと今後のインターンに便利だと思います。 私はrskmmachang-internfafgっていうブランチでpushしておくので、もし今回のハン ズオンで⼿元でうまく動かなかった⼈がいても、このブランチを参考にすることで今後 のインターンでts使いたくなった時にrenderer-ts化できると思います。 % git switch -c rskmm0chang-intern2025 % git add k8s/ skaffold.yaml % git commit -m'rendererΛtypescript࣮૷ʹมߋ' % git push origin rskmm0chang-intern2025 IBUFOBJOUFSO !!"

Slide 113

Slide 113 text

おまけ1 データベースを覗いてみよう アプリケーション開発に役に⽴つと思います。 % mysql -u root -h 127.0.0.1 -P 3306 intern_2025_blog # ͔ͬͪ͜΋(localhost) % mysql -u root -h localhost -P 3306 intern_2025_blog MySQL [intern_2025_blog]> show tables; +----------------------------+ | Tables_in_intern_2025_blog | +----------------------------+ | blogs | | entries | | sessions | | users | +----------------------------+ MySQL [intern_2025_blog]> select count(*) from blogs; +----------+ | count(*) | +----------+ | 0 | +----------+ IBUFOBJOUFSO !!"

Slide 114

Slide 114 text

おまけ1 接続できない場合、ポートの転送ができていない可能性がありま す。以下のコマンドでポートフォワードしてください # ϙʔτͷసૹ % kubectl port-forward svc/blog-db 3306:3306 IBUFOBJOUFSO !!"

Slide 115

Slide 115 text

おまけ2 今回のアプリケーションはgRPCを採⽤しているけれど、service での通信で適切ですか? serviceで接続することはできるが、それが適切かどうか。 ヒント: serviceはL(ロードバランサ 今回のインターンでは⼤規模な負荷試験はないはずだけど、gRPC のアプリケーションを適切に負荷分散する、となると... IBUFOBJOUFSO !!"