Kubernetes:容器资源需求与限制(约束)

Blog:博客园 个人
A Container is guaranteed to have as much memory as it requests, but is not allowed to use more memory than its limit.

概念

资源需求:定义需要系统预留给该容器使用的资源最小可用值,容器运行时可能用不到这些额度的资源,但用到时必须确保有相应数量的资源可用。

资源限制(约束):定义该容器可以申请使用的资源最大可用值,超出该额度的资源使用请求将被拒绝;显然,该限制需要大于等于requests的值,但系统在某项资源紧张时,会从容器回收超出request值的那部分。

一般来讲,资源需求 <= 资源限制。

💡Tips:如果某 Container 设置了自己的内存限制但未设置内存请求,Kubernetes 自动为其设置与内存限制相匹配的请求值。

单位

在Kubernetes上,可由容器或Pod请求与消费的资源主要是指CPU内存(RAM),它可统称为计算资源。 计算资源的数量是可测量的,可以被请求、被分配、被消耗。

CPU属于可压缩型资源,即资源额度可按需弹性变化,而内存(当前)则是不可压缩型资源,对其执行压缩操作可能会导致某种程度的问题,例如进程崩溃等。

在Kubernetes系统上,1个单位的CPU相当于虚拟机上的1颗虚拟CPU(vCPU)或物理机上的一个超线程(Hyperthread,或称为一个逻辑CPU),它支持分数计量方式,一个核心(1 core)相当于1000个微核心(millicores,以下简称为m),因此500m相当于是0.5个核心,即1/2个核心。

CPU 总是按绝对数量来请求的,不可以使用相对数量; 0.1 的 CPU 在单核、双核、48 核的机器上的意义是一样的

内存的计量方式与日常使用方式相同,默认单位是字节,也可以使用E、P、T、G、M和K为单位后缀,或Ei、Pi、Ti、Gi、Mi和Ki形式的单位后缀。

示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations: {}
  labels:
    k8s.kuboard.cn/name: nginx-test
  name: nginx-test
  namespace: test-web
  resourceVersion: '648123'
spec:
  progressDeadlineSeconds: 600
  replicas: 2
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s.kuboard.cn/name: nginx-test
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        k8s.kuboard.cn/name: nginx-test
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - podAffinityTerm:
                labelSelector:
                  matchLabels:
                    k8s.kuboard.cn/name: nginx-test
                namespaces:
                  - test-web
                topologyKey: kubernetes.io/hostname
              weight: 100
      containers:
        - image: 'nginx:latest'
          imagePullPolicy: IfNotPresent
          name: nginx
          ports:
            - containerPort: 80
              protocol: TCP
          resources:
            limits:
              cpu: '1'
              memory: 256Mi
            requests:
              cpu: 100m
              memory: 64Mi
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
  observedGeneration: 2
  readyReplicas: 2
  replicas: 2
  unavailableReplicas: 1
  updatedReplicas: 2

查看:

[root@master ~]# kubectl describe pod nginx-test-994c44d5f-mlfnt -n test-web
Name:         nginx-test-994c44d5f-mlfnt
...
    Limits:
      cpu:     1
      memory:  256Mi
    Requests:
      cpu:        100m
      memory:     64Mi
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-wrl2l (ro)
...

容器CPU资源需求为100m,内存资源需求为64Mi,CPU限制为1,内存限制为256Mi。

metrics-server

从 v1.8 开始,资源使用情况的监控可以通过 Metrics API的形式获取,具体的组件为Metrics Server,用来替换之前的heapster,heapster从1.11开始逐渐被废弃。

安装完Metrics Server,即可用kubectl top命令查看节点和Pod的CPU和内存使用情况。

查看Pod的CPU和内存使用情况:

[root@master ~]# kubectl top pods -n test-web --use-protocol-buffers
NAME                         CPU(cores)   MEMORY(bytes)   
nginx-test-994c44d5f-mlfnt   0m           3Mi             
nginx-test-994c44d5f-t7fvk   0m           3Mi 

总结

对于压缩型的资源CPU来说,若未定义容器的资源请求用量,以确保其最小可用资源量,该Pod占用的CPU资源可能会被其他Pod对象压缩至极低的水平,甚至到该Pod对象无法被调度运行的境地。而对于非压缩型内存资源来说,资源紧缺情形下可能导致相关的容器进程被杀死。因此,在Kubernetes系统上运行关键型业务相关的Pod时,必须要使用requests属性为容器明确定义资源需求。当然,我们也可以为Pod对象定义较高的优先级来改变这种局面。

当节点拥有足够的可用内存时,容器可以使用其请求的内存。 但是,容器不允许使用超过其限制的内存。 如果容器分配的内存超过其限制,该容器会成为被终止的候选容器。 如果容器继续消耗超出其限制的内存,则终止容器(OOMKilled)。 如果终止的容器可以被重启,则 kubelet 会重新启动它,就像其他任何类型的运行时失败一样。