Skip to content

Commit 9e456f9

Browse files
committed
backend: k8cache/cacheInvalidation: filter gvrList to reduce the number of go routines for informers
currently the number of go routines is spawning is around 400, because in CheckForChanges, there are 54 informers are there so because of it it is spawning to much go routines per context. so through this PR it is now filtering out the resources which are important or widely used such as secrets, nodes, pods etc.
1 parent 123b10a commit 9e456f9

File tree

2 files changed

+75
-1
lines changed

2 files changed

+75
-1
lines changed

backend/cmd/headlamp_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1769,6 +1769,44 @@ func TestCacheMiddleware_CacheHitAndCacheMiss_RealK8s(t *testing.T) {
17691769
assert.Equal(t, "true", secondFromCache, "second request should be from cache")
17701770
}
17711771

1772+
// Integration test to verify CacheMiddleware does not cause excessive goroutine usage with a real Kubernetes API server.
1773+
func TestCacheMiddleware_GoRoutines(t *testing.T) {
1774+
if os.Getenv("HEADLAMP_RUN_INTEGRATION_TESTS") != strconv.FormatBool(istrue) {
1775+
t.Skip("skipping integration test")
1776+
}
1777+
1778+
start := runtime.NumGoroutine()
1779+
1780+
c, clusterName := newRealK8sHeadlampConfig(t)
1781+
handler := createHeadlampHandler(c)
1782+
ts := httptest.NewServer(handler)
1783+
defer ts.Close()
1784+
1785+
apiPath := "/clusters/" + clusterName + "/api/v1/pods"
1786+
ctx := context.Background()
1787+
1788+
_, err := httpRequestWithContext(ctx, ts.URL+apiPath, "GET")
1789+
require.NoError(t, err)
1790+
1791+
time.Sleep(3 * time.Second)
1792+
1793+
running := runtime.NumGoroutine()
1794+
1795+
time.Sleep(3 * time.Second)
1796+
1797+
after := runtime.NumGoroutine()
1798+
1799+
expected := false
1800+
afterExpected := false
1801+
if (running >= 50 && running < 200) && (after >= 50 && after < 200) {
1802+
expected = true
1803+
afterExpected = true
1804+
}
1805+
assert.Equal(t, 3, start)
1806+
assert.Equal(t, running >= 50 && running < 200, expected)
1807+
assert.Equal(t, after >= 50 && after < 200, afterExpected)
1808+
}
1809+
17721810
// TestCacheMiddleware_CacheInvalidation_RealK8s tests cache invalidation with a
17731811
// real Kubernetes API server. Creates a ConfigMap, invalidates via DELETE, then
17741812
// verifies the next GET fetches fresh data. Requires HEADLAMP_RUN_INTEGRATION_TESTS=true

backend/pkg/k8cache/cacheInvalidation.go

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,43 @@ func returnGVRList(apiResourceLists []*metav1.APIResourceList) []schema.GroupVer
135135
}
136136
}
137137

138-
return gvrList
138+
// filtering the gvrList to make sure spawning go routines for only important
139+
// resources which are required to be watched and cached,
140+
// this will help to reduce the performance issue and resource utilization.
141+
filtered := filterImportantResources(gvrList)
142+
143+
return filtered
144+
}
145+
146+
// filterImportantResources filters the provided list of GroupVersionResources to
147+
// include only those that are deemed important for caching and watching.
148+
// This helps reduce the number of resources we watch and cache,
149+
// improving performance and resource utilization.
150+
func filterImportantResources(gvrList []schema.GroupVersionResource) []schema.GroupVersionResource {
151+
allowed := map[string]struct{}{
152+
"pods": {},
153+
"services": {},
154+
"deployments": {},
155+
"replicasets": {},
156+
"statefulsets": {},
157+
"daemonsets": {},
158+
"nodes": {},
159+
"configmaps": {},
160+
"secrets": {},
161+
"jobs": {},
162+
"cronjobs": {},
163+
}
164+
165+
filtered := make([]schema.GroupVersionResource, 0, len(allowed))
166+
167+
for _, gvr := range gvrList {
168+
if _, ok := allowed[gvr.Resource]; ok {
169+
filtered = append(filtered, gvr)
170+
}
171+
}
172+
173+
// return the filtered list of GroupVersionResources that are important for caching and watching
174+
return filtered
139175
}
140176

141177
// Corrected CheckForChanges.

0 commit comments

Comments
 (0)