• Kubernetes(k8s) 资源限制:resources,LimitRange,ResourceQuota


    一.系统环境

    本文主要基于Kubernetes1.21.9和Linux操作系统CentOS7.4。

    服务器版本 docker软件版本 Kubernetes(k8s)集群版本 CPU架构
    CentOS Linux release 7.4.1708 (Core) Docker version 20.10.12 v1.21.9 x86_64

    Kubernetes集群架构:k8scloude1作为master节点,k8scloude2,k8scloude3作为worker节点。

    服务器 操作系统版本 CPU架构 进程 功能描述
    k8scloude1/192.168.110.130 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico k8s master节点
    k8scloude2/192.168.110.129 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kubelet,kube-proxy,calico k8s worker节点
    k8scloude3/192.168.110.128 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kubelet,kube-proxy,calico k8s worker节点

    二.前言

    在Kubernetes中,资源限制是一种管理和控制容器资源使用的重要机制。通过资源限制,我们可以为容器分配适当的计算资源,确保集群的稳定性和性能。

    本篇博客将介绍Kubernetes中的资源限制的概念,并详细说明如何使用resourcesLimitRangeResourceQuota来管理容器资源。

    使用Kubernetes资源限制的前提是已经有一套可以正常运行的Kubernetes集群,关于Kubernetes(k8s)集群的安装部署,可以查看博客《Centos7 安装部署Kubernetes(k8s)集群》https://www.cnblogs.com/renshengdezheli/p/16686769.html。

    三.Kubernetes资源限制简介

    在Kubernetes中,资源限制是一种指定容器在节点上可使用的资源量的方法。资源主要包括计算资源(如CPU和内存),还可以包括其他扩展资源(如GPU、存储等)。通过资源限制,我们可以控制容器对集群资源的使用,并确保不同容器之间的资源分配合理,避免资源竞争和冲突。

    四.创建没有资源限制的pod

    4.1 创建没有资源限制的pod

    在kubernetes集群的所有节点下载centos镜像。

    [root@k8scloude1 ~]# cd safe/
    
    [root@k8scloude1 safe]# docker pull hub.c.163.com/library/centos:latest
    
    [root@k8scloude2 ~]# docker pull hub.c.163.com/library/centos:latest
    
    [root@k8scloude3 ~]# docker pull hub.c.163.com/library/centos:latest
    

    准备好memload安装包,memload是内存消耗测试工具。

    [root@k8scloude1 safe]# ls  memload-7.0-1.r29766.x86_64.rpm
    memload-7.0-1.r29766.x86_64.rpm  
    

    如下yaml文件功能为:使用hub.c.163.com/library/centos:latest镜像创建一个休眠10000000秒的pod。

    [root@k8scloude1 safe]# vim pod.yaml 
    
    [root@k8scloude1 safe]# cat pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        test: podtest
      name: podtest
    spec:
      #当需要关闭容器时,立即杀死容器而不等待默认的30秒优雅停机时长。
      terminationGracePeriodSeconds: 0
      containers:
      - name: centos
        image: hub.c.163.com/library/centos:latest
        #imagePullPolicy: IfNotPresent:表示如果本地已经存在该镜像,则不重新下载;否则从远程 Docker Hub 下载该镜像
        imagePullPolicy: IfNotPresent
        #command: ["sh","-c","sleep 10000000"]指定容器启动时要执行的命令,这里是在容器内部执行一个sleep命令,休眠时间为10000000秒。
        command: ["sh","-c","sleep 10000000"]
        resources: {}
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}
    

    创建pod。

    [root@k8scloude1 safe]# kubectl apply -f pod.yaml 
    pod/podtest created
    

    查看pod,可以看到pod运行在k8scloude2节点上。

    [root@k8scloude1 safe]# kubectl get pod -o wide
    NAME      READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
    podtest   1/1     Running   0          7s    10.244.112.180   k8scloude2   <none>           <none>
    

    4.2 内存消耗测试

    把memload安装包拷贝到pod里面。

    [root@k8scloude1 safe]# kubectl cp memload-7.0-1.r29766.x86_64.rpm podtest:/opt
    

    进入pod里面。

    [root@k8scloude1 safe]# kubectl exec -it podtest -- bash
    
    #memload-7.0-1.r29766.x86_64.rpm安装包已经在容器里了
    [root@podtest /]# ls /opt/
    memload-7.0-1.r29766.x86_64.rpm
    
    #安装memload
    [root@podtest /]# rpm -ivh /opt/memload-7.0-1.r29766.x86_64.rpm 
    Preparing...                          ################################# [100%]
    Updating / installing...
       1:memload-7.0-1.r29766             ################################# [100%]
       
    #在pod里面执行memload 1024,使其消耗1024M的内存   
    [root@podtest /]# memload 1024
    Attempting to allocate 1024 Mebibytes of resident memory...
    ^C
    

    因为podtest运行在k8scloude2节点上,所以在k8scloude2节点上观察内存消耗情况,podtest里没执行memload 1024之前,k8scloude2节点内存消耗情况如下。

    [root@k8scloude2 ~]# free -m
                  total        used        free      shared  buff/cache   available
    Mem:           2920         692         660          17        1567        1910
    Swap:             0           0           0
    

    在podtest里执行memload 1024之后,k8scloude2节点内存消耗情况如下。

    [root@k8scloude2 ~]# free -m
                  total        used        free      shared  buff/cache   available
    Mem:           2920        1718         101          17        1099         886
    Swap:             0           0           0
    

    podtest里取消执行memload 1024之后,内存消耗降下来了。

    [root@k8scloude2 ~]# free -m
                  total        used        free      shared  buff/cache   available
    Mem:           2920         688        1126          17        1105        1916
    Swap:             0           0           0
    

    在podtest里继续执行memload 1500,使其消耗1500M的内存。

    [root@podtest /]# memload 1500
    Attempting to allocate 1500 Mebibytes of resident memory...
    ^C
    

    在k8scloude2节点上继续观察内存消耗。

    首先清除一下缓存。

    [root@k8scloude2 ~]# echo 3 > /proc/sys/vm/drop_caches 
    

    podtest里没执行memload 1500之前,k8scloude2节点内存消耗情况如下。

    [root@k8scloude2 ~]# free -m
                  total        used        free      shared  buff/cache   available
    Mem:           2920         670        1770          17         479        1957
    Swap:             0           0           0
    

    在podtest里执行memload 1500之后,k8scloude2节点内存消耗情况如下。

    [root@k8scloude2 ~]# free -m
                  total        used        free      shared  buff/cache   available
    Mem:           2920        2178         134          17         607         448
    Swap:             0           0           0
    

    podtest里取消执行memload 1500之后,内存消耗降下来了。

    [root@k8scloude2 ~]# free -m
                  total        used        free      shared  buff/cache   available
    Mem:           2920         671        1640          17         608        1956
    Swap:             0           0           0
    

    删除pod。

    [root@k8scloude1 safe]# kubectl get pod 
    NAME      READY   STATUS    RESTARTS   AGE
    podtest   1/1     Running   0          26m
    
    [root@k8scloude1 safe]# kubectl delete pod podtest 
    pod "podtest" deleted
    
    [root@k8scloude1 safe]# kubectl get pod 
    No resources found in safe namespace.
    

    由此我们可以发现:现在没有对pod进行资源限制,pod可以无限制的使用内存,CPU等等,接下来对pod进行资源限制。

    五.使用resources字段配置资源限制

    在Kubernetes中,resources字段是一种用于定义和管理容器资源需求和限制的对象。通过指定资源请求和限制,Kubernetes可以根据集群的可用资源进行调度和管理。

    资源包括计算资源(如CPU和内存)以及其他可选的扩展资源(如GPU、存储等)。通过合理配置资源,我们可以避免容器之间的资源竞争和冲突,提高应用程序的性能和可靠性。

    5.1 限制最低内存

    修改yaml文件,对pod的资源限制可以通过pod里的resource字段来限制,resources里的requests字段表示容器所在节点资源的最小值,最低要求,满足不了这个要求pod创建不成功。

    requests:memory: 100Gi表示podtest最低要求100Gi内存,满足不了,pod就创建失败。

    [root@k8scloude1 safe]# vim pod.yaml 
    
    [root@k8scloude1 safe]# cat pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        test: podtest
      name: podtest
    spec:
      #当需要关闭容器时,立即杀死容器而不等待默认的30秒优雅停机时长。
      terminationGracePeriodSeconds: 0
      containers:
      - name: centos
        image: hub.c.163.com/library/centos:latest
        #imagePullPolicy: IfNotPresent:表示如果本地已经存在该镜像,则不重新下载;否则从远程 Docker Hub 下载该镜像
        imagePullPolicy: IfNotPresent
        #command: ["sh","-c","sleep 10000000"]指定容器启动时要执行的命令,这里是在容器内部执行一个sleep命令,休眠时间为10000000秒。
        command: ["sh","-c","sleep 10000000"]
        resources: 
          #requests:memory: 100Gi表示podtest最低要求100Gi内存,满足不了pod就创建失败。
          requests:
            memory: 100Gi
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}
    

    创建pod。

    [root@k8scloude1 safe]# kubectl apply -f pod.yaml 
    pod/podtest created
    

    查看pod,我们现在的机器环境满足不了100G的内存要求,所以pod状态为Pending。

    [root@k8scloude1 safe]# kubectl get pod -o wide
    NAME      READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
    podtest   0/1     Pending   0          9s    <none>   <none>   <none>           <none>
    

    删除pod。

    [root@k8scloude1 safe]# kubectl delete pod podtest 
    pod "podtest" deleted
    

    5.2 限制最低CPU

    修改yaml文件,requests:cpu: 4 表示podtest最低要求有4核CPU,满足不了,pod就创建失败。

    [root@k8scloude1 safe]# vim pod.yaml 
    
    [root@k8scloude1 safe]# cat pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        test: podtest
      name: podtest
    spec:
      #当需要关闭容器时,立即杀死容器而不等待默认的30秒优雅停机时长。
      terminationGracePeriodSeconds: 0
      containers:
      - name: centos
        image: hub.c.163.com/library/centos:latest
        #imagePullPolicy: IfNotPresent:表示如果本地已经存在该镜像,则不重新下载;否则从远程 Docker Hub 下载该镜像
        imagePullPolicy: IfNotPresent
        #command: ["sh","-c","sleep 10000000"]指定容器启动时要执行的命令,这里是在容器内部执行一个sleep命令,休眠时间为10000000秒。
        command: ["sh","-c","sleep 10000000"]
        resources: 
          #requests:cpu: 4 表示podtest最低要求有4核CPU,满足不了,pod就创建失败
          requests:
            cpu: 4
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}
    

    创建pod。

    [root@k8scloude1 safe]# kubectl apply -f pod.yaml 
    pod/podtest created
    

    查看pod,4核CPU无法满足,pod状态为Pending。

    [root@k8scloude1 safe]# kubectl get pod -o wide
    NAME      READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
    podtest   0/1     Pending   0          13s   <none>   <none>   <none>           <none>
    

    删除pod。

    [root@k8scloude1 safe]# kubectl delete pod podtest 
    pod "podtest" deleted
    

    修改yaml文件,requests:cpu: 3 表示podtest最低要求有3核CPU,满足不了,pod就创建失败。

    [root@k8scloude1 safe]# vim pod.yaml 
    
    [root@k8scloude1 safe]# cat pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        test: podtest
      name: podtest
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: centos
        image: hub.c.163.com/library/centos:latest
        imagePullPolicy: IfNotPresent
        command: ["sh","-c","sleep 10000000"]
        resources: 
          #requests:cpu: 3 表示podtest最低要求有3核CPU,满足不了,pod就创建失败
          requests:
            cpu: 3
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}
    

    创建pod。

    [root@k8scloude1 safe]# kubectl apply -f pod.yaml 
    pod/podtest created
    

    requests:cpu: 3 要求有3核CPU之后,podtest满足条件,pod就运行起来了。requests:cpu: 3 可以换成requests:cpu: 3000m ,两者是等价的,1核等于1000个微核心。

    [root@k8scloude1 safe]# kubectl get pod -o wide
    NAME      READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
    podtest   1/1     Running   0          4s    10.244.112.170   k8scloude2   <none>           <none>
    

    查看节点负载。

    [root@k8scloude1 safe]# kubectl top node 
    W0323 08:56:05.755124   39033 top_node.go:119] Using json format to get metrics. Next release will switch to protocol-buffers, switch early by passing --use-protocol-buffers flag
    NAME         CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
    k8scloude1   311m         7%     1429Mi          50%       
    k8scloude2   172m         4%     839Mi           29%       
    k8scloude3   188m         4%     959Mi           34%  
    

    查看safe命名空间的pod负载。

    [root@k8scloude1 safe]# kubectl top pod -n safe
    W0323 08:56:47.844614   39714 top_pod.go:140] Using json format to get metrics. Next release will switch to protocol-buffers, switch early by passing --use-protocol-buffers flag
    NAME      CPU(cores)   MEMORY(bytes)   
    podtest   0m           2Mi            
    

    删除pod。

    [root@k8scloude1 safe]# kubectl delete pod podtest 
    pod "podtest" deleted
    
    [root@k8scloude1 safe]# kubectl get pod
    No resources found in safe namespace.
    

    5.3 限制最低CPU和最高内存

    修改yaml文件,resources:limits表示容器消耗资源最大值,limits: memory: 500Mi 表示容器最多消耗500M内存,requests:cpu: 300m 表示podtest最低要求有300个微核心,满足不了,pod就创建失败。

    [root@k8scloude1 safe]# vim pod.yaml 
    
    [root@k8scloude1 safe]# cat pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        test: podtest
      name: podtest
    spec:
      #当需要关闭容器时,立即杀死容器而不等待默认的30秒优雅停机时长。
      terminationGracePeriodSeconds: 0
      containers:
      - name: centos
        image: hub.c.163.com/library/centos:latest
        #imagePullPolicy: IfNotPresent:表示如果本地已经存在该镜像,则不重新下载;否则从远程 Docker Hub 下载该镜像
        imagePullPolicy: IfNotPresent
        #command: ["sh","-c","sleep 10000000"]指定容器启动时要执行的命令,这里是在容器内部执行一个sleep命令,休眠时间为10000000秒。
        command: ["sh","-c","sleep 10000000"]
        resources: 
          #requests:cpu: 300m 表示podtest最低要求有300个微核心,满足不了,pod就创建失败
          requests:
            cpu: 300m
          #limits: memory: 500Mi 表示容器最多消耗500M内存  
          limits:
            memory: 500Mi
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}
    

    创建pod。

    [root@k8scloude1 safe]# kubectl apply -f pod.yaml 
    pod/podtest created
    

    查看pod,pod创建成功。

    [root@k8scloude1 safe]# kubectl get pod -o wide
    NAME      READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
    podtest   1/1     Running   0          7s    10.244.112.188   k8scloude2   <none>           <none>
    

    5.4 内存消耗测试

    再次进行资源消耗测试,把memload-7.0-1.r29766.x86_64.rpm安装包拷贝到podtest里。

    [root@k8scloude1 safe]# kubectl cp memload-7.0-1.r29766.x86_64.rpm podtest:/opt
    

    进入pod。

    [root@k8scloude1 safe]# kubectl exec -it podtest -- bash
    
    #安装memload
    [root@podtest /]# rpm -ivh /opt/memload-7.0-1.r29766.x86_64.rpm 
    Preparing...                          ################################# [100%]
    Updating / installing...
       1:memload-7.0-1.r29766             ################################# [100%]
       
    #memload 1024消耗1024M内存就自动 killed了 
    [root@podtest /]# memload 1024
    Attempting to allocate 1024 Mebibytes of resident memory...
    Killed   
    
    #memload 600消耗600M内存就自动 killed了 
    [root@podtest /]# memload 600 
    Attempting to allocate 600 Mebibytes of resident memory...
    Killed
    
    #memload 490消耗490M内存就可以
    [root@podtest /]# memload 490
    Attempting to allocate 490 Mebibytes of resident memory...
    ^C
    
    #退出pod
    [root@podtest /]# exit
    exit
    command terminated with exit code 130
    

    可以发现内存消耗不能大于limits:memory: 500Mi,大于500M的内存设置就会OOM Killed,资源限制成功。

    删除pod。

    [root@k8scloude1 safe]# kubectl delete pod podtest 
    pod "podtest" deleted
    
    [root@k8scloude1 safe]# kubectl get pod 
    No resources found in safe namespace.
    

    六.使用LimitRange限制资源范围

    LimitRange是一种用于限制容器资源使用的配置对象。它允许集群管理员定义资源的最小和最大限制,并确保容器在这些限制范围内使用资源。

    通过使用LimitRange,可以避免容器使用过多或过少的资源,保护集群免受资源耗尽和应用程序崩溃的影响。

    默认情况下, Kubernetes 集群上的容器运行使用的计算资源没有限制。 使用 Kubernetes 资源配额, 管理员(也称为 集群操作者)可以在一个指定的命名空间内限制集群资源的使用与创建。 在命名空间中,一个 Pod 最多能够使用命名空间的资源配额所定义的 CPU 和内存用量。 作为集群操作者或命名空间级的管理员,你可能也会担心如何确保一个 Pod 不会垄断命名空间内所有可用的资源。

    LimitRange 是限制命名空间内可为每个适用的对象类别 (例如 Pod 或 PersistentVolumeClaim) 指定的资源分配量(限制和请求)的策略对象。

    一个 LimitRange(限制范围) 对象提供的限制能够做到:

    • 在一个命名空间中实施对每个 Pod 或 Container 最小和最大的资源使用量的限制。

    • 在一个命名空间中实施对每个 PersistentVolumeClaim 能申请的最小和最大的存储空间大小的限制。

    • 在一个命名空间中实施对一种资源的申请值和限制值的比值的控制。

    • 设置一个命名空间中对计算资源的默认申请/限制值,并且自动的在运行时注入到多个 Container 中。

    当某命名空间中有一个 LimitRange 对象时,将在该命名空间中实施 LimitRange 限制。

    如下LimitRange的功能为:创建了一个名为"mem-limit-range"的LimitRange资源对象,用于限制容器的内存使用范围。容器的内存限制在256Mi到512Mi之间,并且仅适用于容器。

    [root@k8scloude1 safe]# vim limitRange.yaml
    
    [root@k8scloude1 safe]# cat limitRange.yaml 
    apiVersion: v1
    kind: LimitRange
    metadata:
      name: mem-limit-range
    spec:
      limits:
      #memory: 512Mi:设置容器的最大内存限制为512MiB。
      - max:
          memory: 512Mi
        #memory: 256Mi:设置容器的最小内存限制为256MiB。  
        min:
          memory: 256Mi
        #type: Container:指定这些限制适用于容器。  
        type: Container
    

    创建LimitRange。

    [root@k8scloude1 safe]# kubectl apply -f limitRange.yaml 
    limitrange/mem-limit-range created
    

    查看LimitRange。

    [root@k8scloude1 safe]# kubectl get LimitRange
    NAME              CREATED AT
    mem-limit-range   2022-03-23T01:23:04Z
    
    [root@k8scloude1 safe]# kubectl get -f limitRange.yaml 
    NAME              CREATED AT
    mem-limit-range   2022-03-23T01:23:04Z
    

    查看mem-limit-range的描述信息。

    [root@k8scloude1 safe]# kubectl describe LimitRange mem-limit-range
    Name:       mem-limit-range
    Namespace:  safe
    Type        Resource  Min    Max    Default Request  Default Limit  Max Limit/Request Ratio
    ----        --------  ---    ---    ---------------  -------------  -----------------------
    Container   memory    256Mi  512Mi  512Mi            512Mi          -
    
    [root@k8scloude1 safe]# kubectl describe -f limitRange.yaml 
    Name:       mem-limit-range
    Namespace:  safe
    Type        Resource  Min    Max    Default Request  Default Limit  Max Limit/Request Ratio
    ----        --------  ---    ---    ---------------  -------------  -----------------------
    Container   memory    256Mi  512Mi  512Mi            512Mi          -
    

    使用hub.c.163.com/library/centos:latest镜像创建pod。

    [root@k8scloude1 safe]# vim pod.yaml 
    
    [root@k8scloude1 safe]# cat pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        test: podtest
      name: podtest
    spec:
      #当需要关闭容器时,立即杀死容器而不等待默认的30秒优雅停机时长。
      terminationGracePeriodSeconds: 0
      containers:
      - name: centos
        image: hub.c.163.com/library/centos:latest
        #imagePullPolicy: IfNotPresent:表示如果本地已经存在该镜像,则不重新下载;否则从远程 Docker Hub 下载该镜像
        imagePullPolicy: IfNotPresent
        #command: ["sh","-c","sleep 10000000"]指定容器启动时要执行的命令,这里是在容器内部执行一个sleep命令,休眠时间为10000000秒。
        command: ["sh","-c","sleep 10000000"]
        resources: {} 
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}
    

    创建pod。

    [root@k8scloude1 safe]# kubectl apply -f pod.yaml 
    pod/podtest created
    
    [root@k8scloude1 safe]# kubectl get pod -o wide
    NAME      READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
    podtest   1/1     Running   0          7s    10.244.112.189   k8scloude2   <none>           <none>
    

    把memload安装包拷贝到podtest里。

    [root@k8scloude1 safe]# kubectl cp memload-7.0-1.r29766.x86_64.rpm podtest:/opt
    

    进入pod,进行内存消耗测试。

    [root@k8scloude1 safe]# kubectl exec -it podtest -- bash
    
    #安装memload
    [root@podtest /]# rpm -ivh /opt/memload-7.0-1.r29766.x86_64.rpm 
    Preparing...                          ################################# [100%]
    Updating / installing...
       1:memload-7.0-1.r29766             ################################# [100%]
    
    #memload 1024表示消耗1024M内存,1024M内存超过limits:max:memory: 512Mi,直接就Killed
    [root@podtest /]# memload 1024
    Attempting to allocate 1024 Mebibytes of resident memory...
    Killed
    
    #memload 500 表示消耗500M内存,500M小于limits:max:memory: 512Mi,成功消耗内存
    [root@podtest /]# memload 500 
    Attempting to allocate 500 Mebibytes of resident memory...
    ^C
    
    [root@podtest /]# exit
    exit
    command terminated with exit code 130
    

    可以发现容器内存设置不能超过limits:max:memory: 512Mi,成功进行资源限制。

    删除pod。

    [root@k8scloude1 safe]# kubectl delete pod podtest 
    pod "podtest" deleted
    

    七.同时使用LimitRange和resource字段配置资源限制

    修改yaml文件,resources字段和LimitRange都进行了资源限制,requests:memory: 200Mi表示podtest最低要求200Mi内存,满足不了pod就创建失败,limits: memory: 600Mi 表示容器最多消耗600Mi内存 。

    [root@k8scloude1 safe]# vim pod.yaml 
    
    [root@k8scloude1 safe]# cat pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        test: podtest
      name: podtest
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: centos
        image: hub.c.163.com/library/centos:latest
        imagePullPolicy: IfNotPresent
        command: ["sh","-c","sleep 10000000"]
        resources:
          #requests:memory: 200Mi表示podtest最低要求200Mi内存,满足不了pod就创建失败。
          requests:
            memory: 200Mi 
          #limits: memory: 600Mi 表示容器最多消耗600Mi内存    
          limits:
            memory: 600Mi 
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}
    

    LimitRange的限制范围为256Mi到512Mi内存。

    [root@k8scloude1 safe]# kubectl get LimitRange
    NAME              CREATED AT
    mem-limit-range   2022-03-23T01:23:04Z
    
    [root@k8scloude1 safe]# kubectl describe -f limitRange.yaml 
    Name:       mem-limit-range
    Namespace:  safe
    Type        Resource  Min    Max    Default Request  Default Limit  Max Limit/Request Ratio
    ----        --------  ---    ---    ---------------  -------------  -----------------------
    Container   memory    256Mi  512Mi  512Mi            512Mi          -
    

    创建pod,pod创建失败,只有满足LimitRange min <= requests

    [root@k8scloude1 safe]# kubectl apply -f pod.yaml 
    Error from server (Forbidden): error when creating "pod.yaml": pods "podtest" is forbidden: [minimum memory usage per Container is 256Mi, but request is 200Mi, maximum memory usage per Container is 512Mi, but limit is 600Mi]
    

    修改yaml文件,requests:memory: 300Mi表示podtest最低要求300Mi内存,满足不了pod就创建失败,limits: memory: 500Mi 表示容器最多消耗500M内存 。

    [root@k8scloude1 safe]# vim pod.yaml 
    
    [root@k8scloude1 safe]# cat pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        test: podtest
      name: podtest
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: centos
        image: hub.c.163.com/library/centos:latest
        imagePullPolicy: IfNotPresent
        command: ["sh","-c","sleep 10000000"]
        resources:
          #requests:memory: 300Mi表示podtest最低要求300Mi内存,满足不了pod就创建失败。
          requests:
            memory: 300Mi 
          #limits: memory: 500Mi 表示容器最多消耗500M内存    
          limits:
            memory: 500Mi 
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}
    

    LimitRange的限制范围为256Mi到512Mi内存。

    [root@k8scloude1 safe]# kubectl describe -f limitRange.yaml 
    Name:       mem-limit-range
    Namespace:  safe
    Type        Resource  Min    Max    Default Request  Default Limit  Max Limit/Request Ratio
    ----        --------  ---    ---    ---------------  -------------  -----------------------
    Container   memory    256Mi  512Mi  512Mi            512Mi          -
    

    创建pod,pod创建成功,因为满足LimitRange min <= requests

    [root@k8scloude1 safe]# kubectl apply -f pod.yaml 
    pod/podtest created
    
    [root@k8scloude1 safe]# kubectl get pod -o wide
    NAME      READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
    podtest   1/1     Running   0          7s    10.244.112.190   k8scloude2   <none>           <none>
    

    如果resources字段和LimitRange都进行了资源限制,最终是resources字段生效,容器内存设置不能大于500Mi。

    删除limitrange和pod。

    [root@k8scloude1 safe]# kubectl delete -f limitRange.yaml 
    limitrange "mem-limit-range" deleted
    
    [root@k8scloude1 safe]# kubectl delete pod podtest 
    pod "podtest" deleted
    

    八.使用ResourceQuota资源配额管理

    ResourceQuota是一种用于限制命名空间内资源使用的对象。它允许集群管理员对命名空间中的资源使用进行配额管理,确保不同的团队或项目之间资源的公平分配和有效利用。

    使用ResourceQuota,可以限制命名空间中的CPU、内存和其他资源的总量,防止资源滥用和浪费。

    资源配额,通过 ResourceQuota 对象来定义,对每个命名空间的资源消耗总量提供限制。 它可以限制命名空间中某种类型的对象的总数目上限,也可以限制命名空间中的 Pod 可以使用的计算资源的总上限。

    资源配额的工作方式如下:

    • 不同的团队可以在不同的命名空间下工作。这可以通过 RBAC 强制执行。

    • 集群管理员可以为每个命名空间创建一个或多个 ResourceQuota 对象。

    • 当用户在命名空间下创建资源(如 Pod、Service 等)时,Kubernetes 的配额系统会跟踪集群的资源使用情况, 以确保使用的资源用量不超过 ResourceQuota 中定义的硬性资源限额。

    • 如果资源创建或者更新请求违反了配额约束,那么该请求会报错(HTTP 403 FORBIDDEN), 并在消息中给出有可能违反的约束。

    • 如果命名空间下的计算资源 (如 cpu 和 memory)的配额被启用, 则用户必须为这些资源设定请求值(request)和约束值(limit),否则配额系统将拒绝 Pod 的创建。 提示: 可使用 LimitRanger 准入控制器来为没有设置计算资源需求的 Pod 设置默认值。

    简而言之,resourcequota 配额就是用来设置一个命名空间最多能创建多少个对象,比如能创建多少svc,能创建多少pod/deploy。

    如下yaml文件功能为:使用hub.c.163.com/library/centos:latest镜像创建一个休眠10000000秒的pod。

    [root@k8scloude1 safe]# vim pod.yaml 
    
    [root@k8scloude1 safe]# cat pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        test: podtest
      name: podtest
    spec:
      #当需要关闭容器时,立即杀死容器而不等待默认的30秒优雅停机时长。
      terminationGracePeriodSeconds: 0
      containers:
      - name: centos
        image: hub.c.163.com/library/centos:latest
        #imagePullPolicy: IfNotPresent:表示如果本地已经存在该镜像,则不重新下载;否则从远程 Docker Hub 下载该镜像
        imagePullPolicy: IfNotPresent
        #command: ["sh","-c","sleep 10000000"]指定容器启动时要执行的命令,这里是在容器内部执行一个sleep命令,休眠时间为10000000秒。
        command: ["sh","-c","sleep 10000000"]
        resources: {}
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}
    

    创建pod。

    [root@k8scloude1 safe]# kubectl apply -f pod.yaml 
    pod/podtest created
    
    [root@k8scloude1 safe]# kubectl get pod
    NAME      READY   STATUS    RESTARTS   AGE
    podtest   1/1     Running   0          3s
    

    给podtest创建4个svc,关于svc的详细内容,请查看博客《Kubernetes(k8s)服务service:service的发现和service的发布》。

    [root@k8scloude1 safe]# kubectl expose --name=svc1 pod podtest --port=80
    service/svc1 exposed
    
    [root@k8scloude1 safe]# kubectl expose --name=svc2 pod podtest --port=80
    service/svc2 exposed
    
    [root@k8scloude1 safe]# kubectl expose --name=svc3 pod podtest --port=80
    service/svc3 exposed
    
    [root@k8scloude1 safe]# kubectl expose --name=svc4 pod podtest --port=80
    service/svc4 exposed
    

    可以发现,此时可以创建很多个svc。

    [root@k8scloude1 safe]# kubectl get svc -o wide
    NAME   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE   SELECTOR
    svc1   ClusterIP   10.98.89.245     <none>        80/TCP    21s   test=podtest
    svc2   ClusterIP   10.109.215.162   <none>        80/TCP    15s   test=podtest
    svc3   ClusterIP   10.96.10.12      <none>        80/TCP    12s   test=podtest
    svc4   ClusterIP   10.109.113.59    <none>        80/TCP    7s    test=podtest
    

    删除svc。

    [root@k8scloude1 safe]# kubectl delete svc svc1 svc2 svc3 svc4
    service "svc1" deleted
    service "svc2" deleted
    service "svc3" deleted
    service "svc4" deleted
    
    [root@k8scloude1 safe]# kubectl get svc -o wide
    No resources found in safe namespace.
    

    现在还没有资源配额resourcequotas。

    [root@k8scloude1 safe]# kubectl get resourcequotas 
    No resources found in safe namespace.
    

    配置ResourceQuota,功能为创建了一个名为"resourcequota"的ResourceQuota资源对象,用于限制集群中的资源配额。使用该ResourceQuota,最多只能创建4个Pod和4个Service。当达到或超过这些限制时,将无法再创建新的Pod或Service,从而避免过度消耗资源并提高整个集群的可靠性和稳定性。

    [root@k8scloude1 safe]# vim resourcequotas.yaml 
    
    #只能创建4个pod和4个svc
    [root@k8scloude1 safe]# cat resourcequotas.yaml 
    apiVersion: v1
    kind: ResourceQuota
    metadata:
      name: resourcequota
    spec:
      #hard:指定资源的硬性限制,即最大允许使用的资源数量。
      hard:
        #pods: "4":设置该集群中最多可以创建4个Pod。
        pods: "4"
        #services: "4":设置该集群中最多可以创建4个Service。
        services: "4"
    

    创建ResourceQuota。

    [root@k8scloude1 safe]# kubectl apply -f resourcequotas.yaml 
    resourcequota/resourcequota created
    

    查看ResourceQuota。

    [root@k8scloude1 safe]# kubectl get resourcequotas 
    NAME            AGE   REQUEST                    LIMIT
    resourcequota   6s    pods: 1/4, services: 0/4   
    

    现在有1个pod,0个service。

    [root@k8scloude1 safe]# kubectl get pod
    NAME      READY   STATUS    RESTARTS   AGE
    podtest   1/1     Running   0          10m
    
    [root@k8scloude1 safe]# kubectl get svc
    No resources found in safe namespace.
    

    查看resourcequota的描述信息。

    [root@k8scloude1 safe]# kubectl describe -f resourcequotas.yaml 
    Name:       resourcequota
    Namespace:  safe
    Resource    Used  Hard
    --------    ----  ----
    pods        1     4
    services    0     4
    

    创建svc。

    [root@k8scloude1 safe]# kubectl expose --name=svc1 pod podtest --port=80
    service/svc1 exposed
    
    [root@k8scloude1 safe]# kubectl expose --name=svc2 pod podtest --port=80
    service/svc2 exposed
    
    [root@k8scloude1 safe]# kubectl expose --name=svc3 pod podtest --port=80
    service/svc3 exposed
    
    [root@k8scloude1 safe]# kubectl expose --name=svc4 pod podtest --port=80
    service/svc4 exposed
    
    [root@k8scloude1 safe]# kubectl get svc
    NAME   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
    svc1   ClusterIP   10.110.233.61    <none>        80/TCP    37s
    svc2   ClusterIP   10.105.108.94    <none>        80/TCP    34s
    svc3   ClusterIP   10.105.226.140   <none>        80/TCP    29s
    svc4   ClusterIP   10.98.10.38      <none>        80/TCP    25s
    

    svc只能创建4个,第五个就创建失败了。

    [root@k8scloude1 safe]# kubectl expose --name=svc5 pod podtest --port=80
    Error from server (Forbidden): services "svc5" is forbidden: exceeded quota: resourcequota, requested: services=1, used: services=4, limited: services=4
    

    查看resourcequotas,可以看到service配额已经满了。

    [root@k8scloude1 safe]# kubectl get resourcequotas 
    NAME            AGE     REQUEST                    LIMIT
    resourcequota   2m17s   pods: 1/4, services: 4/4   
    

    删除svc,pod,resourcequotas。

    [root@k8scloude1 safe]# kubectl delete svc svc1 svc2
    service "svc1" deleted
    service "svc2" deleted
    
    [root@k8scloude1 safe]# kubectl delete svc svc3 svc4
    service "svc3" deleted
    service "svc4" deleted
    
    [root@k8scloude1 safe]# kubectl delete pod podtest 
    pod "podtest" deleted
    
    [root@k8scloude1 safe]# kubectl delete -f resourcequotas.yaml 
    resourcequota "resourcequota" deleted
    

    九.总结

    本篇博客介绍了Kubernetes中资源限制的概念以及如何使用resourcesLimitRangeResourceQuota来管理容器资源。通过合理配置资源限制,可以提高集群的稳定性和性能,并确保资源的公平分配和有效利用。

    资源限制是Kubernetes中重要的管理和控制机制,对于构建可靠且高效的应用程序环境至关重要。

  • 相关阅读:
    Web3.0的测试题
    node插件MongoDB(四)—— 库mongoose 的文档操作使用
    机器学习训练与参数优化的一般过程 (讨论)
    高可用系统有哪些设计原则
    Linux —— 线程
    ucharts最详细教程(含踩坑记录)
    ubuntu下个人觉得必备,好用的应用软件
    JMeter笔记8 | JMeter关联
    python:PyWebIO 模仿 mdict 查英汉词典
    Allegro分Partition操作指导
  • 原文地址:https://www.cnblogs.com/renshengdezheli/p/17528247.html