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

1. 目的:简单监控pod

通过MetricsAPI监控pod资源使用情况(k8s资源监控,java)_第1张图片
我想使用java监控k8s pod的资源的简单使用情况,但是k8s内部并没有采集资源的实现。

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

2. 部署指南

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

  1. 如果证书没问题,部署最新的metrics-server
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:

- --kubelet-insecure-tls
  1. 查看是否部署成功
kubectl get deployment metrics-server -n kube-system

在这里插入图片描述

# 查看所有命名空间的pod资源
kubectl top pods -A

通过MetricsAPI监控pod资源使用情况(k8s资源监控,java)_第2张图片
top 命令就可以使用了。

3. java Api调用

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

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

注入k8s客户端

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

}

通过MetricsAPI监控pod资源使用情况(k8s资源监控,java)_第4张图片
注入8sRestTemplate

@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()));

    }

}

通过MetricsAPI监控pod资源使用情况(k8s资源监控,java)_第5张图片
4. 定时任务读取该数据,存储到redis,保留60分钟,可以根据自动目的设置。

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

@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读取信息。

你可能感兴趣的:(分布式,#,kubernetes,java,kubernetes,java,容器)