backend: caching: implemented caching for single-cluster#3499
backend: caching: implemented caching for single-cluster#3499upsaurav12 wants to merge 42 commits intokubernetes-sigs:mainfrom
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: upsaurav12 The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
Nice one. ps. See commit guidelines, and run |
illume
left a comment
There was a problem hiding this comment.
Nice start. Thanks.
Would you mind separating the code out from headlamp.go? Code can be put into a separate module/package, and then headlamp.go can import it and use it. We are in the process of moving as much code out of headlamp.go as possible into package modules. It's all a bit too much code tangled up in there.
Could you please add tests? As well, please add documentation to your functions.
I left a comment about commit message guidelines and running backend-lint.
|
@illume I have added extracted the cache implementation from I am not sure that this implementation might work for multiple users however i am finding way to test it with services accounts but in development mode it is directly fetching from kubeconfig file and it loads clusters directly without asking for bearer token |
2452767 to
9aa03d1
Compare
|
How about making an own package for pkg/k8cache? I think maybe it should not go inside pkg/cache, since it's topic is slightly different than what pkg/cache already does. |
I was thinking the same but eventually had to impelment in the same package because of cache initialization and ease of importing functions. I will. modify it. |
|
I have moved the code to |
|
Hi I have just tested this cache implementation with different Screen.Recording.-.Jun.28.2025-VEED.mp4However still there are still some points that is need to be fixed/address.
|
I am sorry i could get these replies. i don't know why but they weren't visible to me? |
No worries. I think I wrote them, and then few days came back and noticed they were still pending and submitted the review. I'm not sure why they kept the old date on them, I think it's a github bug. That's why they weren't visible to you - I didn't submit the review yet. |
Co-authored-by: S Santhosh Nagaraj <nssvlr@gmail.com> Signed-off-by: Saurav Upadhyay <116784047+upsaurav12@users.noreply.github.com>
| ctx, span := telemetry.CreateSpan(ctx, r, "cluster-api", "handleClusterAPI", | ||
| attribute.String("cluster", mux.Vars(r)["clusterName"]), | ||
| ) | ||
|
|
||
| defer span.End() |
There was a problem hiding this comment.
I don't think we need this span to be instrumented. @illume wdyt? this function just gets the context key and context.
There was a problem hiding this comment.
i have added because i was getting linting error of length of CacheMiddleware function
There was a problem hiding this comment.
AFAIU telemetry doesn't have anything to do with linting issue. Can you share the exact error that you faced?
There was a problem hiding this comment.
no, i am talking about funlen linting issue, it was saying that the function length is >60 lines of code, that's why i made a saparate function that will return contextKey , KContext, span and ctx
There was a problem hiding this comment.
separate function is okay, not every new function needs to have a telemetry span.
There was a problem hiding this comment.
okay understood, should i need to remove telemetry and span for some new functions such as ReturnAuthErrRespone , ReturnAfterAuthError etc
There was a problem hiding this comment.
for now, lets remove this.
| // RequestK8ClusterAPIAndStore ensures if the key was not found inside the cache then this will make actual call to k8's | ||
| // and this will capture the response body and convert the captured response to string. | ||
| // After converting it will store the response with the key and TTL of 10*min. | ||
| func RequestK8ClusterAPIAndStore(k8scache cache.Cache[string], |
There was a problem hiding this comment.
This function doesn't make a request to K8ClusterAPI, please improve the function name here.
There was a problem hiding this comment.
@illume said that previous one was good, so can we change the name to previous one
There was a problem hiding this comment.
would RequestToK8AndStore be good for you @yolossn
backend/cmd/server.go
Outdated
| err = k8cache.CheckAndPurge(w, r, k8scache, next, rcw, isAllowed) | ||
| if err != nil { | ||
| c.handleError(w, ctx, span, err, "error while purging data", http.StatusInternalServerError) | ||
| } |
There was a problem hiding this comment.
Please add a comment here, It is not clear why the Check is done here.
| // CheckAndPurge check whether the r is POST, if the request was POST then it will let to PURGING DATA. | ||
| func CheckAndPurge(w http.ResponseWriter, r *http.Request, k8scache cache.Cache[string], | ||
| next http.Handler, rcw *responseCapture, isAllowed bool, | ||
| ) error { | ||
| if r.Method != http.MethodPost { | ||
| return nil | ||
| } | ||
|
|
||
| err := PurgeDataForPostRequest(w, r, k8scache, next, rcw, isAllowed) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| return nil | ||
| } |
There was a problem hiding this comment.
Can you please explain the context behind purging post request alone?
There was a problem hiding this comment.
I was adding for more methods but from the last meet you asked for only POST
There was a problem hiding this comment.
Looks like there is a misunderstanding here, all kind of update request that can make the cache stale should be handled here. ie put, post, delete
There was a problem hiding this comment.
Now i am pushing the changes
There was a problem hiding this comment.
Also synchronously looping through every request in cache and deleting the request at the end of each update request will make it slower. Also the method type check in the cacheMiddleware is removed. Almost all of the update request (put,post,delete) will be unique and we need not have to check them in the cache.
There was a problem hiding this comment.
@yolossn @illume
would this work ?
// PurgeDataForPostRequest remove the stale data which is related to POST request.
// It uses UnmarshalCacheData to filter the response for purging the resource data.
// It also uses GetAll method from cache.Cache to retrieve all the data that was stored.
func PurgeDataForPostRequest(w http.ResponseWriter, r *http.Request, k8scache cache.Cache[string],
next http.Handler, rcw *responseCapture, isAllowed bool,
) error {
lasts, _ := GetKindAndVerb(r)
last := Singular(lasts)
go func() error {
// start := time.Now()
val, err := k8scache.GetAll(context.Background(), nil)
if err != nil {
return err
}
for key, v := range val {
var cachedData CachedResponseData
_, err := UnmarshalCacheData(v, cachedData)
if err != nil {
return err
}
err = ProcessCachedItem(key, v, last, k8scache, next, w, r, rcw, isAllowed)
if err != nil {
return err
}
}
// elapsed := time.Since(start)
// fmt.Println("elasped : ", elapsed)
return nil
}()
return nil
}
There was a problem hiding this comment.
i have made some changes in the code
|
PR needs rebase. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
Co-authored-by: S Santhosh Nagaraj <nssvlr@gmail.com> Signed-off-by: Saurav Upadhyay <116784047+upsaurav12@users.noreply.github.com>
Co-authored-by: S Santhosh Nagaraj <nssvlr@gmail.com> Signed-off-by: Saurav Upadhyay <116784047+upsaurav12@users.noreply.github.com>
skoeva
left a comment
There was a problem hiding this comment.
there's an updated PR for this, will close it for now
Implementation
I have implemented caching for the single-cluster. For multi-cluster i am trying to check by creating user by changing
use-context.Here how i have implemented:
ProxyRequestand storing it incachein string.gzipto byte and then to string.selfsubjectrulesreviewsand if it returnsFailurethen it is not authenticated. If doesn't then process to acquire fromcache.kindandnamespaceandclustersand it will be same if the user is making the same requests.cachethen it will go for actual request tok8'sand then store in cache.However more things i have to add like cache should be
syncedwith the latest k8's value but i am finding solution whether i should go forcountinuously make requests to k8's after 5s or fixed timeoruse watch events from k8's.Test Results