如何有效地测试Pod记忆
作者:英豪王(混沌网格贡献者)
编辑:黄了汤姆,政府高级官员
混乱的网是一个云原生的混沌工程平台,它在Kubernetes环境中协调混沌。在它的各种工具中,混沌网格提供StressChaos,它允许你将CPU和内存压力注入你的Pod。当您测试一个cpu敏感或内存敏感的程序,并想知道它在压力下的行为时,这个工具非常有用。
然而,当我们测试和使用stress schaos时,我们发现了可用性和性能方面的一些问题。例如,stress schaos使用的内存比我们配置的要少得多。
为了纠正这些问题,我们开发了一组新的测试。在本文中,我将描述如何对这些问题进行故障排除和修正。这些信息可能会帮助你最大限度地利用“压力混乱”。
向目标Pod注入压力
在你继续之前,你需要安装混乱网在您的集群。
首先,我将教你如何将stress schaos注入目标Pod。为了演示的目的,我将使用hello-kubernetes的演示应用程序执掌图表.第一步是克隆hello-kubernetes
回购和修改图表,给它一个资源限制。
git克隆[https://github.com/paulbouwer/hello-kubernetes.git](https://github.com/paulbouwer/hello-kubernetes.git)代码部署/舵/ hello-kubernetes / values.yaml#或任何你喜欢的编辑器
找到资源配置,按如下方法修改:
资源:请求:内存:“200米”限制:内存:“500米”
在我们注入stress schaos之前,让我们看看目标Pod当前消耗了多少内存。进入花苞,开始一个壳。输入以下命令与您的Pod的名称:
kubectl执行-- -n hello-kubernetes hello-kubernetes-hello-world-b55bfcf68-8mln6——/bin/sh
通过输入:显示内存使用的摘要:
/usr/src/app $ top . /usr/src/app
从下面的输出中可以看到,Pod消耗了4,269 MB内存:
/usr/src/app免费- m Mem使用:4269美元交换:0 /usr/src/app顶级Mem美元:12742432 k使用PID PPID用户统计VSZ % VSZ CPU % CPU命令1 0节点285年代2% 0 0% npm开始18 1节点284年代2% 3 0%节点server.js 29节点0年代/bin/sh 36 29节点R 1568 1636 0% 0% 0% 3 0%
前
和免费的
命令给出了类似的答案,但这些数字没有达到我们的预期。我们已经将Pod的内存使用量限制在500 mib,但现在它似乎使用了几gb。
为了找出原因,我们可以在Pod上做一个应激混乱实验,看看会发生什么。下面是我们使用的YAML文件:
apiVersion:混乱-mesh.org/v1alpha1种类:StressChaos元数据:的名字:mem-压力名称空间:混乱-测试规范:模式:所有选择器:名称空间:-你好-kubernetes压力:内存:工人:4大小:50 mib选项:[""]持续时间:“1 h”
将上述文件保存到memory.yaml
.运行混沌实验:
kubectl应用-f内存。yaml stresschaos.chaos-mesh.org/mem-stress创建
让我们再次检查内存使用情况:
used Mem: 4332 Swap: 0 Mem:12805568 k使用PID PPID用户统计VSZ % VSZ CPU % CPU命令54 50根R 53252 0% 24% {stress-ng-vm} stress-ng——vm 4——vm-keep vm-bytes 50000000 57 52根R 53252 0% 0 22% {stress-ng-vm} stress-ng——vm 4——vm-keep vm-bytes 50000000 55 53根R 53252 2 21% {stress-ng-vm} stress-ng——vm 4 0%——vm-keep vm-bytes 50000000 56 51根R 532520% 3 21% {stress-ng-vm} stress-ng——vm 4——vm-keep vm-bytes 50000000 18 1节点289年代2% 2节点server.js 1 0 0%节点285年代2% 0 0% npm开始51 49根41048年代0% 0 0% {stress-ng-vm} stress-ng——vm 4——vm-keep vm-bytes 41048 49根50年代50000000 2 0% {stress-ng-vm} stress-ng——vm 4 0%——vm-keep vm-bytes 50000000 52 49根41048年代0% 0 0%{stress-ng-vm} stress-ng——vm 4——vm-keep vm-bytes 50000000 53 49根41048 0% 0% {stress-ng-vm} stress-ng——vm 4——vm-keep vm-bytes 50000000 49根年代41044年0% 0 0% stress-ng——vm 4——vm-keep vm-bytes 50000000 29节点0年代/bin/sh 48 R 29节点1568 1636 0% 0% 0% 1 0%
大家可以看到stress-ng
实例被注入到Pod中。Pod上升了60 MiB,这是我们没有预料到的。的stress-ng
文档表示增量为200 MiB (4 * 50 MiB)。
让我们通过将内存压力从50 MiB改变为3000 MiB来增加压力。这会打破花苞的内存限制。我将删除混沌实验,修改内存大小,并重新应用它。
然后,轰!shell以代码137退出。过一会儿,我重新连接到容器,内存使用恢复正常。没有stress-ng
实例被发现!发生了什么事?
为什么压力混乱会消失?
在上面的混沌实验中,我们看到了异常行为:内存使用量没有增加,Shell退出。在这一节中,我们将找出所有的原因。
Kubernetes通过cgroup机制。要查看Pod中的500mib限制,请进入容器并输入:
/usr/src/app美元猫/ sys / fs / cgroup /内存/ memory.limit_in_bytes524288000
输出以字节显示,并转换为500*1024*500 1024 (MiB)。
请求仅用于安排放置Pod的位置。Pod没有内存限制或请求,但可以将其视为其所有容器的总和。
所以,我们从一开始就在犯错。免费的
和前
不是“cgroup。”他们依靠/proc/meminfo
(procfs)数据。不幸的是,/proc/meminfo
都很老了,比c组还老。他们为你提供宿主内存信息而不是容器的内存信息。
记住这一点,让我们重新开始,看看这次得到的内存使用情况。
要获取“cgrouped”的内存使用情况,输入:
/usr/src/app美元猫/ sys / fs / cgroup /内存/ memory.usage_in_bytes39821312
应用50 MiB stress schaos,得到如下结果:
/usr/src/app美元猫/ sys / fs / cgroup /内存/ memory.usage_in_bytes93577216
这比没有压力混乱的情况下多了51个MiB。
下一个问题:为什么shell退出了?退出代码137表示“容器接收到SIGKILL时失败”。所以我们要去检查花苞。注意Pod的状态和事件:
~ kubectl描述豆荚-n你好kubernetes......最后状态:终止原因:错误退出代码:1......事件:原因年龄从消息类型 ---- ------ ---- ---- -------......警告不健康的10米(x4超过16米)kubelet准备就绪探测器失败:得到“http://10.244.1.19:8080”:上下文期限超过(客户端。超时了而等待头)正常死亡10米(x2超过16米)kubelet容器hello-kubernetes激活探测失败,将重新启动......
这些事件告诉我们炮弹坠毁的原因。hello-kubernetes
有一个活性探针。当容器内存达到限制时,应用程序开始失败,Kubernetes决定终止并重新启动Pod。当Pod重启时,应激混乱就会停止。到目前为止,你可以说,stress schaos实验效果很好:它发现了Pod中的一个漏洞。你现在可以修复它,并重新应用混乱。
现在一切似乎都很完美,除了一件事。为什么4个50个MiB vm worker会产生51个MiB ?答案是不会自己显露的,除非我们进入stress-ng源代码:
vm_bytes/ =arg游戏->num_instances;
哦!所以文件是错误的。多个虚拟机工作人员占用指定的总大小,而不是mmap
每个工人有那么多内存。终于,我们得到了所有问题的答案。在接下来的部分中,我们将讨论一些涉及记忆压力的其他情况。
如果没有活性探针呢?
为了弄清楚如果没有活性探针会发生什么,让我们删除探针并再次尝试。
找到下面的行部署/舵/ hello-kubernetes /模板/ deployment.yaml
和删除它们。
livenessProbe:httpGet:路径:/港口:httpreadinessProbe:httpGet:路径:/港口:http
之后,升级部署。
有趣的是,在这种情况下,内存使用量持续上升,然后急剧下降;它来来回回。现在发生了什么?让我们检查内核日志。注意最后两行。
/usr/src/app $ dmesg…[189937.362908] [pid] uid tgid total_vm RSS nr_ptes swapents oom_score_adj name [189937.363092] [441060] 1000 441060 63955 3791 80 3030 988 node [189937.363145] [443265] 0 443265 193367 84215 197 9179 1000 stress-ng-vm…[189937.363148] Memory cgroup out of Memory: Kill process 443160 (stress-ng-vm) score 1272 or sacrifice child . [189937.363186] Kill process 443160 (stress-ng-vm), UID 0, total-vm:773468kB, anon-rss:152704kB, file-rss:164kB, shmems -rss:0kB .
从输出中可以清楚地看出stress-ng-vm
由于内存不足(OOM)错误,进程正在被终止。
如果进程不能得到它们想要的内存,它们很可能会失败。与其等待进程崩溃,不如杀死其中一些进程以释放更多内存。OOM杀手按顺序停止进程,并试图在造成最少麻烦的同时恢复最多的内存。有关此过程的详细信息,请参见介绍伯父杀手。
看看上面的输出,你可以看到节点
,我们的申请过程不应该终止,有一个oom_score_adj
988股。这是相当危险的,因为这是最容易被杀死的过程。
要阻止OOM杀手杀死特定的进程,您可以尝试一个简单的技巧。创建Pod时,分配Pod服务质量(QoS)类.通常,如果使用精确指定的资源请求创建Pod,则将其分类为保证
豆荚。如果有其他杀死选项,OOM杀手不会杀死保证Pod中的容器。这些选项包括non-保证
豆荚和stress-ng
工人。没有资源请求的Pod被标记为BestEffort
他可能会首先被OOM杀手杀死。
参观到此结束。当你将stress schaos注入你的pod时,我们有两个建议:
- 不要使用
免费的
和前
评估容器中的记忆。 - 在为Pod分配资源限制时要小心,并选择正确的QoS。
将来,我们将创建一个更详细的stress schaos文档。
深入了解Kubernetes的内存管理
Kubernetes试图驱逐使用过多内存的pod(但内存不能超过其限制)。Kubernetes获取Pod内存使用情况/ sys / fs / cgroup /内存/ memory.usage_in_bytes
然后减去total_inactive_file
行memory.stat
.
记住,Kubernetes不支持交换。即使您有一个启用了交换的节点,Kubernetes也会用swappiness = 0
,这意味着swap实际上是禁用的。这主要是出于性能考虑。
memory.usage_in_bytes
=驻留集
+缓存
,total_inactive_file
是内存中缓存
当内存耗尽时,操作系统可以检索。memory.usage_in_bytes-total_inactive_file
被称为working_set
.你可以得到这个working_set
价值Kubectl top pod <你的pod>——容器
.Kubernetes使用这个值来决定是否驱逐你的豆荚。
Kubernetes定期检查内存使用情况。如果容器的内存使用量增长过快,或者无法收回容器,则调用OOM杀手。Kubernetes有自己的方法来保护自己的进程,所以OOM杀手总是选择容器。当容器终止时,它可能重新启动,也可能不重新启动,这取决于您的重新启动策略。如果它被杀死了,在你执行的时候Kubectl描述豆荚<你的豆荚>
,您将看到它重新启动,原因是OOMKilled
.
另一件值得一提的事情是内核内存。从1.9版开始,Kubernetes默认启用内核内存支持。这也是cgroup内存子系统的一个特性。您可以限制容器内核内存的使用。不幸的是,这将导致内核版本4.2之前的cgroup泄漏。您可以将内核升级到v4.3,也可以禁用该特性。
我们如何实现压力混乱
stress schaos是在内存不足时测试容器行为的一种简单方法。stress schaos使用了一个强大的工具stress-ng
分配内存并继续写入已分配的内存。因为容器有内存限制,而且容器限制绑定到cgroup,所以我们必须找到一种运行的方法stress-ng
在一个特定的c组中。幸运的是,这部分很简单。只要有足够的权限,我们就可以通过写入文件的方式将任意进程分配给任意cgroup/ sys / fs / cgroup /
.
如果你对混沌网格感兴趣,并想帮助我们改进它,欢迎你的加入我们的松弛通道(# project-chaos-mesh) !或者把你的请求或问题提交给我们GitHub库.