kubernetes提供了两种资源限制的方式:ResourceQuota 和LimitRange。
其中ResourceQuota 是针对namespace做的资源限制,而LimitRange是针对namespace中的每个组件做的资源限制。

一、ResourceQuota是什么

当多个namespace共用同一个集群的时候可能会有某一个namespace使用的资源配额超过其公平配额,导致其他namespace的资源被占用。
这个时候我们可以为每个namespace创建一个ResourceQuota,

  • 用户在namespace中创建资源时,quota 配额系统跟踪使用情况,以确保不超过ResourceQuota的限制值。
  • 如果创建或更新资源违反配额约束,则HTTP状态代码将导致请求失败403 FORBIDDEN。
  • 资源配额的更改不会影响到已经创建的pod。
  • apiserver的启动参数通常kubernetes默认启用了ResourceQuota.在apiserver的启动参数–enable-admission-plugins=中如果有ResourceQuota便为启动。

二、使用ResourceQuota

1、首先创建一个namespace
> kubectl create ns gkn
namespace/gkn created
> kubectl get ns
NAME              STATUS   AGE
default           Active   12d
dev               Active   10d
gkn               Active   13s
2、创建一个ResourceQuota
> cat <<EOF > gkn-resources.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: gkn-resources
  namespace: gkn
spec:
  hard:
    pods: "4"
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi
EOF

> kubectl apply -f gkn-resources.yaml 
resourcequota/gkn-resources created

> kubectl get resourcequota -n gkn
NAME            CREATED AT
gkn-resources   2019-08-02T01:24:24Z

> kubectl describe resourcequota -n gkn
Name:            gkn-resources
Namespace:       gkn
Resource         Used  Hard
--------         ----  ----
limits.cpu       0     2
limits.memory    0     2Gi
pods             0     4
requests.cpu     0     1
requests.memory  0     1Gi
3、创建一个deployment并限制资源
> cat <<EOF > k8s-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: crm-portal-deployment
  namespace: gkn
  labels:
    app: crm-portal
spec:
  replicas: 1
  selector:
    matchLabels:
      app: crm-portal
  template:
    metadata:
      labels:
        app: crm-portal
    spec:
      imagePullSecrets:
      - name: registry
      containers:
      - name: crm-portal
        image: 10.18.37.2:5000/dev/crm-portal:0.1
        env:
          - name: JAVA_OPTS
            value: -Dspring.config.location=/etc_app/application.properties
        resources:
          requests:
            memory: "100Mi"
            cpu: "100m"
          limits:
            memory: "200Mi"
            cpu: "500m"
  EOF
  
> kubectl apply -f k8s-deployment.yaml
deployment.apps/crm-portal-deployment created

> kubectl get po -n gkn
NAME                                       READY   STATUS             RESTARTS   AGE
crm-portal-deployment-7f748cd688-spqzq     1/1     Running            0          6s

4、多创建几个deployment,使pod使用的资源总和超出resourcequota的限制后再创建deployment,就会发现deployment无法创建pod,并且报错。

首先查看现在的资源使用情况。

>  kubectl describe resourcequota -n gkn
Name:            gkn-resources
Namespace:       gkn
Resource         Used   Hard
--------         ----   ----
limits.cpu       2      2
limits.memory    2Gi    2Gi
pods             2      4
requests.cpu     200m   1
requests.memory  200Mi  1Gi

发现资源已经使用完了,这时再创建一个deployment试试.

> kubectl apply -f k8s-deployment-2.yml -n gkn
deployment.apps/crm-portal-deployment-2 created

> kubectl get po -n gkn
NAME                                       READY   STATUS             RESTARTS   AGE
crm-portal-deployment-1-7f7944cf67-kz8qb   1/1     Running   6          10m
crm-portal-deployment-7f748cd688-c4h6z     1/1     Running   6          9m32s

> kubectl get deployment -n gkn
NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
crm-portal-deployment     1/1     1            0           5h51m
crm-portal-deployment-1   1/1     1            0           79m
crm-portal-deployment-2   0/1     0            0           46m

我们发现虽然deployment创建成功了 但是却没有创建对应的pod,我们可以查看deployment报错。

> kubectl describe deployment crm-portal-deployment-2 -n gkn
...
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  9m13s  deployment-controller  Scaled up replica set crm-portal-deployment-2-7f748cd688 to 1

可见是由于已经创建的pod的总和已经超过的namespace总的资源总量限制值而导致的无法创建pod。

总结

在工作中如果有多个环境通过命名空间的方式使用同一个集群资源,可以通过这种方式进行资源限制,避免不同环境之间进行资源争抢。

附录

常用资源类型
资源名称 描述
limits.cpu namespace下所有pod的CPU限制总和
limits.memory 内存限制总和
requests.cpu CPU请求总和
requests.memory 内存限制总和
requests.storage PVC请求的存储值的总和
persistentvolumeclaims PVC的数量
requests.ephemeral-storage 本地临时存储请求总和
limits.ephemeral-storage 本地临时存储限制总和
常用资源数量限制
  • count/<resource>.<group>
    示例如下:
  • count/persistentvolumeclaims
  • count/services
  • count/secrets
  • count/configmaps
  • count/replicationcontrollers
  • count/deployments.apps
  • count/replicasets.apps
  • count/statefulsets.apps
  • count/jobs.batch
  • count/cronjobs.batch
  • count/deployments.extensions
对namespace中的pod设置资源使用的优先级

使用如下代码段对优先级进行设置。

- apiVersion: v1
  kind: ResourceQuota
  metadata:
    name: pods-medium
  spec:
    hard:
      cpu: "10"
      memory: 20Gi
      pods: "10"
    scopeSelector:
      matchExpressions:
      - operator : In
        scopeName: PriorityClass
        values: ["high"]
  
  ---
  apiVersion: v1
kind: Pod
metadata:
  name: high-priority
spec:
  containers:
  - name: high-priority
    image: ubuntu
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo hello; sleep 10;done"]
    resources:
      requests:
        memory: "10Gi"
        cpu: "500m"
      limits:
        memory: "10Gi"
        cpu: "500m"
  priorityClassName: high

上面两个定义文件的含义如下:

  1. 定义一个ResourceQuota限制priorityClassName为high的pod总和。
  2. 定义一个priorityClassName为high的pod,使其符合ResourceQuota的限制。

其中operator的值可以如下:

  • In
  • NotIn
  • Exist
  • DoesNotExist
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