feat(运维监控模块): 【微服务运行状态监控】完成获取容器启停状态接口开发

1. 调用Prometheus接口查询容器状态为“Running”的个数以及容器总数量
2. 调用Prometheus接口查询容器的创建时间,调用Rancher接口查询容器元数据和状态数据,筛选出不为“running”状态的所有容器,并获取该容器状态为False的condition,获取condition的lastTransitionTime作为该容器的停止时间
This commit is contained in:
OTTO 2025-07-30 10:58:31 +08:00
parent 172e0ee92e
commit 705823ec3f
10 changed files with 256 additions and 38 deletions

View File

@ -54,6 +54,10 @@ public interface RemoteRancherService {
@PathVariable("namespace") String namespace,
@RequestHeader(TokenConstants.AUTHENTICATION) String token);
@GetMapping("/rancher/k8s/clusters/{cluster_id}/v1/pods")
Response getK8sPodList(@PathVariable("cluster_id") String cluster_id,
@RequestHeader(TokenConstants.AUTHENTICATION) String token);
@GetMapping("/rancher/k8s/clusters/{cluster_id}/v1/services/{nginxApplicationId}")
Response getK8sServiceByApplicationId(@PathVariable("cluster_id") String cluster_id,
@PathVariable("nginxApplicationId") String nginxApplicationId,

View File

@ -64,6 +64,11 @@ public class RemoteRancherFallbackFactory implements FallbackFactory<RemoteRanch
return null;
}
@Override
public Response getK8sPodList(String cluster_id, String token) {
return null;
}
@Override
public Response getK8sServiceByApplicationId(String cluster_id, String nginxApplicationId, String token) {
return null;

View File

@ -0,0 +1,33 @@
package com.microservices.mon.k8s.controller;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.web.controller.BaseController;
import com.microservices.common.core.web.domain.AjaxResult;
import com.microservices.common.core.web.domain.GenericsAjaxResult;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.mon.k8s.domain.*;
import com.microservices.mon.k8s.domain.vo.ApplicationEnvTypeVo;
import com.microservices.mon.k8s.domain.vo.ApplicationTypeVo;
import com.microservices.mon.k8s.service.IMicroManagementService;
import com.microservices.mon.k8s.service.IMicroStatusService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("microStatus")
@Api(tags = "微服务状态监控")
public class MicroStatusController extends BaseController {
@Autowired
private IMicroStatusService microStatusService;
@ApiOperation(value = "获取容器启停状态")
@GetMapping("/podStartStopStatus")
public GenericsAjaxResult<K8sPodStartStopStatus> getPodStartStopStatus() {
return GenericsAjaxResult.success(microStatusService.getPodStartStopStatus());
}
}

View File

@ -49,35 +49,35 @@ public class K8sClusterStatus {
private HashMap<String, Integer> podStatus;
public void setNodeCount(PrometheusResVo prometheusResVo) {
this.nodeCount = Integer.parseInt(getPromStringValue(prometheusResVo));
this.nodeCount = Integer.parseInt(PrometheusResVo.getPromStringValue(prometheusResVo));
}
public void setUnavailableNodeCount(PrometheusResVo prometheusResVo) {
this.unavailableNodeCount = Integer.parseInt(getPromStringValue(prometheusResVo));
this.unavailableNodeCount = Integer.parseInt(PrometheusResVo.getPromStringValue(prometheusResVo));
}
public void setCpuUsage(PrometheusResVo prometheusResVo) {
this.cpuUsage = Float.parseFloat(getPromStringValue(prometheusResVo));
this.cpuUsage = Float.parseFloat(PrometheusResVo.getPromStringValue(prometheusResVo));
}
public void setPodUsage(PrometheusResVo prometheusResVo) {
this.podUsage = Float.parseFloat(getPromStringValue(prometheusResVo));
this.podUsage = Float.parseFloat(PrometheusResVo.getPromStringValue(prometheusResVo));
}
public void setMemoryUsage(PrometheusResVo prometheusResVo) {
this.memoryUsage = Float.parseFloat(getPromStringValue(prometheusResVo));
this.memoryUsage = Float.parseFloat(PrometheusResVo.getPromStringValue(prometheusResVo));
}
public void setTotalRequestCountToday(PrometheusResVo prometheusResVo) {
this.totalRequestCountToday = Long.parseLong(getPromStringValue(prometheusResVo));
this.totalRequestCountToday = Long.parseLong(PrometheusResVo.getPromStringValue(prometheusResVo));
}
public void setAverageRequestProcessingTimeToday(PrometheusResVo prometheusResVo) {
this.averageRequestProcessingTimeToday = Float.parseFloat(getPromStringValue(prometheusResVo));
this.averageRequestProcessingTimeToday = Float.parseFloat(PrometheusResVo.getPromStringValue(prometheusResVo));
}
public void setRequestSuccessRateToday(PrometheusResVo prometheusResVo) {
this.requestSuccessRateToday = Float.parseFloat(getPromStringValue(prometheusResVo));
this.requestSuccessRateToday = Float.parseFloat(PrometheusResVo.getPromStringValue(prometheusResVo));
}
public void setMicroserviceApplicationCount(List<K8sNamespace> k8sNamespaceList) {
@ -85,43 +85,32 @@ public class K8sClusterStatus {
}
public void setMicroserviceRestartCountToday(PrometheusResVo prometheusResVo) {
this.microserviceRestartCountToday = (int) Float.parseFloat(getPromStringValue(prometheusResVo));
this.microserviceRestartCountToday = (int) Float.parseFloat(PrometheusResVo.getPromStringValue(prometheusResVo));
}
public void setPodStatus(PrometheusResVo prometheusResVo) {
HashMap<String, Integer> podStatus = new HashMap<>();
if (prometheusResVo != null && prometheusResVo.isSuccess()) {
List<PrometheusResultVo> resultList = prometheusResVo.getData().getResult();
for (PrometheusResultVo result : resultList) {
Integer value = result.getValue().getIntValue(1);
switch (result.getMetric().getString("phase")) {
case "Running":
podStatus.put("运行中", value);
break;
case "Pending":
podStatus.put("等待中", value);
break;
case "Succeeded":
podStatus.put("运行已完成", value);
break;
case "Unknown":
podStatus.put("未知", value);
break;
case "Failed":
podStatus.put("运行失败", value);
}
List<PrometheusResultVo> resultList = PrometheusResVo.getPrometheusResultVoList(prometheusResVo);
for (PrometheusResultVo result : resultList) {
Integer value = result.getValue().getIntValue(1);
switch (result.getMetric().getString("phase")) {
case "Running":
podStatus.put("运行中", value);
break;
case "Pending":
podStatus.put("等待中", value);
break;
case "Succeeded":
podStatus.put("运行已完成", value);
break;
case "Unknown":
podStatus.put("未知", value);
break;
case "Failed":
podStatus.put("运行失败", value);
}
}
this.podStatus = podStatus;
}
private String getPromStringValue(PrometheusResVo prometheusResVo) {
String value = "";
if (prometheusResVo != null && prometheusResVo.isSuccess()) {
PrometheusResultVo result = prometheusResVo.getData().getResult().get(0);
return result.getValue().getString(1);
}
return value;
}
}

View File

@ -0,0 +1,26 @@
package com.microservices.mon.k8s.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
@ApiModel("K8S容器启停时间")
public class K8sPodStartStopDate {
@ApiModelProperty(value = "容器名称")
private String podName;
@ApiModelProperty(value = "启动时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startDate;
@ApiModelProperty(value = "停止时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date stopDate;
private Boolean isRunning = true;
}

View File

@ -0,0 +1,21 @@
package com.microservices.mon.k8s.domain;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
@ApiModel("K8S容器启停状态")
public class K8sPodStartStopStatus {
@ApiModelProperty(value = "启动数")
private Integer startCount;
@ApiModelProperty(value = "总数")
private Integer podCount;
@ApiModelProperty(value = "启停时间列表")
private List<K8sPodStartStopDate> podStartStopDateList;
}

View File

@ -2,6 +2,10 @@ package com.microservices.mon.k8s.domain.vo;
import lombok.Data;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@Data
public class PrometheusResVo {
// 状态success代表成功
@ -15,4 +19,20 @@ public class PrometheusResVo {
&& data.getResult() != null
&& !data.getResult().isEmpty();
}
public static String getPromStringValue(PrometheusResVo prometheusResVo) {
String value = "";
if (prometheusResVo != null && prometheusResVo.isSuccess()) {
PrometheusResultVo result = prometheusResVo.getData().getResult().get(0);
return result.getValue().getString(1);
}
return value;
}
public static List<PrometheusResultVo> getPrometheusResultVoList(PrometheusResVo prometheusResVo) {
if (prometheusResVo != null && prometheusResVo.isSuccess()) {
return prometheusResVo.getData().getResult();
}
return Collections.emptyList();
}
}

View File

@ -0,0 +1,12 @@
package com.microservices.mon.k8s.service;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.mon.k8s.domain.*;
import com.microservices.mon.k8s.domain.vo.ApplicationEnvTypeVo;
import com.microservices.mon.k8s.domain.vo.ApplicationTypeVo;
import java.util.List;
public interface IMicroStatusService {
K8sPodStartStopStatus getPodStartStopStatus();
}

View File

@ -0,0 +1,93 @@
package com.microservices.mon.k8s.service.impl;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.context.SecurityContextHolder;
import com.microservices.mon.k8s.domain.K8sNamespace;
import com.microservices.mon.k8s.domain.K8sPodStartStopDate;
import com.microservices.mon.k8s.domain.K8sPodStartStopStatus;
import com.microservices.mon.k8s.domain.MetricCommonData;
import com.microservices.mon.k8s.domain.vo.*;
import com.microservices.mon.k8s.service.IK8sDashboardService;
import com.microservices.mon.k8s.service.IMicroStatusService;
import com.microservices.mon.k8s.utils.PromQLConstant;
import com.microservices.mon.k8s.utils.RancherResponseHandler;
import com.microservices.system.api.RemoteGatewayService;
import com.microservices.system.api.RemoteRancherService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Service
public class MicroStatusServiceImpl extends CommonService implements IMicroStatusService {
@Autowired
private RemoteGatewayService remoteGatewayService;
@Autowired
private IK8sDashboardService k8sDashboardService;
@Autowired
private RemoteRancherService remoteRancherService;
@Override
public K8sPodStartStopStatus getPodStartStopStatus() {
List<K8sNamespace> k8sNamespaceList = k8sDashboardService.getNamespaceDetailList(false);
List<String> namespaceNameList = k8sNamespaceList.stream().map(K8sNamespace::getName).collect(Collectors.toList());
K8sPodStartStopStatus k8sPodStartStopStatus = new K8sPodStartStopStatus();
JSONObject POD_START_COUNT = remoteGatewayService.getPrometheusQueryRes(PromQLConstant.POD_START_COUNT(cluster_id, namespaceNameList), SecurityContextHolder.getUserKey());
PrometheusResVo prometheusResVo = POD_START_COUNT.toJavaObject(PrometheusResVo.class);
k8sPodStartStopStatus.setStartCount(Integer.parseInt(PrometheusResVo.getPromStringValue(prometheusResVo)));
JSONObject POD_STOP_COUNT = remoteGatewayService.getPrometheusQueryRes(PromQLConstant.POD_COUNT(cluster_id, namespaceNameList), SecurityContextHolder.getUserKey());
prometheusResVo = POD_STOP_COUNT.toJavaObject(PrometheusResVo.class);
k8sPodStartStopStatus.setPodCount(Integer.parseInt(PrometheusResVo.getPromStringValue(prometheusResVo)));
JSONObject POD_START_DATE = remoteGatewayService.getPrometheusQueryRes(PromQLConstant.POD_START_DATE(cluster_id, namespaceNameList), SecurityContextHolder.getUserKey());
prometheusResVo = POD_START_DATE.toJavaObject(PrometheusResVo.class);
List<PrometheusResultVo> podStartDateList = PrometheusResVo.getPrometheusResultVoList(prometheusResVo);
List<K8sPodStartStopDate> podStartStopDateList = new ArrayList<>();
for (PrometheusResultVo result : podStartDateList) {
K8sPodStartStopDate podStartStopDate = new K8sPodStartStopDate();
String podName = result.getMetric().getString("pod");
podStartStopDate.setPodName(podName);
Long startTimeStamp = result.getValue().getLong(1);
podStartStopDate.setStartDate(new Date(startTimeStamp * 1000));
podStartStopDateList.add(podStartStopDate);
}
JSONObject podListJson = RancherResponseHandler.handleJsonObject(remoteRancherService.getK8sPodList(cluster_id, SecurityContextHolder.getUserKey()), "获取所有容器列表");
if (podListJson != null && podListJson.containsKey("data")) {
List<RancherPodVo> rancherPodVoList = podListJson.getJSONArray("data").toList(RancherPodVo.class);
for (RancherPodVo rancherPodVo : rancherPodVoList) {
if (rancherPodVo.getMetadata() != null && rancherPodVo.getMetadata().getState() != null && rancherPodVo.getStatus() != null) {
RancherMetadataState status = rancherPodVo.getMetadata().getState();
if (!"running".equalsIgnoreCase(status.getName())) {
JSONArray conditionList = rancherPodVo.getStatus().getConditions();
for (int i = 0; i < conditionList.size(); i++) {
JSONObject condition = conditionList.getJSONObject(i);
if (condition != null && condition.containsKey("status") && !condition.getBoolean("status")) {
Date stopDate = condition.getDate("lastTransitionTime");
podStartStopDateList
.stream()
.filter(x -> x.getPodName().equalsIgnoreCase(rancherPodVo.getMetadata().getName()))
.forEach(x -> {
x.setStopDate(stopDate);
x.setIsRunning(false);
});
}
}
}
}
}
}
podStartStopDateList.sort(Comparator.comparing(K8sPodStartStopDate::getIsRunning));
k8sPodStartStopStatus.setPodStartStopDateList(podStartStopDateList);
return k8sPodStartStopStatus;
}
}

View File

@ -92,4 +92,19 @@ public class PromQLConstant {
public static String NODE_MEMORY_USAGE(String nodeIp) {
return String.format("100 - ((node_memory_MemAvailable_bytes{ip=\"%s\"} * 100) / node_memory_MemTotal_bytes{ip=\"%s\"})", nodeIp, nodeIp);
}
// Pod启动数
public static String POD_START_COUNT(String clusterId, List<String> namespaceNameList) {
return String.format("sum(kube_pod_status_phase{phase=\"Running\",cluster=\"%s\",namespace=~\"%s\"})", clusterId, String.join("|", namespaceNameList));
}
// Pod总数
public static String POD_COUNT(String clusterId, List<String> namespaceNameList) {
return String.format("sum(kube_pod_status_phase{cluster=\"%s\",namespace=~\"%s\"})", clusterId, String.join("|", namespaceNameList));
}
// Pod启动时间
public static String POD_START_DATE(String clusterId, List<String> namespaceNameList) {
return String.format("kube_pod_created{cluster=\"%s\",namespace=~\"%s\"}", clusterId, String.join("|", namespaceNameList));
}
}