zoukankan      html  css  js  c++  java
  • Kubernetes Eviction驱逐

    介绍

    概念功能说明

    • kubelet主动监测和防止Kubernetes集群的资源使用情况,在资源短缺时,如何判断资源短缺根据系统设置的eviction保留策略,当节点资源使用触发到该阈值,开始执行驱逐(主动的结束一个或者多个Pod以回收资源,Pod的状态变为Failed),如果被驱逐的Pod被deployment控制器接管,那么将会被调度到其它的节点
      "evictionHard": {
            "imagefs.available": "15%",
            "memory.available": "100Mi",
            "nodefs.available": "10%",
            "nodefs.inodesFree": "5%"
          },

    驱逐处理

    驱逐信号

    具体信号,参考下表

    驱逐信号 解释  
    memory.available  memory.available := node.status.capacity[memory] - node.stats.memory.workingSet 代表节点可用的内存
    nodefs.available nodefs.available := node.stats.fs.available 可用的文件系统,一般指/,官方说明是指kubelet所使用的卷及日志所在文件系统
    nodefs.inodesFree nodefs.inodesFree := node.stats.fs.inodesFree 同上,inode的使用
    imagefs.available imagefs.available := node.stats.runtime.imagefs.available Container runtimes所在的逻辑卷,用于存储镜像及可写入的镜像层
    imagefs.inodesFree imagefs.inodesFree := node.stats.runtime.imagefs.inodesFree 同上,inode的使用
    pid.available pid.available := node.stats.rlimit.maxpid - node.stats.rlimit.curproc  

    驱逐信号的值,可以用具体数字及百分比代表

    memory.available 的值从 cgroupfs 获取,而不是通过类似 free -m 的工具。因为 free -m 不能在容器中工作,并且如果用户使用了 节点可分配资源 特性,资源不足的判定将同时在本地 cgroup 层次结构的终端用户 Pod 部分和根节点做出。 这个脚本 复现了与 kubelet 计算 memory.available 相同的步骤。 kubelet 将 inactive_file(意即活动 LRU 列表上基于文件后端的内存字节数)从计算中排除, 因为它假设内存在出现压力时将被回收

    官方文档总是那么的认真,一句话,就是节点的available内存,还给出一个具体计算方式

      • 计算方式
        #!/bin/bash
        #!/usr/bin/env bash
        
        # This script reproduces what the kubelet does
        # to calculate memory.available relative to root cgroup.
        
        # current memory usage
        memory_capacity_in_kb=$(cat /proc/meminfo | grep MemTotal | awk '{print $2}')
        memory_capacity_in_bytes=$((memory_capacity_in_kb * 1024))
        memory_usage_in_bytes=$(cat /sys/fs/cgroup/memory/memory.usage_in_bytes)
        memory_total_inactive_file=$(cat /sys/fs/cgroup/memory/memory.stat | grep total_inactive_file | awk '{print $2}')
        
        memory_working_set=${memory_usage_in_bytes}
        if [ "$memory_working_set" -lt "$memory_total_inactive_file" ];
        then
            memory_working_set=0
        else
            memory_working_set=$((memory_usage_in_bytes - memory_total_inactive_file))
        fi
        
        memory_available_in_bytes=$((memory_capacity_in_bytes - memory_working_set))
        memory_available_in_kb=$((memory_available_in_bytes / 1024))
        memory_available_in_mb=$((memory_available_in_kb / 1024))
        
        echo "memory.capacity_in_bytes $memory_capacity_in_bytes"
        echo "memory.usage_in_bytes $memory_usage_in_bytes"
        echo "memory.total_inactive_file $memory_total_inactive_file"
        echo "memory.working_set $memory_working_set"
        echo "memory.available_in_bytes $memory_available_in_bytes"
        echo "memory.available_in_kb $memory_available_in_kb"
        echo "memory.available_in_mb $memory_available_in_mb"

    文件系统驱逐信号

    目前kubelet只支持二种文件系统,如下

    1. nodefs (节点kubelet所在文件系统使用率)
    2. imagefs(docker的Root Dir,docker info查看)

    驱逐阈值

    表示语法

    [eviction-signal][operator][quantity]

    • 合法的 eviction-signal 标志如上所示。
    • operator 是所需的关系运算符,例如 <
    • quantity 是驱逐阈值值标志,例如 1Gi。合法的标志必须匹配 Kubernetes 使用的数量表示。 驱逐阈值也可以使用 % 标记表示百分比
    举例说明,如果一个节点有 10Gi 内存,希望在可用内存下降到 1Gi 以下时引起驱逐操作, 则驱逐阈值可以使用下面任意一种方式指定(但不是两者同时)
    memory.available<10%
    memory.available<1Gi

    驱逐方式

    1. 硬驱逐:硬驱逐阈值没有宽限期,触发阈值,kubelet将立即采取行动回收关联的资源(被触发的资源)。 如果满足硬驱逐阈值,kubelet将立即结束 (kill的方式)Pod 而不是优雅的(stop的方式)它们
    2. 软驱逐:当触发阈值时需要等待指定的宽限期组合使用(阈值&宽限期),在超出宽限期前,kubelet不会采取任何动作回收和驱逐信号关联的资源。如果没有提供宽限期,kubelet启动时将报错;此外,如果达到了软驱逐阈值,可以指定从节点驱逐 pod 时,在宽限期内允许结束的 pod 的最大数量。 如果指定了 pod.Spec.TerminationGracePeriodSeconds值, kubelet取二者(TerminationGracePeriodSeconds & eviction-soft-grace-period)的最小值执行。 如果没有指定,kubelet将立即终止 pod,而不会优雅结束它们
      • eviction-soft 描述了驱逐阈值的集合(例如 memory.available<1.5Gi),如果在宽限期之外满足条件将触发 pod 驱逐。
      • eviction-soft-grace-period 描述了驱逐宽限期的集合(例如 memory.available=1m30s),对应于在驱逐 pod 前软驱逐阈值应该被控制的时长。
      • eviction-max-pod-grace-period 描述了当满足软驱逐阈值并终止 pod 时允许的最大宽限期值(秒数)

    驱逐时间检查间隔

    housekeeping-interval 是容器管理时间间隔

    驱逐节点状态

    当集群中的某个节点,触发到驱逐阈值时,节点会呈现出以下状态
    MemoryPressure memory.available 节点上可用内存量达到逐出阈值
    DiskPressure
    nodefs.available, nodefs.inodesFree, imagefs.available, 或 imagefs.inodesFree
    节点或者节点的根文件系统或镜像文件系统上可用磁盘空间和 inode个数达到逐出阈值
    PIDPressure pid.available 在(Linux)节点上的可用进程标识符已降至驱逐阈值以下

    驱逐时节点资源波动

    kubelet在配置了软驱逐时,如果触发了阈值并在上下波动,时true时flase,针对此种情况会使用以下参数规避

    eviction-pressure-transition-period (默认时间5m0s)是 kubelet从压力状态中退出之前必须等待的时长

    回收节点资源

    当时达到eviction阈值时,kubelet在驱逐Pod释放系统资源,比如硬盘资源缺乏时,如下规则

    imagefs

    1. 如果 nodefs文件系统满足驱逐阈值,kubelet通过删除dead pod & Contaienr以释放磁盘空间
    2. 如果 imagefs文件系统满足驱逐阈值,kubelet通过删除所有未使用的镜像来释放磁盘空间

    no imagefs

    1. 删除所有Dead Pod & Container
    2. 删除所有未使用镜像

    驱逐Pod

    如果kubele在节点上无法回收足够的资源,则需要驱逐Pod,具体顺序如下

    1. 首先对BestEffort或者Burstable此类Qos级别Pod的紧缺资源进行判断,判断的条件是实际使用大于请求分配,然后进行排序,高则驱逐
    2. Guaranteed pod 和 Burstable pod实际使用低于请求分配,最后被驱逐,高则先被驱逐
    3. 如果在节点遇到系统守护进程如(kubelet docker journald)实际使用的资源消耗大于systemReserved & kubeReserved预留的资源,则按优先级驱逐此类Pod以保持节点的稳定性
    4. 具体个人总结为(BestEffort > Burstable > Guaranteed )同级情况比较资源的消耗量,高则先被驱逐
    • imagesfs
    1. 如果是 nodefs触发驱逐,kubelet是按基于nodefs用量进行排序,判断条件(本地卷 + Pod所有容器日志的总和)
    2. 如果 imagefs 触发了驱逐,Kubelet 按Pod中所有容器的写入层进行排序,从高至低,高则驱逐
    • no imagefs
    1. 如果是nodefs触发了驱逐阈值,kubelet基于Pod的所有容器的(Local volumes + 日志用量 + 可写入层)的和进行排序

     最小回收值

    有时会遇到在触发驱逐阈值后,驱逐Pod会回收少量的资源会反反复复进行驱逐这样会引起平台的稳定性,对此可以设置最小回收值解决此类现象,如下

    --eviction-hard=memory.available<500Mi,nodefs.available<1Gi,imagefs.available<100Gi

    --eviction-minimum-reclaim="memory.available=0Mi,nodefs.available=500Mi,imagefs.available=2Gi"

    以上案例表示如果遇到触发了内存驱逐条件时,那么最终回收的内存资源值是(500Mi+0Mi),默认 eviction-minimum-reclaim 值为 0

    节点OOM

    如果kubelet在回收内存前先执行了节点OOM,那么下表是依据Pod的Qos而定义的oom_score_adj的值

    sshd/dmevented / systemd-udevd
    -1000
    kubelet/docker/journalctl
    -999
    Guaranteed
    -998
    BestEffort
    1000
    Burstable
    min(max(2, 1000 - (1000 * memoryRequestBytes) / machineMemoryCapacityBytes), 999)

    如果节点OS在内存紧缺时,并且在节点OOM之前无法进行内存回收,那么oom_killer会计算所有container基于内存使用的百分比得出oom_score,再与oom_score_adj,最终算出容器真正的oom_score,然后kill得分最高的容器,具体公式如下

    init oom_score(基于容器对内存使用的百分比计算) + oom_score_adj = oom_score_adj,计算的结果等于Pod的Qos等级最低及请求内存最高的容器首先被第一个结束

    与Pod驱逐不同的是,如果一个Pod被OOM,会被所属的资源管理器所接管,如deployment接管,kubelet执行对应Deployment中指定的restartPolicy策略

    驱逐建议

    参考场景:

    节点内存容量:10Gi

    系统守护进程保留 5% 内存量(kernel sshd udevf)系统守护进程而预留

    kubeRserved预留 5% 内存量(kubelet  docekr proxy)Kubernetes组件而预留

    在内存用量达到 90% 时驱逐 pod,以减少对系统的冲击并防止系统 OOM 的发生

    • 具体配置,如下
          "evictionHard": {
            "imagefs.available": "15%",
            "memory.available": "10%",
            "nodefs.available": "10%",
            "nodefs.inodesFree": "5%"
          },
          "evictionPressureTransitionPeriod": "4m0s",
          "evictionMinimumReclaim": {
            "imagefs.available": "2Gi",
            "memory.available": "300Mi",
            "nodefs.available": "500Mi"
          },
      ...
          "systemReserved": {
            "cpu": "500m",
            "memory": "500Mi"
          },
          "kubeReserved": {
            "cpu": "500m",
            "memory": "500Mi"
          }

    以上配置总结如下

    systemReserved+kubeReserved ≥ eviction > node OOM(/proc/sys/vm/min_free_kbytes)

    如果systemReserved + kubeReserved < eviction 的值代表OOM的概率增加,因为Pod的Allocatable的值接近Capacity的值

    如果systemReserved + kubeReserved > eviction 的值代表OOM的概率减少,因为Pod的Allocatable的值小于Capacity的值

    最终目的是优先执行eviction,防止应用丢失数据

    DaemonSet

    在配置DaemonSet时资源副本控制器,Qos的等级务必为Guaranteed(requests & limits的值相同),因为如果Qos设置过低的话,会被优先驱逐,由于DaemonSet的特性是每个节点的守护Pod,如果kill或者驱逐则调度器会在相同的节点重新调度

    https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/#active-file-memory-is-not-considered-as-available-memory

  • 相关阅读:
    用户访问过的产品,在cookie记录产品id,id取得产品信息
    文件上传操作
    上次文件先创建目录,再上传到目录里面去
    解决PHPcms 2008 sp4 注册选择模型关闭后,注册不能自动登录的问题
    php输出表格的方法
    php中实现退后功能,不用历史记录
    PHP的substr_replace将指定两位置之间的字符替换为*号
    php算开始时间到过期时间的相隔的天数,同理可以实现相隔年,小时,分,秒等数
    不用js用php做tab选项卡
    再也回不去的从前
  • 原文地址:https://www.cnblogs.com/apink/p/15153490.html
Copyright © 2011-2022 走看看