返回列表 发帖

Kata Containers 在 Kubernetes 中的资源开销与限制

概述
Kata Containers 是一个开源项目,它采用轻量化虚拟机作为容器的隔离来构建一个安全容器运行时,而其虚拟化技术作为容器的二层保护为负载提供了更好的隔离性,这使得 Kata Containers 兼具传统容器的形态和虚拟机的安全性。而也正因为虚拟机的存在,在资源的开销与限制与传统容器有所不同。
Overhead
与传统 runC 运行时不同,由于 Kata Containers 本身是一个轻量化的虚拟机,所以在资源开销方面不容忽视,这部分资源主要用于虚拟机的引导启动与 Kata 自身组件的运作。
在 K8s 1.18 版本之后提供了 PodOverhead 的特性,用于描述运行时所带来的额外资源开销。


apiVersion: node.k8s.io/v1beta1
kind: RuntimeClass
metadata:
  name: kata-runtime
handler: kata
overhead:
  podFixed:
    memory: "2048Mi"
    cpu: "1000m"


如上所示,通过?overhead.podFixed?指定额外的 1C,2G 资源,这部分资源可以被 K8s 感知,从而影响到 Pod 调度、resourceQuota 以及 Pod 驱逐等场景。但是,overhead 中声明的额外资源开销仅作用于 K8s 层面,最终会注入到使用对应 runtimeClass 的 Pod 中,并不会对 Kata VM 的大小产生影响。
Pod QoS
overhead 的注入不会影响到 Pod 的 QoS。overhead 中申请的额外资源,会追加到 Pod 的 request 值,从而影响到控制面的调度等场景,如果 Pod 声明了 limit,同样的也会追加到 limit 中。需要注意的是:虽然 overhead 最终会影响到 pod limit 和 request,但是不会影响到 Pod 绑核条件,绑核仍然依据 request 和 limit。


一个申请了 1C 1G 的容器
apiVersion: v1
kind: Pod
metadata:
  name: guaranteed
spec:
  runtimeClassName: kata-runtime
  containers:
    - name: uname
      image: busybox
      command: ["/bin/sh", "-c", "uname -r && tail -f /dev/null"]
      resources:
        requests:
          memory: "1024Mi"
          cpu: "1000m"
        limits:
          memory: "1024Mi"
          cpu: "1000m"


最终的资源消耗为
CPU Requests  CPU Limits  Memory Requests  Memory Limits
2 (4%)        2 (4%)      3072Mi (2%)      3072Mi (2%)
Kata VM
Kata 配置文件中默认的 VM 大小为 1C 2G
default_vcpus = 1
default_memory = 2048


默认情况下,Kata VM 最小资源为 1C 256M,当低于 256M 时,会重置为 2G。
Kata VM 中额外的资源是通过 hotplug 的方式实现,资源目前特指 CPU 和 Memory 两种,Pod request 影响到调度层面的行为,不同于 limit,request 并不会对 Kata VM 的大小产生影响,也就是说最终 VM 的资源大小为 limit + default,其中 limit 为 Pod 声明的 limit,不包含 overhead 在内,default 为Kata 配置文件中的基础 VM 大小。


以上述 guaranteed Pod 为例,可以看到最终的 VM 是一个 2C,3G 的规格大小
bash-5.0# cat /proc/cpuinfo | grep processor | wc -l
2
bash-5.0# free -m
              total        used        free      shared  buff/cache   available
Mem:           3009          38        2941          29          30        2913
Swap:             0           0           0


Cgroup
从 Kubernetes 角度来讲,Cgroup 指的是 Pod Cgroup,由 Kubelet 创建,限制的是 Pod 的资源;
从 Container 角度来讲,Cgroup 指的是 Container Cgroup,由对应的 runtime 创建,限制的是 container 的资源。
但是为了可以获取到更准确的容器资源,Kubelet 会根据 Container Cgroup 去调整 Pod Cgroup。在传统的 runtime 中,两者没有太大的区别。而 Kata Containers 引入 VM 的概念,所以针对这种情况有两种处理方式:
启用 SandboxCgroupOnly,Kubelet 在调整 Pod Cgroup 的大小时,会将 sandbox 的开销统计进去
禁用 SandboxCgroupOnly,sandbox 的开销和 Pod Cgroup 分开计算,独立存在
从 host 视角来看,在 Kata 没有开启 SandboxCgroupOnly 的时候,存在有两个容器(infra 和 workload)的 Cgroup 策略文件,结构模式类似于 runC,但是并没有找到有关限制进程信息的 task 文件。
从 container 视角看,无论是哪种运行时,Cgroup均为 Pod 工作负载的最大资源限量。
从 VM 视角看,无论是否开启 SandboxCgroupOnly,都可以看到有两个容器(infra 和 workload)的 Cgroup 策略文件,VM 中的 Cgroup 都是针对工作负载做的限制,而这个视图更像是 runC 中看到的一切。
示例
Kata 配置中的基础 VM 大小为 5C 2G
default_vcpus = 5
default_memory = 2048


runtimeClass 中声明了一个额外的 1C




apiVersion: node.k8s.io/v1beta1
kind: RuntimeClass
metadata:
  name: kata-runtime
handler: kata
overhead:
  podFixed:
    memory: "1000Mi"
    cpu: "1000m"


声明了一个最大 2C 的业务容器


apiVersion: v1
kind: Pod
metadata:
  name: guaranteed
spec:
  runtimeClassName: kata-runtime
  containers:
    - name: uname
      image: busybox
      command: ["/bin/sh", "-c", "uname -r && tail -f /dev/null"]
      resources:
        requests:
          memory: "1000Mi"
          cpu: "2"
        limits:
          memory: "1000Mi"
          cpu: "2"


根据以上结论应存在:
1C 的额外资源会作用于 Kata Containers 的额外开销,而不是业务负载
2C 的容器资源为容器能够使用的最大使用上限
overhead 的 1C + Pod 的 2C 一共的 3C为 VM 的最大使用量
VM 中 CPU 的个数应为 7


查看 Pod 的资源限制
# kubectl describe node | grep guaranteed
CPU Requests  CPU Limits  Memory Requests  Memory Limits
3 (6%)        3 (6%)      2000Mi (1%)      2000Mi (1%)  


Pod 中运行高负载应用
在 host 上可以看到,进程占用了 2C,而并非上一步看到的3C
PID   USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
28239 root      20   0 3948324 192908 177888 S 197.7  0.1   0:21.27 qemu-system-x86


VM 中运行高负载应用
在 host 上可以看到,这次进程占用了 3C
PID   USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
28239 root      20   0 3948324 195244 180212 S 298.3  0.1   8:43.44 qemu-system-x86


也就是说,Pod limit 最终作用的对象就是业务容器的资源限制,而 overhead 作用的对象是附加在业务容器之上的,两者之和是最终 VM 的资源限制。
总结
Kubernetes 在用 Kata Containers 作为底层 runtime 后,对于 runtime 运行环境的额外开销不容忽视,但是 K8s 角度又无法感知到这部分资源,而 overhead 的设计就弥补了这一缺陷,并且 overhead 对于资源的额外声明,是会统计在 Cgroup 中的,所以即使底层 Kata Containers 的配置即使很高,也可以通过 limit 实现资源限额,这是因为 Kata 对于资源并不是完全占用,不同的 Kata VM 之间会存在资源抢占现象。在此方面,Kata Containers 和传统容器的设计理念相同。

返回列表