TensorRT inference slow after etcd cluster inconsistency

Problem Description

In a multi‑node on‑premises deployment of TensorRT (via Triton Inference Server), inference latency spiked from ~2 ms per request to 10‑20 ms and occasional errors such as Model version not found for model XYZ appeared. The issue manifested after a brief network partition that caused an etcd leader election. Typical log excerpts were:


[2024-06-18 14:03:12] [Triton] ERROR: Failed to fetch model config from etcd: request timed out
[2024-06-18 14:03:13] [TensorRT] WARN: Checksum mismatch for model configuration; reloading engine
[2024-06-18 14:03:14] [Triton] ERROR: Model version not found for model XYZ

Operational impact included:

  • 3‑5× higher 99th‑percentile latency.
  • Reduced throughput (≈30 % of baseline).
  • Increased CPU usage due to repeated engine rebuilds.
  • Transient “model not found” responses causing client time‑outs.

Root Cause Analysis

TensorRT itself does not store model metadata; it relies on Triton’s model repository abstraction. When Triton is configured with an etcd backend (see NVIDIA Triton “Model Repository and Configuration Management” documentation), the following sequence occurs:

  1. Each inference worker watches a /models/<name>/config key using the etcd v3 Watch API (etcd v3 API Reference – “Watch and Lease”).
  2. On change, the worker validates the JSON checksum and, if different, triggers a metadata reload (TensorRT Performance Tuning Guide – “Impact of Model Metadata Reload on Latency”).
  3. If the etcd cluster loses quorum, the leader steps down and a new leader is elected. During the election window, some nodes continue to serve stale watches while others receive a request timed out error.
  4. Because watches are not retroactively replayed after a leader change, nodes that missed the update retain the old configuration. When the cluster reconverges, nodes fetch divergent JSON payloads (often truncated or corrupted) leading to checksum mismatches.
  5. TensorRT’s fallback logic treats a mismatch as a signal to rebuild the engine on every request, causing the observed latency degradation.

The root cause is therefore an etcd cluster inconsistency (split‑brain or quorum loss) that leaves Triton workers with out‑of‑sync model configuration, forcing repeated engine rebuilds.

Investigation and Debugging

Follow these steps to confirm the inconsistency and pinpoint the affected nodes.

1. Verify etcd cluster health


# Check cluster member health
etcdctl endpoint health --cluster
# Expected output: each member reports "healthy"
# Example of a failing member:
127.0.0.1:2379 is unhealthy: context deadline exceeded

2. Inspect Triton watch status


# Query the watch lease TTL (if used)
etcdctl lease timetolive $(etcdctl get /models/resnet50/lease --print-value-only)

If the lease is missing or has expired, the worker will attempt to re‑establish the watch on the next request.

3. Examine model configuration keys


