将节点配置为使用磁盘空间作为虚拟内存

借助 Google Kubernetes Engine (GKE) 节点内存交换,GKE 节点可以在物理内存耗尽时将磁盘可用空间用作虚拟内存。节点内存交换有助于提高应用弹性,并防止某些工作负载出现内存不足 (OOM) 错误。

何时使用节点内存交换

使用节点内存交换可为内存密集型应用提供针对 OOM 错误的缓冲区,尤其是在意外使用高峰期间。节点内存交换有助于提高工作负载弹性,例如在以下场景中:

  • 运行具有不可预测内存模式的工作负载。
  • 降低应用因节点内存耗尽而崩溃的风险。
  • 避免为应对偶尔出现的峰值而过度预配内存,从而优化费用。

节点内存交换的工作原理

启用节点内存交换后,GKE 会将节点的操作系统配置为使用磁盘可用空间作为虚拟内存。此过程可为遇到临时内存压力的应用提供缓冲区。

GKE 会根据容器的内存资源限制和节点的总内存计算容器交换限制。

您可以在不同的存储类型上配置交换,以平衡性能和费用:

  • 启动磁盘:使用节点的启动磁盘作为交换空间。
  • 临时本地 SSD:使用也与 Pod 临时存储共享的本地 SSD。如果节点使用混合本地 SSD 容量,则交换空间仅使用本地 SSD 的临时存储部分。
  • 专用本地 SSD:预留一个或多个本地 SSD 专门用于交换。

为了保护敏感数据,GKE 默认使用临时密钥对交换空间进行加密。

要求和限制

节点内存交换具有以下要求和限制:

  • GKE 集群必须为 1.34.1-gke.1341000 版或更高版本。
  • 只有具有 Burstable 服务质量 (QoS) 类的 Pod 才能使用节点内存交换。如需详细了解 QoS 类,请参阅 Kubernetes 文档中的 Pod 服务质量类。
  • 如需调整容器的内存资源大小,您必须将容器大小调整政策设置为 RestartContainer。
  • 如果您将节点内存交换配置为使用启动磁盘,则交换大小不能超过启动磁盘总容量的 50%。

如果您将节点内存交换配置为使用本地 SSD,则必须确保满足以下要求:

  • 机器类型必须支持本地 SSD。您只能使用预配为临时存储空间或混合存储空间的本地 SSD。您无法使用预配为原始块存储设备的本地 SSD。如需查看此模式下支持的交换配置文件列表,请参阅具有混合本地 SSD 容量的节点内存交换。
  • 节点必须预配本地 SSD。预配方法取决于机器系列:
    • 对于第一代或第二代机器系列,请设置 --ephemeral-storage-local-ssd=count 标志。
    • 对于第三代或第四代机器系列,请选择捆绑了本地 SSD 的机器类型。
  • 默认的 e2-medium 机器类型不支持本地 SSD,因此您必须选择其他机器类型。
  • 如需了解如何创建或更新集群以预配本地 SSD,请参阅预配和使用本地 SSD 支持的临时存储空间。

最佳做法

节点内存交换旨在作为不可预测的内存峰值的安全网,而不是替代足够的物理内存。如需有关优化工作负载的指导,请参阅大规模合理调整 GKE 工作负载容量。

使用节点内存交换时,您还应考虑以下最佳实践:

  • 通过向节点池应用污点(例如 gke-swap=enabled:NoSchedule)并向要使用交换空间的负载添加相应的容忍度,隔离启用了节点内存交换的节点。
  • 适当调整节点内存交换空间的大小。节点内存交换空间不足可能无法防止 OOM 错误,而过度使用可能会降低性能。
  • 监控工作负载的节点内存交换使用情况。频繁使用节点内存交换可能表示存在内存压力。

准备工作

在开始之前,请确保您已执行以下任务:

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如需使用 Google Cloud CLI 执行此任务,请安装并初始化 gcloud CLI。如果您之前安装了 gcloud CLI,请通过运行 gcloud components update 命令来获取最新版本。较早版本的 gcloud CLI 可能不支持运行本文档中的命令。

