一、pod资源限制
1、什么是pod的资源限制
在Kubernetes集群中,为了使系统能够稳定的运行,通常会对Pod的资源使用量进行限制。
在Kubernetes集群中,如果有一个程序出现异常,并占用大量的系统资源。如果未对该Pod进行资源限制的话,可能会影响其他的Pod正常运行,从而造成业务的不稳定性。
2、pod资源限制的实现方法
Kubernetes通过 Requests 和 Limits字段来实现对Pod的资源进行限制
- Kubernetes通过 Requests 和 Limits字段来实现对Pod的资源进行限制
- Limits: 限制 od 运行时最大可用的资源大小; (Pod在运行时Limits 比较重要)
3、资源限制的计算方法
- CPU的计算方法
1核CPU等于1000毫核,当定义容器为0.5时,所能用到的CPU资源时1核心CPU的一半,对于 CPU 资源单位,表达式 .1 等价于表达式100m,可以看作 1 mitlicpu。
1 核心 =1000 millicpu(1 Core = 1000m)
0.5核=500millicpu(0.5 Core = 500m)
- 内存的计算方法
内存的基本单位是字节数(Bytes),也可以加上国际单位,十进制的E、P、T、G、M,K、m,或二进制的 Ei、Pi、Ti、Gi、Mi、Ki。
1MB = 1000 KB = 100000 Bytes
1Mi = 1024 KB = 1048576 bytes
4、安装metrics-server
- GitHub下载地址
metrics-server的GitHub地址
修改阿里云地址
image: registry.cn-huhehaote.aliyuncs.com/oldxu3957/metrics-server:v0.6.1
kubectl apply -f components.yaml
检查node和pod的资源使用
kubectl top pod
kubectl top node
二、CPU限制实践
1、设置cpu的限制
apiVersion: v1
kind: Pod
metadata:
name: pod-resource-cpu
spec:
containers:
- name: cpu-demo
image: vish/stress
args:
- "-cpus"
- "2"
resources:
requests:
cpu: "1000m"
limits:
cpu: "1000m"
2、设置超过节点CPU的限制
设置CPU的请求的核心数为100核心
apiVersion: v1
kind: Pod
metadata:
name: pod-resource-cpu
spec:
containers:
- name: cpu-demo
image: vish/stress
args:
- "-cpus"
- "2"
resources:
requests:
cpu: "100"
limits:
cpu: "100"
解析:
CPU的调度处于false 失败原因是master处于污点中,无法调度,3个node无法满足。pod状态处于pending中
3、如果不限制CPU的 limits会怎么样
如果没有为容器指定 CPU 限制,那么容器在可以使用的 CPU 资源是没有上限。因而可以使用所在节点上所有的可用 CPU 资源,这样可能会造成某一个Pod占用了大量的CPU时间,可能会影响其他的Pod正常运行从而造成业务的不稳定性。
这个也不用担心,在Kubernetes中,可以通过 LimitRange 自动为容器设定,所使用的CPU资源和内存资源最大最小值。
三、内存限制实践
1、限制pod内存
apiVersion: v1
kind: Pod
metadata:
name: pod-resource-mem
spec:
containers:
- name: memory-demo-ctr
image: polinux/stress
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1" ] # 告知容器尝试分配 150 MiB 内存
resources:
requests:
memory: "100Mi"
limits:
memory: "200Mi"
2、运行容器内存限制的内存
apiVersion: v1
kind: Pod
metadata:
name: pod-resource-mem
spec:
containers:
- name: memory-demo-ctr
image: polinux/stress
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1" ] # 告知容器尝试分配 250 MiB 内存
resources:
requests:
memory: "100Mi"
limits:
memory: "200Mi"
解析:
达到内存的运行的最大运行内存,会触发重启策略
四、pod的服务质量Qos
1、什么是QoS
QoS (Quality of Service) ,可译为 “服务质量等级",或者译作"服务质量保证",是作用在 Pod 上的一个配置,当 Kubernetes 创建一个 Pod 时,它就会给这个 Pod 分配一个 QoS 等级。
在Kubernetes的环境中,Kubernetes允许节点的Pod过载使用资源这意味着节点无法同时满足所有Pod以过载的方式运行。因此在内存资源紧缺的情况下,Kubernetes需要借助Pod对象的服务质量和优先级等完成判定,进而挑选对应的Pod杀死。Kubernetes根据pod的Requests和Limits属性,把Pod对象归类为三类 BestEffort、BurStable、Guaranteed。
2、QoS的等级
- Guaranteed: Pod对象为每个容器都设置了CPU资源需求和资源限制,且两者的值相同;还同时为每个容器设置了内存需求与内存限制,并且两者的值相同。这类Pod对象具有最高级别服务质量。
- Burstable: 至少有一个容器设置了CPU或内存资源Requests属性,但不满足Guaranteed,这类Pod具有中级服务质量。
- BestEffort:没有为任何容器设置Requests和Limits属性,这类Pod对象服务质量是最低级别。
当 Kubernetes 集群内存资源紧缺,优先杀死BestEffort类别的容器,因为系统不为该类资源提供任何服务保证,但此类资源最大的好处就是能够尽可能的使用资源。
如果系统中没有BestEffort类别的容器,接下来就轮到Burstable类别的容器,如果有多个Burstable类别的容器,就看谁的内存资源占用多,就优先干掉谁。比如A容器申请1G内存资源,实际使用了95%,而B容器申请了2G内存资源,实际使用了80%,但任然会优先干掉A容器,虽然A
容器的用量少,但与自身的Requests值相比,它的占比要大于B容器。
对于Guaranteed类别的容器拥有最高优先级,它们不会被杀死,除非其内存资源需求超限,或者00M时没有其他更低优先级的Pod对象存在,才会干掉Guaranteed类容器。
3、实验
3.1 创建Guaranteed的Pod
对于 QoS 类为 Guaranteed 的 Pod:
- Pod 中的每个容器都必须指定内存请求和内存限制,且Pod中每个容器内存请求必须等于内存限制。
- pod 中的每个容器都必须指定CPU请求和CPU限制,且Pod中每个容器CPU请求必须等于CPU限制。
1.创建一个Pod,容器设置了内存请求和内存限制,值都是200MiB。容器设置了CPU请求和CPU限制,值都是70 mitLiCPU
apiVersion: v1
kind: Pod
metadata:
name: pod-qos-guarantee
spec:
containers:
- name: qos-demo
image: nginx
resources :
requests:
cpu: "700m"
memory: "200Mi"
limits:
cpu: "700m"
memory: "200Mi"
kubectl describe pod pod-qos-guarantee
3.2 创建Burstable的Pod
如果满足下面条件,将会指定 Pod 的 QoS 类为 Burstable:
- Pod 不符合 Guaranteed QoS 类的标准
- Pod 中至少一个容器指定了,内存或 CPU 的请求或限制
1.创建一个Pod,容器设置了内存请求 100 MiB,以及内存限制 200MiB。
apiVersion: v1
kind: Pod
metadata:
name: pod-qos-burstable
spec:
containers:
- name: qos-demo
image: nginx
resources :
requests:
memory: "100Mi"
limits:
memory: "200Mi"
kubectl describe pod pod-qos-burstable
3.3 创建BestEffort的Pod
对于 QoS 类为 BestEffort 的 Pod,Pod 中的容器必须没有设置内
存和 CPU 限制或请求。
1.创建一个Pod,容器没有设置内存和 CPU 限制或请求
apiVersion: v1
kind: Pod
metadata:
name: pod-qos-besteffort
spec:
containers:
- name: qos-demo
image: nginx
kubectl describe pod pod-qos-besteffort
3.4 创建多容器pod
创建一个Pod,一个容器指定了内存请求 200 MiB。 另外一个容器没有指定任何请求和限制。此 Pod 满足 Burstable QoS 类的标准但它不满足 Guaranteed QoS 类标准,因为它的一个容器设有内存请求。
apiVersion: v1
kind: Pod
metadata:
name: pod-qos-mutil
spec:
containers:
- name: qos-demo
image: nginx
resources :
requests:
memory: "200Mi"
- name: qos-demo2
image: redis
kubectl describe pod pod-qos-mutil
五、Downward API
1、什么是DownwardAPI
DownwardAPI可以让容器获取Pod的相关元数据信息,比如Pod名称Pod的IP,Pod的资源限制等,获取后通过env、volume的方式将相关的环境信息注入到容器中,从而让容器通过这些信息,来设定容器的运行特性。
- 例如: Nginx进程根据节点的CPU核心数量自动设定要启动的worker进程数。
- 例如: JVM虚拟根据Pod的内存资源限制,来设定对应容器的堆内存大小。
- 例如: 获取Pod名称,以Pod名称注册到某个服务,当Pod结束后,调用prestop清理对应名称的注册信息。
2、DownwardAPI能够注入哪些元素
- 查看命令
kubectl explain pod.spec.containers.env.valueFrom.fieldRef
- metadata.name: Pod对象的名称
- metadata.namespace: Pod对象隶属的名称空间
- metadata.uid: Pod对象的UID
- metadata.Labels[‘’]: 获取Label指定KEY对应的值
- metadata.annotations[‘’]: 获取Annotations对应KEY的值
- status.podIP:Pod对象的IP地址
- status.hostIP: 节点IP
- status.nodeName: 节点名称
- spec.serviceAccountName: Pod对象使用的ServiceAccount资源名称
也可以通过yaml文件,拿相关详情信息
kubectl get pod pod-qos-guarantee -o yaml
使用
kubectl explain pod.spec.containers.env.valueFrom.resourceFieldRef
pod.spec.containers.env.valueFrom.resourceFieldRef 以注入的字段有:
- requests .cpu
- requests .memory
- limits.cpu
- limits.memory
3、通过环境变量的方式注入元数据
- 1、创建Pod容器,将Pod相关环境变量注入到容器中,比如 (pod名称.命名空间、标签、以及cpu、内存的请求和限制)
apiVersion: v1
kind: Pod
metadata:
name: pod-down-api
labels:
app: nginx-app
role: backend
zone: beijing
spec:
containers:
- name: pod-down-api
image: nginx
command: ["/bin/bash" , "-c", "env"]
resources:
requests:
cpu: "200m"
memory: "32Mi"
limits:
cpu: "200m"
memory: "64Mi"
env:
- name: APP1_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: APP1_POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: APP1_POD_LABELS
valueFrom:
fieldRef:
fieldPath: metadata.labels['app']
- name: APP1_CPU_REQUESTS
valueFrom:
resourceFieldRef:
resource: requests.cpu
- name: APP1_MEM_LIMITS
valueFrom:
resourceFieldRef:
resource: limits.memory
divisor: 1Mi # 输出的格式
查看注入的变量信息:
[root@master yaml]# kubectl logs pod-down-api | grep APP1
APP1_POD_LABELS=nginx-app
APP1_POD_NAMESPACE=default
APP1_MEM_LIMITS=64
APP1_CPU_REQUESTS=1
APP1_POD_NAME=pod-down-api
4、通过存储卷的方式注入元数据
apiVersion: v1
kind: Pod
metadata:
name: pod-down-api-volumes
labels:
app: nginx-app
role: backend
zone: beijing
spec:
containers:
- name: pod-down-api
image: nginx
resources:
requests:
cpu: "200m"
memory: "32Mi"
limits:
cpu: "200m"
memory: "64Mi"
volumeMounts:
- name: podinfo
mountPath: /etc/info
volumes:
- name: podinfo
downwardAPI:
items:
- path: pod_name
fieldRef:
fieldPath: metadata.name
- path: pod_namespace
fieldRef:
fieldPath: metadata.namespace
- path: pod_labels
fieldRef:
fieldPath: metadata.labels
- path: req_cpu
resourceFieldRef:
containerName: pod-down-api
resource: requests.cpu
- path: limit_mem
resourceFieldRef:
containerName: pod-down-api
resource: limits.memory
进入pod查看环境变量
kubectl exec -it pod-down-api-volumes -- /bin/bash
5、实战DownwordAPI为JVM注入堆内存大小限制
- 步骤:
1.运行一个默认的Tomcat,检查初始的JVM堆内存大小;
2.对Tomcat设定资源限制,看看这个资源限制对Tomcat分配堆内存有没有什么影
3.手动为TOmcat指定堆内存,300M,对Pod限制 100M;(死)
4.将request limits的值,传递给jvm内存设定; (不会被频繁的Kill)因为,JVM认为自己最多能使用的就是200Mi,没有超过limits限制。
1、启动一个默认的Tomcat
apiVersion: v1
kind: Pod
metadata:
name: pod-tomcat-downword
spec:
containers:
- name: tomcat
image: tomcat:9.0.63
ports:
- containerPort: 8080
kubectl exec -it pod-tomcat-downword -- /bin/bash
- 初始内存是60M 最大内存为1G
最大内存跟物理主机有关系,最大的堆内存是物理内存的1/4内存
初始化内存是物理内存的1/64 ,
4G=4096M 4096/64=64M 所以初始化内存符合初始化堆内存
2、启动一个现在内存大小为100M的pod
- 准备工作
安装ab 压测命令
yum -y install vim*
yum -y install httpd-tools
apiVersion: v1
kind: Pod
metadata:
name: pod-tomcat-downword
spec:
containers:
- name: tomcat
image: tomcat:9.0.63
ports:
- containerPort: 8080
env:
- name: JAVA_OPTS
value: -server -Xms500m -Xmx500m -XX:+UseConcMarkSweepGC
resources:
requests:
memory: 100Mi
limits:
memory: 100Mi
- 跟踪内存使用量和pod 状态
watch -n 1 kubectl top pod pod-tomcat-downword
watch -n 1 kubectl get pod pod-tomcat-downword -o wide
- ab压测pod的请求
ab -n 1000 -c 50 http://10.244.2.10:8080/
- 测试结果
3 、将Tomcat的jvm的启动参数,以环境变量的方式注入jvm 参数中去
apiVersion: v1
kind: Pod
metadata:
name: pod-tomcat-downward
spec:
containers:
- name: tomcat
image: tomcat:9.0.63
ports:
- containerPort: 8080
env:
- name: JAVA_OPTS
value: -server -Xms${JVM_XMS} -Xmx${JVM_XMX} -XX:+UseConcMarkSweepGC
- name: JVM_XMS
valueFrom:
resourceFieldRef:
resource: requests.memory
- name: JVM_XMX
valueFrom:
resourceFieldRef:
resource: limits.memory
resources:
requests:
memory: 100Mi
limits:
memory: 100Mi
- 查看jvm的测试结果,符合jvm的启动参数,已经将JVM的启动参数,已经注入到pod的启动参数中。
6、为服务注册pod名称信息
- 实验背景:
1、当pod创建时,pod的名称,以pod名称创建数据库
2、当pod发生改变,或者删除时,以pod名称创建的数据库名,自动删除