Skip to content

Commit 36105ed

Browse files
[Backport 7.77.x] fix(cluster-agent): Guard against re-admission for APM auto-instrumentation in image_volume mode (#46819)
Backport 2d33331 from #46743. ___ ### What does this PR do? Avoid double-injection by returning early if the pod already has image_volume mode's init containers. Init_container mode was already guarded by checking for per-language init containers (e.g. datadog-lib-python-init). This change adds the same style of guard for image_volume mode by checking for the datadog-apm-inject-preload init container. ### Motivation The webhook may be run twice, but we do not want to inject twice. CSI mode needs a guard in the future as well. ### Describe how you validated your changes Tests in target_mutator_test.go were added for both re-admission cases: one for init_container mode and one for image_volume mode. The test asserts that the pod is not changed ("mutated") at all in the case that the representative init container(s) are present. ### Additional Notes Co-authored-by: sabrina.lu <sabrina.lu@datadoghq.com>
1 parent 6ca22bc commit 36105ed

File tree

3 files changed

+39
-0
lines changed

3 files changed

+39
-0
lines changed

pkg/clusteragent/admission/mutate/autoinstrumentation/target_mutator.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/DataDog/datadog-agent/pkg/clusteragent/admission/metrics"
2424
"github.com/DataDog/datadog-agent/pkg/clusteragent/admission/mutate/autoinstrumentation/annotation"
2525
"github.com/DataDog/datadog-agent/pkg/clusteragent/admission/mutate/autoinstrumentation/imageresolver"
26+
"github.com/DataDog/datadog-agent/pkg/clusteragent/admission/mutate/autoinstrumentation/libraryinjection"
2627
mutatecommon "github.com/DataDog/datadog-agent/pkg/clusteragent/admission/mutate/common"
2728
"github.com/DataDog/datadog-agent/pkg/util/log"
2829
)
@@ -185,12 +186,18 @@ func (m *TargetMutator) MutatePod(pod *corev1.Pod, ns string, _ dynamic.Interfac
185186
log.Debugf("Mutating pod in target mutator %q", mutatecommon.PodString(pod))
186187

187188
// The admission can be re-run for the same pod. Fast return if we injected the library already.
189+
// Check for the init_container mode's per-language init containers.
188190
for _, lang := range supportedLanguages {
189191
if containsInitContainer(pod, initContainerName(lang)) {
190192
log.Debugf("Init container %q already exists in pod %q", initContainerName(lang), mutatecommon.PodString(pod))
191193
return false, nil
192194
}
193195
}
196+
// Check for the image_volume mode's init container.
197+
if containsInitContainer(pod, libraryinjection.InjectLDPreloadInitContainerName) {
198+
log.Debugf("Init container %q already exists in pod %q", libraryinjection.InjectLDPreloadInitContainerName, mutatecommon.PodString(pod))
199+
return false, nil
200+
}
194201

195202
// Get the target to inject. If there is not target, we should not mutate the pod.
196203
target := m.getTarget(pod)

pkg/clusteragent/admission/mutate/autoinstrumentation/target_mutator_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/DataDog/datadog-agent/pkg/clusteragent/admission/common"
2727
"github.com/DataDog/datadog-agent/pkg/clusteragent/admission/mutate/autoinstrumentation/annotation"
2828
"github.com/DataDog/datadog-agent/pkg/clusteragent/admission/mutate/autoinstrumentation/imageresolver"
29+
"github.com/DataDog/datadog-agent/pkg/clusteragent/admission/mutate/autoinstrumentation/libraryinjection"
2930
mutatecommon "github.com/DataDog/datadog-agent/pkg/clusteragent/admission/mutate/common"
3031
configmock "github.com/DataDog/datadog-agent/pkg/config/mock"
3132
"github.com/DataDog/datadog-agent/pkg/languagedetection/languagemodels"
@@ -142,6 +143,34 @@ func TestMutatePod(t *testing.T) {
142143
},
143144
expectNoChange: true,
144145
},
146+
// Re-admission guard: when the webhook runs again on an already-injected pod we must not
147+
// mutate further (e.g. must not append to LD_PRELOAD or add duplicate init containers).
148+
"re-admission with init_container mode init container already present does not mutate": {
149+
configPath: "testdata/filter_simple_namespace.yaml",
150+
in: mutatecommon.FakePodSpec{
151+
NS: "application",
152+
InitContainers: []corev1.Container{
153+
{Name: "datadog-lib-python-init", Image: "registry/dd-lib-python-init:v3"},
154+
},
155+
}.Create(),
156+
namespaces: []workloadmeta.KubernetesMetadata{
157+
newTestNamespace("application", nil),
158+
},
159+
expectNoChange: true,
160+
},
161+
"re-admission with image_volume mode init container already present does not mutate": {
162+
configPath: "testdata/filter_simple_namespace.yaml",
163+
in: mutatecommon.FakePodSpec{
164+
NS: "application",
165+
InitContainers: []corev1.Container{
166+
{Name: libraryinjection.InjectLDPreloadInitContainerName, Image: "registry/apm-inject:0"},
167+
},
168+
}.Create(),
169+
namespaces: []workloadmeta.KubernetesMetadata{
170+
newTestNamespace("application", nil),
171+
},
172+
expectNoChange: true,
173+
},
145174
"tracer configs get applied": {
146175
configPath: "testdata/filter_simple_configs.yaml",
147176
in: mutatecommon.WithLabels(
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fixes:
2+
- |
3+
Fixes a bug in the admission controller webhook that allowed admission to re-run for pods that already had APM injection in image-volume mode.

0 commit comments

Comments
 (0)