Skip to content
Published on

[containerd] ネットワーキングとストレージ

Authors

containerdネットワーキングとストレージ

containerdはネットワーキングとストレージを直接実装せず、標準インターフェースを通じて外部プラグインと統合します。この記事ではCNIによるネットワーク構成、ネームスペース管理、ボリュームマウント、デバイスアクセス、セキュリティモジュール統合を分析します。


1. CNI統合

1.1 CNI概要

Container Network Interface(CNI)はコンテナネットワーキングの標準インターフェースです。containerdはCNIプラグインを呼び出してネットワークを構成します。

CNI呼び出しフロー:

kubelet -> containerd(CRI RunPodSandbox)
                |
                v
        ネットワークネームスペース作成
                |
                v
        CNIプラグイン呼び出し
        (ADDコマンド)
                |
                v
        IP割り当て、ルーティング設定、インターフェース作成
                |
                v
        結果をcontainerdに返す

1.2 CNI設定

CNI設定ファイル位置:
  設定ディレクトリ:/etc/cni/net.d/
  バイナリディレクトリ:/opt/cni/bin/

containerd CNI設定(config.toml):
  [plugins."io.containerd.grpc.v1.cri".cni]
    bin_dir = "/opt/cni/bin"
    conf_dir = "/etc/cni/net.d"
    max_conf_num = 1

1.3 CNIプラグインチェーン

CNI設定例(10-calico.conflist):

ネットワーク構成はプラグインチェーンで定義:

1. メインプラグイン(calico、cilium、flannelなど):
   - ネットワークインターフェース作成
   - IP割り当て(IPAM)
   - ルーティングルール設定

2. メタプラグイン(bandwidth、portmapなど):
   - 帯域幅制限
   - ポートマッピング
   - ファイアウォールルール

実行順序:
  ADD:メイン -> メタプラグイン(順方向)
  DEL:メタ -> メインプラグイン(逆方向)

1.4 CNI呼び出し詳細

CNI ADD実行詳細:

1. containerdがネットワークネームスペースパスを決定
   /var/run/netns/cni-abc123

2. CNI環境変数設定:
   CNI_COMMAND=ADD
   CNI_CONTAINERID=abc123
   CNI_NETNS=/var/run/netns/cni-abc123
   CNI_IFNAME=eth0
   CNI_PATH=/opt/cni/bin

3. CNIプラグインバイナリ実行
   stdinで設定JSONを渡す

4. プラグインがstdoutで結果を返す:
   - 割り当てられたIPアドレス
   - ゲートウェイアドレス
   - DNS設定
   - ルーティング情報

5. containerdが結果を保存

2. ネットワークネームスペース

2.1 ネームスペース作成

Podネットワークネームスペース:

Pod Sandbox作成時:
1. unshare(CLONE_NEWNET)で新しいネットワークネームスペース作成
2. /var/run/netns/にバインドマウントで永続化
3. そのネームスペースでCNIプラグイン実行
4. PodのすべてのコンテナがこのネームスペースをShare

ネームスペース共有:
  PauseコンテナがネットワークネームスペースをProperty
  Appコンテナが同じネームスペースに参加
  -> Pod内コンテナがlocalhostで通信可能

2.2 ネームスペースクリーンアップ

ネームスペースクリーンアップ:

Pod削除時:
1. CNI DELコマンドでネットワークリソース解放
   - IPアドレス返却
   - インターフェース削除
   - ルーティングルール削除
2. /var/run/netns/のバインドマウント解除
3. ネットワークネームスペース自動削除

3. ボリュームマウント

3.1 マウントタイプ

containerdはOCIスペックのマウント構成を通じてボリュームを管理します:

マウントタイプ:

1. bindマウント:
   - ホストファイル/ディレクトリをコンテナにマウント
   - ホストとコンテナが同一データを共有
   - ConfigMap、Secret、emptyDirなどに使用

2. tmpfsマウント:
   - メモリベースのファイルシステム
   - コンテナ終了時にデータ消滅
   - /dev/shm、/runなどに使用

3. 特殊ファイルシステム:
   - proc:/proc
   - sysfs:/sys
   - cgroup:/sys/fs/cgroup
   - devpts:/dev/pts

3.2 マウント伝播

マウント伝播(Propagation)オプション:

1. private:
   - マウントイベント伝播なし
   - デフォルト

2. rprivate:
   - 再帰的private

3. shared:
   - マウントイベントを双方向伝播
   - ホストでマウント -> コンテナでも見える
   - コンテナでマウント -> ホストでも見える

4. rshared:
   - 再帰的shared

5. slave:
   - ホスト -> コンテナ片方向伝播
   - ボリュームプラグインに有用

6. rslave:
   - 再帰的slave

Kubernetesでの使用:
  - MountPropagationフィールドで制御
  - CSIドライバーは主にBidirectional(shared)を使用

3.3 CRIボリューム処理

CRIによるボリューム処理:

kubeletがOCIスペックにマウントを追加:

1. emptyDir:
   - kubeletがホストにディレクトリ作成
   - bindマウントでコンテナに渡す

2. hostPath:
   - ホストパスを直接bindマウント

3. ConfigMap/Secret:
   - kubeletがtmpfsにデータ作成
   - bindマウントでコンテナに渡す

4. PersistentVolumeClaim:
   - kubeletがCSIドライバーでボリュームマウント
   - マウントされたパスをbindマウントで渡す

containerdの役割:
  - kubeletが準備したマウント情報をOCIスペックに反映
  - runcが実際のマウントを実行

