为安全容器配置资源

安全容器运行于虚拟化隔离的轻量级虚拟机内,因此资源的配置应分为两部分:对轻量级虚拟机的资源配置,即Host资源配置;对虚拟机内容器的配置,即Guest容器资源配置。以下资源配置均分为这两部分。

资源共享-27

由于安全容器运行于虚拟化隔离的轻量虚拟机内,故无法访问Host上某些namespace下的资源,因此启动时不支持–net host,–ipc host,–pid host,–uts host。

当启动一个Pod时,同一个Pod中的所有容器默认共享同一个net namespace和ipc namespace。如果同一个Pod中的容器需要共享pid namespace,则可以通过Kubernetes进行配置,Kubernetes 1.11版本该值为默认关闭。

限制CPU资源

  1. 配置轻量级虚拟机CPU运行资源

    对轻量级虚拟机的CPU资源配置即虚拟机运行的vcpu配置,安全容器使用–annotation com.github.containers.virtcontainers.sandbox_cpu配置轻量级虚拟机运行CPU资源,该参数仅可配置在pause容器上:

    1. docker run -tid --runtime kata-runtime --network none --annotation io.kubernetes.docker.type=podsandbox --annotation com.github.containers.virtcontainers.sandbox_cpu=<cpu-nums> <pause-image> <command>

    举例:

    1. # 启动一个pause容器
    2. docker run -tid --runtime kata-runtime --network none --annotation io.kubernetes.docker.type=podsandbox --annotation com.github.containers.virtcontainers.sandbox_cpu=4 busybox sleep 999999
    3. be3255a3f66a35508efe419bc52eccd3b000032b9d8c9c62df611d5bdc115954
    4. # 进入容器查看CPU信息,查看CPU个数是否与com.github.containers.virtcontainers.sandbox_cpu配置的CPU个数相等
    5. docker exec be32 lscpu
    6. Architecture: aarch64
    7. Byte Order: Little Endian
    8. CPU(s): 4
    9. On-line CPU(s) list: 0-3
    10. Thread(s) per core: 1
    11. Core(s) per socket: 1
    12. Socket(s): 4

    为安全容器配置资源 - 图1 说明:
    CPU个数可以设置的最大值为当前OS上可供运行的CPU值(除去隔离核),最小值为0.5个CPU。

  2. 配置容器CPU运行资源

    配置容器CPU运行资源与开源docker容器配置CPU运行资源的方式相同,可以通过docker run命令中CPU资源限制相关的参数进行配置:

    参数

    含义

    –cpu-shares

    设置容器能使用的CPU时间比例。

    –cpus

    设置容器可以使用的 CPU 个数。

    –cpu-period

    设置容器进程的调度周期。

    –cpu-quota

    设置每个容器进程调度周期内能够使用的CPU时间。

    –cpuset-cpus

    设置容器进程可以使用的CPU列表。

    说明:

    安全容器使用 –cpuset-cpus 参数绑定CPU时,CPU的编号不能超过安全容器对应的轻量级虚机中CPU的个数减1(轻量级虚机中CPU的编号从0开始)。

    –cpuset-mems

    设定该容器进程可以访问的内存节点。

    说明:

    安全容器不支持多NUMA架构和配置,使用NUMA memory的–cpuset-mems参数只能配置为0。

  3. 配置CPU热插拔功能

    为安全容器配置资源 - 图2 说明:
    安全容器CPU热插拔功能需要虚拟化组件qemu支持CPU热插拔。

    kata-runtime配置文件config.toml中enable_cpu_memory_hotplug选项负责开启和禁用CPU和内存热插拔。默认取值为false,表示禁用CPU和内存热插拔功能;取值为true,表示开启CPU和内存热插拔功能。

    kata-runtime中复用了–cpus选项实现了CPU热插拔的功能,通过统计Pod中所有容器的–cpus选项的和,然后确定需要热插多少个CPU到轻量级虚机中。

    举例:

    1. # 启动一个pause容器,轻量级虚机默认分配了1个vcpu
    2. docker run -tid --runtime kata-runtime --network none --annotation io.kubernetes.docker.type=podsandbox busybox sleep 999999
    3. 77b40fb72f63b11dd3fcab2f6dabfc7768295fced042af8c7ad9c0286b17d24f
    4. # 查看启动完pause容器后轻量级虚机中CPU个数
    5. docker exec 77b40fb72f6 lscpu
    6. Architecture: x86_64
    7. CPU op-mode(s): 32-bit, 64-bit
    8. Byte Order: Little Endian
    9. CPU(s): 1
    10. On-line CPU(s) list: 0
    11. Thread(s) per core: 1
    12. Core(s) per socket: 1
    13. Socket(s): 1
    14. # 在同一个Pod中启动新的容器并通过--cpus设置容器需要的CPU数量为4
    15. docker run -tid --runtime kata-runtime --network none --cpus 4 --annotation io.kubernetes.docker.type=container --annotation io.kubernetes.sandbox.id=77b40fb72f63b11dd3fcab2f6dabfc7768295fced042af8c7ad9c0286b17d24f busybox sleep 999999
    16. 7234d666851d43cbdc41da356bf62488b89cd826361bb71d585a049b6cedafd3
    17. # 查看当前轻量级虚机中CPU的个数
    18. docker exec 7234d6668 lscpu
    19. Architecture: x86_64
    20. CPU op-mode(s): 32-bit, 64-bit
    21. Byte Order: Little Endian
    22. CPU(s): 4
    23. On-line CPU(s) list: 0-3
    24. Thread(s) per core: 1
    25. Core(s) per socket: 1
    26. Socket(s): 4
    27. # 删除热插了CPU的容器后,查看轻量级虚机中CPU的个数
    28. docker rm -f 7234d666851d
    29. 7234d666851d
    30. docker exec 77b40fb72f6 lscpu
    31. Architecture: x86_64
    32. CPU op-mode(s): 32-bit, 64-bit
    33. Byte Order: Little Endian
    34. CPU(s): 1
    35. On-line CPU(s) list: 0
    36. Thread(s) per core: 1
    37. Core(s) per socket: 1
    38. Socket(s): 1

    为安全容器配置资源 - 图3 说明:
    由于pause容器只是一个占位容器没有工作负载,所以轻量级虚机启动时默认分配的1个CPU可以被其它容器共享,因此上面例子中启动的新容器只需要再热插3个CPU到轻量级虚机中即可。

    • 当停止热插了CPU的容器后,启动容器时热插进去的CPU也会被拔出。

