VM 환경에서는 APM 에이전트를 OS 이미지에 포함하고 systemd로 실행했다. Kubernetes로 전환한 뒤에는 서비스마다 Helm 차트 구조가 달라 같은 방식을 적용하기 어려웠다. 애플리케이션 팀에 initContainer와 환경변수 추가를 반복해서 요청하는 방식도 확장성이 없었다.
초기에는 일부 차트를 직접 수정했지만 신규 서비스나 차트 버전 변경 때 설정이 누락될 수 있었다. Pod 생성 시점에 sidecar와 환경 변수를 자동으로 추가하도록 Mutating Admission Webhook을 적용했다.

Pod 생성 요청이 들어오면 Mutating Webhook이 APM 에이전트 설정을 자동으로 주입한다.
차트 수정으로는 끝이 나지 않았다
애플리케이션 팀이 차트마다 설정하면 적용 여부를 별도로 확인해야 한다. 기본적으로 APM 설정을 주입하고, 적용하면 안 되는 워크로드만 명시적으로 제외하는 opt-out 방식을 선택했다.
Go로 작성한 핸들러
func (h *Handler) Mutate(w http.ResponseWriter, r *http.Request) {
var review admissionv1.AdmissionReview
_ = json.NewDecoder(r.Body).Decode(&review)
pod := corev1.Pod{}
_ = json.Unmarshal(review.Request.Object.Raw, &pod)
patches := []jsonpatch.Operation{}
if shouldInject(&pod) {
patches = append(patches, injectAPMAgent(&pod)...)
patches = append(patches, injectEnvVars(&pod)...)
}
patchBytes, _ := json.Marshal(patches)
review.Response = &admissionv1.AdmissionResponse{
UID: review.Request.UID, Allowed: true,
Patch: patchBytes,
PatchType: ptr.To(admissionv1.PatchTypeJSONPatch),
}
_ = json.NewEncoder(w).Encode(review)
}
shouldInject는 라벨과 네임스페이스 허용 목록을 확인한다. 대상 서비스가 개별적으로 설정해야 하는 opt-in 방식은 누락 가능성이 있어, 기본 적용 후 예외를 명시하는 opt-out 방식을 선택했다.
운영 시 주의할 점
failurePolicy: Fail에서는 Webhook 장애가 Pod 생성 실패로 이어질 수 있다. namespaceSelector로 kube-system을 제외하고 Webhook 자체도 주입 대상에서 제외했다. 인증서는 cert-manager로 발급하고 MutatingWebhookConfiguration의 caBundle을 자동으로 동기화했다.
운영 중 남은 과제
Webhook 적용 이후 애플리케이션 팀에서 APM 설정 추가를 요청하는 PR은 더 이상 접수되지 않았다. 적용 전 요청 건수를 별도로 집계하지 않았으므로 감소율은 산정하지 않았다.
운영 중에는 라벨이 기준과 다르게 지정돼 주입이 누락되거나, 제외해야 할 Job에 APM 설정이 적용되는 경우가 있었다. 제외 규칙을 엄격하게 하면 필요한 워크로드가 빠질 수 있고, 범위를 넓히면 불필요한 주입이 발생한다. 현재도 워크로드 유형과 라벨 기준을 조정하고 있다.
참고