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:8551 → http://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) — neverstandard/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
helm install krypton-node ./deploy/helm/krypton-node -f my-values.yamlPer-role example value files ship under examples/:
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.yamlPer-role values (from the HW matrix)
| validator | rpc / L5 | seed | |
|---|---|---|---|
payloadBuilder | true | false | false |
rpc.api | eth,net,web3 | eth,net,web3,debug | eth,net,web3 |
elSyncMode | --full | --full or "" (archive) | --full |
peers.clPersistentPeers | genesis set | (empty) | (empty) |
resources.el.limits.memory | 12Gi | 24Gi | 6Gi |
resources.cl.limits.memory | 6Gi | 6Gi | 3Gi |
persistence.size | 500Gi | 1–2Ti | 100Gi |
Ports & Service exposure
| Port | Proto | Where | Exposure |
|---|---|---|---|
| 30303 | tcp+udp | EL devp2p+discovery | public — p2p Service (LoadBalancer/NodePort) |
| 26656 | tcp | CL CometBFT p2p | public — p2p Service |
| 8545 | tcp | EL JSON-RPC | internal — rpc Service (ClusterIP) |
| 26657 | tcp | CL CometBFT RPC | internal — rpc Service (ClusterIP) |
| 8551 | tcp | EL engine authrpc | in-pod only — not in any Service |
| 9001 | tcp | EL metrics | private — 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:
kubectl create configmap krypton-network \
--from-file=eth-genesis.json --from-file=spec.toml \
--from-file=kzg-trusted-setup.jsonnetworkBundle:
existingConfigMap: krypton-networkOr 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:
- 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). - Inline value (
jwt.value: <64-hex>) — keep it out of VCS. jwt.generate: true— random hex, dev/test only (regenerates on a freshhelm templatewith 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, andhelm 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
@sha256digest (images.{cl,el}.digest); all operators must pin the same digests. - Keep RPC private. The
rpcService is ClusterIP by design. Do not turn it into a public LoadBalancer — reacheth_getProofvia private ingress / VPN / WireGuard. Metrics (9001) are intentionally exposed by no Service. - Mixed-protocol P2P Service. The
p2pService publishes 30303 on both TCP and UDP in one Service; if your cloud LoadBalancer doesn't support mixed-protocol Services, split it into two. externalIPis 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, thenhelm upgrade --set externalIP=<lb-ip>.ulimit nofile 65536is 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).