资源概念

CGroup 里对于 CPU 资源的单位换算(m 表示毫核):

  • 1 CPU = 1000 millicpu(1 Core = 1000m)
  • 0.5 CPU = 500 millicpu (0.5 Core = 500m)

spec.containers[].resources.limits.cpu #CPU 上限值,可以短暂超过,容器也不会被停止
spec.containers[].resources.requests.cpu #CPU 请求值,Kubernetes 调度算法里的依据值,可以超过

CPU 可分配的是使用时间(即操作系统管理的时间片);而对于内存,系统提供的是内存大小。

CPU 的使用时间是可压缩的,它本身无状态,申请资源快,能快速正常回收;而内存大小是不可压缩的,因为它是有状态的(内存里保存的数据),申请资源慢(需要计算和分配内存块的空间),且回收可能失败(被占用的内存一般不可回收)。

因此会认为CPU是可压缩资源,内存是不可压缩资源

在资源不足场景下,可压缩资源和不可压缩资源表现不同:

  • 对于不可压缩资源,当内存资源不足时,无法继续申请资源,会导致应用运行产生错误;
  • 对于可压缩资源,比如 CPU 时间片,当 CPU 资源不足时,应用性能会下降,但不影响程序的逻辑。

示例说明

示例配置(pod-resource-demo1.yaml)

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: resource-demo1
  5. spec:
  6. containers:
  7. - name: resource-demo1
  8. image: nginx
  9. ports:
  10. - containerPort: 80
  11. resources:
  12. requests:
  13. memory: 50Mi
  14. cpu: 50m
  15. limits:
  16. memory: 100Mi
  17. cpu: 100m

CPU 50m,即 0.05core,也就是占了 1 CPU 里 5% 的资源时间。限制资源 0.1c 100m,CPU 达到设定上限后,容器性能会下降,不会终止或退出。内存使用资源到达上限,会OOM,造成内存溢出,容器会终止和退出。

# 应用资源
$ kubectl apply -f pod-resource-demo1.yaml

# 查看pod所在节点
$ kubectl get pods -o wide
NAME             READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
resource-demo1   1/1     Running   0          12m   10.244.3.58    k8s-node3   <none>           <none>

# node3节点上查看容器
$ docker ps |grep resource-demo1
c9e654d573fd        nginx                                      "nginx -g 'daemon of…"   14 minutes ago      Up 14 minutes                           k8s_resource-demo1_resource-demo1_default_020bc461-170a-4936-9c22-7c8516972d39_0
37ab54a2490a        gcr.azk8s.cn/google_containers/pause:3.1   "/pause"                 14 minutes ago      Up 14 minutes                           k8s_POD_resource-demo1_default_020bc461-170a-4936-9c22-7c8516972d39_0

# 查看主容器信息
$ docker inspect c9e654d573fd
......
"CpuShares": 51,
"Memory": 104857600,
"NanoCpus": 0,
"CgroupParent": "kubepods-burstable-pod020bc461_170a_4936_9c22_7c8516972d39.slice",
"BlkioWeight": 0,
"BlkioWeightDevice": null,
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 100000,
"CpuQuota": 10000,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DiskQuota": 0,
"KernelMemory": 0,
"MemoryReservation": 0,
"MemorySwap": 104857600,
"MemorySwappiness": null,
"OomKillDisable": false,
......

Pod 上的资源配置是通过底层的容器运行时去控制 CGroup 来实现的,如下目录可查看 CGroup 配置,其是 CGroup 父级目录,而 CGroup 是通过文件系统来进行资源限制的。

$ cd /sys/fs/cgroup/cpu/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod020bc461_170a_4936_9c22_7c8516972d39.slice

$ ls
cgroup.clone_children  cpu.cfs_period_us  docker-37ab54a2490a48c88918f53572e053784238bf3720cb1ae5bf01052040aba9a4.scope
cgroup.event_control   cpu.cfs_quota_us   docker-c9e654d573fd3e3e9a8bb78f3f904e60a59aa3384b344117fd401529e982ae37.scope
cgroup.procs           cpu.rt_period_us   notify_on_release
cpuacct.stat           cpu.rt_runtime_us  tasks
cpuacct.usage          cpu.shares
cpuacct.usage_percpu   cpu.stat

$ cat cpu.cfs_quota_us  # cpu.cfs_quota_us是CPU的限制值
10000