Skip to content

文档,https://kubernetes.io/zh-cn/docs/concepts/configuration/manage-resources-containers/

1.Pod资源限制

1.1什么是资源限制

在Kubernetes集群中,为了使系统能够稳定的运⾏,通常会对Pod的资源使⽤量进⾏限制

在Kubernetes集群中,如果有⼀个程序出现异常,并占⽤⼤量的系统资源。如果未对该Pod进⾏资源限制的话,可能会影响其他的Pod正常运⾏,从⽽造成业务的不稳定性

1.2 如何实现资源限制

Kubernetes通过 RequestsLimits 字段来实现对Pod的资源进⾏限制

  • Requests:启动 Pod 时申请分配的资源⼤⼩;(Pod在调度的时候requests⽐较重要)
  • Limits:限制 Pod 运⾏时最⼤可⽤的资源⼤⼩;(Pod在运⾏时limits⽐较重要)
yaml
spec.containers[].resources.requests.cpu		//定义创建容器时预分配的CPU资源
spec.containers[].resources.requests.memory		//定义创建容器时预分配的内存资源
spec.containers[].resources.limits.cpu			//定义 cpu 的资源上限 
spec.containers[].resources.limits.memory		//定义内存的资源上限
spec.containers[].resources.requests.cpu		//定义创建容器时预分配的CPU资源
spec.containers[].resources.requests.memory		//定义创建容器时预分配的内存资源
spec.containers[].resources.limits.cpu			//定义 cpu 的资源上限 
spec.containers[].resources.limits.memory		//定义内存的资源上限

1.3 资源限制的⽬的与意义

CPU:为集群中运⾏的容器配置CPU请求和限制,可以有效利⽤集群上可⽤的 CPU 资源

  • 设置 Pod CPU请求 设定在较低的数值,可以使 Pod 更有机会被调度
  • 设置 CPU 限制⼤于 CPU 请求,可以完成如下两件事
    • 1、当 Pod 碰到⼀些突发负载时,它可以合理利⽤可⽤的 CPU资源
    • 2、当 Pod 在突发流量期间 可使⽤的CPU被限制为合理的数值,从⽽可以避免影响其他Pod的正常运⾏;

内存:为集群中运⾏的容器配置内存请求和限制,可以有效利⽤集群节点上可⽤的内存资源

  • 通过将Pod 的内存请求设定在较低的数值,可以使 Pod 更有机会被调度
  • 通过让内存限制⼤于内存请求,可以完成如下两件事:
    • 当 Pod 碰到⼀些突发负载时,可以更好的利⽤其主机上的可⽤内存
    • 当 Pod 在突发负载期间可使⽤的内存被限制为合理的数值,从⽽可以避免影响其他Pod的运⾏

2.资源限制单位换算

2.1 CPU限制单位

1核CPU等于1000毫核,当定义容器为0.5时,所能⽤到的CPU资源时1核⼼CPU的⼀半,对于 CPU 资源单位,表达式 0.1 等价于表达式100m,可以看作 100 millicpu

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

shell
1 核⼼ = 1000 millicpu (1 Core = 1000m)
0.5  = 500 millicpu (0.5 Core = 500m)
1 核⼼ = 1000 millicpu (1 Core = 1000m)
0.5  = 500 millicpu (0.5 Core = 500m)

💡 说明

m毫核,cpu单位;Kubernetes 集群中的每一个节点可以通过操作系统的命令来确认本节点的 CPU 内核数量,然后将这个数量乘以1000,得到的就是节点总 CPU 总毫数。比如一个节点有四核,那么该节点的 CPU 总毫量为 4000m,如果你要使用0.5 core,则你要求的是 4000*0.5 = 2000m

举例:当我们有1个物理CPU,16核⼼,如果某个Pod最多使⽤⼀半的核⼼数,则表达式可以写⼊如下两种:

yaml
limits.cpu: 8

limits.cpu: 8000m 计算公式:(16000*0.5=8000m)
limits.cpu: 8

limits.cpu: 8000m 计算公式:(16000*0.5=8000m)

❌ 注意

Kubernetes不允许设置精度⼩于 1m 的CPU资源。因此当CPU 单位⼩于1时,只能使⽤毫核来表示。 例如:期望使⽤1个CPU的0.5%,应该写 5m ⽽不是 0.005

2.2 内存分配单位

内存的基本单位是字节数(Bytes),也可以加上国际单位,⼗进制的E、P、T、G、M,K、m,或⼆进制的 Ei、Pi、Ti、Gi、Mi、Ki,内存的计量方式与日常使用方式相同

MiB ≠ MB,MB 是十进制单位,MiB 是二进制,平时我们以为 MB 等于 1024KB,其实1MB=1000KB,1MiB才等于1024KiB。中间带字母 i 的是国际电工协会(IEC)定的,走1024乘积;KB、MB、GB是国际单位制,走1000乘积

