Kubernetes and Cloud Native Associate (KCNA) #4 Container Orchestration (22%): ランタイム、セキュリティ、ネットワーキング、ストレージ、Service Mesh

#3 までが Kubernetes 自体の中核リソースと API だったとすれば、この記事は その Kubernetes の下でコンテナを実際に支える層 です。Pod 内のコンテナがどのランタイムの上で動くのか、ネットワークパケットがどのプラグインを経由するのか、データがどこに保存されるのか、そしてこれらすべてを呼び出す権限を誰が持つのかを扱います。

この層を貫く 1 つの思想が 標準インターフェース です。Kubernetes はランタイム・ネットワーク・ストレージを自前で実装せず、CRI・CNI・CSI という標準の境界だけを定義したうえで、実装をプラグインとして差し替えます。KCNA Container Orchestration ドメインの比重は 22% で、Fundamentals に次いで大きく、この 3 種のインターフェースの区別が試験頻出です。

コンテナランタイム #

コンテナランタイムは イメージを実際のプロセスとして起動し隔離するソフトウェア です。Kubernetes では worker node の kubelet が Pod を起動するとき、コンテナを直接作らず、このランタイムに仕事を任せます。ランタイムは抽象化のレベルによって 2 つの層に分かれます。

高レベルランタイムと低レベルランタイム #

  • 高レベル (high-level) ランタイム。イメージを取得して展開し、ストレージを管理し、コンテナのライフサイクルを扱います。containerdCRI-O が代表的です。kubelet が直接やり取りする相手がこの高レベルランタイムです。
  • 低レベル (low-level) ランタイム。実際に Linux カーネルの namespace と cgroup を設定してプロセスを隔離し実行する最も低い層です。runc が事実上の標準であり、高レベルランタイムが内部的に runc を呼び出します。

まとめると、kubelet が containerd を呼び、containerd が runc を呼んでコンテナプロセスを起動する流れです。containerd が「管理者」、runc が「実行器」の役割を分担すると捉えればよいでしょう。

OCI 標準 #

ランタイムとイメージがばらばらだと互換性が崩れます。これを防ぐ標準が OCI (Open Container Initiative) です。OCI は 2 つの仕様で構成されます。

  • image-spec。コンテナイメージのフォーマット (レイヤー構造、マニフェストなど) を定義します。
  • runtime-spec。展開したイメージをどう実行するか (ファイルシステムバンドル、ライフサイクル) を定義します。

OCI のおかげで、どのツールでビルドしたイメージでも、OCI に従うどのランタイムでも同じように動きます。runc は OCI runtime-spec の参照実装です。

CRI: kubelet とランタイムの境界 #

CRI (Container Runtime Interface) は kubelet とコンテナランタイムの間の標準 gRPC API です。kubelet は CRI という約束されたインターフェースだけでランタイムと対話するので、その後ろに containerd があろうと CRI-O があろうと、kubelet のコードは変わりません。ランタイムを差し替えても Kubernetes が揺らがない理由は、この境界にあります。

初期の Kubernetes は Docker を使うために dockershim という変換層をコアに置いていましたが、標準 CRI ランタイムが定着するにつれ、dockershim は v1.24 で削除されました (dockershim deprecation)。Docker でビルドしたイメージは OCI 標準に従うので、containerd の上でもそのまま問題なく動きます。ビルドツールとランタイムは別物だという点が肝心です。

標準インターフェース 3 種: CRI・CNI・CSI #

このドメインで最も混同しやすい点であり、最も頻出する設問が 3 つのインターフェースの区別 です。3 つとも「Kubernetes が直接実装せずプラグインに委ねる標準の境界」という共通点がありますが、委ねる対象が異なります。

インターフェースフルネーム何をプラグイン化するか代表的な実装
CRIContainer Runtime Interfaceコンテナ ランタイム (実行)containerd、CRI-O
CNIContainer Network InterfacePod ネットワーキング (接続)Calico、Cilium、Flannel
CSIContainer Storage Interface永続 ストレージ (保存)EBS・Ceph などのドライバー

