百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

k8s实践(六):Pod资源管理 k8s pod资源限制

bigegpt 2024-10-26 08:18 5 浏览

一、计算资源管理(Compute Resources)

1. 概念

??在配置Pod时,我们可以为其中的每个容器指定需要使用的计算资源(CPU和内存)。计算资源的配置项分为两种:Requests和Limits。Requests表示容器希望被分配到的、可完全保证的资源量(资源请求量);Limits是容器最多能使用的资源量的上限(资源限制量)。

??资源请求量能够保证Pod有足够的资源来运行,资源限制量则是防止某个Pod无限制地使用资源,导致其他Pod崩溃。

??我们创建一个pod时,可以指定容器对CPU和内存的资源请求量及资源限制量,它们并不在pod里定义,而是针对每个容器单独指定。pod对资源的请求量和限制量是它所包含的所有容器的请求量和限制量之和。

CPU和内存的Requests和Limits有如下特点:


  • Requests和Limits都是可选的。在Pod创建和更新时,如果未设置Requests和Limits,则使用系统提供的默认值,该默认值取决于集群配置。
  • 如果Requests没有配置,默认被设置等于Limits。
  • 任何情况下Limits都应该设置为大于或等于Requests。

2. 查看节点资源总量

2.1 命令方式

[root@master ~]# kubectl describe nodes 

2.2 Dashboard方式

3. requests

3.1 创建包含资源requests的pod

[root@master ~]# more 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内存
  nodeName: node01
[root@master ~]# kubectl apply -f requests-pod.yaml 
pod/requests-pod created

在Kubernetes系统上,l个单位的CPU相当于虚拟机上的l颗虚拟CPU(vCPU)或物理机上的一个超线程(Hyperthread,或称为一个逻辑CPU),它支持分数计量方式,一个核心(1core)相当于1000个微核心(millicores),因此500m相当于是0.5个核心,即二分之一个核心。内存的计量方式与日常使用方式相同,默认单位是字节,也可以使用E,P、T、G、M和K作为单位后缀,或Ei、Pi、Ti、Gi、Mi和Ki形式的单位后缀。

3.2 查看pod

[root@master ~]# kubectl get po -o wide
[root@master ~]# kubectl describe po requests-pod

3.3 基于requests的pod调度机制

3.3.1 不指定requests

[root@master ~]# kubectl delete all --all
[root@master ~]# more deploy-busybox.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: busybox
spec:
  selector:
    matchLabels:
      env: prod
  replicas: 10 
  template:
    metadata:
      labels:
        env: prod
    spec:
      containers:
      - name: busybox
        image: busybox
        args:
        - /bin/sh
        - -c
        - sleep 60000
      nodeSelector:
        node: node01
[root@master ~]# kubectl apply -f deploy-busybox.yaml 
deployment.apps/busybox created

若不指定资源请求量,节点node01上可成功运行10个pod

3.3.2 OutOfmemory

[root@master ~]# more 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: 800Mi    #容器申请800M内存
  nodeName: node01
[root@master ~]# more requests-pod-2.yaml                             
apiVersion: v1
kind: Pod
metadata:
  name: requests-pod-2
spec:
  containers:
  - image: busybox
    name: busybox 
    args:
    - /bin/sh
    - -c
    - sleep 60000
    resources:
      requests:
        cpu: 500m 
        memory: 800Mi
  nodeName: node01
[root@master ~]# kubectl apply -f requests-pod.yaml 
pod/requests-pod created
[root@master ~]# kubectl get po -o wide             
NAME           READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
requests-pod   1/1     Running   0          4s    10.244.1.67   node01   <none>           <none>
[root@master ~]# kubectl apply -f requests-pod-2.yaml 
pod/requests-pod-2 created
[root@master ~]# kubectl get po -o wide               
NAME             READY   STATUS        RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
requests-pod     1/1     Running       0          14s   10.244.1.67   node01   <none>           <none>
requests-pod-2   0/1     OutOfmemory   0          2s    <none>        node01   <none>           <none>

报节点node01 内存资源不足,pod requests-pod-2调度失败

3.3.3 OutOfcpu

[root@master ~]# kubectl delete all --all 
[root@master ~]# more 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: 1           #容器申请一个CPU核心时间
        memory: 80Mi    #容器申请80M内存
  nodeName: node01
