1. 程式人生 > 其它 >SpringBoot 呼叫 K8s metrics-server

SpringBoot 呼叫 K8s metrics-server

起因

官方 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