Skip to content

Commit 84e3d6c

Browse files
committed
Merge remote-tracking branch 'origin/main' into support-k8s-1-35
2 parents 47648cc + e9dec70 commit 84e3d6c

7 files changed

Lines changed: 191 additions & 6 deletions

File tree

.github/workflows/release-integration-sidecar.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ jobs:
5959
echo "DOCKER_IMAGE_TAG=${VERSION}-sidecar" >> $GITHUB_ENV
6060
6161
- name: Set up QEMU
62-
uses: docker/setup-qemu-action@v3
62+
uses: docker/setup-qemu-action@v4
6363
- name: Set up Docker Buildx
6464
uses: docker/setup-buildx-action@v4
6565

.github/workflows/sidecarImage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
steps:
5252
- uses: actions/checkout@v7
5353
- name: Set up QEMU
54-
uses: docker/setup-qemu-action@v3
54+
uses: docker/setup-qemu-action@v4
5555
- name: Set up Docker Buildx
5656
uses: docker/setup-buildx-action@v4
5757

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1010
### enhancement
1111
- Support Kubernetes 1.35 @jamescripter [#1493](https://github.com/newrelic/nri-kubernetes/pull/1493)
1212

13+
### bugfix
14+
- Fix fillContainerStatuses panics @changliu-wk [#1488](https://github.com/newrelic/nri-kubernetes/pull/1488)
15+
1316
## v4.3.3 - 2026-06-29
1417

1518
### ⛓️ Dependencies

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ require (
1919
k8s.io/apimachinery v0.36.2
2020
k8s.io/client-go v0.36.2
2121
k8s.io/kubelet v0.36.2
22-
k8s.io/utils v0.0.0-20260507154919-ff6756f316d2
22+
k8s.io/utils v0.0.0-20260626114624-be93311217bd
2323
)
2424

2525
require (

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbe
207207
k8s.io/utils v0.0.0-20260319190234-28399d86e0b5/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
208208
k8s.io/utils v0.0.0-20260507154919-ff6756f316d2 h1:wU4tMEhLGgIbLvXQb1cfN+EcM0wf7zC6CPF+C79jroc=
209209
k8s.io/utils v0.0.0-20260507154919-ff6756f316d2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
210+
k8s.io/utils v0.0.0-20260626114624-be93311217bd h1:Ea7fgQ5we8Y9T0OX5o0dAHzQOBRI07D/dEYRaB9ZZEs=
211+
k8s.io/utils v0.0.0-20260626114624-be93311217bd/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
210212
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
211213
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
212214
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=

src/kubelet/metric/pods.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,15 @@ func (podsFetcher *PodsFetcher) fetchContainersData(pod *v1.Pod) map[string]defi
257257
func fillContainerStatuses(pod *v1.Pod, dest map[string]definition.RawMetrics) {
258258
containerStatuses := pod.Status.ContainerStatuses
259259

260-
// Add sidecar containers
261-
for idx, initContainer := range pod.Spec.InitContainers {
260+
// Add sidecar containers (init containers with RestartPolicy Always)
261+
for _, initContainer := range pod.Spec.InitContainers {
262262
if initContainer.RestartPolicy != nil && *initContainer.RestartPolicy == v1.ContainerRestartPolicyAlways {
263-
containerStatuses = append(containerStatuses, pod.Status.InitContainerStatuses[idx])
263+
for _, initContainerStatus := range pod.Status.InitContainerStatuses {
264+
if initContainerStatus.Name == initContainer.Name {
265+
containerStatuses = append(containerStatuses, initContainerStatus)
266+
break
267+
}
268+
}
264269
}
265270
}
266271

src/kubelet/metric/pods_test.go

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,181 @@ func TestFetchContainersData_WithSidecarContainers(t *testing.T) {
373373
assert.Equal(t, "192.168.0.33", result[sidecarBID]["nodeIP"])
374374
}
375375

376+
func TestFetchContainersData_WithoutOrderOfInitContainers(t *testing.T) {
377+
t.Parallel()
378+
379+
startedAt, _ := time.Parse(time.RFC3339, "2025-01-02T15:04:05Z")
380+
restartPolicyAlways := corev1.ContainerRestartPolicyAlways
381+
podName := "test-pod"
382+
namespace := "default"
383+
sideCarAContainerName := "sidecar-a"
384+
sideCarBContainerName := "sidecar-b"
385+
initContainerName := "normal-init"
386+
387+
pod := &corev1.Pod{
388+
ObjectMeta: metav1.ObjectMeta{
389+
Name: podName,
390+
Namespace: namespace,
391+
},
392+
Spec: corev1.PodSpec{
393+
InitContainers: []corev1.Container{
394+
{
395+
Name: sideCarAContainerName,
396+
RestartPolicy: &restartPolicyAlways,
397+
},
398+
{
399+
Name: initContainerName,
400+
},
401+
{
402+
Name: sideCarBContainerName,
403+
RestartPolicy: &restartPolicyAlways,
404+
},
405+
},
406+
},
407+
Status: corev1.PodStatus{
408+
HostIP: "192.168.0.33",
409+
410+
InitContainerStatuses: []corev1.ContainerStatus{
411+
// Normal init containers should be skipped
412+
{
413+
Name: initContainerName,
414+
State: corev1.ContainerState{
415+
Terminated: &corev1.ContainerStateTerminated{
416+
FinishedAt: metav1.NewTime(startedAt),
417+
ExitCode: 0,
418+
Reason: "Completed",
419+
},
420+
},
421+
Ready: true,
422+
},
423+
{
424+
Name: sideCarBContainerName,
425+
State: corev1.ContainerState{
426+
Waiting: &corev1.ContainerStateWaiting{
427+
Reason: "ContainerCreating",
428+
},
429+
},
430+
LastTerminationState: corev1.ContainerState{
431+
Terminated: &corev1.ContainerStateTerminated{
432+
FinishedAt: metav1.NewTime(startedAt),
433+
ExitCode: 137,
434+
Reason: "OOMKilled",
435+
},
436+
},
437+
Ready: false,
438+
},
439+
// statuses are not in the same order as the init containers
440+
{
441+
Name: sideCarAContainerName,
442+
State: corev1.ContainerState{
443+
Running: &corev1.ContainerStateRunning{
444+
StartedAt: metav1.NewTime(startedAt),
445+
},
446+
},
447+
Ready: true,
448+
RestartCount: 2,
449+
},
450+
},
451+
},
452+
}
453+
454+
podFetcher := &PodsFetcher{}
455+
result := podFetcher.fetchContainersData(pod)
456+
457+
sidecarAID := fmt.Sprintf("%s_%s_%s", namespace, podName, sideCarAContainerName)
458+
sidecarBID := fmt.Sprintf("%s_%s_%s", namespace, podName, sideCarBContainerName)
459+
assert.Equal(t, 2, len(result), "expected only the sidecar containers to be processed")
460+
assert.Contains(t, result, sidecarAID, "expected sidecar-a to be present as a key")
461+
assert.Contains(t, result, sidecarBID, "expected sidecar-b to be present as a key")
462+
463+
assert.Equal(t, "Running", result[sidecarAID]["status"])
464+
assert.Equal(t, "Waiting", result[sidecarBID]["status"])
465+
assert.Equal(t, true, result[sidecarAID]["isReady"])
466+
assert.Equal(t, int32(2), result[sidecarAID]["restartCount"])
467+
assert.Equal(t, startedAt, result[sidecarAID]["startedAt"])
468+
assert.Equal(t, "OOMKilled", result[sidecarBID]["lastTerminatedExitReason"])
469+
assert.Equal(t, int32(137), result[sidecarBID]["lastTerminatedExitCode"])
470+
assert.Equal(t, "192.168.0.33", result[sidecarAID]["nodeIP"])
471+
assert.Equal(t, "192.168.0.33", result[sidecarBID]["nodeIP"])
472+
}
473+
474+
func TestFetchContainersData_WithLessInitContainerStatuses(t *testing.T) {
475+
t.Parallel()
476+
477+
startedAt, _ := time.Parse(time.RFC3339, "2025-01-02T15:04:05Z")
478+
restartPolicyAlways := corev1.ContainerRestartPolicyAlways
479+
podName := "test-pod"
480+
namespace := "default"
481+
sideCarAContainerName := "sidecar-a"
482+
sideCarBContainerName := "sidecar-b"
483+
initContainerName := "normal-init"
484+
485+
pod := &corev1.Pod{
486+
ObjectMeta: metav1.ObjectMeta{
487+
Name: podName,
488+
Namespace: namespace,
489+
},
490+
Spec: corev1.PodSpec{
491+
InitContainers: []corev1.Container{
492+
{
493+
Name: sideCarAContainerName,
494+
RestartPolicy: &restartPolicyAlways,
495+
},
496+
{
497+
Name: initContainerName,
498+
},
499+
{
500+
Name: sideCarBContainerName,
501+
RestartPolicy: &restartPolicyAlways,
502+
},
503+
},
504+
},
505+
Status: corev1.PodStatus{
506+
HostIP: "192.168.0.33",
507+
508+
InitContainerStatuses: []corev1.ContainerStatus{
509+
{
510+
Name: sideCarAContainerName,
511+
State: corev1.ContainerState{
512+
Running: &corev1.ContainerStateRunning{
513+
StartedAt: metav1.NewTime(startedAt),
514+
},
515+
},
516+
Ready: true,
517+
RestartCount: 2,
518+
},
519+
},
520+
},
521+
}
522+
523+
podFetcher := &PodsFetcher{}
524+
result := podFetcher.fetchContainersData(pod)
525+
526+
sidecarAID := fmt.Sprintf("%s_%s_%s", namespace, podName, sideCarAContainerName)
527+
sidecarBID := fmt.Sprintf("%s_%s_%s", namespace, podName, sideCarBContainerName)
528+
assert.Equal(t, 2, len(result), "expected only the sidecar containers to be processed")
529+
assert.Contains(t, result, sidecarAID, "expected sidecar-a to be present as a key")
530+
assert.Contains(t, result, sidecarBID, "expected sidecar-b to be present as a key")
531+
532+
assert.Equal(t, "Running", result[sidecarAID]["status"])
533+
assert.Equal(t, true, result[sidecarAID]["isReady"])
534+
assert.Equal(t, int32(2), result[sidecarAID]["restartCount"])
535+
assert.Equal(t, startedAt, result[sidecarAID]["startedAt"])
536+
537+
// sidecar-b has no corresponding init status in the PodStatus, so status-related fields should be absent
538+
_, hasStatus := result[sidecarBID]["status"]
539+
assert.False(t, hasStatus, "expected sidecar-b to have no status when init status is missing")
540+
541+
_, hasLastTermReason := result[sidecarBID]["lastTerminatedExitReason"]
542+
assert.False(t, hasLastTermReason)
543+
544+
_, hasLastTermCode := result[sidecarBID]["lastTerminatedExitCode"]
545+
assert.False(t, hasLastTermCode)
546+
547+
assert.Equal(t, "192.168.0.33", result[sidecarAID]["nodeIP"])
548+
assert.Equal(t, "192.168.0.33", result[sidecarBID]["nodeIP"])
549+
}
550+
376551
const (
377552
testContainerName = "app"
378553
testNodeName = "node"

0 commit comments

Comments
 (0)