Kubenetesとcgroups

Kubernetesでコンテナのリソースの上限を指定するのに使われるlimitはcgroupを使って実現されています。


      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 100m
            memory: 125Mi
          requests:
            cpu: 90m
            memory: 115Mi

nginxのmasterプロセスのPIDは14611でした。このプロセスのcgroupがどこに定義されているかは、/proc/プロセスID/cgroupを見れば分かります。


cat /proc/14611/cgroup
7:memory:/kubepods/burstable/pod0684166a-df5e-4c54-b489-5b1e3c38dd1d/f66dd3c1e442f0da10aaf0d6954fcafa4d3533da5f3bb597ca7003c66bbb437d
3:cpu,cpuacct:/kubepods/burstable/pod0684166a-df5e-4c54-b489-5b1e3c38dd1d/f66dd3c1e442f0da10aaf0d6954fcafa4d3533da5f3bb597ca7003c66bbb437d

CPU

まずは、CPUから確認していきましょう。cgroupのtasksをみると、nginxのmasterプロセスの14611とworkerプロセスの14656が対象になっています。


# cat /hostroot/sys/fs/cgroup/cpu,cpuacct/kubepods/burstable/pod0684166a-df5e-4c54-b489-5b1e3c38dd1d/f66dd3c1e442f0da10aaf0d6954fcafa4d3533da5f3bb597ca7003c66bbb437d/tasks
14611
14656

limitのcpu: 100mは以下の2つの値で表現されています。

・cpu.cfs_quota_us 10000
・cpu.cfs_period_us 100000

# cat /hostroot/sys/fs/cgroup/cpu,cpuacct/kubepods/burstable/pod0684166a-df5e-4c54-b489-5b1e3c38dd1d/f66dd3c1e442f0da10aaf0d6954fcafa4d3533da5f3bb597ca7003c66bbb437d/cpu.cfs_quota_us
10000
cat /hostroot/sys/fs/cgroup/cpu,cpuacct/kubepods/burstable/pod0684166a-df5e-4c54-b489-5b1e3c38dd1d/f66dd3c1e442f0da10aaf0d6954fcafa4d3533da5f3bb597
ca7003c66bbb437d/cpu.cfs_period_us
100000
6bbb437d/cpu.cfs_period_us
100000

メモリ

次に、メモリを確認します。memory.limit_in_bytesを見てみると131072000と出てきますね。計算すると分かりますが、これは125MBのことです。想定どおり、limitの値が反映されていることが分かります。


# cat /hostroot/sys/fs/cgroup/memory/kubepods/burstable/pod0684166a-df5e-4c54-b489-5b1e3c38dd1d/f66dd3c1e442f0da10aaf0d6954fcafa4d3533da5f3bb597ca700
3c66bbb437d/memory.limit_in_bytes
131072000

KubenetesとCapability

確認したように、User namespaceは分離されていません。したがって、ホストのrootはコンテナのrootと違うものではありません。その状態でコンテナの権限を制限しているのはCapabilityです。nginxのプロセスのCapabilityを確認してみましょう。getcapsコマンドを使います。

nginxのプロセスには、cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcapだけを許可されていることが分かります。


$ nsenter --target 1 --all
$ getpcaps 1
Capabilities for `1': = cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read+ep
$ getpcaps 14611
Capabilities for `14611': = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap+eip

許可されているものの一覧は、以下になります。説明はMan page of CAPABILITIESからの引用です。

Capability 意味
cap_chown ファイルの UID とGID を任意に変更する
cap_dac_override ファイルの読み出し、書き込み、実行の権限チェック(DAC)をバイパスする
cap_fowner プロセスのファイルシステム UID がファイルの UID に一致することが 要求される操作における権限チェックをバイパスする
cap_fsetid ファイルが変更されたときに set-user-ID とset-group-ID の許可ビットをクリア しない
cap_kill シグナルを送信する際に権限チェックをバイパスする
cap_setgid プロセスの GID と追加の GID リストに対する任意の操作を行う
cap_setuid プロセスの UID に対する任意の操作 (setuid(2), setreuid(2), setresuid(2), setfsuid(2)) を行う
lcap_setpcap ファイルケーパビリティがサポートされていない場合: 呼び出し元が許可されているケーパビリティセットに含まれる任意のケーパビリティを他のプロセスに付与したり、削除したりできる
cap_net_bind_service インターネットドメインの特権ポート (ポート番号が 1024 番未満) をバインドできる
cap_net_raw RAW ソケットと PACKET ソケットを使用する
cap_sys_chroot chroot(2). を呼び出す
cap_mknod mknod(2) を使用してスペシャルファイルを作成する
cap_audit_write カーネル監査のログにレコードを書き込む
cap_setfcap ファイルケーパビリティを設定する

今回は、コンテナセキュリティを学ぶ上での基礎となる技術について説明しました。次回は、Kubernetes クラスタの保護について説明します。

著者プロフィール


野村総合研究所(NRI) 湯川勇太(ゆかわ ゆうた)


前職で大手家電量販店のECモールの立ち上げとECサイトの刷新プロジェクトを経験。NRI入社後は製造業の商品検索システムを担当した。現在は大手物流企業向けの基幹システムの方式設計や技術検証、トラブル対応を行っている。