k8s超卖验证
一、测试内存限制1.1 环境准备名词说明:limits:容器能使用资源的最大值requests:容器使用的最小资源需求LimitRange:用来给Namespace增加一个资源限制,包括最小、最大和默认资源 LimitRange 的规则限定在 K8S namespace当前线上业务使用default namespace,且未设置Limit...
一、测试内存限制
1.1 环境准备
名词说明:
limits: 容器能使用资源的最大值
requests: 容器使用的最小资源需求
LimitRange: 用来给Namespace增加一个资源限制,包括最小、最大和默认资源 LimitRange 的规则限定在 K8S namespace
当前线上业务使用default namespace,且未设置LimitRange
Name: default
Labels: <none>
Annotations: <none>
Status: Active
No resource quota.
No resource limits.
1.2 测试创建Pod时指定container的limits但不指定requests
pod test-mem
apiVersion: v1
kind: Pod
metadata:
name: test-mem
labels:
app: test-mem
spec:
containers:
- name: test-mem
image: harbor-test.api.com:80/library/ubuntu-16.04-base:190806
command: ["top","-b"]
resources:
limits:
memory: 100Mi
tolerations:
- effect: "NoSchedule"
operator: "Exists"
- key: "dedicated"
operator: "Equal"
value: "autotest"
nodeSelector:
kubernetes.io/hostname: 192.168.1.1
describe pod可发现,pod成功创建,requests和limits的值均为:100Mi
结论:如果指定pod/container的limits但未指定requests,则创建的pod/container的requests值会取limits的值。
1.3 验证超过limit限制的内存资源后 OOM
实验准备:创建一个pod,内存限制Limits为100Mi
test_mem_pod.yml
apiVersion: v1
kind: Pod
metadata:
name: test-mem
labels:
app: test-mem
spec:
containers:
- name: test-mem
image: harbor-test.api.com:80/library/ubuntu-16.04-base:190806
command: ["top","-b"]
resources:
limits:
memory: 100Mi
requests:
memory: 100Mi
tolerations:
- effect: "NoSchedule"
operator: "Exists"
- key: "dedicated"
operator: "Equal"
value: "autotest"
nodeSelector:
kubernetes.io/hostname: 192.168.1.1
压力测试
容器中安装压力测试工具:
#apt update; apt install -y stress
终端一:容器中压力测试,创建第一个压测,限制内存为50M,可以创建成功,继续第二次压力测试,使用51M内存,创建失败。
终端二:查看宿主机系统日志
可以看出当内存使用超过limit100Mi时,cgruops 出发 OOM
总论:k8s根据limits限制pod使用资源,当内存超过limits时会触发OOM。
二、超卖内存测试
2.1、环境准备
测试超配场景:按mem 1:3超卖,创建pod时设置container的request: 500Mi, limits:1500Mi (单pod单container)
测试预计效果:pod指定发布在宿主机15G的内存机器,除去kubelet和系统预留3G,可用内存为12G,理论可创建pod 24个(单个requests为500MI),单个pod的最大使用内存为1500Mi;
deployment
#创建deployment,设置container的request为500Mi, limits为1500Mi
#cat test_mem_deployment.yml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: test-mem-pod
spec:
replicas: 1
selector:
matchLabels:
app: test-mem-pod
template:
metadata:
labels:
app: test-mem-pod
deployment: test-mem-pod
spec:
nodeSelector:
environment: test
kubernetes.io/hostname: 192.169.1.1
containers:
- image: 'harbor-test.api.com:80/library/ubuntu-16.04-base:190806'
command: ["top","-b"]
name: test-mem-pod
resources:
limits:
memory: 1500Mi
requests:
memory: 500Mi
tolerations:
- effect: "NoSchedule"
operator: "Exists"
- key: "dedicated"
operator: "Equal"
value: "autotest"
#创建deployment, 数量为1
#kubectl create -f test_mem_deployment.yml
2.2 实验测试验证
2.2.1 确认宿主机空闲内存
#free -g
total used free shared buff/cache available
Mem: 15 0 4 0 10 13
Swap: 0 0 0
2.2.2 验证宿主机最大可创建24个pod
在宿主机上创建pod,扩容至30个;可见24个running,其中6个为pending,因为宿主机内存不足,无法调度。
2.2.3 单个pod的最大使用内存为1.5G验证
a. 在容器窗口进行压力测试,使用内存 1000M,如下图,可以正常使用,request: 500Mi, limits:1500Mi
b. 在容器窗口进行压力测试,使用内存 1501M;出现OOM,超过limits1500Mi
结论:k8s调度时根据pod 的requests值计算调度策略,通过limits限制单个pod使用最大资源;
三、 Namespace配置内存的默认值以及超卖最大比例
3.1 准备环境
namespace
创建namespace
$ kubectl create namespace default-mem-example
创建LimitRange
$ cat memory-defaults.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: mem-limit-range
namespace: default-mem-example
spec:
limits:
- default:
memory: 512Mi #default limit
defaultRequest:
memory: 256Mi #default request
max:
memory: 1000Mi #max limit
min:
memory: 10Mi #min request
maxLimitRequestRatio:
memory: 10 #max value for limit / request
type: Container #limit type, support: Container / Pod / PersistentVolumeClaim
$ kubectl create -f memory-defaults.yaml --namespace=default-mem-example
验证环境
Name: default-mem-example
Labels: <none>
Annotations: <none>
Status: Active
No resource quota.
Resource Limits
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container memory 10Mi 1000Mi 256Mi 512Mi 10
3.2 验证默认参数LimitRange限制
3.2.1 验证default 配置,创建一个pod,yml文件中不设定requests和limits
deployment.yml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: test-mem-pod
namespace: default-mem-example
spec:
replicas: 1
selector:
matchLabels:
app: test-mem-pod
template:
metadata:
labels:
app: test-mem-pod
deployment: test-mem-pod
spec:
nodeSelector:
environment: test
kubernetes.io/hostname: 192.168.2.1
containers:
- image: 'harbor-test.api.com:80/library/ubuntu-16.04-base:190806'
command: ["top","-b"]
name: test-mem-pod
describe pod可发现,pod成功创建,并且使用LimitRange对象定义的默认值设置了requests和limits (default request:256Mi; default limits:512Mi)
结论:如果没有指定pod的request和limit,则创建的pod会使用LimitRange对象定义的默认值(request和limit)
3.2.2 验证自定义限制,创建一个pod,设定request:80Mi,limit:800Mi;
describe pod可发现,pod成功创建,并且requests和limits的值为yml文件中设定的值(request:80Mi; default limits:800Mi)
结论:如果指定了pod的request和limit,按自己指定的值创建设定request和limit
3.2.3 验证创建一个pod,yml文件中仅设置limit不设置request(limits:800Mi)
describe pod可发现,pod成功创建,其中limits值为800Mi,request值也为800Mi,而LimitRange对象定义的request默认值为256Mi
**结论:如果指定container的limits但未指定requests,则创建的container的requests值会取limits的值,而不会取LimitRange对象定义的requests默认值
3.2.4 验证创建一个pod,yml文件中仅设置requests不设置limit (requests:80Mi)
describe pod可发现,pod成功创建,其中request值为80Mi,limits值为512Mi;可见没有指定limits取LimitRange对象定义的limit默认值(默认值limits为512Mi)
测试创建一个pod,yml文件中仅设置requests不设置limits ,且request值为600Mi(大于LimitRange对象定义的limits默认值512Min)
创建失败,如果仅设置requests,requests的值必须设置小于LimitRange对象定义的limits默认值
kubectl create -f test-mem-pod.yml
The Pod "test-mem" is invalid: spec.containers[0].resources.requests: Invalid value: "600Mi": must be less than or equal to memory limit
结论:如果指定pod的request但未指定limit,则创建的pod的limit值会取LimitRange对象定义的limit默认值,且requests的值必须设置小于LimitRange对象定义的limits默认值。
3.2.5 验证设置的limits大于max limits或者min小于requests
创建一个pod,yml文件中设置limits的值为1001Mi(LimitRange对象定义的max limits为1000Mi);requests同理测试,这里不列出了。
创建失败,超过max limits mem 1000Mi
结论:LimitRange对象可定义的pod/container的max limits和min requests,用来限制pod创建时对limits和requests的误设置
3.2.6 配置超卖比例maxLimitRequestRatio: mem 10(10倍)
创建一个pod,yml文件中设置limits的值为500Mi,requests值为20Mi,(则超卖比例为500/20=25,大于LimitRange对象定义的maxLimitRequestRatio: mem 10)
创建失败,超过内存超卖比例10
#kubectl create -f test-mem-pod.yml
Error from server (Forbidden): error when creating "test.yml": pods "test-mem" is forbidden: memory max limit to request ratio per Container is 10, but provided ratio is 25.000000.
结论:LimitRange对象可定义的pod/container的maxLimitRequestRatio,用来限制pod创建时超卖的最大比例。
整体结论
- k8s 调度时根据pod 的requests 值计算调度策略,通过limits 限制单个pod 使用最大资源;
- 超卖比例可以设置requests 和 limits 值进行调整;
- Namespace 可以通过 LimitRange 限制超卖比例最大值、单个pod 的最大limit和最小 request、以及
pod 的默认limit 和默认 request 值;
更多推荐
所有评论(0)