从Container内存监控限制到CPU使用率限制方案

前言最近在运维我们部门的hadoop集群时,发现了很多Job OOM的现象,因为在机器上可以用命令进行查看,full gc比较严重.我们都知道,full gc带来的后果是比较大的,会"stop the world"的,一旦你的full gc elapsed time超过几分钟,那么其他的活动都得暂停这么多时间.所以Full gc一旦出现并且异常,一定要找到根源并将其解决.本篇文章就为大家讲述一下我
摘要由CSDN通过智能技术生成

前言

最近在运维我们部门的hadoop集群时,发现了很多Job OOM的现象,因为在机器上可以用命令进行查看,full gc比较严重.我们都知道,full gc带来的后果是比较大的,会"stop the world"的,一旦你的full gc elapsed time超过几分钟,那么其他的活动都得暂停这么多时间.所以Full gc一旦出现并且异常,一定要找到根源并将其解决.本篇文章就为大家讲述一下我们是如何解决这类问题并且在这个基础上做了一些别的什么优化的.


Full Gc源于何处

OOM发生了,导致频繁的Full Gc的现象,首先就要想到底是什么导致Full gc.第一个联想一定是上面跑的Job,Job的运行时的体现又是从每个task身上来的,而每个Task又是表现于每个TaskAttempt.而TaskAttempt是跑在所申请到的container中的.每个container都是一个独立的进程,你可以在某台datanode上用jps命令,可以看到很多叫"YarnChild"的进程,那就是container所起的.找到了源头之后,我们估计会想,那应该是container所启的jvm的内存大小配小了,导致内存不够用了,内存配大些不就可以解决问题了?事实上问题并没有这么简单,这里面的水还是有点深的.


为什么会发生Full Gc

一.为什么会发生full gc,第一种原因就是平常大家所说的内存配小了,就是下面2个配置项:

public static final String MAP_MEMORY_MB = "mapreduce.map.memory.mb";
public static final String REDUCE_MEMORY_MB = "mapreduce.reduce.memory.mb";
默认都是1024M,就是1个G.

二.另外一个原因估计想到的人就不太多了,除非你真的在生活中碰到过,概况来说一句话:错误的配置导致.上面的这个配置其实并不是container设置他所启的jvm的配置,而是每个Task所能用的内存的上限值,但是这里会有个前提,你的jvm必须保证可以用到这么多的内存,如果你的jvm最大内存上限就只有512M,你的task的memory设的再大也没有,最后造成的直接后果就是内存一用超,就会出现full gc.上面的2个值更偏向于理论值.而真正掌控jvm的配置项的其实是这2个配置:

public static final String MAP_JAVA_OPTS = "mapreduce.map.java.opts";
public static final String REDUCE_JAVA_OPTS = "mapreduce.reduce.java.opts";
所以理想的配置应该是java.opts的值必须大于等于memory.mb的值.所以说,这种配置不当的方式也会引发频繁的full gc.


Container内存监控

不过比较幸运的是针对上面所列举的第二种问题,hadoop自身已经对此进行了contaienr级别的监控,对于所有启动过container,他会额外开启一个叫container-monitor的线程,专门有对于这些container的pmem(物理内存),vmem(虚拟内存)的监控.相关的配置属于如下:

String org.apache.hadoop.yarn.conf.YarnConfiguration.NM_PMEM_CHECK_ENABLED = "yarn.nodemanager.pmem-check-enabled"
String org.apache.hadoop.yarn.conf.YarnConfiguration.NM_VMEM_CHECK_ENABLED = "yarn.nodemanager.vmem-check-enabled"
默认都是开启的.内存监控的意思就是一旦这个container所使用的内存超过这个jvm本身所能使用的最大上限值,则将此conyainer kill掉.下面简单的从源代码的级别为大家分析一下,过其实不难.首先进入到ContainersMonitorImpl.java这个类.