shell
1MB = 1000 KB = 1000000 Bytes
1Mi = 1024 KB = 1048576 bytes
1MB = 1000 KB = 1000000 Bytes
1Mi = 1024 KB = 1048576 bytes

❌ 注意

如果你为某个资源指定了限制,但不指定请求, 并且没有应用准入时机制为该资源设置默认请求, 然后 Kubernetes 复制你所指定的限制值,将其用作资源的请求值

内存的计量方式与日常使用方式相同

2.3 计算

cpu

shell
##查看CPU的限制##
[root@k8s-node1 ~]# docker exec -it 6933185dbe4b /bin/bash

root@pod-limits:/# cd /sys/fs/cgroup/cpu/

root@pod-limits:/sys/fs/cgroup/cpu# cat cpu.cfs_period_us 
100000
root@pod-limits:/sys/fs/cgroup/cpu# cat cpu.cfs_quota_us  
200000

#反向计算出--cpus参数
#cpu.cfs_quota_us / cpu.cfs_period_us = cpu的限制
root@pod-limits:/sys/fs/cgroup/cpu# expr `cat cpu.cfs_quota_us` / `cat cpu.cfs_period_us`
2
##查看CPU的限制##
[root@k8s-node1 ~]# docker exec -it 6933185dbe4b /bin/bash

root@pod-limits:/# cd /sys/fs/cgroup/cpu/

root@pod-limits:/sys/fs/cgroup/cpu# cat cpu.cfs_period_us 
100000
root@pod-limits:/sys/fs/cgroup/cpu# cat cpu.cfs_quota_us  
200000

#反向计算出--cpus参数
#cpu.cfs_quota_us / cpu.cfs_period_us = cpu的限制
root@pod-limits:/sys/fs/cgroup/cpu# expr `cat cpu.cfs_quota_us` / `cat cpu.cfs_period_us`
2

cpu.cfs_period_us和cpu.cfs_quota_us来限制该组中的所有进程在单位时间里可以使用的cpu时间。 cpu.cfs_period_us:时间周期(微秒); cpu.cfs_quota_us:指的是在cpu.cfs_period_us周期内可使用的cpu的时间(微秒); 多核场景下,如配置cpu.cfs_period_us=10000,而cfs_quota_us=20000,表示该cgroup可以完全使用2个cpu。 所以cpu的计算方法为:cfs_quota_us / cpu.cfs_period_us

mem

shell
##查看内存的限制##
[root@k8s-node1 ~]# docker exec -it 6933185dbe4b /bin/bash

root@pod-limits:~# cd /sys/fs/cgroup/memory/

root@pod-limits:/sys/fs/cgroup/memory# cat memory.limit_in_bytes 
2147483648 (Byte字节)

内存的计算方法为:2147483648÷1024÷1024÷1024 = 2(G)
##查看内存的限制##
[root@k8s-node1 ~]# docker exec -it 6933185dbe4b /bin/bash

root@pod-limits:~# cd /sys/fs/cgroup/memory/

root@pod-limits:/sys/fs/cgroup/memory# cat memory.limit_in_bytes 
2147483648 (Byte字节)

内存的计算方法为:2147483648÷1024÷1024÷1024 = 2(G)

3.实践

安装metrics-server

官方文档,https://github.com/kubernetes-sigs/metrics-server

requests

shell
kubectl explain pod.spec.containers.resources
kubectl explain pod.spec.containers.resources
yaml
[root@kube-master yaml]# cat requests-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: requests-pod
spec:
  containers:
  - image: busybox
    name: busybox
    args:
      - "/bin/sh"
      - "-c"
      - "sleep 60000"
    resources:
      requests:			#资源申请
        cpu: 500m		#容器申请500毫核(一个CPU核心时间的1/2)
        memory: 500Mi	#容器申请500M内存
[root@kube-master yaml]# cat requests-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: requests-pod
spec:
  containers:
  - image: busybox
    name: busybox
    args:
      - "/bin/sh"
      - "-c"
      - "sleep 60000"
    resources:
      requests:			#资源申请
        cpu: 500m		#容器申请500毫核(一个CPU核心时间的1/2)
        memory: 500Mi	#容器申请500M内存
  • 超出内存
shell
[root@kube-master yaml]# cat requests-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: requests-pod
spec:
  containers:
  - image: busybox
    name: busybox
    args:
      - "/bin/sh"
      - "-c"
      - "sleep 60000"
    resources:
      requests:
        cpu: 500m
        memory: 2048Mi
  nodeName: kube-node01
[root@kube-master yaml]# cat requests-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: requests-pod
spec:
  containers:
  - image: busybox
    name: busybox
    args:
      - "/bin/sh"
      - "-c"
      - "sleep 60000"
    resources:
      requests:
        cpu: 500m
        memory: 2048Mi
  nodeName: kube-node01
