Skip to content

Commit 9284154

Browse files
authored
Merge pull request #116 from devzero-inc/garvit/karpenter-collector-fix
detecting karpenter controller availability with karpenter version
2 parents 72165fb + fb09934 commit 9284154

1 file changed

Lines changed: 91 additions & 33 deletions

File tree

internal/collector/karpenter_collector.go

Lines changed: 91 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ type KarpenterCollector struct {
3535
informers map[string]cache.SharedIndexInformer
3636
informerStopChs map[string]chan struct{}
3737
excludedResources map[string]map[string]bool // resourceType -> resourceName -> excluded
38+
version string
3839
mu sync.RWMutex
3940
}
4041

@@ -324,13 +325,13 @@ func (c *KarpenterCollector) handleKarpenterResourceEvent(
324325
// Add more detailed logging before sending to batch channel
325326
c.logger.Info("Karpenter resource details",
326327
"resourceType", Karpenter,
327-
"key", key,
328-
"eventType", eventType.String(),
329-
"kind", kind,
330-
"name", name,
331-
"namespace", namespace,
332-
"apiVersion", obj.GetAPIVersion(),
333-
"processedFields", processedObj)
328+
"key", key,
329+
"eventType", eventType.String(),
330+
"kind", kind,
331+
"name", name,
332+
"namespace", namespace,
333+
"apiVersion", obj.GetAPIVersion(),
334+
"processedFields", processedObj)
334335

335336
// Send the Karpenter resource to the batch channel
336337
c.batchChan <- CollectedResource{
@@ -544,6 +545,7 @@ func (c *KarpenterCollector) extractCommonFields(obj *unstructured.Unstructured)
544545
// Basic metadata
545546
result := map[string]interface{}{
546547
"name": obj.GetName(),
548+
"karpenterVersion": c.version,
547549
"namespace": obj.GetNamespace(),
548550
"uid": string(obj.GetUID()),
549551
"kind": obj.GetKind(),
@@ -666,36 +668,92 @@ func (c *KarpenterCollector) GetType() string {
666668
return "karpenter"
667669
}
668670

669-
// IsAvailable checks if Karpenter resources can be accessed in the cluster
671+
// detectKarpenterVersion detects the version of Karpenter from the deployment object
672+
func (c *KarpenterCollector) detectKarpenterVersion(obj *unstructured.Unstructured) {
673+
containers, found, _ := unstructured.NestedSlice(obj.Object, "spec", "template", "spec", "containers")
674+
if !found {
675+
return
676+
}
677+
678+
for _, container := range containers {
679+
containerMap, ok := container.(map[string]interface{})
680+
if !ok {
681+
continue
682+
}
683+
684+
name, found, _ := unstructured.NestedString(containerMap, "name")
685+
if !found || name != "controller" {
686+
continue
687+
}
688+
689+
image, found, _ := unstructured.NestedString(containerMap, "image")
690+
if !found {
691+
continue
692+
}
693+
694+
// Image format: public.ecr.aws/karpenter/controller:0.37.7@sha256:...
695+
imageParts := strings.Split(image, "@")[0]
696+
versionParts := strings.Split(imageParts, ":")
697+
if len(versionParts) != 2 {
698+
c.logger.V(4).Info("Invalid image format", "image", image)
699+
continue
700+
}
701+
702+
version := versionParts[1]
703+
c.mu.Lock()
704+
c.version = version
705+
c.mu.Unlock()
706+
c.logger.Info("Detected Karpenter version", "version", version)
707+
return
708+
}
709+
710+
c.logger.V(4).Info("Could not detect Karpenter version from deployment")
711+
}
712+
713+
// Update IsAvailable to detect version
670714
func (c *KarpenterCollector) IsAvailable(ctx context.Context) bool {
671-
// Try to list NodePools to see if Karpenter is installed
672-
// Check both v1beta1 and v1 api versions
673-
gvrs := []schema.GroupVersionResource{
674-
{
675-
Group: "karpenter.sh",
676-
Version: "v1",
677-
Resource: "nodepools",
678-
},
679-
{
680-
Group: "karpenter.sh",
681-
Version: "v1beta1",
682-
Resource: "nodepools",
683-
},
684-
{
685-
Group: "karpenter.sh",
686-
Version: "v1alpha5",
687-
Resource: "provisioners",
688-
},
715+
gvr := schema.GroupVersionResource{
716+
Group: "apps",
717+
Version: "v1",
718+
Resource: "deployments",
689719
}
690720

691-
for _, gvr := range gvrs {
692-
_, err := c.dynamicClient.Resource(gvr).List(ctx, metav1.ListOptions{Limit: 1})
693-
if err == nil {
694-
c.logger.Info("Karpenter resources available", "gvr", gvr.String())
695-
return true
721+
// Karpenter deployment has these labels
722+
labelSelector := "app.kubernetes.io/name=karpenter,app.kubernetes.io/instance=karpenter"
723+
724+
// List deployments across all namespaces with the Karpenter labels
725+
deployments, err := c.dynamicClient.Resource(gvr).List(ctx, metav1.ListOptions{
726+
LabelSelector: labelSelector,
727+
})
728+
if err != nil {
729+
c.logger.Error(err, "Failed to list deployments")
730+
return false
731+
}
732+
733+
if len(deployments.Items) == 0 {
734+
c.logger.Info("No Karpenter deployment found")
735+
return false
736+
}
737+
738+
// Check if at least one deployment is ready
739+
for _, d := range deployments.Items {
740+
status, found, _ := unstructured.NestedMap(d.Object, "status")
741+
if found {
742+
readyReplicas, found, _ := unstructured.NestedInt64(status, "readyReplicas")
743+
if found && readyReplicas > 0 {
744+
c.detectKarpenterVersion(&d)
745+
746+
ns, _, _ := unstructured.NestedString(d.Object, "metadata", "namespace")
747+
name, _, _ := unstructured.NestedString(d.Object, "metadata", "name")
748+
c.logger.Info("Found running Karpenter deployment",
749+
"namespace", ns,
750+
"name", name,
751+
"version", c.version)
752+
return true
753+
}
696754
}
697755
}
698756

699-
c.logger.Info("Karpenter resources not available in the cluster")
757+
c.logger.Info("No ready Karpenter deployment found")
700758
return false
701-
}
759+
}

0 commit comments

Comments
 (0)