本章概述
- kubernetes资源限制概括
- kubernetes对单个容器的CPU及memory实现资源限制
- kubernetes对单个pod的CPU及memory实现资源限制
- kubernetes对整个namespace的CPU及memory实现资源限制
11.1 kubernetes资源限制概括
前言
1、如果运行的容器没有定义资源(memory、CPU)等限制,但是在namespace定义了LimitRange限制,那么该容器会继承LimitRange中的默认限制。
2、如果namespace没有定义LimitRange限制,那么该容器可以只要宿主机的最大可用资源,直到无资源可用而触发宿主机(OOM Killer)。
CPU资源分配:
官网链接:https://kubernetes.io/zh/docs/tasks/configure-pod-container/assign-cpu-resource/
CPU 以核心为单位进行限制,单位可以是整核、浮点核心数或毫核(m/milli)
如:2=2核心=200% #使用2核CPU或者200%的CPU
0.5=500m=50% #使用500毫核或者50%的CPU
1.2=1200m=120% #使用1200毫核或者120%的CPU
内存资源分配:
官网链接:https://kubernetes.io/zh/docs/tasks/configure-pod-container/assign-memory-resource/
memory 以字节为单位,单位可以是E、P、T、G、M、K、Ei、Pi、Ti、Gi、Mi、Ki
如:1536Mi=1.5Gi
requests(请求)为kubernetes scheduler执行pod调度时node节点至少需要拥有的资源。(如果不满足则pod不会向该node调度)。
limits(限制)为pod运行成功后最多可以使用的资源上限。
limits值要大于等于request的值。(两个值建议不要相差太大或者相等)
需要注意的是:requests值和limits值两个值之间相差越小越好,建议相等
原因:假如1个pod内存的requests值为100M,limits值为512M,假设存在node,内存为300M,满足该pod的requests值,将该pod调度到node上。当运行一段时间后,pod内存的使用量逐渐增加,pod的limits值为512M,pod就会继续向node申请内存至512M,但node只有300M内存,不能提供超出300M的内存,就会因内存不足出现OOM。
如果requests值和limits值相等,调度pod时只会选取满足条件的node(即内存大于512M),此时即使pod使用最大内存,node也可以满足
11.2 kubernetes对单个容器的CPU及memory实现资源限制
11.2.1 对单个容器内存进行限制
示例:为了便于实验,使用压测镜像拉起容器
vim case1-pod-memory-limit.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: limit-test-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels: #rs or deployment
app: limit-test-pod
# matchExpressions:
# - {key: app, operator: In, values: [ng-deploy-80,ng-rs-81]}
template:
metadata:
labels:
app: limit-test-pod
spec:
containers:
- name: limit-test-container
image: lorel/docker-stress-ng #使用压测镜像
resources:
limits:
memory: "512Mi" #内存限制最多可用512M
requests:
memory: "100Mi" #内存最低为100M
#command: ["stress"]
args: ["--vm", "2", "--vm-bytes", "256M"] #通过传参启用两个进程,占用2核CPU,2*256M(即512)内存
#nodeSelector:
# env: group1
创建pod
kubectl apply -f case1-pod-memory-limit.yml
查看pod的cpu和内存使用情况
kubectl top pod -n magedu
可以看到容器占用2核左右CPU和512M内存,由于CPU没做限制,因此CPU会占用2核,而内存则不会超过limits的值
验证:
调整内存limits值,可限制容器使用的内存大小
将yaml文件中内存的limtis值从512M调整为256M,查看容器内存使用情况
kubectl top pod -n magedu
容器内存占用从512M左右变成256M左右,说明内存限制已生效
11.2.2 对单个容器CPU进行限制
示例:
vim case2-pod-memory-and-cpu-limit.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: limit-test-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels: #rs or deployment
app: limit-test-pod
# matchExpressions:
# - {key: app, operator: In, values: [ng-deploy-80,ng-rs-81]}
template:
metadata:
labels:
app: limit-test-pod
spec:
containers:
- name: limit-test-container
image: lorel/docker-stress-ng
resources:
limits:
cpu: "1.3" #限制CPU最多使用1.3核
memory: "512Mi"
requests:
cpu: "500m" #要求容器CPU最低为500毫核
memory: "100Mi"
#command: ["stress"]
args: ["--vm", "2", "--vm-bytes", "256M"] #通过传参启用两个进程,占用2核CPU,2*256M(即512)内存
#nodeSelector:
# env: group1
创建pod
kubectl apply -f case2-pod-memory-and-cpu-limit.yml
查看pod CPU使用率
可以看到CPU使用率在1.3核左右,说明CPU限制已生效
使用docker stats命令可以查看宿主机上容器资源使用情况
11.3 kubernetes对单个pod的CPU及memory实现资源限制
LimitRange概述:
官网链接:https://kubernetes.io/zh/docs/concepts/policy/limit-range/
Limit Range是对具体某个Pod或容器的资源使用进行限制,防止单个pod会占用整个命名空间的资源
管理员在一个命名空间内创建一个 LimitRange 对象。
用户在命名空间内创建 Pod ,Container 和 PersistentVolumeClaim 等资源。
LimitRanger 准入控制器对所有没有设置计算资源需求的 Pod 和 Container 设置默认值与限制值, 并跟踪其使用量以保证没有超出命名空间中存在的任意 LimitRange 对象中的最小、最大资源使用量以及使用量比值。
若创建或更新资源(Pod、 Container、PersistentVolumeClaim)违反了 LimitRange 的约束, 向 API 服务器的请求会失败,并返回 HTTP 状态码 403 FORBIDDEN 与描述哪一项约束被违反的消息。
若命名空间中的 LimitRange 启用了对 cpu 和 memory 的限制, 用户必须指定这些值的需求使用量与限制使用量。否则,系统将会拒绝创建 Pod。
LimitRange 的验证仅在 Pod 准入阶段进行,不对正在运行的 Pod 进行验证。
限制范围:
限制namespace中每个Pod或容器的最小与最大计算资源
限制namespace中每个Pod或容器计算资源request、limit之间的比例
限制namespace中每个存储卷声明(PersistentVolumeClaim)可使用的最小与最大存储空间
设置namespace中容器默认计算资源的request、limit,并在运行时自动注入到容器中
示例:创建limitrange
vim case3-LimitRange.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: limitrange-magedu
namespace: magedu
spec:
limits:
- type: Container #限制的资源类型
max:
cpu: "2" #限制单个容器的最大CPU
memory: "2Gi" #限制单个容器的最大内存
min:
cpu: "500m" #限制单个容器的最小CPU
memory: "512Mi" #限制单个容器的最小内存
default:
cpu: "500m" #默认单个容器的CPU限制
memory: "512Mi" #默认单个容器的内存限制
defaultRequest:
cpu: "500m" #默认单个容器的CPU创建请求
memory: "512Mi" #默认单个容器的内存创建请求
maxLimitRequestRatio:
cpu: 2 #限制CPU limit/request比例最大为2,若CPU requests值为500m,则limits值不能超过1000m。
memory: 1.5 #限制内存limit/request比例最大为1.5,若内存requets值为550Mi,则limits值不能超过750Mi。
- type: Pod
max:
cpu: "4" #限制单个Pod的最大CPU
memory: "4Gi" #限制单个Pod最大内存
- type: PersistentVolumeClaim
max:
storage: 50Gi #限制PVC最大的requests.storage
min:
storage: 30Gi #限制PVC最小的requests.storage
创建LimitRange
kubectl apply -f case3-LimitRange.yaml
查看LimitRange
先获取LimitRange名称
kubectl get limitranges -n magedu
再查看LimitRange具体内容
kubectl describe limitranges limitrange-magedu -n magedu
11.3.1 CPU与内存 RequestRatio比例限制
验证:使用CPU的requets/limits的比例值超过2的yaml文件创建容器
使用yaml文件创建pod
vim case4-pod-RequestRatio-limit.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
app: magedu-wordpress-deployment-label
name: magedu-wordpress-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-wordpress-selector
template:
metadata:
labels:
app: magedu-wordpress-selector
spec:
containers:
- name: magedu-wordpress-nginx-container
image: nginx:1.16.1
imagePullPolicy: Always
ports:
- containerPort: 80
protocol: TCP
name: http
env:
- name: "password"
value: "123456"
- name: "age"
value: "18"
resources:
limits:
cpu: 2
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
- name: magedu-wordpress-php-container
image: php:5.6-fpm-alpine
imagePullPolicy: Always
ports:
- containerPort: 80
protocol: TCP
name: http
env:
- name: "password"
value: "123456"
- name: "age"
value: "18"
resources:
limits:
cpu: 1
#cpu: 2
memory: 1Gi
requests:
cpu: 2
memory: 512Mi
---
kind: Service
apiVersion: v1
metadata:
labels:
app: magedu-wordpress-service-label
name: magedu-wordpress-service
namespace: magedu
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
nodePort: 30036
selector:
app: magedu-wordpress-selector
注意:以上yaml文件中CPU的配置违反了:(1)magedu-wordpress-nginx-container容器的CPU requests/limits比例值大于2
创建pod
kubectl apply -f case4-pod-RequestRatio-limit.yaml
查看pod,获取不到pod信息
这是因为违反limitrange的pod无法通过获取pod的方式查看,需要查看pod所在的deployment控制器信息
(1)先获取deployment名称
可以发现控制器READY状态为0/1
(2)获取deployment信息
kubectl get deployments magedu-wordpress-deployment -n magedu -o json
信息提示:limitrange配置的CPU最大限制的比值为2,当前比值为4
修改yaml文件:需要更改第一个容器magedu-wordpress-nginx-container的cpu requests值或者limits值(如将requests值更改为1.2)
11.3.2 CPU与内存超分限制
验证:单个pod使用的CPU超过设置的值
编辑yaml文件
vim case4-pod-RequestRatio-limit.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
app: magedu-wordpress-deployment-label
name: magedu-wordpress-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-wordpress-selector
template:
metadata:
labels:
app: magedu-wordpress-selector
spec:
containers:
- name: magedu-wordpress-nginx-container
image: nginx:1.16.1
imagePullPolicy: Always
ports:
- containerPort: 80
protocol: TCP
name: http
env:
- name: "password"
value: "123456"
- name: "age"
value: "18"
resources:
limits:
cpu: 2
memory: 1Gi
requests:
cpu: 1.2
memory: 512Mi
- name: magedu-wordpress-php-container
image: php:5.6-fpm-alpine
imagePullPolicy: Always
ports:
- containerPort: 80
protocol: TCP
name: http
env:
- name: "password"
value: "123456"
- name: "age"
value: "18"
resources:
limits:
cpu: 3
#cpu: 2
memory: 1Gi
requests:
cpu: 1.5
memory: 512Mi
---
kind: Service
apiVersion: v1
metadata:
labels:
app: magedu-wordpress-service-label
name: magedu-wordpress-service
namespace: magedu
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
nodePort: 30036
selector:
app: magedu-wordpress-selector
注意:以上yaml文件中违反了两个条件:(1)单个pod中两个容器的cpu最大值超过4 (2)单个容器的cpu最大值超过2。
创建pod
kubectl apply -f case4-pod-RequestRatio-limit.yaml
查看pod,获取不到pod信息
原因
这是因为违反limitrange的pod无法通过获取pod的方式查看,需要查看pod所在的deployment控制器信息
(1)先获取deployment名称
可以发现控制器READY状态为0/1
(2)获取deployment信息
kubectl get deployments magedu-wordpress-deployment -n magedu -o json
提示:单个容器cpu为3,超过2;单个pod的cpu为5,超过4
修改:将第二个容器magedu-wordpress-php-container的CPU limits修改为2即可
11.4 kubernetes对整个namespace的CPU及memory实现资源限制
当多个用户或团队共享具有固定节点数目的集群时,人们会担心有人使用超过其基于公平原则所分配到的资源量。
资源配额是帮助管理员解决这一问题的工具。
资源配额,通过 ResourceQuota 对象来定义,对每个命名空间的资源消耗总量提供限制。 包括:(1)限定某个对象类型(如Pod、service)可创建对象的总数;(2)限定某个对象类型可消耗的计算资源(CPU、内存)与存储资源(存储卷声明)总数
资源配额的工作方式如下:
不同的团队可以在不同的命名空间下工作,目前这是非约束性的,在未来的版本中可能会通过 ACL (Access Control List 访问控制列表) 来实现强制性约束。
集群管理员可以为每个命名空间创建一个或多个 ResourceQuota 对象。
当用户在命名空间下创建资源(如 Pod、Service 等)时,Kubernetes 的配额系统会 跟踪集群的资源使用情况,以确保使用的资源用量不超过 ResourceQuota 中定义的硬性资源限额。
如果资源创建或者更新请求违反了配额约束,那么该请求会报错(HTTP 403 FORBIDDEN), 并在消息中给出有可能违反的约束。
如果命名空间下的计算资源 (如 cpu 和 memory)的配额被启用,则用户必须为 这些资源设定请求值(request)和约束值(limit),否则配额系统将拒绝 Pod 的创建。 提示: 可使用 LimitRanger 准入控制器来为没有设置计算资源需求的 Pod 设置默认值。
官网链接:https://kubernetes.io/zh/docs/concepts/policy/resource-quotas/
示例:创建ResourceQuota
vim case6-ResourceQuota-magedu.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: quota-magedu
namespace: magedu #指定所在的namespace,也是限制的namespace
spec:
hard:
requests.cpu: "8" #指定magedu namespace中pod可使用的CPU request值
limits.cpu: "8" #指定magedu namespace中pod可使用的CPU limits值
requests.memory: 4Gi #指定magedu namespace中pod可使用的内存request值
limits.memory: 4Gi #指定magedu namespace中pod可使用的内存limits值
requests.nvidia.com/gpu: 4 #指定magedu namespace中pod可使用的gpu imits值
pods: "5" #指定magedu namespace中可创建的pod总数
services: "6" #指定magedu namespace中可创建的service总数
创建ResourceQuota
kubectl apply -f case6-ResourceQuota-magedu.yaml
查看ResourceQuota
kubectl get resourcequotas -n magedu
kubectl describe resourcequotas quota-magedu -n magedu
11.4.1 Pod副本数限制
注意:在resourcequota创建之前创建的pod不受影响,但是在resourcequota创建之后,会将已经创建的pod计算在内。如:resourcequota限制当前namespace可以创建5个pod,如果在esourcequota创建之前已经创建了6个pod,那么新建的pod将无法被创建。
验证:创建pod
编辑yaml文件
vim case7-namespace-pod-limit-test.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
app: magedu-nginx-deployment-label
name: magedu-nginx-deployment
namespace: magedu
spec:
replicas: 5
selector:
matchLabels:
app: magedu-nginx-selector
template:
metadata:
labels:
app: magedu-nginx-selector
spec:
containers:
- name: magedu-nginx-container
image: nginx:1.16.1
imagePullPolicy: Always
ports:
- containerPort: 80
protocol: TCP
name: http
env:
- name: "password"
value: "123456"
- name: "age"
value: "18"
resources:
limits:
cpu: 1
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
---
kind: Service
apiVersion: v1
metadata:
labels:
app: magedu-nginx-service-label
name: magedu-nginx-service
namespace: magedu
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
#nodePort: 30033
selector:
app: magedu-nginx-selector
查看pod,无法获取pod信息
查看deployment控制器信息(注意要先获取控制器名称)
kubectl get deployments.apps magedu-nginx-deployment -n magedu -o json
提示当前pod数量超出了resourcequota限制的数量
修改:删除其他无用的pod,或者修改resoucequota中pod限制数量
修改之后再查看pod,pod已经开始创建
11.4.2 CPU总计核心数限制
验证:创建pod超出resourcequota限制
编辑yaml文件
vim case8-namespace-cpu-limit-test.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
app: magedu-nginx-deployment-label
name: magedu-nginx-deployment
namespace: magedu
spec:
replicas: 4
selector:
matchLabels:
app: magedu-nginx-selector
template:
metadata:
labels:
app: magedu-nginx-selector
spec:
containers:
- name: magedu-nginx-container
image: nginx:1.16.1
imagePullPolicy: Always
ports:
- containerPort: 80
protocol: TCP
name: http
env:
- name: "password"
value: "123456"
- name: "age"
value: "18"
resources:
limits:
cpu: 1
memory: 2Gi
requests:
cpu: 1
memory: 512Mi
---
kind: Service
apiVersion: v1
metadata:
labels:
app: magedu-nginx-service-label
name: magedu-nginx-service
namespace: magedu
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
nodePort: 30033
selector:
app: magedu-nginx-selector
创建pod
kubectl apply -f case8-namespace-cpu-limit-test.yaml
查看pod,只有2个pod
这是因为:resourcequota限制namespace只能使用4G内存,而单个pod内存为2G,则只能创建2个pod
获取deployment控制器,READY为2/4
查看deployment控制器信息
信息提示:resourcequota限制内存为4G,当前使用超出了4G,无法创建
修改:修改resourcequota的限制
文章评论