Skip to content

Kubernetes (Helm)

The krypton-node Helm chart runs a Krypton L1 node on Kubernetes — one StatefulSet pod with two containers: EL (bera-reth, fee-router patched) + CL (beacond, epoch-mint patched), wired by the Engine API. It is a faithful port of the proven from-source/deploy/docker-compose.yml; every EL/CL command flag is copied verbatim, and only the EL engine dial URL changes (http://el:8551http://127.0.0.1:8551, since both containers share the pod). Role-aware (validator | rpc | seed) for the public testnet (chain-id 473374).

The Testnet deployment manual and the node-operator guides are the authoritative source for roles, the HW matrix, networking, and key management.

Prerequisites

  • An NVMe-backed StorageClass (persistence.storageClass). bera-reth's MDBX needs fast local NVMe / AWS gp3 (io2 for archive) — never standard / sc1 / EBS below gp3, or it corrupts/falls behind. See Hardware specs.
  • The network bundle (eth-genesis.json, spec.toml, kzg-trusted-setup.json).
  • The Engine JWT (shared by EL + CL).
  • For private images: a registry pull secret (imagePullSecrets).

Install

sh
helm install krypton-node ./deploy/helm/krypton-node -f my-values.yaml

Per-role example value files ship under examples/:

sh
helm install kry ./deploy/helm/krypton-node -f examples/validator-values.yaml
helm install kry ./deploy/helm/krypton-node -f examples/rpc-values.yaml
helm install kry ./deploy/helm/krypton-node -f examples/seed-values.yaml

Per-role values (from the HW matrix)

validatorrpc / L5seed
payloadBuildertruefalsefalse
rpc.apieth,net,web3eth,net,web3,debugeth,net,web3
elSyncMode--full--full or "" (archive)--full
peers.clPersistentPeersgenesis set(empty)(empty)
resources.el.limits.memory12Gi24Gi6Gi
resources.cl.limits.memory6Gi6Gi3Gi
persistence.size500Gi1–2Ti100Gi

Ports & Service exposure

PortProtoWhereExposure
30303tcp+udpEL devp2p+discoverypublicp2p Service (LoadBalancer/NodePort)
26656tcpCL CometBFT p2ppublicp2p Service
8545tcpEL JSON-RPCinternalrpc Service (ClusterIP)
26657tcpCL CometBFT RPCinternalrpc Service (ClusterIP)
8551tcpEL engine authrpcin-pod only — not in any Service
9001tcpEL metricsprivate — container port only, no Service

See Ports & firewall for the canonical port table.

Network bundle (the /network mount)

Two ways in. Existing ConfigMap (recommended) — avoids the ~1 MiB ConfigMap limit when bundling the large kzg-trusted-setup.json:

sh
kubectl create configmap krypton-network \
  --from-file=eth-genesis.json --from-file=spec.toml \
  --from-file=kzg-trusted-setup.json
yaml
networkBundle:
  existingConfigMap: krypton-network

Or inline the three files under networkBundle.files (fine for small test bundles). Either way, the spec must be named spec.toml (the CL reads /network/spec.toml), exactly as in the compose stack. See Genesis & the network bundle.

Engine JWT

EL and CL must share the same jwt.hex. In production-preference order:

  1. Existing Secret backed by a secret manager — sync from Vault / cloud KMS into a k8s Secret via External Secrets Operator or Vault Agent, then jwt.existingSecret: krypton-jwt. See Secrets (Vault / KMS).
  2. Inline value (jwt.value: <64-hex>) — keep it out of VCS.
  3. jwt.generate: true — random hex, dev/test only (regenerates on a fresh helm template with no cluster).

Validator key management

The validator's priv_validator_key.json lives inside the CL data at cl/config/priv_validator_key.json. The chart does not manage this key — place it into the PVC before first start (init step or kubectl cp), then restart. See Key management (Horcrux).

Double-sign hazard

Never run the same priv_validator_key.json on two nodes at once — it's slashable equivocation. replicas is fixed at 1; do not scale the StatefulSet, and fully stop a validator before migrating its key.

Honest caveats

  • Templated, helm lint-clean, and helm template-verified for all three roles — but NOT deployed to a real Kubernetes cluster. Treat the first real deploy as a bring-up: verify chain-id, peer count, sync, and INFLATION_SINK/FEE_SINK growth before trusting the node.
  • Pin images by @sha256 digest (images.{cl,el}.digest); all operators must pin the same digests.
  • Keep RPC private. The rpc Service is ClusterIP by design. Do not turn it into a public LoadBalancer — reach eth_getProof via private ingress / VPN / WireGuard. Metrics (9001) are intentionally exposed by no Service.
  • Mixed-protocol P2P Service. The p2p Service publishes 30303 on both TCP and UDP in one Service; if your cloud LoadBalancer doesn't support mixed-protocol Services, split it into two.
  • externalIP is mandatory and must be the node's reachable public address (the P2P LoadBalancer/NodePort IP). A wrong value means no inbound peers — typically install once, read the assigned external IP, then helm upgrade --set externalIP=<lb-ip>.
  • ulimit nofile 65536 is governed by the node/runtime on k8s — ensure your nodes allow it.
  • Drain order on the live network is CL-then-EL; k8s tears both down together within terminationGracePeriodSeconds (300s, covering the CL's 5m grace).

See also

Operator docs. Testnet chain-id 473374; mainnet 47337 (gated on external audit). Not financial advice.