Kubeneresと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
メモリ
次に、メモリを確認します。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
Kubeneresと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からの引用です。
許可されているものの一覧は、以下になります。説明は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_kil | シグナルを送信する際に権限チェックをバイパスする |
cap_setgid | プロセスの GID と追加の GID リストに対する任意の操作を行う |
cap_setuid | プロセスの UID に対する任意の操作 (setuid(2), setreuid(2), setresuid(2), setfsuid(2)) を行う |
cap_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入社後は製造業の商品検索システムを担当した。現在は大手物流企業向けの基幹システムの方式設計や技術検証、トラブル対応を行っている。