[root@master ~]# more requests-pod-2.yaml   
apiVersion: v1
kind: Pod
metadata:
  name: requests-pod-2
spec:
  containers:
  - image: busybox
    name: busybox 
    args:
    - /bin/sh
    - -c
    - sleep 60000
    resources:
      requests:
        cpu: 1 
        memory: 80Mi
  nodeName: node01
[root@master ~]# kubectl apply -f requests-pod.yaml 
pod/requests-pod created
[root@master ~]# kubectl get po -o wide             
NAME           READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
requests-pod   1/1     Running   0          4s    10.244.1.68   node01   <none>           <none>
[root@master ~]# kubectl apply -f requests-pod-2.yaml 
pod/requests-pod-2 created
[root@master ~]# kubectl get po -o wide               
NAME             READY   STATUS     RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
requests-pod     1/1     Running    0          13s   10.244.1.68   node01   <none>           <none>
requests-pod-2   0/1     OutOfcpu   0          2s    <none>        node01   <none>           <none>

报节点node01 cpu资源不足,pod requests-pod-2调度失败

3.3.4 结论

  • 调度器在调度时并不关注各类资源在当前时刻的实际使用量(node01可以同时运行10个busybox pod)
  • 调度器只关心节点上部署的所有pod的资源申请量之和(超出时就会报OutOfmemory或OutOfcpu)
  • 尽管现有pods的资源实际使用量可能小于它的申请量,但如果使用基于实际资源消耗量的调度算法将打破系统为这些已部署成功的pods提供足够资源的保证

4. limits

4.1 创建包含资源limits的pod

[root@master ~]# more limited-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: node01
[root@master ~]# kubectl apply -f limited-pod.yaml 
pod/limited-pod created
[root@master ~]# kubectl get po -o wide
NAME          READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
limited-pod   1/1     Running   0          12s   10.244.1.75   node01   <none>           <none>

创建pod limited-pod,资源限制为cpu 2核,内存2G

4.2 limits overcommitted

4.2.1 创建pod

创建limited-pod和limited-pod-2,cpu为2核,内存2G,pod运行正常。

4.2.2 查看node01资源使用

4.2.3 结论

  • 节点上所有pod的资源limits之和可以超过节点资源总量的100%
  • requests不同的是,limits并不会影响pod的调度结果

二、服务质量管理(QoS)

1. 概念

??前面曾提到过,Kubernetes允许节点资源对Limits的过载使用,这意味着节点无法同时满足其上的所有Pod对象以资源满载的方式运行。于是,在内存资源紧缺时,应该以何种次序先后终止哪些Pod对象?Kubernetes无法自行对此做出决策,它需要借助于Pod对象的优先级完成判定。根据Pod对象的requests和limits属性,Kubernetes将Pod象归类到BestEffort、Burstable和Guaranteed三个服务质量(Quality of Service,QoS)类别下,具体说明如下。


  • Guaranteed:每个容器都为CPU资源设置了具有相同值的requests和limits属性,以及每个容器都为内存资源设置了具有相同值的requests和limits属性的Pod资源会自动归属于此类别,这类Pod资源具有最高优先级。
  • Burstable:至少有一个容器设置了CPU或内存资源requests属性,但不满足Guaranteed类别要求的Pod资源将自动归属于此类别,它们具有中等优先级。
  • BestEffort:未为任何一个容器设置requests或limits属性的Pod资源将自动归属于此类别,它们的优先级为最低级别。

在一个overcommitted的系统,QoS等级决定着哪个容器第一个被杀掉,这样释放出的资源可以提供给高优先级的pod使用。BestEffort等级的pod首先被杀掉,其次是Burstable pod, 最后是Guaranteed pod。Guaranteed pod只有在系统进程需要内存时才会被杀掉。

2. 定义QoS

资源的requests、limits和QoS等级

3. 相同等级QoS容器处理

每个行状态容器都有其OOM得分,得分越高越会被优先杀死。OOM得分主要根据两个纬度进行计算:由QoS类别继承而来的默认分值和容器的可用内存资源比例。同等类别的Pod资源的默认分值相同,同等级别优先级的Pod资源在OOM时,与自身的requests属性相比,其内存占用比例最大的Pod对象将被首先杀死。

三、资源配置范围管理(LimitRange)

1. 概念

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

2. 为什么需要LimitRange

