VM 記憶體不足錯誤的疑難排解

本頁說明 Managed Service for Apache Spark on Compute Engine VM 發生記憶體不足 (OOM) 錯誤的狀況,並說明如何排解及解決 OOM 錯誤。

OOM 錯誤的影響

當 Managed Service for Apache Spark VM 發生記憶體不足 (OOM) 錯誤時,會造成下列影響:

  • 主要執行個體和 worker VM 會凍結一段時間。

  • 主要執行個體 VM 的 OOM 錯誤會導致工作失敗,並顯示「task not acquired」(未獲取任務) 錯誤。

  • Worker VM 發生記憶體不足錯誤,會導致 YARN HDFS 上的節點遺失,進而延遲 Managed Service for Apache Spark 工作執行作業。

YARN 記憶體控制選項

Apache YARN 提供下列類型的記憶體控制選項

  • 輪詢式 (舊版)
  • 嚴格
  • Elastic

根據預設,Managed Service for Apache Spark 不會設定 yarn.nodemanager.resource.memory.enabled 來啟用 YARN 記憶體控制選項,原因如下:

  • 在嚴格記憶體控制模式下,如果容器大小設定有誤,即使記憶體充足也可能終止容器。
  • 彈性記憶體控制模式的需求條件,可能會對工作執行效能造成負面影響。
  • 如果程序大量消耗記憶體,YARN 記憶體控制選項可能無法防止 OOM 錯誤。

Managed Service for Apache Spark 記憶體保護機制

如果 Managed Service for Apache Spark 叢集 VM 的記憶體不足,Managed Service for Apache Spark 記憶體保護機制會終止程序或容器,直到記憶體不足的狀況解除為止。

Managed Service for Apache Spark 會為下列Managed Service for Apache Spark 映像檔版本中的叢集節點提供記憶體保護功能:

角色 1.5 2.0 2.1 2.2
主要執行個體 VM 1.5.74+ 2.0.48+ 全部 全部
Worker VM 不適用 2.0.76+ 2.1.24+ 全部
驅動程式集區 VM 不適用 2.0.76+ 2.1.24+ 全部

識別並確認記憶體保護機制所觸發的終止事件

以下資訊可用於識別並確認工作是否因記憶體壓力而終止。

程序終止

  • 由 Managed Service for Apache Spark 記憶體保護機制所終止的程序,會以 137143 程式碼結束。

  • 如果 Managed Service for Apache Spark 因記憶體壓力而終止程序,可能會發生下列動作或情況:

    • Managed Service for Apache Spark 會遞增累計指標,並將 reason 設為 ProcessKilledDueToMemoryPressuredataproc.googleapis.com/node/problem_count請參閱「Managed Service for Apache Spark 資源指標收集」。
    • Managed Service for Apache Spark 會寫入 google.dataproc.oom-killer 記錄檔,並顯示以下訊息: "A process is killed due to memory pressure: process name。 如要查看這些訊息,請啟用 Logging,然後使用下列記錄篩選條件:
      resource.type="cloud_dataproc_cluster"
      resource.labels.cluster_name="CLUSTER_NAME"
      resource.labels.cluster_uuid="CLUSTER_UUID"
      jsonPayload.message:"A process is killed due to memory pressure:"
      

終止主要執行個體節點或 driver 節點集區工作

  • 如果 Managed Service for Apache Spark 主要節點或 driver 節點集區工作因記憶體壓力而終止,工作會失敗並顯示錯誤「Driver received SIGTERM/SIGKILL signal and exited with INT code」。如要查看這些訊息,請啟用 Logging,然後使用下列記錄篩選條件:

    resource.type="cloud_dataproc_cluster"
    resource.labels.cluster_name="CLUSTER_NAME"
    resource.labels.cluster_uuid="CLUSTER_UUID"
    jsonPayload.message:"Driver received SIGTERM/SIGKILL signal and exited with"
        

    • 檢查 google.dataproc.oom-killer 記錄檔或 dataproc.googleapis.com/node/problem_count,確認 Managed Service for Apache Spark 記憶體保護機制已終止作業 (請參閱「程序終止」)。

    解決方法:

    • 如果叢集有驅動程式集區,請將 driver-required-memory-mb 提高至實際的工作記憶體用量。
    • 如果叢集沒有驅動程式集區,請重新建立叢集,並降低叢集上執行的並行工作數量上限
    • 使用記憶體增量的主要節點機型。

