@@ -32,11 +32,15 @@ import (
3232 "github.com/gorilla/mux"
3333 corev1 "k8s.io/api/core/v1"
3434 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
35+ "k8s.io/apimachinery/pkg/runtime"
36+ "k8s.io/apimachinery/pkg/runtime/schema"
3537 "k8s.io/apimachinery/pkg/types"
3638 "k8s.io/apiserver/pkg/util/flushwriter"
3739 "k8s.io/client-go/kubernetes"
40+ clientgoscheme "k8s.io/client-go/kubernetes/scheme"
3841 clientremotecommand "k8s.io/client-go/tools/remotecommand"
3942
43+ "github.com/gocrane/kubeocean/pkg/proxier/podcache"
4044 localremotecommand "github.com/gocrane/kubeocean/pkg/proxier/remotecommand"
4145)
4246
@@ -60,12 +64,13 @@ type NodeEventHandler interface {
6064
6165// NodeInfo node information (consistent with NodeController)
6266type NodeInfo struct {
67+ NodeName string
6368 InternalIP string
6469 ProxierPort string
6570}
6671
6772func (n NodeInfo ) String () string {
68- return fmt .Sprintf ("%s %s" , n .InternalIP , n .ProxierPort )
73+ return fmt .Sprintf ("%s %s %s" , n . NodeName , n .InternalIP , n .ProxierPort )
6974}
7075
7176// ServerEntry HTTP server entry
@@ -120,6 +125,9 @@ type VNodeProxierAgent struct {
120125 // Cluster identification for VNode name generation
121126 clusterID string // ClusterBinding.Spec.ClusterID for generating VNode names
122127
128+ // Pod cache manager
129+ podCacheManager podcache.Manager
130+
123131 // Node state management
124132 nodeStates map [string ]NodeInfo // key: nodeName, value: NodeInfo
125133 httpServers map [string ]* ServerEntry // key: port
@@ -135,26 +143,27 @@ type VNodeProxierAgent struct {
135143}
136144
137145// NewVNodeProxierAgent creates a new VNode proxier agent
138- func NewVNodeProxierAgent (config * MetricsConfig , tokenManager * TokenManager , kubeletProxy KubeletProxy , kubeClient kubernetes.Interface , clusterID string , log logr.Logger ) * VNodeProxierAgent {
146+ func NewVNodeProxierAgent (config * MetricsConfig , tokenManager * TokenManager , kubeletProxy KubeletProxy , kubeClient kubernetes.Interface , clusterID string , log logr.Logger , podCacheManager podcache. Manager ) * VNodeProxierAgent {
139147 // Initialize VictoriaMetrics unmarshal workers (referring to vnode_metrics)
140148 log .Info ("Starting VictoriaMetrics unmarshal workers" )
141149 common .StartUnmarshalWorkers ()
142150
143151 mc := & VNodeProxierAgent {
144- config : config ,
145- tokenManager : tokenManager ,
146- kubeletClient : NewKubeletClient (log .WithName ("kubelet-client" ), tokenManager ),
147- metricsParser : NewMetricsParser (),
148- kubeletProxy : kubeletProxy ,
149- log : log ,
150- kubeClient : kubeClient ,
151- clusterID : clusterID ,
152- nodeStates : make (map [string ]NodeInfo ),
153- httpServers : make (map [string ]* ServerEntry ),
154- metricsCache : make (map [string ][]byte ),
155- summaryCache : make (map [string ]* Summary ),
156- lastUpdate : make (map [string ]time.Time ),
157- stopChan : make (chan struct {}),
152+ config : config ,
153+ tokenManager : tokenManager ,
154+ kubeletClient : NewKubeletClient (log .WithName ("kubelet-client" ), tokenManager ),
155+ metricsParser : NewMetricsParser (),
156+ kubeletProxy : kubeletProxy ,
157+ log : log ,
158+ kubeClient : kubeClient ,
159+ clusterID : clusterID ,
160+ podCacheManager : podCacheManager ,
161+ nodeStates : make (map [string ]NodeInfo ),
162+ httpServers : make (map [string ]* ServerEntry ),
163+ metricsCache : make (map [string ][]byte ),
164+ summaryCache : make (map [string ]* Summary ),
165+ lastUpdate : make (map [string ]time.Time ),
166+ stopChan : make (chan struct {}),
158167 }
159168
160169 // Load TLS configuration if provided
@@ -646,6 +655,9 @@ func (va *VNodeProxierAgent) setupRoutes(port string, nodeInfo NodeInfo) *mux.Ro
646655 // Container exec endpoint (same as main server)
647656 router .HandleFunc ("/exec/{namespace}/{pod}/{container}" , va .handleContainerExec ).Methods ("POST" , "GET" )
648657
658+ // Pods endpoint
659+ router .HandleFunc ("/pods" , va .handlePods (nodeInfo .NodeName )).Methods ("GET" )
660+
649661 // Health check endpoint
650662 router .HandleFunc ("/healthz" , va .handleHealthz ).Methods ("GET" )
651663
@@ -703,6 +715,57 @@ func (va *VNodeProxierAgent) handleSummary(port string) http.HandlerFunc {
703715 }
704716}
705717
718+ // handlePods handles /pods endpoint to return pods by node name
719+ func (va * VNodeProxierAgent ) handlePods (nodeName string ) http.HandlerFunc {
720+ return func (w http.ResponseWriter , r * http.Request ) {
721+ if va .podCacheManager == nil {
722+ va .log .Error (nil , "Pod cache manager is not available" )
723+ http .Error (w , "Pod cache manager is not available" , http .StatusServiceUnavailable )
724+ return
725+ }
726+
727+ va .log .V (1 ).Info ("Processing pods request" ,
728+ "nodeName" , nodeName ,
729+ "remoteAddr" , r .RemoteAddr ,
730+ "userAgent" , r .UserAgent (),
731+ )
732+
733+ // Get pods by node name
734+ ctx := r .Context ()
735+ podList , err := va .podCacheManager .GetPodsByNode (ctx , nodeName )
736+ if err != nil {
737+ va .log .Error (err , "Failed to get pods by node name" , "nodeName" , nodeName )
738+ http .Error (w , fmt .Sprintf ("Failed to get pods: %v" , err ), http .StatusInternalServerError )
739+ return
740+ }
741+
742+ // Encode PodList to JSON using k8s client-go codec (following kubelet's encodePods pattern)
743+ // Use LegacyCodec like kubelet does for v1 API version
744+ codec := clientgoscheme .Codecs .LegacyCodec (schema.GroupVersion {Group : corev1 .GroupName , Version : "v1" })
745+ jsonBytes , err := runtime .Encode (codec , podList )
746+ if err != nil {
747+ va .log .Error (err , "Failed to encode PodList to JSON" , "nodeName" , nodeName )
748+ http .Error (w , fmt .Sprintf ("Failed to encode pods: %v" , err ), http .StatusInternalServerError )
749+ return
750+ }
751+
752+ // Set response headers
753+ w .Header ().Set ("Content-Type" , "application/json" )
754+ w .WriteHeader (http .StatusOK )
755+
756+ // Write JSON response
757+ if _ , err := w .Write (jsonBytes ); err != nil {
758+ va .log .Error (err , "Failed to write response" , "nodeName" , nodeName )
759+ return
760+ }
761+
762+ va .log .V (2 ).Info ("Successfully served pods data" ,
763+ "nodeName" , nodeName ,
764+ "podCount" , len (podList .Items ),
765+ "dataSize" , len (jsonBytes ))
766+ }
767+ }
768+
706769// handleContainerLogs handles container logs requests (same as main server)
707770func (va * VNodeProxierAgent ) handleContainerLogs (w http.ResponseWriter , r * http.Request ) {
708771 if va .kubeletProxy == nil {
0 commit comments