启用节点内存交换

您可以按集群或节点池启用节点内存交换。如需启用节点内存交换,请创建或更新包含所需节点内存交换配置的 system-config.yaml 文件。以下示例使用默认设置启用节点内存交换:

linuxConfig:
  swapConfig:
    enabled: true

您还可以配置其他设置。以下示例将未加密的交换空间配置为使用临时本地 SSD 存储空间的 30%:

linuxConfig:
  swapConfig:
    enabled: true
    encryptionConfig:
      disabled: true
    ephemeralLocalSsdProfile:
      swapSizePercent: 30

如需查看您可以配置的可选字段列表,请参阅 LinuxNodeConfig API 文档。

在集群上启用节点内存交换

如需在集群上启用节点内存交换,请完成以下任一步骤:

  • 如需创建启用了节点内存交换的新集群,请运行以下命令:

    gcloud container clusters create CLUSTER_NAME \
        --location=LOCATION \
        --cluster-version=1.34.1-gke.1341000 \
        --system-config-from-file=system-config.yaml
    

    替换以下内容:

    • CLUSTER_NAME:新集群的名称。
    • LOCATION:集群所在的区域或可用区。
  • 如需更新现有集群以启用节点内存交换,请运行以下命令:

    gcloud container clusters update CLUSTER_NAME \
        --location=LOCATION \
        --system-config-from-file=system-config.yaml
    

    替换以下内容:

    • CLUSTER_NAME:新集群的名称。
    • LOCATION:集群所在的区域或可用区。

在节点池池上启用节点内存交换

如需在节点池池上启用节点内存交换,请完成以下任一步骤:

  • 如需创建启用了节点内存交换的新节点池,请运行以下命令:

    gcloud container node-pools create NODEPOOL_NAME \
        --cluster=CLUSTER_NAME \
        --location=LOCATION \
        --node-version=1.34.1-gke.1293000 \
        --system-config-from-file=system-config.yaml \
        --machine-type=MACHINE_TYPE
    

    替换以下内容:

    • NODEPOOL_NAME:新节点池的名称。
    • CLUSTER_NAME:您的集群的名称。
    • LOCATION:集群所在的区域或可用区。
    • MACHINE_TYPE:兼容的机器类型。对于本地 SSD,请确保选择捆绑了本地 SSD 的机器类型,例如 n1-standard-1。
  • 如需更新现有节点池以启用节点内存交换,请运行以下命令:

    gcloud container node-pools update NODEPOOL_NAME \
        --cluster=CLUSTER_NAME \
        --location=LOCATION \
        --system-config-from-file=system-config.yaml
    

    替换以下内容:

    • NODEPOOL_NAME:节点池的名称。
    • CLUSTER_NAME:您的集群的名称。
    • LOCATION:集群所在的区域或可用区。

验证配置

如需验证是否已启用节点内存交换,请完成以下步骤:

  1. 通过运行以下命令,验证是否已使用 swapConfig 设置应用 system-config.yaml:

    gcloud container node-pools describe NODEPOOL_NAME \
        --cluster=CLUSTER_NAME \
        --location=LOCATION \
        --format='yaml(config.linuxNodeConfig.swapConfig)'
    
  2. 运行以下命令,验证节点上是否存在 kubelet 配置:

    kubectl get --raw "/api/v1/nodes/NODE_NAME/proxy/configz" | jq .kubeletconfig.memorySwap
    

监控内存交换使用情况

您可以使用 Cloud Monitoring 或 kubectl 监控节点内存。

监控

默认情况下,以下系统指标可用于观察交换空间使用情况:

  • kubernetes.io/node/memory/swap_used_bytes
  • kubernetes.io/container/memory/swap_used_bytes