shell
[root@kube-master yaml]# kubectl get pod
NAME                              READY   STATUS        RESTARTS        AGE
requests-pod                      0/1     OutOfmemory   0               4s
[root@kube-master yaml]# kubectl get pod
NAME                              READY   STATUS        RESTARTS        AGE
requests-pod                      0/1     OutOfmemory   0               4s
shell
[root@kube-master yaml]# kubectl describe pod requests-pod
...
Status:       Failed
Reason:       OutOfmemory
Message:      Pod Node didn't have enough resource: memory, requested: 2147483648, used: 0, capacity: 1934282752
...
Events:
  Type     Reason       Age   From     Message
  ----     ------       ----  ----     -------
  Warning  OutOfmemory  10s   kubelet  Node didn't have enough resource: memory, requested: 2147483648, used: 0, capacity: 1934282752
[root@kube-master yaml]# kubectl describe pod requests-pod
...
Status:       Failed
Reason:       OutOfmemory
Message:      Pod Node didn't have enough resource: memory, requested: 2147483648, used: 0, capacity: 1934282752
...
Events:
  Type     Reason       Age   From     Message
  ----     ------       ----  ----     -------
  Warning  OutOfmemory  10s   kubelet  Node didn't have enough resource: memory, requested: 2147483648, used: 0, capacity: 1934282752

limits

yaml
[root@kube-master yaml]# cat limit-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: limited-pod
spec:
  containers:
  - image: busybox
    command: ["sleep","600000"]
    name: busybox 
    resources:
      requests:         #资源申请
        cpu: 200m       #容器申请200毫核(一个CPU核心时间的1/5)
        memory: 80Mi    #容器申请80M内存
      limits:           #资源限制
        cpu: 2          #容器最大允许使用2核CPU
        memory: 2Gi     #容器最大允许使用2GB内存
  nodeName: kube-node01
[root@kube-master yaml]# cat limit-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: limited-pod
spec:
  containers:
  - image: busybox
    command: ["sleep","600000"]
    name: busybox 
    resources:
      requests:         #资源申请
        cpu: 200m       #容器申请200毫核(一个CPU核心时间的1/5)
        memory: 80Mi    #容器申请80M内存
      limits:           #资源限制
        cpu: 2          #容器最大允许使用2核CPU
        memory: 2Gi     #容器最大允许使用2GB内存
  nodeName: kube-node01
shell
kubectl describe nodes kube-node01
kubectl describe nodes kube-node01

image-20240426141514746

❌ 注意

节点上所有pod的资源limits之和可以超过节点资源总量的100%

requests不同的是,limits并不会影响pod的调度结果

如果只设置了limit,则request默认会根据limit自动设定

运⾏超过容器内存限制的应⽤

当节点拥有足够的可用内存时,容器可以使用其请求的内存。但是,容器不允许使用超过其限制的内存。如果容器分配的内存超过其限制,该容器会成为被终止的候选容器。如果容器继续消耗超出其限制的内存,则终止容器。如果终止的容器可以被重启,则kubelet会重新启动它。

yaml
[root@kube-master yaml]# cat memory-request-limit-2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: memory-request-limit-2
spec:
  containers:
  - name: memory-request
    image: polinux/stress
    command: ["stress", "--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"] ## 容器会尝试分配 250 MiB 内
存,这远⾼于 100 MiB 的限制,模拟1个进程产⽣250M内存
    resources:
      requests:
        memory: "100Mi"
      limits:
        memory: "200Mi"
[root@kube-master yaml]# cat memory-request-limit-2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: memory-request-limit-2
spec:
  containers:
  - name: memory-request
    image: polinux/stress
    command: ["stress", "--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"] ## 容器会尝试分配 250 MiB 内
存,这远⾼于 100 MiB 的限制,模拟1个进程产⽣250M内存
    resources:
      requests:
        memory: "100Mi"
      limits:
        memory: "200Mi"

4.资源配置范围管理LimitRange

4.1 概念

默认情况下,Kubernetes中所有容器都没有任何CPU和内存限制。LimitRange用来给Namespace增加一个资源限制,包括最小、最大和默认资源。

4.2 为什么需要LimitRange

为单个容器设置资源requests和limits很有必要性:

1.提升QoS等级,防止在OOM时被首先kill;

2.默认情况下Pod会以无限制的CPU和内存运行,很有可能因故吞掉所在工作节点上的所有可用计算资源。

通过配置Pod的计算资源Requests和Limits,我们可以限制Pod的资源使用,但对于Kubemetes集群管理员而言,配置每一个Pod的Requests和Limits是烦琐且限制性过强的。更多时,我们需要的是对集群内Requests和Limits的配置做一个全局的统一的限制。

💡 说明

LimitRange资源支持限制Container、Pod和PersistentVolumeClaim三种资源对象的系统资源用量

创建

yaml
# more limits.yaml 
apiVersion: v1
kind: LimitRange
metadata:
  name: limitrange 