「R は Runtime、N は Network、S は Storage」と略語を解いておけば、選択肢ですぐに見分けがつきます。試験では「Pod に永続ボリュームを付ける標準インターフェースは?」のような設問は CSI を、「ランタイムを交換する標準は?」は CRI を問う形です。

セキュリティ #

RBAC #

RBAC (Role-Based Access Control) は「誰が何をできるか」を定義する権限モデルです。4 種類のリソースが対になります。

  • Role。特定の Namespace 内で許可する動作 (verb) と対象 (resource) をまとめた権限の束です。
  • ClusterRole。クラスター全体のスコープの権限の束です。Namespace に縛られません。
  • RoleBinding / ClusterRoleBinding。Role または ClusterRole を ユーザー・グループ・ServiceAccount に結び付けます。権限の束と主体をつなぐ橋です。

ここで ServiceAccount は、Pod 内で動くプロセスが Kubernetes API を呼び出すときに使う身元です。人間のユーザーではなくワークロードの身元だという点が区別のポイントです。RBAC はホワイトリスト方式なので、明示的に付与していない権限はデフォルトで拒否されます。

NetworkPolicy #

デフォルト状態の Kubernetes は すべての Pod が互いに自由に通信 できます (default allow)。NetworkPolicy はこの平面にファイアウォールルールを重ねて、ingress (入ってくるトラフィック) と egress (出ていくトラフィック) を制限します。

核心となる動作は次のとおりです。ある Pod に NetworkPolicy が 1 つでも適用された瞬間、その Pod はポリシーで明示的に許可されたトラフィックだけを受け取り、残りは遮断されます。つまりポリシーがなければすべて許可、ポリシーが付くと許可リスト以外はすべて遮断に変わります。ただし NetworkPolicy は、これを実際に強制する CNI プラグインが対応していなければ 効果がありません (例: Calico、Cilium)。対応していないプラグインでは、ポリシーを作っても動作しません。

SecurityContext と Pod Security #

SecurityContext は、コンテナや Pod がどの権限で実行されるかを指定します。runAsNonRoot: true でルート実行を防いだり、readOnlyRootFilesystemallowPrivilegeEscalation: false のような設定で権限を狭めたりします。コンテナがホストを脅かさないよう実行権限を最小化する仕組みです。

クラスターレベルでは Pod Security Admission (PSA) がゲートの役割を果たします。Pod が作成されるとき、Pod Security Standards という 3 段階のポリシーに照らして通過の可否を判定します。

  • Privileged。制限なし。信頼されたシステムワークロード向けです。
  • Baseline。既知の権限昇格を防ぐ最小限の制限です。
  • Restricted。ベストプラクティスを強く強制する最も厳格な段階です。

過去の PodSecurityPolicy (PSP) が削除され、その座を Pod Security Admission が引き継いだという流れ程度を知っておけば十分です。

RBAC と NetworkPolicy の実務適用は 実務トラック中級 #7 でマニフェストとともに扱います。

ネットワーキング #

Kubernetes ネットワークモデル #

Kubernetes ネットワーキングの出発点はシンプルなルールです。すべての Pod は NAT なしで互いの IP に直接通信する というものです。つまりすべての Pod が平坦な 1 つのネットワークに属しているように見え、各 Pod は固有の IP を持ちます。このモデルを実際に実装する責任が CNI プラグインにあります。

CNI プラグイン #

CNI (Container Network Interface) は、Pod が作成されるときネットワークインターフェースを付け IP を割り当てる標準です。代表的な実装は次のとおりです。

  • Flannel。シンプルなオーバーレイネットワークです。設定が簡単で軽量です。
  • Calico。NetworkPolicy を強力にサポートし、BGP ルーティングを提供します。
  • Cilium。eBPF ベースで、高性能と精緻なポリシー・観測を提供します。

