metrics-server采集数据失败问题排查

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了metrics-server采集数据失败问题排查相关的知识,希望对你有一定的参考价值。

参考技术A 按照文档 《Kubernetes heapster监控插件安装》 和 《Kubernetes Metrics Server安装》 完成Heapster和Metrics Server之后,想尝试通过 kubectl top nodes 查看安装效果,结果抛出下面的错误:

我用下面一张图简单描述了一下APIService、Service、Pod、kubelet四者的关系,APIService负责对外提供服务,Pod访问个节点的kubelet抓取节点上各种指标数据,然后提供给APIService。

所以,我首先查看了一下APIService的状态,看APIService是否正常。通过下面的命令查看 kube-system/metrics-server APIService 的状态,可以看到有下面的报错信息:

从上面信息可以看到,APIService访问后端服务无响应,所以我再去查看Pod的日志:

从错误信息可以看到: metrics-server在调用各节点的kubelet获取对应节点上的指标信息时,指标数据没有有效的时间戳
根本原因是: 某些pod或node没有正常运行 ,如下图所示。只要保证pod或node运行正常后,这些错误信息就会消失。

然而,这个错误并不是根本原因,在纠结了两天之后,我突然想到,既然https请求无法访问,是不是和代理有关系。

我之前在 /etc/kubernetes/manifests/kube-apiserver.yaml 中加了一个https代理:

删掉这个代理问题就解决了,如果不能删除这个代理,也可以配置 no_proxy 环境变量,把10.108.78.78加上。

业务指标采集影响系统性能问题排查

文章目录


背景:

  • 规则引擎 + 图结构的执行逻辑
  • Datadog 指标监控系统
  • 多组 Kafka 集群

1. 现象描述

业务处理逻辑比较重, 执行代码的效率上不去, 系统吞吐量不足。

部署了N个Docker节点(8C8G), CPU使用率80~90%, 每秒吞吐量总计只有2万左右,远远小于生产者的速度。

2. 原因分析

经过排查,发现2个瓶颈点:

  • 并行流: parallelStream();
  • 指标采集: Micrometer的 Timed 注解, 以及 StatsDClient#time() 方法;

并行流的性能问题:

如果不是纯粹CPU密集型的任务, 并行流默认会使用 ForkJoinPool 来执行, 高并发场景下会导致任务堆积以及阻塞问题。

Timed 注解的问题:

这是早期进行性能调优时, 为了进行指标监控加上的;

根据业务特征, 导致这里每一条数据都会执行几十次方法(图+递归), 恰好大部分方法都标注了 @Timed 注解, 被

StatsDClient指标上报客户端的实现:

public final class NonBlockingStatsDClient
    
    private final BlockingQueue<String> queue;
    // ... ... 
    // final int queueSize = Integer.MAX_VALUE
    // queue = new LinkedBlockingQueue<String>(queueSize);
    private void send(final String message) 
        queue.offer(message);
    

LinkedBlockingQueue 之类的阻塞队列, 高并发时可能会发生一些问题, 比如 锁争抢, 队列过大等等.


public class LinkedBlockingQueue<E> extends AbstractQueue<E>
        implements BlockingQueue<E>, java.io.Serializable 

    public boolean offer(E e) 
        if (e == null) throw new NullPointerException();
        final AtomicInteger count = this.count;
        if (count.get() == capacity)
            return false;
        final int c;
        final Node<E> node = new Node<E>(e);
        final ReentrantLock putLock = this.putLock;
        putLock.lock();
        try 
            if (count.get() == capacity)
                return false;
            enqueue(node);
            c = count.getAndIncrement();
            if (c + 1 < capacity)
                notFull.signal();
         finally 
            putLock.unlock();
        
        if (c == 0)
            signalNotEmpty();
        return true;
    

3. 解决办法

  1. 将并行流改成普通流, 或者取消流:
        /*
        taskIdList.parallelStream().forEach(taskId -> 
        */
        taskIdList.forEach(taskId -> 
            // ... ...
        );

需要提高并发度可以采用自定义线程池处理;

  1. 取消 TimedAspect, 让 @Timed 注解失效:
/*
    @Bean
    public TimedAspect timedAspect(MeterRegistry reg) 
        return new TimedAspect(reg);
    
*/
  1. 屏蔽部分无效指标
    private static StatsDClient statsDClient;
    public static void recordTime(String aspectPrefix, long usedMillisecond, String... tags) 
        if(usedMillisecond < 1L)
            return;
        
        statsDClient.time(aspectPrefix + ".time", usedMillisecond, tags == null ? EMPTY_TAG : tags);
    

根据业务特征, 小于1ms的指标, 直接抛弃;

这个阈值看具体业务来确定, 也可以在业务代码中按批次进行聚合与上报, 减小指标系统压力;

4. 优化效果

重新发版之后, 每秒总吞吐量达到了 80 万左右, 基本跟上生产者的速度;

CPU使用率也降低到30~40%左右;

至此, 本次优化基本完成, 后续需要在提高并发度的同时防止背压问题。

5. 总结

早期进行性能优化时, 追踪了详细的业务指标监控信息。 当然,业务复杂度也在持续上升, 等到吞吐量达到一定阶段时, 指标采集的部分又形成了新的瓶颈点, 根据需求, 去除不必要的指标采集之后, 性能得到了大幅度提升。

当然, 在特定的系统容量下, 性能满足业务的需求即可, 调优成果很多时候还是不稳定的产出,有时候得靠一点经验。

知识储备:
有些任务你可以不做、做不到、暂时没资格做,比如有价值的事都被上司和前辈分摊了。
但你不能一直不懂、不会做。
如果你不懂、不会, 还不学习,那么就永远跟机会无缘。
通过看书和网络进行积累, 大致明白和了解,那么日常工作中起码可以争取到一些机会,慢慢的机会就越来越多。

相关链接

以上是关于metrics-server采集数据失败问题排查的主要内容,如果未能解决你的问题,请参考以下文章

大数据问题排查系列-大数据集群开启 kerberos 认证后 HIVE 作业执行失败

业务指标采集影响系统性能问题排查

数据库日志采集系统方案设计

业务指标采集影响系统性能问题排查

业务指标采集影响系统性能问题排查

业务指标采集影响系统性能问题排查