Kubernetes-native HTTP traffic capture for service meshes
meshcap captures HTTP traffic flowing through your service mesh and persists it to cloud storage. It runs transparently alongside your services using a Proxy-Wasm plugin — compatible with any proxy that implements the spec (Istio/Envoy, Gloo Edge, etc.). No application changes required. Supports pluggable output formats (Parquet, HAR) and storage backends (AWS S3, Azure Blob Storage).
flowchart TD
A[Service Pod] -->|HTTP request| B[Envoy Sidecar]
B -->|captures headers + body| C[WASM Plugin]
C -->|POST /ingest| D[meshcap Collector]
D -->|batches by host| E[Parquet Writer]
E -->|zstd compressed| F[(S3 / MinIO)]
style A fill:#4a9eff,color:#fff
style C fill:#ff6b6b,color:#fff
style D fill:#51cf66,color:#fff
style F fill:#ffd43b,color:#333
- Transparent capture — Envoy WASM plugin intercepts HTTP traffic without code changes
- Pluggable formats — Parquet (zstd compressed) or HAR (HTTP Archive 1.2)
- Multi-cloud storage — AWS S3, MinIO, or Azure Blob Storage
- Hive partitioning — Files organized by
host/year/month/day/hourfor query efficiency - Prometheus metrics — Built-in observability with counters, gauges, and histograms
- Helm chart — Production-ready Kubernetes deployment with HPA and KEDA support
- Graceful shutdown — Flushes all buffered records before stopping
All release artifacts are published to GitHub Container Registry:
| Package | Pull command |
|---|---|
| Collector image | docker pull ghcr.io/jycamier/meshcap:<version> |
| WASM plugin (OCI) | oras pull ghcr.io/jycamier/meshcap/wasm-plugin:<version> |
| Helm chart (OCI) | helm pull oci://ghcr.io/jycamier/meshcap/chart/meshcap --version <version> |
Replace <version> with a release version (e.g. 0.1.0) or use latest for the WASM plugin.
helm install meshcap oci://ghcr.io/jycamier/meshcap/chart/meshcap \
--version <version> \
--namespace capture --create-namespace \
--set collector.s3Bucket=my-bucket \
--set collector.s3Region=eu-west-1The WASM plugin is consumed directly by Istio via its OCI URL — no manual download needed:
apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
name: traffic-capture
namespace: default
spec:
selector:
matchLabels:
meshcap.io/enabled: "true"
url: oci://ghcr.io/jycamier/meshcap/wasm-plugin:0.1.0
imagePullPolicy: IfNotPresent
phase: AUTHN
pluginConfig:
collectorCluster: "outbound|8080||meshcap-meshcap.capture.svc.cluster.local"
maxBodySize: 1048576Then label pods to opt-in:
kubectl patch deployment myapp \
-p '{"spec":{"template":{"metadata":{"labels":{"meshcap.io/enabled":"true"}}}}}'
kubectl rollout restart deployment myappSee the WASM Plugin Guide for full details including troubleshooting.
Get a local environment running in seconds with Docker Compose:
git clone https://github.com/jycamier/meshcap.git
cd meshcap
docker compose upThis starts the collector and a MinIO instance. Send a test request:
curl -X POST http://localhost:8080/ingest \
-H "Content-Type: application/json" \
-d '{"request_id":"test-1","req_method":"GET","req_path":"/api/users","req_host":"myapp.example.com","captured_at":"2025-01-01T00:00:00Z","timestamp_ns":1735689600000000000}'Parquet files will appear in the MinIO capture bucket (console at localhost:9001, credentials: minioadmin/minioadmin).
| Document | Description |
|---|---|
| Architecture | System design, data flow, component internals, and S3 partitioning strategy |
| Getting Started | Local development with Docker Compose and Kubernetes deployment with Helm |
| Configuration | Complete reference for CLI flags, environment variables, and Helm values |
| WASM Plugin | Building, deploying, and configuring the Envoy/Istio traffic capture plugin |
Contributions are welcome! Please open an issue or submit a pull request.
make build # Build the collector binary
make test # Run tests with race detection
make lint # Run linterThis project is licensed under the Apache License 2.0 — see the LICENSE file for details.