通过MetricsAPI监控pod资源使用情况(k8s资源监控,java)

1. 目的:简单监控pod

我想使用java监控k8s pod的资源的简单使用情况,但是k8s内部并没有采集资源的实现。

但是k8s提供了一套k8s的对接标准,只要适配这套标准,就可以通过kubelet采集资源数据,并且通过k8s api服务器输出。这些对于故障排查以及自动伸缩至关重要

2. 部署指南

metrics-server是Kubernetes的一个集群范围内的聚合器,用于收集所有节点和Pods的资源使用信息,如CPU和内存。metrics指标统计器(github)

  1. 如果证书没问题,部署最新的metrics-server
powershell 复制代码
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.4.1/components.yaml
  1. 如果你的集群使用自签名的证书,你可能需要添加参数来忽略 TLS 验证错误

把commponents.yaml wget下来后, 在 components.yaml 文件中,找到 metrics-server 的 Deployment 部分,并添加以下参数到 args:

powershell 复制代码
- --kubelet-insecure-tls
  1. 查看是否部署成功
powershell 复制代码
kubectl get deployment metrics-server -n kube-system
powershell 复制代码
# 查看所有命名空间的pod资源
kubectl top pods -A

top 命令就可以使用了。

3. java Api调用

在官方提供的客户端 java库里是没有直接调用metrics的方法的。我们只能使用restful api进行访问,

  1. 添加maven依赖(获取tls上下文,如果只是过去资源可以不添加)
xml 复制代码
<dependency>
            <groupId>io.kubernetes</groupId>
            <artifactId>client-java</artifactId>
            <version>18.0.0</version>
        </dependency>
  1. 测试restful api(测试,可不做)
    我这里是手动把证书导入到了postman(k8s的权限认证非常关键,没有权限是无法访问api的)
  2. java访问 restapi
    我这里吧k8s 客户端和 rest http前后文都注入spring了,这样调用起来比较方便

注入k8s客户端

java 复制代码
在这里插入代码片@Configuration
public class KubernetesClientConfig {
         @Bean
    public AppsV1Api appsV1Api(ApiClient apiClient) {
        return  new AppsV1Api(apiClient);
    }

}

注入8sRestTemplate

java 复制代码
@Configuration
public class RestTemplateConfig {
    private final ApiClient apiClient;

    public RestTemplateConfig(ApiClient apiClient) {
        this.apiClient = apiClient;
    }
    @Bean
    public RestTemplate extendK8sRestTemplate() {
       return  new RestTemplate(new OkHttp3ClientHttpRequestFactory(apiClient.getHttpClient()));

    }

}
  1. 定时任务读取该数据,存储到redis,保留60分钟,可以根据自动目的设置。

里面代码看起来比较杂乱,整体思路是使用上面注入的extendK8sRestTemplate访问api,然后存入redis,只保留30分钟

java 复制代码
@Service
public class LogResourceTaskService implements TaskService {
    @Resource
    private final RedisService redisService;
    @Resource
    private final RestTemplate extendK8sRestTemplate;
    @Resource

    private final KubernetesServiceImpl kubernetesServiceImpl;
    @Resource

    private final ApiClient apiClient;
    public LogResourceTaskService(RedisService redisService,RestTemplate extendK8sRestTemplate, KubernetesServiceImpl kubernetesServiceImpl,ApiClient apiClient) {
        this.redisService = redisService;
        this.extendK8sRestTemplate = extendK8sRestTemplate;
        this.apiClient = apiClient;
        this.kubernetesServiceImpl = kubernetesServiceImpl;

    }

    @Override
    public void work(String guid) {
        String mapKey0 = "metrics_cpu:"+PodDataSynConfig.CURRENT_POD;
        String mapKey1 = "metrics_memory:"+PodDataSynConfig.CURRENT_POD;

        String url = String.format("%s/apis/metrics.k8s.io/v1beta1/namespaces/%s/pods/%s", apiClient.getBasePath(),kubernetesServiceImpl.getNamespace(), PodDataSynConfig.CURRENT_POD);
        ResponseEntity<PodMetrics> response =  extendK8sRestTemplate.getForEntity(url, PodMetrics.class);

        if (response.getBody() != null && response.hasBody()){
            if(response.getBody().getContainers() != null && response.getBody().getContainers().get(0) != null){
                String cpu = response.getBody().getContainers().get(0).getUsage().getCpu();
                String memory = response.getBody().getContainers().get(0).getUsage().getMemory();
                long timestamp = Instant.now().getEpochSecond();

                redisService.getRedisTemplate().opsForZSet().add(mapKey0, timestamp+":"+cpu,timestamp);
                redisService.getRedisTemplate().opsForZSet().add(mapKey1, timestamp+":"+memory,timestamp);
            }
        }
        removeOldData(mapKey0,mapKey1);
        
    }
    public void removeOldData(String key0, String key1) {
        long cutoffTimestamp = Instant.now().getEpochSecond() - 3600; // 60分钟前
        redisService.getRedisTemplate().opsForZSet().removeRangeByScore(key0, -Double.MAX_VALUE, cutoffTimestamp);
        redisService.getRedisTemplate().opsForZSet().removeRangeByScore(key1, -Double.MAX_VALUE, cutoffTimestamp);

    }

}

4. 完工:

这样简单读取pod资源的任务就完成了,主要步骤就是 metrics server服务器的部署,然后使用restful api读取信息。

相关推荐
廋到被风吹走2 小时前
【Spring】Spring Data JPA Repository 自动实现机制深度解析
java·后端·spring
MX_93592 小时前
Spring中Bean的配置(一)
java·后端·spring
sg_knight6 小时前
Spring 框架中的 SseEmitter 使用详解
java·spring boot·后端·spring·spring cloud·sse·sseemitter
郑州光合科技余经理8 小时前
同城系统海外版:一站式多语种O2O系统源码
java·开发语言·git·mysql·uni-app·go·phpstorm
一只乔哇噻8 小时前
java后端工程师+AI大模型开发进修ing(研一版‖day60)
java·开发语言·人工智能·学习·语言模型
Dolphin_Home8 小时前
笔记:SpringBoot静态类调用Bean的2种方案(小白友好版)
java·spring boot·笔记
如果未来,9 小时前
k8s介绍,及其主要组件作用
云原生·容器·kubernetes
MetaverseMan9 小时前
Java虚拟线程实战
java
浪潮IT馆9 小时前
Tomcat运行war包的问题分析与解决步骤
java·tomcat
bendan509 小时前
服务通过docker部署后,调用确定相互调用的URL
运维·docker·容器