limitRange


LimitRange有个好听的中文名字,叫"资源配置访问管理"。用过K8S的都知道,在默认情况下,K8S不会对Pod进行CPU和内存限制,这就意味着这个未被限制的Pod可以随心所欲的使用节点上的CPU和内存,如果某个Pod发生内存泄漏那么将是一个非常糟糕的事情。

所以正常情况下,我们在部署Pod的时候都会把Requests和Limits加上,如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ng-deploy
spec:
  selector:
    matchLabels:
      app: ng-demo
  replicas: 2
  template:
    metadata:
      labels:
        app: ng-demo
    spec:
      containers:
      - name: ng-demo
        image: nginx
        imagePullPolicy: IfNotPresent
        resources:
          requests:
            cpu: 100m
            memory: 216Mi
          limits:
            cpu: 100m
            memory: 216Mi

但是,如果Pod非常多,而且很多Pod只需要相同的限制,我们还是像上面那样一个一个的加就非常繁琐了,这时候我们就可以通过LimitRange做一个Namespace资源限制。如果在部署Pod的时候指定了requests和Limits,则指定的生效。反之则由全局的给Pod加上默认的限制。

总结,LimitRange可以实现的功能:

  • 限制namespace中每个pod或container的最小和最大资源用量。
    
  • 限制namespace中每个PVC的资源请求范围。
    
  • 限制namespace中资源请求和限制数量的比例。
    
  • 配置资源的默认限制。
    
创建LimitRange之后,LimitRange会在它所属namespace范围内生效。

常用的场景如下(来自《Kubernetes权威指南》)

  • 集群中的每个节点都有2GB内存,集群管理员不希望任何Pod申请超过2GB的内存:因为在整个集群中都没有任何节点能满足超过2GB内存的请求。如果某个Pod的内存配置超过2GB,那么该Pod将永远都无法被调度到任何节点上执行。为了防止这种情况的发生,集群管理员希望能在系统管理功能中设置禁止Pod申请超过2GB内存。
    
  • 集群由同一个组织中的两个团队共享,分别运行生产环境和开发环境。生产环境最多可以使用8GB内存,而开发环境最多可以使用512MB内存。集群管理员希望通过为这两个环境创建不同的命名空间,并为每个命名空间设置不同的限制来满足这个需求。
    
  • 用户创建Pod时使用的资源可能会刚好比整个机器资源的上限稍小,而恰好剩下的资源大小非常尴尬:不足以运行其他任务但整个集群加起来又非常浪费。因此,集群管理员希望设置每个Pod都必须至少使用集群平均资源值(CPU和内存)的20%,这样集群能够提供更好的资源一致性的调度,从而减少了资源浪费。
    

LimitRange可以用来限制Pod,也可以限制Container。下面我们以一个例子来详细说明。

配置LimitRange

(1)、首先创建一个namespace

apiVersion: v1
kind: Namespace
metadata:
  name: coolops

(2)、为namespace配置LimitRange

apiVersion: v1
kind: LimitRange
metadata:
  name: mylimit
  namespace: coolops
spec:
  limits:
  - max:
      cpu: "1"
      memory: 1Gi
    min:
      cpu: 100m
      memory: 10Mi
    maxLimitRequestRatio:
      cpu: 3
      memory: 4
    type: Pod
  - default:
      cpu: 300m
      memory: 200Mi
    defaultRequest:
      cpu: 200m
      memory: 100Mi
    max:
      cpu: "2"
      memory: 1Gi
    min:
      cpu: 100m
      memory: 10Mi
    maxLimitRequestRatio:
      cpu: 5
      memory: 4
    type: Container

参数说明:

  • max:如果type是Pod,则表示pod中所有容器资源的Limit值和的上限,也就是整个pod资源的最大Limit,如果pod定义中的Limit值大于LimitRange中的值,则pod无法成功创建。如果type是Container,意义类似。
    
  • min:如果type是Pod,则表示pod中所有容器资源请求总和的下限,也就是所有容器request的资源总和不能小于min中的值,否则pod无法成功创建。如果type是Container,意义类似。
    
  • maxLimitRequestRatio:如果type是Pod,表示pod中所有容器资源请求的Limit值和request值比值的上限,例如该pod中cpu的Limit值为3,而request为0.5,此时比值为6,创建pod将会失败。
    
  • defaultrequest和defaultlimit则是默认值,只有type为Container才有这两项配置
    
