Skip to content

Commit 68fa274

Browse files
When processing events, look back to the owning deployment to understand
if the pod's replica count is being changed to avoid excessive requests
1 parent ba747f3 commit 68fa274

2 files changed

Lines changed: 49 additions & 8 deletions

File tree

deploy/manifest.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ rules:
1717
- apiGroups: [""]
1818
resources: ["pods"]
1919
verbs: ["get", "list", "watch"]
20+
- apiGroups: ["apps"]
21+
resources: ["deployments"]
22+
verbs: ["get"]
2023
---
2124
apiVersion: rbac.authorization.k8s.io/v1
2225
kind: ClusterRoleBinding

internal/controller/controller.go

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313
"github.com/github/deployment-tracker/pkg/metrics"
1414

1515
corev1 "k8s.io/api/core/v1"
16+
k8serrors "k8s.io/apimachinery/pkg/api/errors"
17+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1618
"k8s.io/apimachinery/pkg/util/runtime"
1719
"k8s.io/apimachinery/pkg/util/wait"
1820
"k8s.io/client-go/informers"
@@ -93,8 +95,9 @@ func New(clientset kubernetes.Interface, namespace string, cfg *Config) (*Contro
9395
return
9496
}
9597

96-
// Only process pods that are running
97-
if pod.Status.Phase == corev1.PodRunning {
98+
// Only process pods that are running and belong
99+
// to a deployment
100+
if pod.Status.Phase == corev1.PodRunning && getDeploymentName(pod) != "" {
98101
key, err := cache.MetaNamespaceKeyFunc(obj)
99102

100103
// For our purposes, there are in practice
@@ -124,8 +127,9 @@ func New(clientset kubernetes.Interface, namespace string, cfg *Config) (*Contro
124127
return
125128
}
126129

127-
// Skip if pod is being deleted
128-
if newPod.DeletionTimestamp != nil {
130+
// Skip if pod is being deleted or doesn't belong
131+
// to a deployment
132+
if newPod.DeletionTimestamp != nil || getDeploymentName(newPod) == "" {
129133
return
130134
}
131135

@@ -162,8 +166,13 @@ func New(clientset kubernetes.Interface, namespace string, cfg *Config) (*Contro
162166
return
163167
}
164168
}
165-
key, err := cache.MetaNamespaceKeyFunc(obj)
166169

170+
// Only process pods that belong to a deployment
171+
if getDeploymentName(pod) == "" {
172+
return
173+
}
174+
175+
key, err := cache.MetaNamespaceKeyFunc(obj)
167176
// For our purposes, there are in practice
168177
// no error event we care about, so don't
169178
// bother with handling it.
@@ -176,7 +185,6 @@ func New(clientset kubernetes.Interface, namespace string, cfg *Config) (*Contro
176185
}
177186
},
178187
})
179-
180188
if err != nil {
181189
return nil, fmt.Errorf("failed to add event handlers: %w", err)
182190
}
@@ -261,16 +269,27 @@ func (c *Controller) processEvent(ctx context.Context, event PodEvent) error {
261269

262270
if event.EventType == "DELETED" {
263271
// For delete events, use the pod captured at deletion time
264-
// since it's already been removed from the cache
265272
pod = event.DeletedPod
266273
if pod == nil {
267274
slog.Error("Delete event missing pod data",
268275
"key", event.Key,
269276
)
270277
return nil
271278
}
279+
280+
// Check if the parent deployment still exists
281+
// If it does, this is just a scale-down event, skip it
282+
deploymentName := getDeploymentName(pod)
283+
if deploymentName != "" && c.deploymentExists(ctx, pod.Namespace, deploymentName) {
284+
slog.Debug("Deployment still exists, skipping pod delete (scale down)",
285+
"namespace", pod.Namespace,
286+
"deployment", deploymentName,
287+
"pod", pod.Name,
288+
)
289+
return nil
290+
}
272291
} else {
273-
// For other events, get the pod from the informer's cache
292+
// For create events, get the pod from the informer's cache
274293
obj, exists, err := c.podInformer.GetIndexer().GetByKey(event.Key)
275294
if err != nil {
276295
slog.Error("Failed to get pod from cache",
@@ -318,6 +337,25 @@ func (c *Controller) processEvent(ctx context.Context, event PodEvent) error {
318337
return lastErr
319338
}
320339

340+
// deploymentExists checks if a deployment exists in the cluster.
341+
func (c *Controller) deploymentExists(ctx context.Context, namespace, name string) bool {
342+
_, err := c.clientset.AppsV1().Deployments(namespace).Get(ctx, name, metav1.GetOptions{})
343+
if err != nil {
344+
if k8serrors.IsNotFound(err) {
345+
return false
346+
}
347+
// On error, assume it exists to be safe
348+
// (avoid false decommissions)
349+
slog.Warn("Failed to check if deployment exists, assuming it does",
350+
"namespace", namespace,
351+
"deployment", name,
352+
"error", err,
353+
)
354+
return true
355+
}
356+
return true
357+
}
358+
321359
// recordContainer records a single container's deployment info.
322360
func (c *Controller) recordContainer(ctx context.Context, pod *corev1.Pod, container corev1.Container, status, eventType string) error {
323361
dn := getARDeploymentName(pod, container, c.cfg.Template)

0 commit comments

Comments
 (0)