亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

GKE容器被“內存cgroup內存不足”殺死,但監控,本地測試和pprof顯示使用率遠低于限制

GKE容器被“內存cgroup內存不足”殺死,但監控,本地測試和pprof顯示使用率遠低于限制

Go
ibeautiful 2022-08-24 18:53:50
我最近將一個新的容器映像推送到我的一個GKE部署中,并注意到API延遲上升,請求開始返回502。查看日志,我發現容器由于OOM而開始崩潰:Memory cgroup out of memory: Killed process 2774370 (main) total-vm:1801348kB, anon-rss:1043688kB, file-rss:12884kB, shmem-rss:0kB, UID:0 pgtables:2236kB oom_score_adj:980從內存使用情況圖來看,Pod 使用的內存加起來并不超過 50MB。我最初的資源請求是:...spec:...  template:...    spec:...      containers:      - name: api-server...        resources:          # You must specify requests for CPU to autoscale          # based on CPU utilization          requests:            cpu: "150m"            memory: "80Mi"          limits:            cpu: "1"            memory: "1024Mi"      - name: cloud-sql-proxy        # It is recommended to use the latest version of the Cloud SQL proxy        # Make sure to update on a regular schedule!        image: gcr.io/cloudsql-docker/gce-proxy:1.17        resources:          # You must specify requests for CPU to autoscale          # based on CPU utilization          requests:            cpu: "100m"...然后我嘗試將API服務器的請求提高到1GB,但沒有幫助。最后,幫助將容器映像還原到以前的版本:通過查看golang二進制文件中的更改,沒有明顯的內存泄漏。當我在本地運行它時,它最多使用80MB的內存,即使在來自與生產中相同的請求的負載下也是如此。我從GKE控制臺獲得的上圖也顯示了Pod使用遠遠低于1GB內存限制的Pod。所以我的問題是:當GKE監控和本地運行它僅使用1GB限制中的80MB時,什么可能導致GKE終止我的OOM進程?
查看完整描述

3 回答

?
海綿寶寶撒

TA貢獻1809條經驗 獲得超8個贊

我猜這是由Pod QoS類引起的


當系統過度使用時,QoS 類會確定哪個 pod 首先被殺死,以便將釋放的資源提供給優先級更高的 Pod。


在你的情況下,你的 Pod 的 QoS 是可爆發的


每個正在運行的進程都有一個超出內存 (OOM) 分數。系統通過比較所有正在運行的進程的OOM分數來選擇要終止的進程。當需要釋放內存時,得分最高的進程將被終止。有關如何計算的詳細信息,請參閱如何計算內核 oom 分數?。score


如果兩者都在可爆破類中,哪個 pod 會先被殺死?


簡而言之,系統將使用比另一個請求的內存更多的百分比來殺死一個。


Pod A


used: 90m

requests: 100m

limits: 200m

Pod B


used: 150m

requests: 200m

limits: 400m

Pod A之前會被殺死,因為它使用了 90% 的請求內存,而只使用了請求內存的 75%。Pod BPod B


查看完整回答
反對 回復 2022-08-24
?
有只小跳蛙

TA貢獻1824條經驗 獲得超8個贊

確保 QoS 類為“有保證”在你的方案中無濟于事。其中一個進程導致父 cgroup 超過其內存限制(反過來由針對相應容器指定的內存限制值設置),OOM 殺手將其終止。這不是 Pod 逐出,因為您可以在日志中清楚地看到 OOM 殺手的商標信息。如果另一個 Pod 分配了如此多的內存,使節點處于內存壓力之下,那么“有保證的”QoS 類將會有所幫助 - 在這種情況下,您的“保證”Pod 將幸免于難。但在你的情況下,Kubelet從來沒有在所有這些事情中得到一個字 - 就像決定完全驅逐豆莢一樣 - 因為OOM殺手行動更快。

Burak Serdar在其評論中有一個很好的觀點 - 臨時分配大內存塊。情況很可能就是這樣,因為從您粘貼的消息中收集數據的分辨率為60s。那是很多時間。一個人可以在不到1秒的時間內輕松填充GB的RAM。我的假設是,內存“峰值”永遠不會被渲染,因為指標永遠不會被及時收集(即使你直接查詢cAdvisor,它也會很棘手,因為它的分辨率為10-15秒來收集其指標)。

如何了解更多有關正在發生的事情的信息?幾個想法:

  • 有一些工具可以顯示應用程序實際分配了多少,一直到框架級別。在.NET中,dotMemory是一種常用的工具,可以在容器內運行并捕獲正在發生的事情。Go 可能有一個等價物。這種方法的問題在于,當容器被OOM殺死時,該工具也會隨之被刪除。

  • 在這里,您將找到一個影片,該影片捕獲了一個進程分配內存,直到其父容器被 OOM 殺死。相應的 .NET 應用程序會不時地將它使用的內存量寫入控制臺,即使在容器不再存在后,Kubernetes 日志也會顯示這些內存量,從而允許查看發生了什么

  • 限制應用,使其處理少量數據(例如,如果您每分鐘只處理 1 張圖片,則從內存角度臨時查看會發生什么)

  • 查看詳細的 OOM 殺手內核日志,了解 cgroup 中的所有進程。在一個容器內有多個進程是完全有效的(就像在其他進程中一樣,除了該容器中帶有PID 1的進程),OOM殺手很可能殺死其中任何一個。在這種情況下,您可能會偶然發現意想不到的轉折。然而,在你的場景中,它似乎被終止了,否則容器就不會被OOM殺死,所以這種情況不太可能發生。

只是為了完整性:底層框架可以對容器強制實施低于內存限制的限制。例如,在.NET中,當在具有內存限制的容器中運行時,此值為75%。換句話說,在限制為 2,000 MiB 的容器內分配內存的 .NET 應用將在 1,500 MiB 時出錯。然而,在這種情況下,你得到的退出代碼為139(SIGSEGV)。這似乎不適用于這里,因為OOM殺手終止了該過程,并且從內核日志中可以清楚地看到所有1 GiB實際上都被使用了()。據我所知,Go還沒有類似的設置,盡管社區一再要求它。anon-rss:1043688kB


查看完整回答
反對 回復 2022-08-24
?
阿波羅的戰車

TA貢獻1862條經驗 獲得超6個贊

此處的資源規范是 OOM 的根本原因。


在 Kubernetes 中,所需內存和有限內存的定義不同。所需的內存是 內存 。有限內存是容器可以突增到的內存。但有限的內存并不能保證容器可以擁有該資源。must-have


在大多數生產系統中,不建議有限和所需的資源差異太大。例如,在您的情況下,


requests:

  cpu: "150m"

  memory: "80Mi"

limits:

  cpu: "1"

  memory: "1024Mi"

容器只能有80Mi保證內存,但它可以以某種方式爆發為1024Mi。節點可能沒有足夠的內存用于容器,容器本身將進入 OOM。


因此,如果要改善這種情況,則需要將資源配置為類似此類的資源。


requests:

  cpu: "150m"

  memory: "1024Mi"

limits:

  cpu: "1"

  memory: "1024Mi"

請注意,CPU很好,因為您不會在低CPU時間下殺死進程。但是OOM將導致該過程被殺死。


正如上面提到的答案,這與 pod 中的服務質量有關。通常,對于大多數最終用戶,應始終將容器配置為保證類,即請求 == 受限。在將其配置為突發類之前,您可能需要有一些理由。


查看完整回答
反對 回復 2022-08-24
  • 3 回答
  • 0 關注
  • 177 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號