@Override
  protected void serviceInit(Configuration conf) throws Exception {
    this.monitoringInterval =
        conf.getLong(YarnConfiguration.NM_CONTAINER_MON_INTERVAL_MS,
            YarnConfiguration.DEFAULT_NM_CONTAINER_MON_INTERVAL_MS);

    ....
    pmemCheckEnabled = conf.getBoolean(YarnConfiguration.NM_PMEM_CHECK_ENABLED,
        YarnConfiguration.DEFAULT_NM_PMEM_CHECK_ENABLED);
    vmemCheckEnabled = conf.getBoolean(YarnConfiguration.NM_VMEM_CHECK_ENABLED,
        YarnConfiguration.DEFAULT_NM_VMEM_CHECK_ENABLED);
    LOG.info("Physical memory check enabled: " + pmemCheckEnabled);
    LOG.info("Virtual memory check enabled: " + vmemCheckEnabled);
    ....
在serviceInit方法中就会从配置中读取是否开启内存监控功能,并输出日志信息.然后我们直接进入到此类的MonitorThread监控线程类中.

  ....
  private class MonitoringThread extends Thread {
    public MonitoringThread() {
      super("Container Monitor");
    }

    @Override
    public void run() {

      while (true) {

        // Print the processTrees for debugging.
        if (LOG.isDebugEnab
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Prometheus来监控Pod的使用率,并设置告警规则来触发警报。以下是一些步骤: 1. 安装Prometheus Operator ``` kubectl create namespace monitoring helm install prometheus-operator stable/prometheus-operator --namespace monitoring ``` 2. 安装Node Exporter ``` kubectl apply -f https://raw.githubusercontent.com/prometheus/node_exporter/master/examples/k8s/node-exporter.yaml ``` 3. 配置Prometheus 在Prometheus的配置文件中,添加以下规则: ``` - name: kubernetes-pods kubernetes_sd_configs: - role: pod relabel_configs: - source_labels: [__meta_kubernetes_pod_container_name] action: keep regex: '.*' - action: labelmap regex: __meta_kubernetes_pod_(.+) - source_labels: [__meta_kubernetes_namespace] action: replace target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_pod_name] action: replace target_label: kubernetes_pod_name - source_labels: [__address__, __meta_kubernetes_pod_container_port_name] action: replace target_label: __address__ regex: (.+):(?:\d+);(?:.+) replacement: $1:9100 - source_labels: [__address__] action: replace target_label: instance ``` 4. 配置告警规则 在Prometheus的配置文件中,添加以下告警规则: ``` groups: - name: example rules: - alert: HighPodUsage expr: sum(rate(container_cpu_usage_seconds_total{container_name!="POD"}[5m])) by (kubernetes_pod_name) / sum(container_spec_cpu_quota{container_name!="POD"}) by (kubernetes_pod_name) > 0.8 for: 5m labels: severity: critical annotations: summary: "High pod CPU usage (instance {{ $labels.instance }})" description: "{{ $labels.kubernetes_namespace }}/{{ $labels.kubernetes_pod_name }} is using more than 80% of the CPU allocated to it." ``` 5. 在Prometheus中启用告警规则 在Prometheus的配置文件中,添加以下配置: ``` rule_files: - /etc/prometheus/rules/*.rules ``` 6. 设置警报接收者 可以使用Alertmanager来设置警报接收者。在Alertmanager的配置文件中,添加以下配置: ``` receivers: - name: 'slack-notifications' slack_configs: - api_url: '<your_slack_webhook_url>' channel: '#alerts' send_resolved: true ``` 7. 启用Alertmanager 在Prometheus的配置文件中,添加以下配置: ``` alerting: alertmanagers: - static_configs: - targets: ['alertmanager:9093'] ``` 通过以上步骤,可以使用Prometheus监控Pod的使用率,并设置告警规则来触发警报。如果Pod的CPU使用率超过80%,将会触发警报,并发送到Slack通知接收者。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值