??为单个容器设置资源requests和limits很有必要性:1.提升QoS等级,防止在OOM时被首先kill;2.默认情况下Pod会以无限制的CPU和内存运行,很有可能因故吞掉所在工作节点上的所有可用计算资源。

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

3 创建LimitRange

[root@master ~]# 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
[root@master ~]# kubectl apply -f limits.yaml 
limitrange/limitrange created

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

4. 查看LimitRange

[root@master ~]# kubectl describe limitranges limitrange 

5. LimitRange测试

5.1 requests和limits默认值

新建pod

[root@master ~]# more default.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: default-pod
spec:
  containers:
  - image: busybox
    name: busybox 
    args:
    - /bin/sh
    - -c
    - sleep 60000
[root@master ~]# kubectl apply -f default.yaml 
pod/default-pod created
[root@master ~]# kubectl get po -o wide           
NAME            READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
default-pod     1/1     Running   0          8s    10.244.2.43   node02   <none>           <none>
limited-pod     1/1     Running   1          22h   10.244.1.81   node01   <none>           <none>
limited-pod-2   1/1     Running   1          22h   10.244.1.82   node01   <none>           <none>

新建pod default-pod,yaml中未指定requests和limits

查看pod

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

5.2 强制限制

5.2.1 cpu超限制

[root@master ~]# 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

5.2.2 内存超限制

[root@master ~]# 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

四、资源配额管理(ResourceQuota)

1. 概念

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

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

资源配额类型:

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

2. ResourceQuota作用

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

3. 为CPU和内存创建ResourceQuota

[root@master ~]# more 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
[root@master ~]# kubectl apply -f quota-cpu-memory.yaml 
resourcequota/cpu-and-mem created

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

3.1 查看ResourceQuota

[root@master ~]# kubectl describe resourcequotas cpu-and-mem

3.2 resourcequota测试

[root@master ~]# kubectl run  quota-test --image=busybox  --limits='cpu=200m,memory=90Mi' --replicas=10 sleep 6000
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/quota-test created
[root@master ~]# kubectl get po -o wide
NAME                          READY   STATUS    RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES
default-pod                   1/1     Running   0          31m     10.244.2.52   node02   <none>           <none>
quota-test-5d4f79c664-2tq66   1/1     Running   0          5m44s   10.244.1.90   node01   <none>           <none>
quota-test-5d4f79c664-cvptj   1/1     Running   0          5m44s   10.244.0.68   master   <none>           <none>
quota-test-5d4f79c664-ph79j   1/1     Running   0          5m44s   10.244.2.64   node02   <none>           <none>
quota-test-5d4f79c664-tvwpz   1/1     Running   0          5m44s   10.244.2.65   node02   <none>           <none>

发现只运行了4个pod,原因是requests的cpu为200(requests值未设置时与limits相同),resourcequotas中requests.cpu的限制值为1000m,系统之前使用了100m(default-pod),故只有900m可用,所以最多只能新建4个pod

4. 限制可创建对象的个数

[root@master ~]# more 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@master ~]# kubectl apply -f quota-count.yaml 
resourcequota/count-quota created

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

pod

Replication Controller

Secret

ConfigMap

PVC

Service

LoadBalancer

NodePort

ssd PVC

10

5

10

10

4

5

1

2

2

4.1 查看ResourceQuota

[root@master ~]# kubectl describe resourcequotas count-quota 

4.2 resourcequota测试

[root@master ~]# kubectl create service nodeport nodeport01 --tcp=5678:8080
service/nodeport01 created
[root@master ~]# kubectl create service nodeport nodeport02 --tcp=5678:8081
service/nodeport02 created
[root@master ~]# kubectl create service nodeport nodeport03 --tcp=5678:8082
Error from server (Forbidden): services "nodeport03" is forbidden: exceeded quota: count-quota, requested: services.nodeports=1, used: services.nodeports=2, limited: services.nodeports=2

services.nodeports只能创建2个,当创建第三个时报错。

5. 特定的pod状态或者QoS等级指定配额

[root@master ~]# more quota-scoped.yaml 
apiVersion: v1
kind: ResourceQuota
metadata:
  name: scoped-quota 
spec:
  scopes:
  - BestEffort
  - NotTerminating
  hard:
    pods: 4
[root@master ~]# kubectl apply -f quota-scoped.yaml 
resourcequota/scoped-quota created

这个quota只会应用于拥有BestEffort QoS以及没有设置有效期的pod上,这样的pod只允许存在4个。