GKE 还通过 cAdvisor 提供容器级交换空间用量指标。如需使用这些指标,请在集群上启用 cAdvisor:

  • prometheus.googleapis.com/container_memory_swap/gauge

kubectl

通过完成以下步骤,使用 kubectl 命令监控交换空间使用情况:

  1. 通过运行以下命令,检查节点对象上的 SwapDetected 条件:

    kubectl get node NODE_NAME -o jsonpath='{.status.conditions[?(@.type=="Swap")]}' | jq .
    

    输出类似于以下内容:

    {
      "lastHeartbeatTime": "2025-07-11T00:14:52Z",
      "lastTransitionTime": "2025-06-25T05:20:10Z",
      "message": "Swap is active: Total=49Gi Used=0B Free=49Gi",
      "reason": "SwapDetected",
      "status": "True",
      "type": "Swap"
    }
    
  2. 运行以下命令,检查交换容量:

    kubectl get node NODE_NAME -o jsonpath='{.status.nodeInfo.swap}'
    

    输出类似于以下内容:

    {"capacity":53687087104}
    

具有混合本地 SSD 容量的节点内存交换

您可以在预配混合本地 SSD 的节点池上启用节点内存交换。GKE 支持以下交换配置文件:

  • 启动磁盘 (bootDiskProfile)
  • 临时本地 SSD (ephemeralLocalSsdProfile):GKE 从本地 SSD 的临时存储部分(而非原始块分区)分配交换空间。

GKE 不支持将专用本地 SSD 交换配置文件 (dedicatedLocalSsdProfile) 与混合本地 SSD 搭配使用。

如果您使用临时本地 SSD 配置文件,请注意以下事项:

  • swapSizePercent 字段是您使用 capacity 子字段设置的临时容量的百分比,而不是物理本地 SSD 总容量。例如,如果设置了 capacity=200GB 和 swapSizePercent: 20,GKE 会分配 40 GiB 的交换空间。
  • 交换空间会减少 Pod 可用的临时存储空间。 GKE 会根据临时容量减去交换空间大小来计算预留的临时存储空间。
  • 交换空间大小不能超过临时容量的 80% 减去 GKE 为系统预留的临时存储空间。如果临时容量太小,无法容纳交换,则请求会失败。

以下示例 system-config.yaml 文件将 20% 的临时容量分配给交换空间:

linuxConfig:
  swapConfig:
    enabled: true
    ephemeralLocalSsdProfile:
      swapSizePercent: 20

如需创建具有混合本地 SSD 容量和节点内存交换的节点池,请运行以下命令:

gcloud container node-pools create POOL_NAME \
    --cluster=CLUSTER_NAME \
    --machine-type=MACHINE_TYPE \
    --ephemeral-storage-local-ssd count=NUMBER_OF_DISKS,capacity=CAPACITY \
    --system-config-from-file=system-config.yaml

替换以下内容:

  • POOL_NAME:要创建的新节点池的名称。
  • CLUSTER_NAME:集群的名称。
  • MACHINE_TYPE:要使用的机器类型。您无法将本地 SSD 与默认的 e2-medium 机器类型搭配使用,因为共享核心机器类型不支持本地 SSD。
  • NUMBER_OF_DISKS:每个节点上预配的本地固态硬盘的数量。
  • CAPACITY:要格式化以用作临时存储的本地 SSD 总容量。此值必须大于 0 且严格小于本地 SSD 物理总容量(磁盘数量 × 每个磁盘的大小),例如 200GB。

停用节点内存交换

如需停用节点内存交换,请完成以下步骤来更新 system-config.yaml 文件:

  1. 更新 system-config.yaml 文件,将 swapConfig.enabled 设置为 false:

    linuxConfig:
      swapConfig:
        enabled: false
    
  2. 使用新配置更新节点池:

    gcloud container node-pools update NODEPOOL_NAME \
        --cluster=CLUSTER_NAME \
        --location=LOCATION \
        --system-config-from-file=system-config.yaml
    

后续步骤