限制内存资源

  1. 配置轻量级虚拟机MEM运行资源

    对轻量级虚拟机的MEM资源配置即虚拟机运行的内存进行配置,安全容器使用–annotation com.github.containers.virtcontainers.sandbox_mem配置轻量级虚拟机运行MEM资源,该参数仅可配置在pause容器上:

    1. docker run -tid --runtime kata-runtime --network none --annotation io.kubernetes.docker.type=podsandbox --annotation com.github.containers.virtcontainers.sandbox_mem=<memory-size> <pause-image> <command>

    举例:

    1. # 启动一个pause容器,通过--annotation com.github.containers.virtcontainers.sandbox_mem=4G为轻量级虚机分配4G内存
    2. docker run -tid --runtime kata-runtime --network none --annotation io.kubernetes.docker.type=podsandbox --annotation com.github.containers.virtcontainers.sandbox_mem=4G busybox sleep 999999
    3. 1532c3e59e7a45cd6b419aa1db07dd0069b0cdd93097f8944177a25e457e4297
    4. # 查看轻量级虚机中内存信息,查看内存大小是否与com.github.containers.virtcontainers.sandbox_mem配置的内存大小相等
    5. docker exec 1532c3e free -m
    6. total used free shared buff/cache available
    7. Mem: 3950 20 3874 41 55 3858
    8. Swap: 0 0 0

    为安全容器配置资源 - 图4 说明:
    - 如果没有通过–annotation com.github.containers.virtcontainers.sandbox_mem显示地设置轻量级虚机的内存大小,则轻量级虚机默认使用的内存大小为1GB。
    - 安全容器一个Pod的最小内存规格是1GB,支持的最大内存规格是256GB。如果用户分配的内存规格超过256GB,可能会出现未定义的错误,安全容器暂不支持超过256GB的大内存场景。

  2. 配置容器MEM运行资源

    配置容器MEM运行资源与开源docker容器配置MEM运行资源的方式相同,可以通过docker run命令中MEM资源限制相关的参数进行配置:

    参数

    含义

    -m/–memory

    设置容器进程可以使用的内存大小。

    说明:
    • 当内存热插拔开关关闭时,-m的取值要小于等于轻量级虚机启动时分配的内存大小。
  3. 配置MEM热插功能

    同配置CPU热插拔功能一样,MEM的热插功能也是由kata-runtime配置文件config.toml中enable_cpu_memory_hotplug选项配置,用法参见3

    为安全容器配置资源 - 图5 说明:
    内存资源当前只支持热插,不支持内存热拔。

    kata-runtime中复用了-m选项实现了MEM热插的功能,通过统计Pod中所有容器的-m选项的和,然后确定需要热插多少内存到轻量级虚机中,例如,

    举例:

    1. # 启动一个pause容器,轻量级虚机默认分配了1GB内存
    2. docker run -tid --runtime kata-runtime --network none --annotation io.kubernetes.docker.type=podsandbox busybox sleep 999999
    3. 99b78508ada3fa7dcbac457bb0f6e3784e64e7f7131809344c5496957931119f
    4. # 查看启动完pause容器后轻量级虚机中的内存大小
    5. docker exec 99b78508ada free -m
    6. total used free shared buff/cache available
    7. Mem: 983 18 914 36 50 908
    8. Swap: 0 0 0
    9. # 在同一个Pod中启动新的容器并通过-m设置容器需要的内存大小为4G
    10. docker run -tid --runtime kata-runtime --network none -m 4G --annotation io.kubernetes.docker.type=container --annotation io.kubernetes.sandbox.id=99b78508ada3fa7dcbac457bb0f6e3784e64e7f7131809344c5496957931119f busybox sleep 999999
    11. c49461745a712b2ef3127fdf43b2cbb034b7614e6060b13db12b7a5ff3c830c8
    12. # 查看当前轻量级虚机中内存的大小
    13. docker exec c49461745 free -m
    14. total used free shared buff/cache available
    15. Mem: 4055 69 3928 36 57 3891
    16. Swap: 0 0 0
    17. # 删除热插了CPU的容器后,查看轻量级虚机中内存的大小
    18. docker rm -f c49461745
    19. c49461745
    20. # 因为热插的内存暂不支持热拔功能,所以轻量级虚机中在删除热插内存容器之后还是拥有4GB的内存
    21. docker exec 99b78508ada free -m
    22. total used free shared buff/cache available
    23. Mem: 4055 69 3934 36 52 3894
    24. Swap: 0 0 0

    为安全容器配置资源 - 图6 说明:
    由于pause容器只是一个占位容器没有工作负载,所以轻量级虚机启动时分配的内存可以被其它容器共享使用,因此上面例子中启动的新容器只需要再热插3GB的内存到轻量级虚机中即可。