spec:
  limits:
  - type: Pod                      #指定整个pod的资源limits
    min:                           #pod中所有容器的Requests值的总和的下限
      cpu: 50m
      memory: 5Mi
    max:                           #pod中所有容器的Limits值的总和的上限
      cpu: 1
      memory: 1Gi
  - type: Container                #指定容器的资源限制
    defaultRequest:                #容器Requests默认值
      cpu: 100m
      memory: 10Mi
    default:                       #容器Limits默认值
      cpu: 200m
      memory: 100Mi
    min:                           #pod中所有容器的Requests值的下限
      cpu: 50m
      memory: 5Mi
    max:                           #pod中所有容器的Limits值的上限
      cpu: 1
      memory: 1Gi
    maxLimitRequestRatio:          #每种资源Requests与Limits的最大比值
      cpu: 4
      memory: 10
  - type: PersistentVolumeClaim    #指定请求PVC存储容量的最小值和最大值
    min:
      storage: 1Gi
    max:
      storage: 10Gi
# more limits.yaml 
apiVersion: v1
kind: LimitRange
metadata:
  name: limitrange 
spec:
  limits:
  - type: Pod                      #指定整个pod的资源limits
    min:                           #pod中所有容器的Requests值的总和的下限
      cpu: 50m
      memory: 5Mi
    max:                           #pod中所有容器的Limits值的总和的上限
      cpu: 1
      memory: 1Gi
  - type: Container                #指定容器的资源限制
    defaultRequest:                #容器Requests默认值
      cpu: 100m
      memory: 10Mi
    default:                       #容器Limits默认值
      cpu: 200m
      memory: 100Mi
    min:                           #pod中所有容器的Requests值的下限
      cpu: 50m
      memory: 5Mi
    max:                           #pod中所有容器的Limits值的上限
      cpu: 1
      memory: 1Gi
    maxLimitRequestRatio:          #每种资源Requests与Limits的最大比值
      cpu: 4
      memory: 10
  - type: PersistentVolumeClaim    #指定请求PVC存储容量的最小值和最大值
    min:
      storage: 1Gi
    max:
      storage: 10Gi

查看

shell
#kubectl describe limitranges limitrange

Name:                  limitrange
Namespace:             default
Type                   Resource  Min  Max   Default Request  Default Limit  Max Limit/Request Ratio
----                   --------  ---  ---   ---------------  -------------  -----------------------
Pod                    cpu       50m  1     -                -              -
Pod                    memory    5Mi  1Gi   -                -              -
Container              memory    5Mi  1Gi   10Mi             100Mi          10
Container              cpu       50m  1     100m             200m           4
PersistentVolumeClaim  storage   1Gi  10Gi  -                -              -
#kubectl describe limitranges limitrange

Name:                  limitrange
Namespace:             default
Type                   Resource  Min  Max   Default Request  Default Limit  Max Limit/Request Ratio
----                   --------  ---  ---   ---------------  -------------  -----------------------
Pod                    cpu       50m  1     -                -              -
Pod                    memory    5Mi  1Gi   -                -              -
Container              memory    5Mi  1Gi   10Mi             100Mi          10
Container              cpu       50m  1     100m             200m           4
PersistentVolumeClaim  storage   1Gi  10Gi  -                -              -

测试

yaml
#cat default.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: default-pod
spec:
  containers:
  - image: busybox
    name: busybox 
    args:
    - /bin/sh
    - -c
    - sleep 60000
#cat default.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: default-pod
spec:
  containers:
  - image: busybox
    name: busybox 
    args:
    - /bin/sh
    - -c
    - sleep 60000
  • 查看
[root@kube-master yaml]# kubectl describe pod default-pod
[root@kube-master yaml]# kubectl describe pod default-pod

容器的requests和limits与我们在LimitRange对象中设置的一致

cpu超限制

shell
# kubectl run  cpu-over --image=busybox --restart=Never --requests='cpu=1200m,memory=30Mi' sleep 6000 
The Pod "cpu-over" is invalid: spec.containers[0].resources.requests: Invalid value: "1200m": must be less than or equal to cpu limit
# kubectl run  cpu-over --image=busybox --restart=Never --requests='cpu=1200m,memory=30Mi' sleep 6000 
The Pod "cpu-over" is invalid: spec.containers[0].resources.requests: Invalid value: "1200m": must be less than or equal to cpu limit

内存超限制

shell
# kubectl run  cpu-over --image=busybox --restart=Never --requests='cpu=200m,memory=300Mi' sleep 6000 
The Pod "cpu-over" is invalid: spec.containers[0].resources.requests: Invalid value: "300Mi": must be less than or equal to memory limit
# kubectl run  cpu-over --image=busybox --restart=Never --requests='cpu=200m,memory=300Mi' sleep 6000 
The Pod "cpu-over" is invalid: spec.containers[0].resources.requests: Invalid value: "300Mi": must be less than or equal to memory limit

不指定CPU和mem Limits

如果没有为容器指定CPU限制,那么容器在可以使用的CPU资源是没有上限。因而可以使用所在节点上所有的可用CPU资源,这样可能会造成某一个Pod占用了大量的CPU时间,可能会影响其他的Pod正常运行,从而造成业务的不稳定性。