# Retrieve raw JSON from each node’s perspective
etcdctl get /models/resnet50/config --consistent
# Compare outputs from two nodes:
Node A: {"version":"1","checksum":"a1b2c3","...}
Node B: {"version":"1","checksum":"d4e5f6","...}

A checksum mismatch indicates divergent config state.

4. Correlate logs with watch events


# Filter Triton logs for watch failures
journalctl -u triton -g "Failed to fetch model config"
# Sample line:
2024-06-18T14:03:12.123Z [Triton] ERROR: Failed to fetch model config from etcd: request timed out

5. Capture a short packet trace (optional)


tcpdump -i eth0 port 2379 -w etcd_trace.pcap
# Look for TCP retransmissions or RST packets during the partition.

6. Check engine rebuild frequency


# Triton metrics (Prometheus endpoint)
curl http://localhost:8002/metrics | grep triton_inference_engine_reload_total
# High counter values confirm repeated reloads.

Resolution

Fix the problem in two phases: restore cluster consistency, then enforce deterministic configuration propagation.

Phase 1 – Restore etcd quorum


# Restart any unhealthy members
systemctl restart etcd

# Force a new snapshot to purge corrupted keys
etcdctl snapshot save /var/lib/etcd/snapshot.db
etcdctl snapshot restore /var/lib/etcd/snapshot.db \
  --name etcd-node-1 \
  --initial-cluster etcd-node-1=https://10.0.0.1:2380,etcd-node-2=https://10.0.0.2:2380,etcd-node-3=https://10.0.0.3:2380 \
  --initial-cluster-state new

After the snapshot restore, verify health:


etcdctl endpoint health --cluster
# All members should report "healthy"

Phase 2 – Enforce atomic configuration updates

Update the model deployment pipeline to use a single transaction that writes both the configuration JSON and its checksum, then attaches a lease that expires atomically.


// Example using etcdctl transaction
etcdctl txn <

Deploy the updated transaction script to the CI/CD pipeline that publishes model artifacts.

Phase 3 – Restart Triton workers to clear stale watches


systemctl restart triton
# Or, for containerized deployments:
docker restart triton-inference-server

Workers will re‑establish watches against the now‑consistent etcd cluster, fetch the correct configuration, and load the engine only once.

Validation

After applying the fix, perform the following checks:

  1. Cluster health
    
    etcdctl endpoint health --cluster
    # All members: healthy
    
  2. Configuration consistency
    
    etcdctl get /models/resnet50/config --consistent | sha256sum
    # Compare checksum across all nodes – must match.
    
  3. Engine reload counter
    
    curl http://localhost:8002/metrics | grep triton_inference_engine_reload_total
    # Counter should remain static after restart.
    
  4. Latency benchmark
    
    # Using wrk for a 30‑second run
    wrk -t4 -c32 -d30s http://inference-host:8000/v2/models/resnet50/infer
    # Expected median latency ~2‑3 ms, throughput ~10k rps.
    
  5. Application logs
    
    journalctl -u triton -g "Failed to fetch model config"
    # No new error lines should appear.
    

Prevention and Best Practices

  • Enable etcd auto‑compaction (e.g., --auto-compaction-retention=1) to keep the KV store healthy.
  • Use quorum‑aware client libraries (e.g., NVIDIA’s etcd‑cpp‑client) that retry watch re‑registration after leader changes.
  • Deploy an odd number of etcd nodes (minimum three) to avoid split‑brain scenarios.
  • Monitor etcd leader health via Prometheus metrics etcd_server_leader_changes_seen_total and alert on rapid leader churn.
  • Validate model config checksum in the deployment pipeline; reject configs that differ from the stored checksum.
  • Graceful rolling restarts of Triton workers during etcd maintenance to force re‑synchronization.

Related Topic Hub: Model Serving Troubleshooting Hub

FAQ

  1. Why does inference latency only increase after an etcd leader election?
    During leader election some workers lose their watch connection and keep loading stale or corrupted configuration. Each request then triggers a full engine rebuild, which is CPU‑bound and adds tens of milliseconds per inference.
  2. Can I disable etcd watches and poll for config changes instead?
    Polling eliminates the race condition caused by missed watch events, but introduces latency in config propagation. If you choose polling, set the interval to < 5 seconds and ensure the poller validates checksums to avoid unnecessary reloads.
  3. What is the recommended etcd snapshot frequency for Triton deployments?
    A snapshot every 30 minutes combined with a retention policy of 24 hours balances recovery speed and storage cost. Use etcdctl snapshot save with a cron job.
  4. How do I differentiate between a corrupted config payload and a legitimate version bump?
    A corrupted payload often triggers “request is too large” or JSON parsing errors. A legitimate version bump will have a matching checksum field and an incremented version number. Validate both fields before applying the update.
  5. Is there a way to force Triton to ignore checksum mismatches and keep the old engine?
    Triton’s default behavior is to reload on mismatch for correctness. Overriding this requires modifying the server source to bypass the checksum check, which is not recommended for production because it can lead to serving stale or incompatible models.