我想使用java监控k8s pod的资源的简单使用情况,但是k8s内部并没有采集资源的实现。
但是k8s提供了一套k8s的对接标准,只要适配这套标准,就可以通过kubelet采集资源数据,并且通过k8s api服务器输出。这些对于故障排查以及自动伸缩至关重要。
metrics-server是Kubernetes的一个集群范围内的聚合器,用于收集所有节点和Pods的资源使用信息,如CPU和内存。metrics指标统计器(github)
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.4.1/components.yaml
把commponents.yaml wget下来后, 在 components.yaml 文件中,找到 metrics-server 的 Deployment 部分,并添加以下参数到 args:
- --kubelet-insecure-tls
kubectl get deployment metrics-server -n kube-system
# 查看所有命名空间的pod资源
kubectl top pods -A
在官方提供的客户端 java库里是没有直接调用metrics的方法的。我们只能使用restful api进行访问,
<dependency>
<groupId>io.kubernetesgroupId>
<artifactId>client-javaartifactId>
<version>18.0.0version>
dependency>
注入k8s客户端
在这里插入代码片@Configuration
public class KubernetesClientConfig {
@Bean
public AppsV1Api appsV1Api(ApiClient apiClient) {
return new AppsV1Api(apiClient);
}
}
@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()));
}
}
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);
}
}
这样简单读取pod资源的任务就完成了,主要步骤就是 metrics server服务器的部署,然后使用restful api读取信息。