Blog Post
Zero-Code Observability di Kubernetes dengan OpenTelemetry eBPF dan Collector
Panduan hands-on untuk menambahkan tracing dan metrics dasar di Kubernetes tanpa ubah kode aplikasi, memakai eBPF instrumentation dan OpenTelemetry Collector.
TL;DR
- Zero-code observability cocok untuk baseline visibility yang cepat, terutama di cluster polyglot yang sulit disentuh semua tim aplikasi.
- eBPF instrumentation memberi trace dan network insight tanpa rebuild image, tetapi tidak menggantikan custom metrics bisnis.
- OpenTelemetry Collector tetap menjadi komponen inti karena di situlah sampling, filtering, dan routing telemetry sebaiknya dikendalikan.
Pendahuluan
Salah satu hambatan terbesar dalam observability modern adalah koordinasi lintas tim. Tim platform ingin trace menyala cepat, tetapi tim aplikasi belum siap menambahkan SDK, mengubah image, atau merilis ulang semua service. Di sinilah pendekatan zero-code berbasis eBPF menjadi menarik. Ia tidak menyelesaikan seluruh problem observability, tetapi sangat efektif untuk baseline visibility di cluster yang kompleks dan heterogen.
Masalahnya, banyak implementasi zero-code berhenti pada “trace sudah muncul”. Itu belum cukup. Tanpa Collector yang jelas, pipeline observability cepat menjadi mahal, noisy, atau tidak stabil. Operator juga sering lupa bahwa eBPF punya prasyarat kernel, overhead, dan keterbatasan pada traffic terenkripsi atau metadata bisnis yang memang tidak terlihat dari kernel boundary.
Tutorial ini membangun pipeline minimal yang production-minded: instrumentasi eBPF untuk baseline trace dan RED metrics, lalu OpenTelemetry Collector sebagai gateway pemrosesan sebelum data dikirim ke backend observability. Contohnya menggunakan cluster Linux, karena eBPF memang bergantung pada kernel capability yang tepat.
Problem di Production
Banyak cluster Kubernetes punya blind spot besar justru karena terlalu banyak layanan lama, bahasa campuran, atau release cycle yang lambat. Saat incident datang, operator melihat CPU dan memory, tetapi tidak tahu request path mana yang lambat atau dependency mana yang paling sering error. Menunggu semua tim mengadopsi SDK bisa memakan kuartal, sedangkan kebutuhan visibility ada sekarang.
Problem lain adalah biaya. Telemetry yang dikirim mentah dari semua service ke vendor backend sering cepat membengkak. Tanpa pipeline yang menyaring dan merutekan data, proyek observability berubah menjadi tagihan besar yang sulit dipertahankan.
Prerequisites
- Cluster Kubernetes 1.29+ berbasis node Linux.
- Kernel host mendukung eBPF modern. Kernel 5.x lebih aman untuk baseline deployment.
helmdankubectl.- Namespace khusus observability, misalnya
observability. - Endpoint backend OTLP, misalnya Grafana Tempo, Jaeger, atau vendor APM yang menerima OTLP.
- Akses untuk memasang DaemonSet di node aplikasi.
Architecture / Context
Arsitektur yang digunakan terdiri dari dua lapisan. Lapisan pertama adalah eBPF-based instrumentation yang berjalan dekat node atau workload dan menghasilkan telemetry tanpa modifikasi kode. Lapisan kedua adalah OpenTelemetry Collector gateway yang menerima data itu, memberi attribute enrichment, melakukan batching, sampling, atau filtering, lalu meneruskannya ke backend pilihan.
Model ini cocok untuk fase akselerasi observability. Tim mendapatkan coverage yang cukup cepat, sementara adopsi manual SDK bisa dilakukan kemudian hanya pada jalur yang butuh business metric atau custom span.
Step-by-Step Implementation
Step 1: Buat namespace observability
kubectl create namespace observability
Step 2: Tambahkan repo Helm yang dibutuhkan
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
Collector akan dipasang dari chart OpenTelemetry. Untuk eBPF instrumentation, contoh ini menggunakan Beyla sebagai agent zero-code yang sudah mengekspor data dengan OpenTelemetry pipeline.
Step 3: Pasang OpenTelemetry Collector sebagai gateway
Buat file values:
mode: deployment
config:
receivers:
otlp:
protocols:
grpc:
http:
processors:
memory_limiter:
check_interval: 2s
limit_mib: 1024
batch:
send_batch_size: 2048
timeout: 5s
resource:
attributes:
- key: k8s.cluster.name
value: prod-cluster-01
action: upsert
exporters:
otlp:
endpoint: tempo-distributor.observability.svc.cluster.local:4317
tls:
insecure: true
logging:
verbosity: normal
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, resource, batch]
exporters: [otlp, logging]
metrics:
receivers: [otlp]
processors: [memory_limiter, resource, batch]
exporters: [otlp]
resources:
limits:
cpu: 1000m
memory: 2Gi
requests:
cpu: 250m
memory: 512Mi
Install:
helm upgrade --install otel-gateway open-telemetry/opentelemetry-collector \
-n observability \
-f otel-gateway-values.yaml
Collector gateway adalah titik kendali paling penting. Kalau tim butuh filter noisy endpoint, sampling, atau enrich cluster metadata, lakukan di sini.
Step 4: Pasang Beyla sebagai DaemonSet
apiVersion: v1
kind: ConfigMap
metadata:
name: beyla-config
namespace: observability
data:
beyla-config.yml: |
attributes:
kubernetes:
enable: true
routes:
unmatched: heuristic
otel_metrics_export:
endpoint: http://otel-gateway-opentelemetry-collector.observability.svc.cluster.local:4318
otel_traces_export:
endpoint: http://otel-gateway-opentelemetry-collector.observability.svc.cluster.local:4318
discovery:
services:
- namespace: payments
- namespace: checkout
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: beyla
namespace: observability
spec:
selector:
matchLabels:
app: beyla
template:
metadata:
labels:
app: beyla
spec:
serviceAccountName: default
hostPID: true
containers:
- name: beyla
image: grafana/beyla:2.4.0
securityContext:
privileged: true
capabilities:
add: ["BPF", "SYS_ADMIN", "NET_ADMIN", "PERFMON"]
env:
- name: BEYLA_CONFIG_PATH
value: /config/beyla-config.yml
volumeMounts:
- name: config
mountPath: /config
volumes:
- name: config
configMap:
name: beyla-config
Apply:
kubectl apply -f beyla.yaml
Privilege di sini adalah trade-off yang harus dipahami. eBPF observability butuh kemampuan kernel-level; karena itu deployment semacam ini layak berada di namespace platform yang dikontrol ketat.
Step 5: Label namespace yang ingin dipantau
kubectl label namespace payments observability=enabled --overwrite
kubectl label namespace checkout observability=enabled --overwrite
Jika tim ingin coverage lebih sempit dulu, mulai dari service yang paling sering incident.
Step 6: Tambahkan filter di Collector untuk noisy path
Jika health check dan metrics endpoint terlalu banyak, filter di Collector:
processors:
filter:
traces:
span:
- 'attributes["http.target"] == "/health"'
- 'attributes["http.target"] == "/metrics"'
Lalu masukkan ke pipeline:
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, filter, resource, batch]
exporters: [otlp, logging]
Step 7: Tambahkan backend quick check jika belum ada
Untuk verifikasi lokal, misalnya pakai Jaeger all-in-one:
helm upgrade --install jaeger jaegertracing/jaeger \
-n observability \
--set provisionDataStore.cassandra=false \
--set allInOne.enabled=true
Jika sudah punya Tempo atau vendor APM, arahkan OTLP exporter langsung ke sana.
Verification
Cek pod observability:
kubectl -n observability get pods
Cek log Collector:
kubectl -n observability logs deploy/otel-gateway-opentelemetry-collector
Cek log Beyla:
kubectl -n observability logs ds/beyla
Uji traffic ke salah satu service yang dipantau, lalu pastikan trace masuk:
kubectl -n payments port-forward svc/payments-api 8080:80
curl http://127.0.0.1:8080/health
curl http://127.0.0.1:8080/api/checkout
Hasil yang sehat:
- Collector menerima OTLP traffic tanpa drop besar
- Beyla mendeteksi process atau workload target
- trace dan metric dasar seperti request rate, error, dan latency terlihat di backend
Troubleshooting
Jika Beyla tidak jalan, cek capability kernel dan security context:
kubectl -n observability describe pod -l app=beyla
kubectl -n observability logs ds/beyla | tail -n 50
Jika Collector sehat tetapi trace kosong, cek endpoint exporter dan port OTLP:
kubectl -n observability get svc
kubectl -n observability exec deploy/otel-gateway-opentelemetry-collector -- netstat -lnt
Jika beberapa service tidak terdeteksi, kemungkinan process discovery tidak cocok, kernel terlalu lama, atau traffic terenkripsi di boundary yang tidak bisa di-inspect seperti yang dibayangkan. Dalam kasus ini, gabungkan dengan manual SDK untuk service kritis.
Production Notes
Zero-code observability sebaiknya dipakai sebagai baseline visibility, bukan pengganti total instrumentation. Untuk service dengan business-critical tracing, tambahkan manual span agar context bisnis tetap ada. Pertimbangkan sampling adaptif di Collector agar biaya tidak melonjak. Pantau overhead CPU pada node yang menjalankan eBPF agent, terutama di cluster dengan network churn tinggi.
Pisahkan ownership pipeline. Tim platform mengelola agent dan Collector, sedangkan tim aplikasi bertanggung jawab menambahkan telemetry kustom di jalur yang benar-benar membutuhkan detail domain.
Trade-offs
eBPF memberi time-to-value yang cepat, tetapi tidak selalu bisa melihat semua detail aplikasi. Collector gateway memberi fleksibilitas tinggi, tetapi menjadi dependency operasional baru. Menaruh instrumentation di kernel boundary menurunkan kebutuhan modifikasi kode, tetapi meningkatkan kebutuhan review pada node privilege dan compat matrix kernel.
Failure Modes
- Agent eBPF tidak kompatibel dengan kernel atau security profile node.
- Telemetry terlalu noisy sehingga Collector overload atau biaya backend naik drastis.
- Tim mengira zero-code sudah cukup dan tidak pernah menambahkan business telemetry yang sebenarnya diperlukan.
- Filter yang terlalu agresif membuang trace yang justru dibutuhkan saat incident.
Best Practices
- Mulai dari coverage terbatas pada namespace paling kritis.
- Gunakan Collector sebagai tempat sentral untuk filter, enrich, dan sampling.
- Pantau overhead agent pada node, bukan hanya health pod.
- Dokumentasikan service mana yang hanya memakai zero-code dan mana yang sudah diberi manual instrumentation.
- Gunakan naming, resource attribute, dan cluster metadata yang konsisten.
Kesalahan Umum
- memasang eBPF agent di semua node tanpa uji overhead
- mengirim semua trace mentah ke backend tanpa filter
- menganggap zero-code dapat menggantikan seluruh observability strategy
- tidak memeriksa kecocokan kernel dan capability
Kesimpulan
OpenTelemetry eBPF instrumentation memberi jalur cepat untuk menutup blind spot Kubernetes tanpa menunggu semua tim aplikasi merilis ulang image mereka. Nilai sebenarnya baru terasa ketika data itu diarahkan melalui Collector yang disiplin, sehingga visibilitas meningkat tanpa mengorbankan kontrol biaya dan stabilitas pipeline observability.
Kalau artikel ini membantu, kamu bisa support eksperimen berikutnya.
Apresiasi di TrakteerKeep Reading
Related posts
eBPF Runtime Security di Kubernetes dengan Guardrail yang Praktis
Panduan production-grade untuk menerapkan eBPF runtime security di Kubernetes tanpa menciptakan alert noise dan operability issue yang tidak perlu.
Ephemeral GitHub Actions Runners di Kubernetes dengan Actions Runner Controller
Panduan operasional untuk menjalankan GitHub Actions runner yang ephemeral di Kubernetes dengan isolasi lebih baik, autoscaling, dan kontrol secret yang lebih rapi.
Hardening vLLM Inference Service di Kubernetes dengan Istio dan OPA
Panduan production-ready untuk menjalankan vLLM di Kubernetes dengan kontrol jaringan, policy admission, mTLS, dan guardrail operasional yang lebih aman.