4. デバイスアクセス

4.1 デバイスマッピング

デバイスアクセスメカニズム:

OCIスペックのdevicesセクション:
  linux:
    devices:
      - path: "/dev/nvidia0"
        type: "c"
        major: 195
        minor: 0
        fileMode: 438
        uid: 0
        gid: 0

cgroupデバイスアクセス制御:
  linux:
    resources:
      devices:
        - allow: true
          type: "c"
          major: 195
          access: "rwm"

4.2 GPUサポート

GPUアクセス(NVIDIA):

NVIDIA Container Toolkit統合:

1. nvidia-container-runtime-hook:
   - OCIランタイムフックとして動作
   - コンテナ起動前に実行
   - NVIDIAドライバーライブラリをコンテナにマウント
   - GPUデバイスノードをコンテナに追加

2. CDI(Container Device Interface):
   - デバイスベンダー中立的標準
   - /etc/cdi/にデバイススペック定義
   - containerdがCDIスペックを読んでOCIスペックに反映

CDIスペック例:
  cdiVersion: "0.5.0"
  kind: "nvidia.com/gpu"
  devices:
    - name: "0"
      containerEdits:
        deviceNodes:
          - path: "/dev/nvidia0"
        mounts:
          - hostPath: "/usr/lib/x86_64-linux-gnu/libnvidia-ml.so"
            containerPath: "/usr/lib/x86_64-linux-gnu/libnvidia-ml.so"

4.3 その他のデバイス

その他のデバイスアクセス:

1. FPGA:
   - CDIスペックでFPGAデバイスを公開
   - ベンダー別デバイスプラグイン

2. InfiniBand/RDMA:
   - /dev/infiniband/*デバイスマッピング
   - ネットワークデバイスネームスペース共有

3. シリアル/USB:
   - ホストデバイス直接マッピング
   - privilegedモードまたは明示的デバイス許可

5. SELinux統合

5.1 SELinuxコンテキスト

SELinuxコンテナセキュリティ:

OCIスペックのSELinux設定:
  linux:
    mountLabel: "system_u:object_r:container_file_t:s0:c1,c2"
    processLabel: "system_u:system_r:container_t:s0:c1,c2"

構成要素:
  - user:system_u
  - role:system_r(プロセス)/ object_r(ファイル)
  - type:container_t(プロセス)/ container_file_t(ファイル)
  - level:s0:c1,c2(MCSカテゴリ)

MCS(Multi-Category Security):
  - 各コンテナに一意のカテゴリを割り当て
  - 他のコンテナのファイルにアクセス不可
  - ホストとコンテナ間の分離

5.2 SELinux処理フロー

SELinux適用:

1. kubeletがPodのSELinuxオプションを決定
   - securityContext.seLinuxOptions
   - 自動MCSラベル割り当て

2. CRIを通じてcontainerdに伝達
   - processLabel:プロセスセキュリティコンテキスト
   - mountLabel:ファイルセキュリティコンテキスト

3. containerdがOCIスペックに反映

4. runcが実行時に:
   - プロセスにSELinuxラベル適用
   - rootfsにSELinuxラベル適用
   - マウントにSELinuxラベル適用

6. AppArmor統合

6.1 AppArmorプロファイル

AppArmorコンテナセキュリティ:

デフォルトプロファイル:cri-containerd.apparmor.d

主要ルール:
  - ファイルシステムアクセス制限
    deny /proc/kcore r,
    deny /sys/firmware/** r,
  - ネットワークアクセス制御
  - 能力(capability)制限
  - マウント操作制限

プロファイル適用:
  OCIスペック:
    process:
      apparmorProfile: "cri-containerd.apparmor.d"

6.2 カスタムプロファイル

カスタムAppArmorプロファイル:

1. ホストにプロファイルインストール:
   /etc/apparmor.d/にプロファイルファイル配置
   apparmor_parser -r /etc/apparmor.d/my-profile

2. Podで指定:
   annotations:
     container.apparmor.security.beta.kubernetes.io/app: localhost/my-profile

3. containerdがOCIスペックに反映:
   process:
     apparmorProfile: "my-profile"

7. Seccomp統合

7.1 Seccompプロファイル

Seccomp(Secure Computing):

許可/ブロックするシステムコールを定義:

デフォルトアクション:SCMP_ACT_ERRNO(拒否)

許可システムコール例:
  - read、write、open、close
  - mmap、mprotect、munmap
  - socket、connect、accept
  - ...

ブロックシステムコール例:
  - mount、umount(コンテナ脱出防止)
  - reboot
  - kexec_load
  - ptrace(一部環境)

7.2 Seccomp適用

Seccompプロファイル適用:

1. Kubernetes SecurityContext:
   securityContext:
     seccompProfile:
       type: RuntimeDefault

2. RuntimeDefaultプロファイル:
   - containerd/runcデフォルトSeccompプロファイル
   - 危険なシステムコールをブロック
   - 大半のワークロードに適合

3. カスタムプロファイル:
   securityContext:
     seccompProfile:
       type: Localhost
       localhostProfile: "profiles/my-seccomp.json"

8. まとめ

containerdのネットワーキングとストレージは標準インターフェースによる委譲モデルに従います。CNIによるネットワーク構成、OCIスペックによるマウント管理、CDIによるデバイスアクセス、SELinux/AppArmor/Seccompによるセキュリティ分離が核心です。この標準ベースの設計によりcontainerdは多様なネットワーキングソリューションとセキュリティモジュールを柔軟に統合します。