这个也不用担心,在Kubernetes中,可以通过LimitRange自动为容器设定,所使用的CPU资源和内存资源最大最小值

5.资源配额管理(ResourceQuota)

5.1 概念

Kubemetes可以通过存活探针(liveness probe)检查容器是否还在运行。可以为pod中的每个容器单独指定存活探针。如果探测失败,Kubemetes将定期执行探针并重新启动容器。

资源配额(Resource Quotas)是用来限制用户资源用量的一种机制,限制Pod的请求不会超过配额,需要在namespace中创建一个ResourceQuota对象

资源配额类型:

  • 计算资源。包括 cpu 和 memory
  • 存储资源。包括存储资源的总量以及指定 storage class 的总量
  • 对象数。即可创建的对象的个数

5.2 ResourceQuota作用

尽管LimitRange资源能限制单个容器、Pod及PVC等相关计算资源或存储资源的用量,但用户依然可以创建数量众多的此类资源对象进而侵占所有的系统资源。于是,Kubernetes提供了ResourceQuota资源用于定义名称空间的对象数量或系统资源配额

❌ 注意

LimitRange应用于单独的pod,ResourceQuota应用于命名空间中所有的pod

image-20240426160154222

5.3 创建

shell
#cat quota-cpu-memory.yaml                
apiVersion: v1
kind: ResourceQuota
metadata:
  name: cpu-and-mem
spec:
  hard:
    requests.cpu: 1
    requests.memory: 1Gi
    limits.cpu: 1500m
    limits.memory: 1500Mi

# kubectl apply -f quota-cpu-memory.yaml 
resourcequota/cpu-and-mem created
#cat quota-cpu-memory.yaml                
apiVersion: v1
kind: ResourceQuota
metadata:
  name: cpu-and-mem
spec:
  hard:
    requests.cpu: 1
    requests.memory: 1Gi
    limits.cpu: 1500m
    limits.memory: 1500Mi

# kubectl apply -f quota-cpu-memory.yaml 
resourcequota/cpu-and-mem created

查看

shell
#kubectl describe resourcequotas cpu-and-mem

Name:            cpu-and-mem
Namespace:       default
Resource         Used  Hard
--------         ----  ----
limits.cpu       0     1500m
limits.memory    0     1500Mi
requests.cpu     0     1
requests.memory  0     1Gi
#kubectl describe resourcequotas cpu-and-mem

Name:            cpu-and-mem
Namespace:       default
Resource         Used  Hard
--------         ----  ----
limits.cpu       0     1500m
limits.memory    0     1500Mi
requests.cpu     0     1
requests.memory  0     1Gi

测试resourcequota

  • 创建
yaml
[root@kube-master yaml]# cat replicas-quota-test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: replicas-quota-test
spec:
  replicas: 10
  selector:
    matchLabels:
      app: replicas-quota-test
  template:
    metadata:
      labels:
        app: replicas-quota-test
    spec:
      containers:
      - name: replicas-quota-test
        image: busybox
        command: ["/bin/sh","-c","sleep 60000"]
        resources:
          limits:
            cpu: "200m"
            memory: "90Mi"
[root@kube-master yaml]# cat replicas-quota-test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: replicas-quota-test
spec:
  replicas: 10
  selector:
    matchLabels:
      app: replicas-quota-test
  template:
    metadata:
      labels:
        app: replicas-quota-test
    spec:
      containers:
      - name: replicas-quota-test
        image: busybox
        command: ["/bin/sh","-c","sleep 60000"]
        resources:
          limits:
            cpu: "200m"
            memory: "90Mi"
  • 查看
shell
[root@kube-master yaml]# kubectl get pod
NAME                                   READY   STATUS    RESTARTS         AGE
replicas-quota-test-84bd8d9fb4-bnbm9   1/1     Running   0                7m6s
replicas-quota-test-84bd8d9fb4-ctjdz   1/1     Running   0                7m6s
replicas-quota-test-84bd8d9fb4-n2kv9   1/1     Running   0                7m6s
replicas-quota-test-84bd8d9fb4-n445x   1/1     Running   0                7m6s
replicas-quota-test-84bd8d9fb4-s8jt2   1/1     Running   0                7m6s
[root@kube-master yaml]# kubectl get pod
NAME                                   READY   STATUS    RESTARTS         AGE
replicas-quota-test-84bd8d9fb4-bnbm9   1/1     Running   0                7m6s
replicas-quota-test-84bd8d9fb4-ctjdz   1/1     Running   0                7m6s
replicas-quota-test-84bd8d9fb4-n2kv9   1/1     Running   0                7m6s
replicas-quota-test-84bd8d9fb4-n445x   1/1     Running   0                7m6s
replicas-quota-test-84bd8d9fb4-s8jt2   1/1     Running   0                7m6s

💡 说明

