在 Kubernetes 中,像 CPU 这样的资源被称作“可压缩资源”(compressible resources)。它的典型特点是,当可压缩资源不足时,Pod 只会“饥饿”,但不会退出。而像内存这样的资源,则被称作“不可压缩资源(incompressible resources)。当不可压缩资源不足时,Pod 就会因为 OOM(Out-Of-Memory)被内核杀掉。

1.容器最小内存和最大内存设置为一致

简单来理解:最小内存等同于k8s的resources:requests资源,最大内存等同于resources:limits资源。参考:为容器和 Pod 分配内存资源 | Kubernetes

刚才的配置,我们查看对应yml文件可以看到,对应的memory的请求和限制保持一致。

一般情况下,对于核心资源,我们推荐 requests == limits,这个是为什么呢?

这里涉及pod的三种模式:

  • Guaranteed 类别:当 Pod 里的每一个 Container 都同时设置了 requests 和 limits,并且 requests 和 limits 值相等的时候
  • Burstable类别: 而当 Pod 不满足 Guaranteed 的条件,但至少有一个 Container 设置了 requests。那么这个 Pod 就会被划分到 Burstable 类别。
  • BestEffort类别:一个 Pod 既没有设置 requests,也没有设置 limits

当资源不足,需要强制剔除部分pod时候,kubelet 具体会挑选哪些 Pod 进行删除操作,就需要参考这些 Pod 的 QoS 类别了:

  • 首当其冲的,自然是 BestEffort 类别的 Pod。
  • 其次,是属于 Burstable 类别、并且发生“饥饿”的资源使用量已经超出了 requests 的 Pod。
  • 最后,才是 Guaranteed 类别。并且,Kubernetes 会保证只有当 Guaranteed 类别的 Pod 的资源使用量超过了其 limits 的限制,或者宿主机本身正处于 Memory Pressure 状态时,Guaranteed 的 Pod 才可能被选中进行 Eviction 操作。

所以,一般我们设置reqeust和limit一致可以保证资源比较稳定。

2.最大堆内存和最小堆内存设置为一致

当堆内存使用发生变化时并不是简单的增加和减少堆内存即可,还会进行GC操作,如果-xms起始值设置的比较小,就会进行频繁的GC操作,当GC操作无法释放更多的内存时,才会进行内存的扩充。在这期间GC操作需要耗时,且FULL GC还会引起线程暂停,导致性能问题

因为是容器化部署,一个容器就部署了一个节点,一个节点也就是一个服务,所以独占服务器就没有必要动态调内存

但是同样会有弊端:最大值和最小值设置为一样,GC次数会减小,在JVM使用完之前,内存会一直增长。

并且同一 JDK 的 GC 策略也有很多种,不能一概而论。另外,对于Hotspot虚拟机,Xms和Xmx设置为一样的,可以减轻伸缩堆大小带来的压力。但对于IBM虚拟机,设置为一样会增大堆碎片产生的几率,并且这种负面影响足以抵消前者产生的益处。