/deployment/kubernetes.llms.txt
Kubernetes
eRPC is a stateless proxy — every replica is identical, rolling restarts are safe, and you can scale to any count without session affinity. The reference manifests in kube/ give you a Namespace, Deployment, ConfigMap, ClusterIP Service, and PodMonitor in one apply. A companion manifest adds a PostgreSQL cache store. Zero in-flight requests are dropped when you tune the termination grace period to match your timeout settings.
kubectl apply -f kube/erpc.yml
kubectl apply -f kube/postgres.yml # optional cache storeAgent reference
Copy one of these prompts into your AI agent session (Claude Code, Cursor, …) — each one points the agent at this page's machine-readable reference so it can do the work correctly:
Prompt Example #1: deploy eRPC to Kubernetes from scratch
Apply the eRPC Kubernetes manifests to my cluster: Namespace, Deployment, ConfigMap, ClusterIP Service, and PodMonitor. Set GOMEMLIMIT to 90% of the memory limit, wire the Downward API for POD_NAME, and pin the image to a specific release tag. My Work with my existing eRPC config. Read the full reference first: https://docs.erpc.cloud/deployment/kubernetes.llms.txt
Prompt Example #2: tune graceful drain to avoid dropped requests
My Kubernetes pods are dropping in-flight requests during rolling deploys. Tune terminationGracePeriodSeconds, server.waitBeforeShutdown, and server.waitAfterShutdown so all requests drain cleanly before SIGKILL. Work with my existing eRPC config. Reference: https://docs.erpc.cloud/deployment/kubernetes.llms.txt
Prompt Example #3: fix OOM kills and high tail latency on pods
My eRPC pods are being OOM-killed under load and I also see high p99 latency spikes. Help me set GOMEMLIMIT, GOGC, and resource limits/requests correctly, and explain whether I should remove the CPU limit to avoid CFS throttling. Work with my existing eRPC config. Reference: https://docs.erpc.cloud/deployment/kubernetes.llms.txt
Prompt Example #4: wire Prometheus scraping via PodMonitor
My Prometheus Operator is not scraping eRPC metrics. Verify the PodMonitor spec, labels, and port names match my cluster's podMonitorSelector, and explain what metrics to alert on for production. Work with my existing eRPC config. Reference: https://docs.erpc.cloud/deployment/kubernetes.llms.txt
Kubernetes — full agent referenceExpand for every option, default, and edge case — or copy this entire section into your AI assistant.
How it works
kube/erpc.yml defines five Kubernetes resources: a erpc Namespace, a Deployment (single replica by default, safe to scale), a ConfigMap erpc-config with an embedded example erpc.yaml, a ClusterIP Service (port 80 → 4000), and a PodMonitor for Prometheus Operator. kube/postgres.yml adds a PersistentVolumeClaim (500 Gi), Deployment, Service, and Secret for a companion PostgreSQL cache store.
Config delivery. The Deployment mounts the ConfigMap as a volume at /erpc.yaml. To change config, update the ConfigMap and run kubectl rollout restart deployment/erpc — ConfigMap updates alone do not trigger a rolling restart.
Graceful drain. eRPC handles SIGTERM via signal.NotifyContext. After receiving SIGTERM:
- Healthcheck starts returning 503 — readiness probe fails, pod is removed from Service endpoints.
server.waitBeforeShutdownelapses — in-flight requests drain.- HTTP server calls
Shutdown. server.waitAfterShutdownelapses — lets kube-proxy/Envoy close lingering TCP connections.- Process exits.
Set terminationGracePeriodSeconds >= waitBeforeShutdown + waitAfterShutdown + server.maxTimeout. 180s is a safe default for most workloads.
Prometheus scraping. The pod template carries annotations and a PodMonitor (monitoring.coreos.com/v1) is created in the erpc namespace:
# Pod annotations (kube/erpc.yml:L20-L23)
prometheus.io/scrape: "true"
prometheus.io/port: "4001"
prometheus.io/path: "/metrics"The PodMonitor is labeled release: monitoring, targets the port named http, scrapes every 10s with a 5s timeout, and matches pods labeled app: erpc.
Probes. The /healthcheck HTTP endpoint drives all three probe types. See Healthcheck for the full evaluation strategy.
startupProbe:
httpGet:
path: /healthcheck
port: 4000
initialDelaySeconds: 10
periodSeconds: 10
failureThreshold: 6 # 60s window to absorb slow upstream init
readinessProbe:
httpGet:
path: /healthcheck
port: 4000
periodSeconds: 5
failureThreshold: 2 # removed from endpoints after ~10s
livenessProbe:
tcpSocket:
port: 4000
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3After SIGTERM, the readiness probe fails immediately by design, signalling the orchestrator to drain traffic before the in-flight drain completes.
Config schema
No erpc.yaml fields are specific to the Kubernetes deployment layer. The following env vars are relevant in the pod spec:
| Variable | Recommended value | Notes |
|---|---|---|
GOMEMLIMIT | 90% of resources.limits.memory (e.g. 2700MiB for 3Gi) | Not set in reference manifest; absence risks OOM kill at container limit |
GOGC | 40 | Lower GC target reduces heap swings; pair with GOMEMLIMIT |
POD_NAME | Downward API metadata.name | Used for shared-state lock ownership; resolution order: INSTANCE_ID → POD_NAME → HOSTNAME → random UUID |
LOG_LEVEL | info or warn | trace is extremely verbose at high RPC traffic; can saturate log shippers |
LOG_WRITER | console | If set to "console", switches to a zerolog console writer with 04:05.000ms time format; default is JSON structured output |
CLI subcommands available in the container binary (cmd/erpc/main.go (opens in a new tab)):
| Subcommand | Purpose |
|---|---|
erpc start (or erpc [config]) | Start the server |
erpc validate [--format json|md] | Parse config, run validation report, exit non-zero on errors — useful in CI pre-deploy checks |
erpc dump [--format yaml|json] | Parse config and dump the resolved effective config (including selection policy expansion) to stdout |
Reference resource specs from the kube manifest (the only code-grounded recommendations):
| Resource | Requests | Limits |
|---|---|---|
| eRPC pod | 3Gi memory, 2 CPU | 3Gi memory, 2 CPU |
| PostgreSQL pod | 8Gi memory, 4 CPU | 8Gi memory, 4 CPU |
| PostgreSQL PVC | — | 500Gi |
Worked examples
1. Minimal production Deployment patch. Add GOMEMLIMIT, remove the CPU limit to avoid CFS throttling, and wire the Downward API for POD_NAME:
env:
- name: GOMEMLIMIT
value: "2700MiB"
- name: GOGC
value: "40"
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
resources:
requests:
memory: "3Gi"
cpu: "2"
limits:
memory: "3Gi"
# no cpu limit — avoids CFS throttling on Go goroutines2. Graceful drain tuning for a 30s maxTimeout. Set these in erpc.yaml and match terminationGracePeriodSeconds in the pod spec:
# erpc.yaml (inside ConfigMap)
server:
waitBeforeShutdown: 30s
waitAfterShutdown: 30s# Deployment pod spec
terminationGracePeriodSeconds: 18030s drain + 30s TCP teardown + 30s max request timeout + buffer = 180s is safe for most workloads.
3. Triggering a config reload. After updating the ConfigMap with a new erpc.yaml, restart the Deployment — ConfigMap edits alone are not detected at runtime:
kubectl apply -f kube/erpc.yml
kubectl rollout restart deployment/erpc -n erpc
kubectl rollout status deployment/erpc -n erpc4. Horizontal scaling. eRPC has no replica-count constraint. Scale freely — no sticky sessions, no leader election needed for the proxy path:
kubectl scale deployment/erpc --replicas=5 -n erpcBest practices
- Set
GOMEMLIMIT=2700MiB(or 90% of your memory limit) as a container env var. The reference manifest omits it — without it, Go's GC may allow the heap to reach the hard 3 Gi limit and trigger an OOM kill instead of a managed GC cycle. - Remove
resources.limits.cpu. Go's work-stealing scheduler is sensitive to Linux CFS throttling; a hard CPU limit raises tail latency without reducing memory usage. Setresources.requests.cpufor scheduler placement but leave limits absent. - Pin the image tag. The reference manifest uses
ghcr.io/erpc/erpc:latest— pin to a specific tag or SHA for reproducible production rollouts. - Pin PostgreSQL too.
kube/postgres.ymlusespostgres:latest— pin a specific PostgreSQL version and digest for production. - Always
kubectl rollout restartafter ConfigMap changes. A ConfigMap update in place does not trigger pod restarts; traffic keeps hitting the old config until you explicitly restart. - Size
terminationGracePeriodSecondsgenerously. It must be ≥waitBeforeShutdown + waitAfterShutdown + server.maxTimeout; otherwise Kubernetes sends SIGKILL before the drain completes, dropping active requests. - Allow egress to upstream RPC endpoints. eRPC makes outbound connections on 443/TCP and 80/TCP to upstream providers, plus 5432/TCP (PostgreSQL) and 6379/TCP (Redis) for cache backends. Include these in your NetworkPolicy.
Edge cases & gotchas
- No
GOMEMLIMITin reference manifest: With3Gilimit, Go GC may trigger OOM. SetGOMEMLIMIT=2700MiB. - CPU limits cause throttling: Hard CPU limits engage Linux CFS throttling on Go goroutines, raising tail latency. Omit
resources.limits.cpu. terminationGracePeriodSecondstoo small: If shorter thanwaitBeforeShutdown + waitAfterShutdown + maxTimeout, Kubernetes sends SIGKILL before drain completes, dropping active requests.- Startup probe
initialDelaySecondstoo low: If upstreams are slow to respond at startup, the probe fails and Kubernetes restarts the pod in a loop. Use astartupProbewith generousfailureThreshold(6 × 10s = 60s window). - ConfigMap update alone does not restart pods: Run
kubectl rollout restart deployment/erpcor checksum the ConfigMap in pod template annotations to force a rolling update. - Image tag
:latestis not reproducible: Reference manifest pins:latest— operators should pin a specific tag or SHA. kube/postgres.ymlPVC isReadWriteOnce: Multi-zone clusters may fail to reschedule the pod to a different availability zone. Ensure your StorageClass supports cross-zone access or use a managed database instead.- No official Helm chart: The repository provides raw manifests under
kube/. Community-maintained charts may exist on Artifact Hub. - Network policy egress: eRPC makes outbound connections to upstream RPC endpoints (443/TCP, 80/TCP) and optional cache backends (5432/TCP PostgreSQL, 6379/TCP Redis). Allow ingress on 4000/TCP from app pods and 4001/TCP from the Prometheus scraper.
kube/postgres.ymlusespostgres:latest: Pin a specific PostgreSQL version and digest for production.- gRPC and HTTP share port 4000 by default:
server.grpcPortV4andserver.httpPortV4both default to4000. If you override the gRPC port to a different value, a second listener is bound and you must add a correspondingcontainerPortand Service port entry. The manifest only exposes 4000 and 4001. - pprof binary present but never invoked by default: The image ships
/erpc-server-pprof(built with-tags pprof) alongside the default/erpc-server. To enable profiling on port 6060, override the containercommandto/erpc-server-pprof; the defaultCMDruns the non-pprof binary.
Observability
Scraped by Prometheus via PodMonitor at 4001/metrics every 10s. Key metrics for Kubernetes-level alerting:
| Metric | Type | When it fires |
|---|---|---|
erpc_upstream_request_errors_total | counter | Every upstream request error (used in HighErrorRate alert) |
erpc_upstream_request_duration_seconds_budget | histogram | Per-upstream request duration (used in SlowRequests p95 alert) |
erpc_upstream_request_total | counter | Every upstream request; drives HighRequestRate alert (> 1000 req/s for 5 min) and LowRequestRate alert (< 1 req/s for 15 min, warning) |
erpc_upstream_request_self_rate_limited_total | counter | Upstream self-rate-limiting events |
erpc_network_request_self_rate_limited_total | counter | Network-level self-rate-limiting events |
The PodMonitor is labeled release: monitoring and must match your Prometheus Operator's serviceMonitorSelector / podMonitorSelector. [kube/erpc.yml:L145-160]
Source code entry points
kube/erpc.yml(opens in a new tab) — Namespace, Deployment, ConfigMap, Service, PodMonitorkube/postgres.yml(opens in a new tab) — PVC (500Gi), Deployment, Service, Secret for PostgreSQLkube/erpc.yml:L33-L36(opens in a new tab) — reference resource sizing:3Gimemory,2CPUkube/erpc.yml:L145-L160(opens in a new tab) — PodMonitor spec (10s scrape interval, 5s timeout)kube/erpc.yml:L54-L130(opens in a new tab) — embedded ConfigMap with Arbitrum example configcmd/erpc/main.go:L72-L74(opens in a new tab) — SIGTERM graceful shutdown viasignal.NotifyContextcmd/erpc/main.go:L279-L294(opens in a new tab) — config file search order (12 paths)
Related pages
- Docker — single-container run and local compose stack with monitoring.
- Railway — one-click managed deploy.
- Healthcheck — probe strategy and evaluation logic.
- Monitoring & metrics — full metrics reference for dashboards and alerting.
- Authentication — secure the ingress before exposing the Service externally.