From f4114f02d4999131a375cfdbf17551a504df4c58 Mon Sep 17 00:00:00 2001 From: Luna Stadler Date: Wed, 26 Apr 2023 21:43:53 +0200 Subject: [PATCH] Fetch only the required podMetrics for the given component (#17489) The `PodMetrics` are now limited by `labelSelector` like already done for pods and probably other requests to Kubernetes. This limits the amount of data that is fetched. Tested locally by modifying `app-config.yaml` and an example component to use an internal cluster, which leads to the following request size improvements: Before: 344.71 kB compressed, 6.89 MB uncompressed After: 12.01 kB compressed, 238.86 kB uncompressed For the POST http://localhost:7007/api/kubernetes/services/playback-order call, in a Kubernetes cluster with ~500 pods. Fixes #17450. Signed-off-by: Luna Stadler --- .changeset/clean-lobsters-brake.md | 7 +++++++ .../src/service/KubernetesFanOutHandler.test.ts | 2 +- .../src/service/KubernetesFanOutHandler.ts | 6 +++++- .../kubernetes-backend/src/service/KubernetesFetcher.ts | 6 ++++-- plugins/kubernetes-backend/src/types/types.ts | 1 + 5 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 .changeset/clean-lobsters-brake.md diff --git a/.changeset/clean-lobsters-brake.md b/.changeset/clean-lobsters-brake.md new file mode 100644 index 0000000000..f6da6e986e --- /dev/null +++ b/.changeset/clean-lobsters-brake.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-kubernetes-backend': minor +--- + +Allow fetching pod metrics limited by a `labelSelector`. + +This is used by the Kubernetes tab on a components' page and leads to much smaller responses being received from Kubernetes, especially with larger Kubernetes clusters. diff --git a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.test.ts b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.test.ts index e24c08cafd..4397bce441 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.test.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.test.ts @@ -918,7 +918,7 @@ describe('getKubernetesObjectsByEntity', () => { { errorType: 'FETCH_ERROR', message: - 'request to https://fails/api/v1/pods?labelSelector=backstage.io/kubernetes-id=test-component failed, reason: socket error', + 'request to https://fails/api/v1/pods?labelSelector=backstage.io%2Fkubernetes-id%3Dtest-component failed, reason: socket error', }, ], }, diff --git a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts index 8441effabd..79003ae1ca 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts @@ -283,7 +283,9 @@ export class KubernetesFanOutHandler { })), namespace, }) - .then(result => this.getMetricsForPods(clusterDetailsItem, result)) + .then(result => + this.getMetricsForPods(clusterDetailsItem, labelSelector, result), + ) .catch( (e): Promise => e.name === 'FetchError' @@ -365,6 +367,7 @@ export class KubernetesFanOutHandler { async getMetricsForPods( clusterDetails: ClusterDetails, + labelSelector: string, result: FetchResponseWrapper, ): Promise { if (clusterDetails.skipMetricsLookup) { @@ -385,6 +388,7 @@ export class KubernetesFanOutHandler { const podMetrics = await this.fetcher.fetchPodMetricsByNamespaces( clusterDetails, namespaces, + labelSelector, ); result.errors.push(...podMetrics.errors); diff --git a/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts b/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts index 48bea3106b..b2be199d50 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts @@ -119,6 +119,7 @@ export class KubernetesClientBasedFetcher implements KubernetesFetcher { fetchPodMetricsByNamespaces( clusterDetails: ClusterDetails, namespaces: Set, + labelSelector?: string, ): Promise { const fetchResults = Array.from(namespaces).map(async ns => { const [podMetrics, podList] = await Promise.all([ @@ -128,8 +129,9 @@ export class KubernetesClientBasedFetcher implements KubernetesFetcher { 'v1beta1', 'pods', ns, + labelSelector, ), - this.fetchResource(clusterDetails, '', 'v1', 'pods', ns), + this.fetchResource(clusterDetails, '', 'v1', 'pods', ns, labelSelector), ]); if (podMetrics.ok && podList.ok) { return topPods( @@ -213,7 +215,7 @@ export class KubernetesClientBasedFetcher implements KubernetesFetcher { } if (labelSelector) { - url.search = `labelSelector=${labelSelector}`; + url.search = `labelSelector=${encode(labelSelector)}`; } return fetch(url, requestInit); diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts index e460edbc29..15ed1662de 100644 --- a/plugins/kubernetes-backend/src/types/types.ts +++ b/plugins/kubernetes-backend/src/types/types.ts @@ -56,6 +56,7 @@ export interface KubernetesFetcher { fetchPodMetricsByNamespaces( clusterDetails: ClusterDetails, namespaces: Set, + labelSelector?: string, ): Promise; }