Insiden produksi terjadi pada layanan parser kompilator berbasis binari native FreeOberon yang dijalankan di cluster Kubernetes. Pod mengalami siklus CrashLoopBackOff seketika setelah release container image baru. Analisis runtime menunjukkan pod gagal start dengan kode keluar kontainer yang mengindikasikan masalah dynamic linking tingkat rendah.
1. Gejala Kegagalan: Exit Code 127 dan 139
Identifikasi awal dilakukan melalui kubectl describe pod dan inspeksi status container. Ditemukan dua gejala primer pada deployment:
- Exit Code 127: Pesan log kontainer menampilkan
exec /usr/local/bin/oberon-runner: no such file or directory. Path file binari valid di dalam image, namun kernel gagal memuat interpreter ELF dynamic loader (/lib64/ld-linux-x86-64.so.2) yang tidak tersedia di filesystem target. - Exit Code 139: Terjadi pada varian image glibc-compat ketika dynamic linker memaksakan resolusi symbol ke library runtime yang memiliki struct padding atau calling convention berbeda, memicu Segmentation Fault (SIGSEGV).
Observabilitas: Probe, Metrics, dan Dump Collector
Deteksi otomatis mengandalkan metrik ekspor kube-state-metrics dan probe liveness TCP/exec. Jika binari mati sebelum bind network socket, liveness probe memicu restart cepat.
# Query Prometheus untuk restart loop dalam 5 menit
rate(kube_pod_container_status_restarts_total{container="oberon-runner"}[5m]) > 0
Pengumpulan stderr dan core dump dikonfigurasi melalui shared volume dan pengaturan kernel core_pattern pada host level untuk membaca crash state:
apiVersion: v1
kind: Pod
metadata:
name: oberon-debug
spec:
containers:
- name: oberon-runner
image: registry.internal/oberon-runner:v1.4.2
command: ["/bin/sh", "-c"]
args:
- ulimit -c unlimited; /usr/local/bin/oberon-runner 2>> /var/log/oberon/stderr.log
volumeMounts:
- name: crash-dumps
mountPath: /var/log/oberon
volumes:
- name: crash-dumps
emptyDir: {}
2. Automated Canary Rollback via Argo Rollouts
Deployment service menggunakan CRD Rollout. Evaluasi metrics dilakukan saat fasa canary. Analisis kegagalan pod langsung membatalkan deployment otomatis sebelum trafik dialihkan ke versi baru.
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: oberon-runner
spec:
replicas: 10
strategy:
canary:
analysis:
templates:
- templateName: pod-restart-analysis
args:
- name: service-name
value: oberon-runner
steps:
- setWeight: 10
- pause: {duration: 60s}
---
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: pod-restart-analysis
spec:
metrics:
- name: restart-rate
interval: 15s
failureLimit: 1
provider:
prometheus:
address: http://prometheus-k8s.monitoring:9090
query: |
sum(rate(kube_pod_container_status_restarts_total{container="oberon-runner"}[1m])) > 0
Argo Rollouts menghentikan step canary, menetapkan status Degraded, dan mengembalikan routing trafik sepenuhnya ke revision Stable (Rollback).
3. Root Cause Analysis (RCA)
Penyebab utama insiden adalah ABI Mismatch antara build runner dan container runtime:
- Kompiler FreeOberon dikompilasi pada host Linux (Ubuntu CI runner) menggunakan
gccyang di-link secara dinamis terhadapglibc(GNU C Library). - Container image target berbasis
alpine:3.19yang menggunakanmusl libcsebagai implementasi library sistem default. - Binary format ELF 64-bit menyertakan header
PT_INTERPyang menunjuk ke dynamic linker glibc. Kernel Linux pada kontainer Alpine mencari path tersebut, gagal menemukannya, dan menghasilkan error misleadingno such file or directory(Exit Code 127).
4. Solusi dan Pencegahan
A. Multi-stage Dockerfile untuk Fully Static Compilation
Gunakan compiler toolchain yang mendukung flag -static untuk mengeliminasi ketergantungan runtime shared object.
# Stage 1: Build binary statically
FROM alpine:3.19 AS builder
RUN apk add --no-cache build-base git
WORKDIR /src
COPY . .
# Kompilasi C source dari output transpile FreeOberon secara statis
RUN gcc -static -O2 -o oberon-runner main.c
# Stage 2: Minimal runtime image
FROM scratch
WORKDIR /app
COPY --from=builder /src/oberon-runner /app/oberon-runner
USER 65534:65534
ENTRYPOINT ["/app/oberon-runner"]
B. Verifikasi Binary via CI Pipeline
Tambahkan langkah inspeksi dynamic linking pada pipeline integrasi (GitHub Actions atau GitLab CI) sebelum container image di-push ke registry:
# Verifikasi binary statis di pipeline
file ./bin/oberon-runner | grep "statically linked" || {
echo "Error: Binary bukan static binary!";
exit 1;
}
# Pastikan ldd memberikan return non-zero atau not a dynamic executable
if ldd ./bin/oberon-runner 2>&1 | grep -E "not a dynamic executable|statically linked"; then
echo "OK: Verifikasi dynamic linking lolos.";
else
echo "Error: Terdeteksi dynamic link dependency:";
ldd ./bin/oberon-runner;
exit 1;
fi
C. Pre-deployment Smoke Test
Eksekusi binary di lingkungan runtime identik dalam CI job sebelum trigger CD rollout:
docker run --rm -i registry.internal/oberon-runner:local-test --version || exit 1
Uji eksekusi langsung mendeteksi ketiadaan loader dynamic library sebelum manifest Kubernetes diterapkan pada cluster.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!