5.1 查看ResourceQuota

[root@master ~]# kubectl describe resourcequotas scoped-quota 

resourcequota测试思路同cpu-and-mem和count-quota,这里不再赘述。

本文所有脚本和配置文件已上传github:https://github.com/loong576/k8s-Managing-pods-computational-resources.git

相关推荐

Docker篇(二):Docker实战,命令解析

大家好,我是杰哥上周我们通过几个问题,让大家对于Docker有了一个全局的认识。然而,说跟练往往是两个概念。从学习的角度来说,理论知识的学习,往往只是第一步,只有经过实战,才能真正掌握一门技术所以,本...

docker学习笔记——安装和基本操作

今天学习了docker的基本知识,记录一下docker的安装步骤和基本命令(以CentOS7.x为例)一、安装docker的步骤:1.yuminstall-yyum-utils2.yum-con...

不可错过的Docker完整笔记(dockerhib)

简介一、Docker简介Docker是一个开源的应用容器引擎,基于Go语言并遵从Apache2.0协议开源。Docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,...

扔掉运营商的 IPTV 机顶盒,全屋全设备畅看 IPTV!

其实现在看电视节目的需求确实大大降低了,折腾也只是为了单纯的让它实现,享受这个过程带来的快乐而已,哈哈!预期构想家里所有设备直接接入网络随时接收并播放IPTV直播(电信点播的节目不是太多,但好在非常稳...

第五节 Docker 入门实践:从 Hello World 到容器操作

一、Docker容器基础运行(一)单次命令执行通过dockerrun命令可以直接在容器中执行指定命令,这是体验Docker最快捷的方式:#在ubuntu:15.10容器中执行ech...

替代Docker build的Buildah简单介绍

Buildah是用于通过较低级别的coreutils接口构建OCI兼容镜像的工具。与Podman相似,Buildah不依赖于Docker或CRI-O之类的守护程序,并且不需要root特权。Builda...

Docker 命令大全(docker命令大全记录表)

容器生命周期管理run-创建并启动一个新的容器。start/stop/restart-这些命令主要用于启动、停止和重启容器。kill-立即终止一个或多个正在运行的容器rm-于删除一个或...

docker常用指令及安装rabbitMQ(docker安装rabbitmq配置环境)

一、docker常用指令启动docker:systemctlstartdocker停止docker:systemctlstopdocker重启docker:systemctlrestart...

使用Docker快速部署Storm环境(docker部署confluence)

Storm的部署虽然不是特别麻烦,但是在生产环境中,为了提高部署效率,方便管理维护,使用Docker来统一管理部署是一个不错的选择。下面是我开源的一个新的项目,一个配置好了storm与mono环境的D...

Docker Desktop安装使用指南:零基础教程

在之前的文章中,我多次提到使用Docker来安装各类软件,尤其是开源软件应用。鉴于不少读者对此有需求,我决定专门制作一期关于Docker安装与使用的详细教程。我主要以Macbook(Mac平台)为例进...

Linux如何成功地离线安装docker(linux离线安装httpd)

系统环境:Redhat7.2和Centos7.4实测成功近期因项目需要用docker,所以记录一些相关知识,由于生产环境是不能直接连接互联网,尝试在linux中离线安装docker。步骤1.下载...

Docker 类面试题(常见问题)(docker面试题目)

Docker常见问题汇总镜像相关1、如何批量清理临时镜像文件?可以使用sudodockerrmi$(sudodockerimages-q-fdanging=true)命令2、如何查看...

面试官:你知道Dubbo怎么优雅上下线的吗?你:优雅上下线是啥?

最近无论是校招还是社招,都进行的如火如荼,我也承担了很多的面试工作,在一次面试过程中,和候选人聊了一些关于Dubbo的知识。Dubbo是一个比较著名的RPC框架,很多人对于他的一些网络通信、通信协议、...

【Docker 新手入门指南】第五章:Hello Word

适合人群:完全零基础新手|学习目标:30分钟掌握Docker核心操作一、准备工作:先确认是否安装成功打开终端(Windows用户用PowerShell或GitBash),输入:docker--...

松勤软件测试:详解Docker,如何用portainer管理Docker容器

镜像管理搜索镜像dockersearch镜像名称拉取镜像dockerpullname[:tag]列出镜像dockerimages删除镜像dockerrmiimage名称或id删除...