发现只运行了5个pod,原因是requests的cpu为200(requests值未设置时与limits相同),resourcequotas中requests.cpu的限制值为1500m,所以最多只能新建5个pod

限制可创建对象的个数

  • 创建
shell
[root@kube-master yaml]# cat quota-count.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: count-quota
spec:
  hard:
    pods: 10
    replicationcontrollers: 5
    secrets: 10
    configmaps: 10
    persistentvolumeclaims: 5
    services: 5
    services.loadbalancers: 1
    services.nodeports: 2
    ssd.storageclass.storage.k8s.io/persistentvolumeclaims: 2
[root@kube-master yaml]# cat quota-count.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: count-quota
spec:
  hard:
    pods: 10
    replicationcontrollers: 5
    secrets: 10
    configmaps: 10
    persistentvolumeclaims: 5
    services: 5
    services.loadbalancers: 1
    services.nodeports: 2
    ssd.storageclass.storage.k8s.io/persistentvolumeclaims: 2

该命名空间最多创建10个pod、5个Replication Controller、10个Secret、10个ConfigMap、4个PVC、5个Service、1个LoadBalancer、2个NodePort和2个StorageClass为ssd的PVC。

podReplication ControllerSecretConfigMapPVCServiceLoadBalancerNodePortssd PVC
105101045122
  • 查看
shell
[root@kube-master yaml]# kubectl apply  -f quota-count.yaml
resourcequota/count-quota created

[root@kube-master yaml]# kubectl describe resourcequotas count-quota
Name:                                                   count-quota
Namespace:                                              default
Resource                                                Used  Hard
--------                                                ----  ----
configmaps                                              1     10
persistentvolumeclaims                                  0     5
pods                                                    11    10
replicationcontrollers                                  0     5
secrets                                                 1     10
services                                                3     5
services.loadbalancers                                  0     1
services.nodeports                                      1     2
ssd.storageclass.storage.k8s.io/persistentvolumeclaims  0     2
[root@kube-master yaml]# kubectl apply  -f quota-count.yaml
resourcequota/count-quota created

[root@kube-master yaml]# kubectl describe resourcequotas count-quota
Name:                                                   count-quota
Namespace:                                              default
Resource                                                Used  Hard
--------                                                ----  ----
configmaps                                              1     10
persistentvolumeclaims                                  0     5
pods                                                    11    10
replicationcontrollers                                  0     5
secrets                                                 1     10
services                                                3     5
services.loadbalancers                                  0     1
services.nodeports                                      1     2
ssd.storageclass.storage.k8s.io/persistentvolumeclaims  0     2

6.Pod服务质量QoS

6.1 QoS定义

QoS(QualityofService),可译为"服务质量等级",或者译作"服务质量保证",是作用在Pod上的一个配置,当

Kubernetes创建一个 Pod 时,它就会给这个Pod 分配一个QoS 等级。

在Kubernetes的环境中,Kubernetes允许节点的Pod过载使用资源,这意味着节点无法同时满足所有Pod以过载的方式运行。因此在内存资源紧缺的情况下,Kubernetes需要借助Pod对象的服务质量和优先级等完成判定,进而挑选对应的Pod杀死。Kubernetes根据pod的Requests和Limits属性,把Pod对象归类为三类 BestEffort、BurStabLe、Guaranteed

优先级,Guaranteed > BurStabLe > BestEffort

6.2 QoS类别

  • Guaranteed:Pod对象为每个容器都设置了CPU资源需求和资源限制,且两者的值相同;还同时为每个容器设置了内存需求与内存限制,并且两者的值相同。这类Pod对象具有最高级别服务质量。

  • BurstabLe:至少有一个容器设置了CPU或内存资源Requests属性,但不满足Guaranteed,这类Pod具有中级服务质量

  • BestEffort:没有为任何容器设置Requests和Limits属性,这类Pod对象服务质量是最低级别

​ 当 Kubernetes 集群内存资源紧缺,优先杀死BestEffort类别的容器,因为系统不为该类资源提供任何服务保证,但此类资源最⼤的好处就是能够尽可能的使⽤资源.

​ 如果系统中没有BestEffort类别的容器,接下来就轮到Burstable类别的容器,如果有多个Burstable类别的容器,就看谁的内存资源占⽤多,就优先⼲掉谁。⽐如A容器申请1G内存资源,实际使⽤了95%,⽽B容器申请了2G内存资源,实际使⽤了80%,但任然会优先⼲掉A容器,虽然A容器的⽤量少,但与⾃身的Requests值相⽐,它的占⽐要⼤于B容器。

​ 对于Guaranteed类别的容器拥有最高优先级,它们不会被杀死,除非其内存资源需求超限,或者00M时没有其他更低优先级的Pod对象存在,才会干掉Guaranteed类容器.

创建Guaranteed的Pod

对于 QoS 类为 Guaranteed 的 Pod

  • Pod中的每个容器都必须指定内存请求和内存限制,且Pod中每个容器内存请求必须等于内存限制

  • Pod中的每个容器都必须指定CPU请求和CPU限制,且Pod中每个容器CPU请求必须等于CPU限制

