在Kubernetes集群中,为了使系统能够稳定的运行,通常会对Pod的资源使用量进行限制。
在Kubernetes集群中,如果有一个程序出现异常,并占用大量的系统资源。如果未对该Pod进行资源限制的话,可能会影响其他的Pod正常运行,从而造成业务的不稳定性。
Kubernetes通过 Requests 和 Limits字段来实现对Pod的资源进行限制
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)
修改阿里云地址
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
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"
设置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中
如果没有为容器指定 CPU 限制,那么容器在可以使用的 CPU 资源是没有上限。因而可以使用所在节点上所有的可用 CPU 资源,这样可能会造成某一个Pod占用了大量的CPU时间,可能会影响其他的Pod正常运行从而造成业务的不稳定性。
这个也不用担心,在Kubernetes中,可以通过 LimitRange 自动为容器设定,所使用的CPU资源和内存资源最大最小值。
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"
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"
解析:
达到内存的运行的最大运行内存,会触发重启策略
QoS (Quality of Service) ,可译为 “服务质量等级",或者译作"服务质量保证",是作用在 Pod 上的一个配置,当 Kubernetes 创建一个 Pod 时,它就会给这个 Pod 分配一个 QoS 等级。
在Kubernetes的环境中,Kubernetes允许节点的Pod过载使用资源这意味着节点无法同时满足所有Pod以过载的方式运行。因此在内存资源紧缺的情况下,Kubernetes需要借助Pod对象的服务质量和优先级等完成判定,进而挑选对应的Pod杀死。Kubernetes根据pod的Requests和Limits属性,把Pod对象归类为三类 BestEffort、BurStable、Guaranteed。
当 Kubernetes 集群内存资源紧缺,优先杀死BestEffort类别的容器,因为系统不为该类资源提供任何服务保证,但此类资源最大的好处就是能够尽可能的使用资源。
如果系统中没有BestEffort类别的容器,接下来就轮到Burstable类别的容器,如果有多个Burstable类别的容器,就看谁的内存资源占用多,就优先干掉谁。比如A容器申请1G内存资源,实际使用了95%,而B容器申请了2G内存资源,实际使用了80%,但任然会优先干掉A容器,虽然A
容器的用量少,但与自身的Requests值相比,它的占比要大于B容器。
对于Guaranteed类别的容器拥有最高优先级,它们不会被杀死,除非其内存资源需求超限,或者00M时没有其他更低优先级的Pod对象存在,才会干掉Guaranteed类容器。
对于 QoS 类为 Guaranteed 的 Pod:
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
如果满足下面条件,将会指定 Pod 的 QoS 类为 Burstable:
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
对于 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
创建一个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
DownwardAPI可以让容器获取Pod的相关元数据信息,比如Pod名称Pod的IP,Pod的资源限制等,获取后通过env、volume的方式将相关的环境信息注入到容器中,从而让容器通过这些信息,来设定容器的运行特性。
kubectl explain pod.spec.containers.env.valueFrom.fieldRef
也可以通过yaml文件,拿相关详情信息
kubectl get pod pod-qos-guarantee -o yaml
使用
kubectl explain pod.spec.containers.env.valueFrom.resourceFieldRef
pod.spec.containers.env.valueFrom.resourceFieldRef 以注入的字段有:
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
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
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
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
watch -n 1 kubectl top pod pod-tomcat-downword
watch -n 1 kubectl get pod pod-tomcat-downword -o wide
ab -n 1000 -c 50 http://10.244.2.10:8080/
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