限制Blkio资源

  1. 配置轻量级虚拟机Blkio运行资源

    对轻量级虚拟机的BlkIio资源配置,安全容器使用–annotation com.github.containers.virtcontainers.blkio_cgroup配置轻量级虚拟机使用的块设备的blkio资源,该参数仅可配置在pause容器上:

    1. docker run -tid --runtime --network none --annotation io.kubernetes.docker.type=podsandbox --annotation com.github.containers.virtcontainers.blkio_cgroup=<blkio json格式字符串> <pause-image> <command>

    其中–annotation com.github.containers.virtcontainers.blkio_cgroup的取值要符合下面BlkioCgroup结构体的定义:

    1. // BlkioCgroup for Linux cgroup 'blkio' data exchange
    2. type BlkioCgroup struct {
    3. // Items specifies per cgroup values
    4. Items []BlockIOCgroupItem `json:"blkiocgroup,omitempty"`
    5. }
    6. type BlockIOCgroupItem struct {
    7. // Path represent path of blkio device
    8. Path string `json:"path,omitempty"`
    9. // Limits specifies the blkio type and value
    10. Limits []IOLimit `json:"limits,omitempty"`
    11. }
    12. type IOLimit struct {
    13. // Type specifies IO type
    14. Type string `json:"type,omitempty"`
    15. // Value specifies rate or weight value
    16. Value uint64 `json:"value,omitempty"`
    17. }

    IOLimit结构体中Type字段取值列表为:

    1. // BlkioThrottleReadBps is the key to fetch throttle_read_bps
    2. BlkioThrottleReadBps = "throttle_read_bps"
    3. // BlkioThrottleWriteBps is the key to fetch throttle_write_bps
    4. BlkioThrottleWriteBps = "throttle_write_bps"
    5. // BlkioThrottleReadIOPS is the key to fetch throttle_read_iops
    6. BlkioThrottleReadIOPS = "throttle_read_iops"
    7. // BlkioThrottleWriteIOPS is the key to fetch throttle_write_iops
    8. BlkioThrottleWriteIOPS = "throttle_write_iops"
    9. // BlkioWeight is the key to fetch blkio_weight
    10. BlkioWeight = "blkio_weight"
    11. // BlkioLeafWeight is the key to fetch blkio_leaf_weight
    12. BlkioLeafWeight = "blkio_leaf_weight"

    举例:

    1. docker run -tid --runtime kata-runtime --network none --annotation com.github.containers.virtcontainers.blkio_cgroup='{"blkiocgroup":[{"path":"/dev/sda","limits":[{"type":"throttle_read_bps","value":400},{"type":"throttle_write_bps","value":400},{"type":"throttle_read_iops","value":700},{"type":"throttle_write_iops","value":699}]},{"limits":[{"type":"blkio_weight","value":78}]}]}' busybox sleep 999999

    上面命令表示对启动的安全容器所使用的/dev/sda磁盘进行blkio限流,分别将throttle_read_bps限速为400bps,throttle_write_bps限速为400bps,throttle_read_iops限速为700次/秒,throttle_write_iops限速为699次/秒,以及所在blkio cgroup组的权重值设置为78。

限制文件描述符资源

为了避免在容器中打开大量9p共享目录中的文件导致主机上文件描述符资源耗尽,使得安全容器无法正常提供服务,安全容器支持自定义配置安全容器qemu进程最多可以打开的文件描述符数量限制。

安全容器通过复用docker run命令中的–files-limit选项来设置安全容器qemu进程最多可以打开文件描述符,该参数仅可配置在pause容器上,使用方法如下所示:

  1. docker run -tid --runtime kata-runtime --network none --annotation io.kubernetes.docker.type=podsandbox --files-limit <max-open-files> <pause-image> bash

为安全容器配置资源 - 图7 说明:
- 如果–files-limit选项的取值小于安全容器默认设置的最小值1024且不为0时,安全容器qemu进程最多可以打开的文件描述符数量会被设置为最小值1024。
- 如果–files-limit选项的取值为0时,安全容器qemu进程最多可以打开的文件描述符数量为系统可以打开文件描述符的最大值/proc/sys/fs/file-max除以400后得到的默认值。
- 如果启动安全容器时没有显示指定–files-limit可以打开的文件描述符的上限,安全容器qemu进程可以打开的文件描述符数量的上限和系统默认值保持一致。