1.创建⼀个Pod,容器设置了内存请求和内存限制,值都是200MiB。容器设置了CPU请求和CPU限制,值都是700 milliCPU.

yaml
cat pod-qos-guaranteed.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-qos-guaranteed
spec:
  containers:
  - name: nginx
    image: nginx:latest
    resources:
      requests:
        cpu: "500m"
        memory: "128Mi"
      limits:
        cpu: "500m"
        memory: "128Mi"
cat pod-qos-guaranteed.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-qos-guaranteed
spec:
  containers:
  - name: nginx
    image: nginx:latest
    resources:
      requests:
        cpu: "500m"
        memory: "128Mi"
      limits:
        cpu: "500m"
        memory: "128Mi"
shell
#查看
[root@kube-master ~]# kubectl describe pod pod-qos-guaranteed
。。。
    Limits:
      cpu:     500m
      memory:  128Mi
    Requests:
      cpu:        500m
      memory:     128Mi
。。。
QoS Class:                   Guaranteed
。。。
#查看
[root@kube-master ~]# kubectl describe pod pod-qos-guaranteed
。。。
    Limits:
      cpu:     500m
      memory:  128Mi
    Requests:
      cpu:        500m
      memory:     128Mi
。。。
QoS Class:                   Guaranteed
。。。

创建Burstable的Pod

如果满⾜下⾯条件,将会指定 Pod 的 QoS 类为 Burstable:

  • Pod 不符合 Guaranteed QoS 类的标准
  • Pod 中⾄少⼀个容器指定了,内存或 CPU 的请求或限制

1.创建⼀个Pod,容器设置了内存请求 100 MiB,以及内存限制 200MiB

yaml
cat pod-qos-burstable.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-qos-burstable
spec:
  containers:
  - name: nginx
    image: nginx:latest
    resources:
      requests:
        memory: "128Mi"
      limits:
        memory: "128Mi"
cat pod-qos-burstable.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-qos-burstable
spec:
  containers:
  - name: nginx
    image: nginx:latest
    resources:
      requests:
        memory: "128Mi"
      limits:
        memory: "128Mi"
shell
#查看
[root@kube-master yaml]# kubectl describe pod pod-qos-burstable

。。。
    Limits:
      cpu:     500m
      memory:  128Mi
    Requests:
      cpu:        500m
      memory:     128Mi
。。。
QoS Class:                   Burstable
。。。
#查看
[root@kube-master yaml]# kubectl describe pod pod-qos-burstable

。。。
    Limits:
      cpu:     500m
      memory:  128Mi
    Requests:
      cpu:        500m
      memory:     128Mi
。。。
QoS Class:                   Burstable
。。。

创建BestEffort的Pod

对于 QoS 类为 BestEffort 的 Pod,Pod 中的容器必须没有设置内存和 CPU 限制或请求

1.创建⼀个Pod,容器没有设置内存和 CPU 限制或请求

yaml
[root@kube-master yaml]# cat pod-qos-besteffort.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-qos-besteffort
spec:
  containers:
  - name: nginx
    image: nginx:latest
[root@kube-master yaml]# cat pod-qos-besteffort.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-qos-besteffort
spec:
  containers:
  - name: nginx
    image: nginx:latest
shell
#查看
[root@kube-master yaml]# kubectl describe pod pod-qos-besteffort
...
QoS Class:                   BestEffort
...
#查看
[root@kube-master yaml]# kubectl describe pod pod-qos-besteffort
...
QoS Class:                   BestEffort
...

创建多容器Pod

1.创建⼀个Pod,⼀个容器指定了内存请求 200 MiB。 另外⼀个容器没有指定任何请求和限制。此 Pod 满⾜ Burstable QoS 类的标准。但它不满⾜ Guaranteed QoS 类标准,因为它的⼀个容器设有内存请求

yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-qos-mutil
spec:
  containers:
  - name: nginx
    image: nginx:latest
    resources:
      limits:
        memory: "100Mi"
  - name: redis
    image: redis:latest
apiVersion: v1
kind: Pod
metadata:
  name: pod-qos-mutil
spec:
  containers:
  - name: nginx
    image: nginx:latest
    resources:
      limits:
        memory: "100Mi"
  - name: redis
    image: redis:latest
shell
#查看
[root@kube-master yaml]# kubectl describe pod pod-qos-mutil
...
    Limits:
      memory:  100Mi
    Requests:
      memory:     100Mi
...
QoS Class:                   Burstable
...
#查看
[root@kube-master yaml]# kubectl describe pod pod-qos-mutil
...
    Limits:
      memory:  100Mi
    Requests:
      memory:     100Mi
...
QoS Class:                   Burstable
...

7.Downward API

文档,https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/downward-api/

作用:让Pod里的容器能够直接获取到这个Pod API对象本身的信息