CNI プラグインの選択と動作原理は 実務トラック上級 #1 でより深く扱います。

Service と kube-proxy #

Pod の IP は Pod が再生成されるたびに変わります。この不安定な IP を覆い隠す安定した接点が Service です。Service は固定の仮想 IP (ClusterIP) と名前を提供し、ラベルセレクターでまとめた Pod の集合へトラフィックを分配します。この分配ルールを各ノードで実際に適用するコンポーネントが kube-proxy です。Service タイプは 3 つを区別しておく必要があります。

タイプ公開範囲用途
ClusterIPクラスター内部専用 (デフォルト)内部サービス間の通信
NodePort各ノードの特定ポートで外部公開簡単な外部アクセス・テスト
LoadBalancerクラウドロードバランサーで外部公開本番環境の外部入口

3 つのタイプは包含関係で理解すると簡単です。NodePort は ClusterIP を含み、LoadBalancer は NodePort を含みます。

CoreDNS とサービスディスカバリ #

Service に名前でアクセスするには、その名前を IP に解決してくれる DNS が必要です。その役割を CoreDNS が担います。クラスター内で動く DNS サーバーで、my-svc.my-namespace.svc.cluster.local のような名前を Service の ClusterIP に変換します。Pod は他のサービスの IP を知らなくても名前だけでたどり着けます。この名前ベースの探索を サービスディスカバリ と呼びます。

Ingress #

Service の LoadBalancer タイプはサービスごとにロードバランサーを 1 つずつ立てる必要があり、コストが大きくなります。Ingress は 1 つの入口で HTTP/HTTPS リクエストをホスト・パスのルールに従って複数の Service へルーティングする L7 層です。ただし Ingress リソースを作るだけでは動作せず、これを解釈して実際のトラフィックを処理する Ingress Controller (例: nginx、Traefik) がクラスターに立っている必要があります。

ストレージ #

ephemeral vs persistent #

コンテナのファイルシステムは、コンテナが消えると一緒に消えます。ストレージは寿命によって 2 つに分かれます。

  • 一時 (ephemeral) ボリューム。Pod の寿命と共にあります。代表例が emptyDir で、Pod が削除されるとデータも消えます。キャッシュやコンテナ間の一時共有に使います。
  • 永続 (persistent) ボリューム。Pod が消えてもデータが残ります。データベースのように状態を守るべきワークロードに必要です。

Volume / PV / PVC / StorageClass #

永続ストレージは 4 つの概念の関係で整理されます。

  • PersistentVolume (PV)。実際の保存領域リソースです。クラスター管理者または動的プロビジョニングが供給します。
  • PersistentVolumeClaim (PVC)。ユーザーが「これだけの保存領域が必要だ」と要求する申請書です。Pod は PVC を通じてボリュームを使います。
  • StorageClass。PV をどの種類・性能で作るかを定義するテンプレートです。動的プロビジョニングの基準になります。

ユーザーは PVC を提出し、その要求が適切な PV にバインドされて Pod にマウントされる流れです。PV・PVC の実務での使用は 実務トラック中級 #2 でマニフェストとともに扱います。

CSI と動的プロビジョニング #

CSI (Container Storage Interface) は外部ストレージシステムを Kubernetes に接続する標準です。クラウドブロックストレージや分散ファイルシステムのベンダーが CSI ドライバーを提供すれば、Kubernetes はこれを通じてボリュームを付けたり外したりします。CSI と StorageClass が噛み合うと 動的プロビジョニング が可能になります。つまり PVC が入ってくると、管理者があらかじめ PV を作っておかなくても、StorageClass の定義に従って PV が自動で生成されバインドされます。

PVC が解放されるとき PV をどう処理するかは reclaim policy が決めます。Delete は実際の保存先まで削除し、Retain はデータを残して手動処理を待ちます。

Service Mesh #

何であり、なぜ使うのか #