注意: (1)、如果container设置了max, pod中的容器必须设置limit,如果未设置,则使用defaultlimt的值,如果defaultlimit也没有设置,则无法成功创建 (2)、如果设置了container的min,创建容器的时候必须设置request的值,如果没有设置,则使用defaultrequest,如果没有defaultrequest,则默认等于容器的limit值,如果limit也没有,启动就会报错

创建上面配置的LimitRange:

# kubectl apply -f limitrange.yaml 
limitrange/mylimit created

# kubectl get limitrange -n coolops 
NAME      CREATED AT
mylimit   2020-03-26T09:46:33Z

# kubectl describe limitranges -n coolops mylimit 
Name:       mylimit
Namespace:  coolops
Type        Resource  Min   Max  Default Request  Default Limit  Max Limit/Request Ratio
----        --------  ---   ---  ---------------  -------------  -----------------------
Pod         memory    10Mi  1Gi  -                -              4
Pod         cpu       100m  1    -                -              3
Container   cpu       100m  2    200m             300m           5
Container   memory    10Mi  1Gi  100Mi            200Mi          4

测试LimitRange

(1)、创建一个允许范围之内的requests和limits的pod

apiVersion: v1
kind: Pod
metadata:
  name: pod01
  namespace: coolops
spec:
  containers:
  - name: pod-01
    image: nginx
    imagePullPolicy: IfNotPresent
    resources:
      requests:
        cpu: 200m
        memory: 30Mi
      limits:
        cpu: 300m
        memory: 50Mi

我们通过kubectl apply -f pod-01.yaml可以正常创建Pod。

(2)、创建一个cpu超出允许访问的Pod

apiVersion: v1
kind: Pod
metadata:
  name: pod02
  namespace: coolops
spec:
  containers:
  - name: pod-02
    image: nginx
    imagePullPolicy: IfNotPresent
    resources:
      requests:
        cpu: 200m
        memory: 30Mi
      limits:
        cpu: 2
        memory: 50Mi

然后我们创建会报如下错误:

# kubectl apply -f pod-02.yaml 
Error from server (Forbidden): error when creating "pod-02.yaml": pods "pod02" is forbidden: [maximum cpu usage per Pod is 1, but limit is 2, cpu max limit to request ratio per Pod is 3, but provided ratio is 10.000000, cpu max limit to request ratio per Container is 5, but provided ratio is 10.000000]

(3)创建低于允许范围的Pod

apiVersion: v1
kind: Pod
metadata:
  name: pod03
  namespace: coolops
spec:
  containers:
  - name: pod-03
    image: nginx
    imagePullPolicy: IfNotPresent
    resources:
      requests:
        cpu: 200m
        memory: 30Mi
      limits:
        cpu: 100m
        memory: 10Mi

然后会报如下错误:

# kubectl apply -f pod-03.yaml 
The Pod "pod03" is invalid: 
* spec.containers[0].resources.requests: Invalid value: "200m": must be less than or equal to cpu limit
* spec.containers[0].resources.requests: Invalid value: "30Mi": must be less than or equal to memory limit

(4)、创建一个未定义request或Limits的Pod

apiVersion: v1
kind: Pod
metadata:
  name: pod04
  namespace: coolops
spec:
  containers:
  - name: pod-04
    image: nginx
    imagePullPolicy: IfNotPresent
    resources:
      requests:
        cpu: 200m
        memory: 200Mi

然后我们创建完Pod后会发现自动给我们加上了limits。如下:

# kubectl describe pod -n coolops pod04
...
    Limits:
      cpu:     300m
      memory:  200Mi
    Requests:
      cpu:        200m
      memory:     200Mi
...

上面我指定了requests,LimitRange自动给我们加上了defaultLimits,你也可以试一下全都不加或者加一个,道理是一样的。值得注意的是这里要注意一下我们设置的maxLimitRequestRatio,配置的比列必须小于等于我们设置的值。

上文有介绍LimitRange还可以限制还可以限制PVC,如下:

apiVersion: v1
kind: LimitRange
metadata:
  name: storagelimits
  namespace: coolops
spec:
  limits:
  - type: PersistentVolumeClaim
    max:
      storage: 2Gi
    min:
      storage: 1Gi

创建完后即可查看:

 kubectl describe limitranges -n coolops storagelimits 
Name:                  storagelimits
Namespace:             coolops
Type                   Resource  Min  Max  Default Request  Default Limit  Max Limit/Request Ratio
----                   --------  ---  ---  ---------------  -------------  -----------------------
PersistentVolumeClaim  storage   1Gi  2Gi  -                -              -

你可以创建PVC进行测试,道理是一样的。

参考资料

[1] https://kubernetes.io/docs/concepts/policy/limit-range/

[2] 《Kubernetes权威指南》