DownwardAPI可以让容器获取Pod的相关元数据信息,比如Pod名称,Pod的IP,Pod的资源限制等,获取后通过env、voLume的方式将相关的环境信息注入到容器中,从而让容器通过环境变量这些信息,来设定容器的运行特性。

  • 例如:Nginx进程根据节点的CPU核心数量自动设定要启动的worker进程数
  • 例如:JVM虚拟根据Pod的内存资源限制,来设定对应容器的堆内存大小
  • 例如:获取Pod名称,以Pod名称注册到某个服务,当Pod结束后,调用prestop清理对应名称的注册信息

7.1可注⼊的元数据信息

使⽤ pod.spec.containers.env.valueFrom.fieldRef 可以注⼊的字段有:

shell
metadata.name:Pod对象的名称

metadata.namespace:Pod对象隶属的名称空间

metadata.uid:Pod对象的UID

metadata.abels['<KEY>']:获取LabeL指定KEY对应的值

metadata.annotations['<KEY>']:获取Annotations对应KEY的值

status.podIP:Pod对象的IP地址

status.hostIP:节点IP

status.nodeName:节点名称

spec.serviceAccountName:Pod对象使用的ServiceAccount资源名称
metadata.name:Pod对象的名称

metadata.namespace:Pod对象隶属的名称空间

metadata.uid:Pod对象的UID

metadata.abels['<KEY>']:获取LabeL指定KEY对应的值

metadata.annotations['<KEY>']:获取Annotations对应KEY的值

status.podIP:Pod对象的IP地址

status.hostIP:节点IP

status.nodeName:节点名称

spec.serviceAccountName:Pod对象使用的ServiceAccount资源名称

使⽤pod.spec.containers.env.valueFrom.resourceFieldRef 可以注⼊的字段有:

requests.cpu
requests.memory
limits.cpu
limits.memory
requests.cpu
requests.memory
limits.cpu
limits.memory

7.2环境变量⽅式注⼊元数据

1.创建Pod容器,将Pod相关环境变量注⼊到容器中,⽐如(pod名称、命名空间、标签、以及cpu、内存的请求和限制)

[root@kube-master yaml]# kubectl apply pod-downward.yaml

yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-downward
  labels:
    app: pod-downward
spec:
  containers:
  - name: pod-downward
    image: nginx:latest
    command: ["/bin/sh","-c","env"]
    resources:
      limits:
        cpu: "200m"
        memory: "128Mi"
      requests:
        cpu: "200m"
        memory: "64Mi"
    env:
    - name: THIS_POD_NAME
      valueFrom:
        fieldRef:
          fieldPath: metadata.name
    - name: THIS_POD_NAMESPACE
      valueFrom:
        fieldRef:
          fieldPath: metadata.namespace
    - name: THIS_POD_APP_LABEL
      valueFrom:
        fieldRef:
          fieldPath: metadata.labels['app']
    - name: THIS_CPU_LIMIT
      valueFrom:
        resourceFieldRef:
          resource: limits.cpu
    - name: THIS_MEMORY_REQUEST
      valueFrom:
        resourceFieldRef:
          resource: requests.memory
          divisor: 1Mi  # 默认显示为字节,通过divisor调整显示单位为兆
apiVersion: v1
kind: Pod
metadata:
  name: pod-downward
  labels:
    app: pod-downward
spec:
  containers:
  - name: pod-downward
    image: nginx:latest
    command: ["/bin/sh","-c","env"]
    resources:
      limits:
        cpu: "200m"
        memory: "128Mi"
      requests:
        cpu: "200m"
        memory: "64Mi"
    env:
    - name: THIS_POD_NAME
      valueFrom:
        fieldRef:
          fieldPath: metadata.name
    - name: THIS_POD_NAMESPACE
      valueFrom:
        fieldRef:
          fieldPath: metadata.namespace
    - name: THIS_POD_APP_LABEL
      valueFrom:
        fieldRef:
          fieldPath: metadata.labels['app']
    - name: THIS_CPU_LIMIT
      valueFrom:
        resourceFieldRef:
          resource: limits.cpu
    - name: THIS_MEMORY_REQUEST
      valueFrom:
        resourceFieldRef:
          resource: requests.memory
          divisor: 1Mi  # 默认显示为字节,通过divisor调整显示单位为兆
  • 查看
shell
[root@kube-master yaml]# kubectl logs pod-downward |grep THIS
THIS_CPU_LIMIT=1
THIS_POD_APP_LABEL=pod-downward
THIS_POD_NAME=pod-downward
THIS_MEMORY_REQUEST=64
THIS_POD_NAMESPACE=default
[root@kube-master yaml]# kubectl logs pod-downward |grep THIS
THIS_CPU_LIMIT=1
THIS_POD_APP_LABEL=pod-downward
THIS_POD_NAME=pod-downward
THIS_MEMORY_REQUEST=64
THIS_POD_NAMESPACE=default

7.3存储卷⽅式注⼊元数据