マイクロサービスが増えると、サービス間通信で再試行、タイムアウト、暗号化、認証、トラフィック分配、呼び出し追跡といった要求が繰り返されます。これをアプリケーションコードごとに実装すると、言語・チームごとにばらばらになります。Service Mesh は、このサービス間通信の管理を アプリコードの外のインフラ層へ引き出す アプローチです。

sidecar パターン #

伝統的な Service Mesh は sidecar パターン を使います。各 Pod にプロキシコンテナ (例: Envoy) を一緒に付け、その Pod がやり取りするすべてのトラフィックがプロキシを経由するようにします。アプリケーションは通信制御を意識せず、プロキシが集まった データプレーン と、それを統制する コントロールプレーン がメッシュ全体を管理します。代表的な実装に IstioLinkerd があります。

何が得られるのか #

Service Mesh がコードの外で提供する機能は大きく 3 つです。

  • mTLS。サービス間通信を自動で相互認証・暗号化します。
  • トラフィック管理。カナリアデプロイ、重み付けルーティング、再試行・タイムアウトを宣言的に扱います。
  • 観測性。サービス間の呼び出しの指標とトレースを自動で収集します。

KCNA は Service Mesh を 概念レベル でのみ問います。「サービス間通信をアプリの外で sidecar プロキシで管理し、mTLS・トラフィック管理・観測を提供する層」という 1 文と、Istio・Linkerd という名前程度で十分です。

試験ポイント #

  • CRI・CNI・CSI の区別。Runtime・Network・Storage。このドメイン最多出題のパターンです。
  • 高レベル vs 低レベルランタイム。containerd・CRI-O (高レベル) が runc (低レベル) を呼び出します。dockershim は削除され、Docker イメージは OCI 標準なのでそのまま動作します。
  • NetworkPolicy のデフォルト動作。ポリシーがなければすべて許可、ポリシーが付くと明示許可以外は遮断。動作には対応する CNI が必要です。
  • Service タイプ。ClusterIP (内部) ⊂ NodePort (ノードポート) ⊂ LoadBalancer (クラウド)。CoreDNS がサービスディスカバリを担当します。
  • PV・PVC・StorageClass・CSI。ユーザーは PVC で要求し、CSI と StorageClass が動的プロビジョニングを処理します。
  • RBAC の構成要素。Role/ClusterRole + RoleBinding/ClusterRoleBinding + ServiceAccount (ワークロードの身元)。

まとめ #

この記事で押さえたもの:

  • ランタイム。kubelet が CRI で高レベルランタイム (containerd・CRI-O) を呼び、それが低レベルランタイム (runc) を呼び出す。OCI (image-spec・runtime-spec) が互換性を保証
  • インターフェース 3 種。CRI (ランタイム)・CNI (ネットワーク)・CSI (ストレージ) がそれぞれ異なる層をプラグイン化
  • セキュリティ。RBAC (権限)・NetworkPolicy (トラフィック隔離)・SecurityContext と Pod Security Standards (実行権限の制限)
  • ネットワーキング。NAT なしの Pod 通信モデル、CNI プラグイン、Service タイプ (ClusterIP・NodePort・LoadBalancer)、CoreDNS と Ingress
  • ストレージ。一時 (emptyDir) vs 永続 (PV・PVC・StorageClass)、CSI 動的プロビジョニング、reclaim policy
  • Service Mesh。サービス間通信を sidecar プロキシでアプリの外から管理。mTLS・トラフィック管理・観測。Istio・Linkerd

次回: Cloud Native Architecture #

コンテナを支える層まで押さえました。ここからは Kubernetes を超えて クラウドネイティブの設計思想 へ視野を広げます。

#5 Cloud Native Architecture (16%): オートスケーリング、サーバーレス、コミュニティ、オープンスタンダード では、オートスケーリング (HPA・VPA・Cluster Autoscaler)、サーバーレスと FaaS、CNCF コミュニティとプロジェクトの成熟度段階、オープンスタンダードまで整理します。

X