SpringBoot 呼叫 K8s metrics-server
阿新 • • 發佈:2021-06-24
起因
官方 API io.kubernetes.client-java
無法呼叫 metrics-server API
解決
ApiClient 內部會建立一個 OkHttpClient 用於傳送 http 請求,該 clinet 包含授權引數等資訊
K8sConfig
public class K8sConfig { public static ApiClient getApiClient() { ApiClient client = null; try { File file = new File("E:\\k3s.yaml"); client = ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(file))).build(); client.setDebugging(true); Configuration.setDefaultApiClient(client); } catch (IOException e) { log.error("K8s ApiClient 初始化失敗!"); } return client; } }
MetricsService
@Service public class MetricsService { private ApiClient apiClient; private static final String BASE_URL="/apis/metrics.k8s.io/v1beta1"; private static final String URL_NODES = "/nodes"; private static final String URL_PODS = "/pods"; private static final String URL_NAMESPACES = "/namespaces/"; public MetricsService() { this.apiClient = K8sConfig.getApiClient(); } /** * 獲取叢集節點的資源統計資訊 */ public MetricsNodeList getNodeMetrics() throws IOException, ApiException { String path = BASE_URL + URL_NODES; Call call = buildCall(path, "GET"); ApiResponse<MetricsNodeList> r = apiClient.execute(call, MetricsNodeList.class); return r.getData(); } /** * 獲取所有pods的資源統計資訊 */ public MetricsPodList getPodMetrics() throws IOException, ApiException { String path = BASE_URL + URL_PODS; Call call = buildCall(path, "GET"); ApiResponse<MetricsPodList> r = apiClient.execute(call, MetricsPodList.class); return r.getData(); } /** * 獲取namespace下pods的資源統計資訊 */ public MetricsPodList getPodsMetrics(String namespace) throws IOException, ApiException { String path = BASE_URL + URL_NAMESPACES + namespace + URL_PODS; Call call = buildCall(path, "GET"); ApiResponse<MetricsPodList> r = apiClient.execute(call, MetricsPodList.class); return r.getData(); } /** * 構建Call */ private Call buildCall(String path, String method) throws ApiException { List<Pair> localVarQueryParams = new ArrayList<>(); List<Pair> localVarCollectionQueryParams = new ArrayList<>(); Map<String, String> localVarHeaderParams = new HashMap<>(); localVarHeaderParams.put("Accept", apiClient.selectHeaderAccept(new String[]{"*/*"})); localVarHeaderParams.put("Content-Type", apiClient.selectHeaderContentType(new String[]{})); Map<String, String> localVarCookieParams = new HashMap<>(); Map<String, Object> localVarFormParams = new HashMap<>(); String[] localVarAuthNames = new String[]{"BearerToken"}; return apiClient.buildCall(path, method, localVarQueryParams, localVarCollectionQueryParams, null, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, null); } }
Models
@Data public class MetricsNodeList { private String kind; private String apiVersion; private V1ListMeta metadata; private List<MetricsNode> items; @Data public static class MetricsNode{ private V1ObjectMeta metadata; private DateTime timestamp; private String window; private MetricsUsage usage; } }
@Data
public class MetricsPodList {
private String kind;
private String apiVersion;
private V1ListMeta metadata;
private List<MetricsPod> items;
@Data
public static class MetricsPod{
private V1ObjectMeta metadata;
private DateTime timestamp;
private String window;
private List<MetricsPodContainer> containers;
}
@Data
public static class MetricsPodContainer{
private String name;
private MetricsUsage usage;
}
}
public class MetricsUsage {
private static Map<String,Double> UNIT_CPU = new HashMap<>();
private static Map<String,Double> UNIT_MEMORY = new HashMap<>();
static {
UNIT_CPU.put("n", Math.pow(10, -6));
UNIT_CPU.put("u", Math.pow(10, -3));
UNIT_CPU.put("m", Math.pow(10, 0));
UNIT_CPU.put("", Math.pow(10, 3));
UNIT_CPU.put("k", Math.pow(10, 6));
UNIT_CPU.put("M", Math.pow(10, 9));
UNIT_CPU.put("G", Math.pow(10, 3*4));
UNIT_CPU.put("T", Math.pow(10, 3*5));
UNIT_CPU.put("P", Math.pow(10, 3*6));
UNIT_CPU.put("E", Math.pow(10, 3*7));
UNIT_MEMORY.put("Ki", Math.pow(1024, -1));
UNIT_MEMORY.put("Mi", Math.pow(1024, 0));
UNIT_MEMORY.put("Gi", Math.pow(1024, 1));
UNIT_MEMORY.put("Ti", Math.pow(1024, 2));
UNIT_MEMORY.put("Pi", Math.pow(1024, 3));
UNIT_MEMORY.put("Ei", Math.pow(1024, 4));
}
private String cpu;
private String memory;
public String getCpu() {
return commomUnifiedUnit(cpu,1,UNIT_CPU) + "m";
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getMemory() {
return commomUnifiedUnit(memory, 2, UNIT_MEMORY) + "Mi";
}
public void setMemory(String memory) {
this.memory = memory;
}
/**
* 獲取的cpu和memory是帶單位的字串,加入轉換邏輯,cpu統一單位為m,memory統一單位為Mi,如果不需要轉換單位可以去掉相關邏輯
*/
private static String commomUnifiedUnit(String unitValStr, int unitLength, Map<String, Double> unitMap) {
Long r = 0L;
if(unitValStr == null) {
return "0";
}
String unit = unitValStr.substring(unitValStr.length() - unitLength, unitValStr.length());
String val = unitValStr.substring(0, unitValStr.length() - unitLength);
if(unit.matches("\\d")) {
unit = "";
val = unitValStr;
}
Double factor = unitMap.get(unit);
if(factor == null) {
throw new IllegalArgumentException("無法解析單位:" + unitValStr);
}
r = Math.round(Integer.parseInt(val) * factor);
return r + "";
}
}
參考:https://blog.csdn.net/suo082407128/article/details/106804811