Worker 節點 YARN 容器終止

  • Managed Service for Apache Spark 會在 YARN Resource Manager 中寫入以下訊息:container id exited with code EXIT_CODE。如要查看這些訊息,請啟用 Logging,然後使用下列記錄篩選條件:

    resource.type="cloud_dataproc_cluster"
    resource.labels.cluster_name="CLUSTER_NAME"
    resource.labels.cluster_uuid="CLUSTER_UUID"
    jsonPayload.message:"container" AND "exited with code" AND "which potentially signifies memory pressure on NODE
    
  • 如果容器以 code INT 結束,請檢查 google.dataproc.oom-killer 記錄或 dataproc.googleapis.com/node/problem_count,確認 Managed Service for Apache Spark 記憶體保護機制已終止工作 (請參閱「程序終止」)。

    解決方法:

    • 確認容器大小設定正確無誤。
    • 建議調低 yarn.nodemanager.resource.memory-mb。這項屬性控制了 YARN 容器所能分配到的記憶體用量。
    • 如果工作容器持續執行失敗,請檢查是否因資料偏斜而導致特定容器用量增加。若是如此,請重新分割工作或增加 worker大 小,以因應額外的記憶體需求。

在主要節點上微調 Linux 記憶體保護功能 (進階)

在可用記憶體嚴重不足時,Managed Service for Apache Spark 主要節點會使用 earlyoom 公用程式釋放記憶體,避免系統停止回應。系統預設的設定適用於多種工作負載。但若主要節點記憶體容量較大,且記憶體消耗迅速,則可能需要調整設定。

在記憶體壓力過大的情況下,系統可能會進入「輾轉現象」狀態,將大部分時間用於管理記憶體,導致沒有回應。此現象可能發生得極快,導致 earlyoom 來不及根據預設設定採取行動,或無法在叫用核心 OOM 回覆之前及時動作。

事前準備

  • 這是進階調整選項。在調整 earlyoom 設定前,請優先採用其他解決方案,例如使用配備更多記憶體的主要執行個體 VM、減少工作並行數量,或是最佳化工作記憶體用量。

自訂 earlyoom 設定

預設的 earlyoom 設定使用固定數量的可用記憶體做為觸發條件。在 RAM 容量較大的虛擬機器上 (例如 32GB 以上),此固定數量可能只占總記憶體的一小部分。這會導致系統容易出現記憶體用量突然激增的情況。

如要自訂 earlyoom 設定,請連線至主要執行個體節點並修改設定檔。

  1. 使用 SSH 連線至主要節點

  2. 開啟設定檔進行編輯:

    sudo nano /etc/default/earlyoom
    
  3. 調整記憶體最低閾值。找出 EARLYOOM_ARGS 這一行。-M <kbytes> 選項會設定 earlyoom 嘗試維持的可用記憶體數量下限 (以 KiB 為單位)。預設值為 -M 65536,也就是 64 MiB

    如果主要節點的記憶體容量較大,請調高這個值。例如,若要將閾值設為 1 GiB (1048576 KiB),請如下修改該行:

    EARLYOOM_ARGS="-r 15 -M 1048576 -s 1"
    

    附註:

    • -r:記憶體報告間隔 (以秒為單位)
    • -s:觸發 earlyoom 的交換空間閾值
  4. 重新啟動 earlyoom 服務,以套用變更:

    sudo systemctl restart earlyoom