k8s☞11-1pod资源约束

阅读量: zyh 2020-09-19 18:30:04
Categories: > Tags:

基本

https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/

资源约束在我们平时使用的时候主要是cpu和内存层面, 以及本地临时存储(emptyDir)

k8s资源约束分为两种: request(软约束) 和 limits(硬约束)

k8s通过request(软约束)将Pod调度到有资源的Node上,确保了pod中的容器至少可以使用这么多资源. 不过当节点如果没有其它容器,则此容器可以突破request限制.

k8s通过limits(硬约束) 将调度完毕的Pod所使用的资源限制在limits之内。如果容器请求的内存大于了limits,则会收到oom错误。

如果只设置了limits,则k8s会将request的值自动设置为和limits一致。

写法

单位

k8s将一个超线程称为一个vcpu. 1vcpu=1000m. 我们在定义资源限制时, 应该始终用 m 作为单位.假设你限制0.5个vcpu,则填写500m.

k8s的内存和临时存储单位和平时我们所用的没什么区别. 你只需要记住 K/M/G/T/P/E 这些即可. 例如, 100M就是100兆

一个例子:

apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    resources:
      requests:
        memory: "64M"
        cpu: "250m"
        ephemeral-storage: "2Gi"
      limits:
        memory: "128M"
        cpu: "500m"
        ephemeral-storage: "4Gi"
  - name: log-aggregator
    image: images.my-company.example/log-aggregator:v6
    resources:
      requests:
        memory: "64M"
        cpu: "250m"
        ephemeral-storage: "2Gi"
      limits:
        memory: "128M"
        cpu: "500m"
        ephemeral-storage: "4Gi"

资源限制如何运作

k8s会通过kubelet将pod定义的资源限制传递给容器.

如果你容器使用的是docker.

cpu软限制将对标docker的–cpu-shares. 而cpu硬限制会告诉容器每100ms可以使用的CPU时间总量是 limits.cpu * 100.

关于docker的–cpu-shares, 可以参考https://docs.docker.com/engine/reference/run/#cpu-share-constraint

总的来说, --cpu-shares 会让容器按照所设定的分值比例去使用cpu.不过, 在多核心节点上, 这个规则又不是很适用. 按照官方的说法, 当多核心cpu的时候,它的规则是:

On a multi-core system, the shares of CPU time are distributed over all CPU cores. Even if a container is limited to less than 100% of CPU time, it can use 100% of each individual CPU core.

For example, consider a system with more than three cores. If you start one container {C0} with -c=512 running one process, and another container {C1} with -c=1024 running two processes, this can result in the following division of CPU shares:

PID    container	CPU	CPU share
100    {C0}		0	100% of CPU0
101    {C1}		1	100% of CPU1
102    {C1}		2	100% of CPU2

这里三个容器,都是单核心程序

内存的限制没有什么特别需要注意的.

容器中的可见资源

默认情况下,不管你如何设置资源限制,容器里的可见资源都等于节点资源.也就是说你在容器里查看/proc/meminfo显示的资源并不是你设置的.这个问题会带来很多麻烦.

因为很多程序的参数都是根据可见资源来设定的.例如nginx的auto, 或者jvm里的内存参数.

从 Java 8u191开始, jvm 已经默认实现了容器感知( -XX:+UseContainerSupport). 因此无需安装下面的 lxcfs 方案.

并且, 在容器中建议只设置如下内存参数:

-XX:MaxRAMPercentage 最大堆内存=物理内存百分比, 建议为容器限制的50%-75% . 毕竟还需要预留其它内存.

而社区常见的作法是用lxcfs 来提升资源的可见性.lxcfs 是一个开源的FUSE(用户态文件系统)实现来支持LXC容器, 它也可以支持Docker容器.

LXCFS通过用户态文件系统, 在容器中提供下列 procfs 的文件.

/proc/cpuinfo
/proc/diskstats
/proc/meminfo
/proc/stat
/proc/swaps
/proc/uptime

与我们资源限制有关的, 主要是 cpuinfo 和 meminfo.

目前社区的做法如下:

  1. 所有节点安装 fuse-libs 包.

    yum install -y fuse-libs
    
  2. 安装部署lxcfs

    git clone https://github.com/denverdino/lxcfs-admission-webhook.git
    cd lxcfs-admission-webhook
    vim deployment/lxcfs-daemonset.yaml
    === 修正配置里的 apiVersion
    === 当前git里的代码是陈旧的...代码里的版本在 1.18 已经被废弃). 具体归属于什么版本, 请参考k8s官方api文档 
    === https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#daemonset-v1-apps
    apiVersion:apps/v1  
    
    kubectl apply -f deployment/lxcfs-daemonset.yaml
    kubectl get pod
    #等待 lxcfs pod 状态成 running
    #如果你发现 pod 始终出错,那么执行下列命令:
    kubectl delete -f deployment/lxcfs-daemonset.yaml
    rm -rf /var/lib/lxcfs
    kubectl apply -f deployment/lxcfs-daemonset.yaml
    
    deployment/install.sh
    kubectl get secrets,pods,svc,mutatingwebhookconfigurations
    === 查看各个对象状态
    
  3. 给相关namespace注入lxcfs,例如default

    kubectl label namespace default lxcfs-admission-webhook=enabled
    
  4. 重启添加了资源限制的pod, 此时 /proc/cpuinfo 和 /proc/meminfo 将会正确显示.