Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 57 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ The **Blockchain Operator** codifies SRE operational knowledge into software. It

### Key Features

- βœ… **Intent-Based Types:** Just define the `nodeType` (e.g., `validator`, `gateway`), and the operator configures the topology, flags, and sidecars automatically.
- βœ… **GitOps Ready:** Declarative `EthereumNode` CRD.
- βœ… **The "Merge" Architecture:** Automatically deploys Geth + Prysm as sidecars with shared auth.
- βœ… **Self-Healing:** Detects configuration drift (e.g., deleted services, changed ports) and fixes it automatically.
Expand Down Expand Up @@ -50,6 +51,9 @@ graph TD
subgraph "Pod (Sidecar Pattern)"
Geth[Execution Client] <--> Prysm[Consensus Client]
Geth ---|Engine API Auth| Prysm

%% Optional Container injected only for nodeType: validator
Prysm -.->|gRPC| Validator[Validator Client (Optional)]
end
end
```
Expand All @@ -76,44 +80,81 @@ helm install blockchain-operator ./deploy/charts/blockchain-operator \

```

### Usage: Deploying your First Node
## Usage: Node Types

The operator supports 4 distinct node types optimized for different use cases. You don't need to manually configure flags; just pick a type!

| Type | Description | Implications |
|-----------|-----------------------------------------------------------------------------|------------------------------------------------------------------------------|
| `full` | A standard node that maintains current state and verifies blocks. | Uses `snap` sync. Optimized for keeping up with the head of the chain. |
| `archive` | An archive node that retains all historical state data for querying the past. | Uses `archive` sync and GC mode. **Requires significantly more storage.** |
| `validator`| A node that participates in Proof-of-Stake consensus by validating blocks. | Uses `snap` sync. **Automatically injects the Validator Client sidecar.** |
| `gateway` | A node optimized for high-volume JSON-RPC traffic. | Uses `snap` sync. Tunes API limits and resource allocation for serving dApps.|


### Example 1: Deploying a Full Node

Once the operator is running, deploying a full node is as simple as applying this manifest:

```
``` yaml
apiVersion: infra.blockchain.corp/v1
kind: EthereumNode
metadata:
name: ethereumnode-sample
name: my-full-node
namespace: blockchain-operator-system
spec:
# Network Configuration
# Here is the magic: we only define the INTENTION of the node.
# The operator will automatically set up Geth (snap) + Prysm.
nodeType: full

# Choose the network: mainnet, sepolia, or holesky
network: "sepolia"
syncMode: "snap"

# Number of replicas (Pods)
replicas: 1

# Storage (NVMe/SSD recommended)
# Disk size.
# For a Full Node on Sepolia or Mainnet, I recommend at least 500Gi of SSD/NVMe.
storageSize: "500Gi"

# Performance Tuning
# Checkpoint Sync: Essential for the node to become "Ready" in minutes, not days.
# This endpoint is public and reliable for the Sepolia network.
checkpointSyncURL: "https://sepolia.beaconstate.info"

# Recommended resources for a stable Full Node
resources:
requests:
cpu: "2000m"
memory: "4Gi"
cpu: "2000m" # 2 vCPUs guaranteed
memory: "4Gi" # 4GB RAM guaranteed
limits:
cpu: "4000m"
memory: "8Gi"

# Instant Sync (Checkpoint)
checkpointSyncURL: "[https://sepolia.beaconstate.info](https://sepolia.beaconstate.info)"

cpu: "4000m" # Up to 4 vCPUs at peak
memory: "8Gi" # Up to 8GB RAM at peak
```

Apply it:

```
``` bash
kubectl apply -f config/samples/infra_v1_ethereumnode.yaml
```

### Example 2: Deploying a Validator Node

Automatically injects the Validator Client sidecar. Requires a secret named <node-name>-validator-keys with your keystores.

``` yaml
apiVersion: infra.blockchain.corp/v1
kind: EthereumNode
metadata:
name: my-validator
namespace: blockchain-operator-system
spec:
nodeType: validator
network: "sepolia"
replicas: 1
storageSize: "500Gi"
checkpointSyncURL: "[https://sepolia.beaconstate.info](https://sepolia.beaconstate.info)"

# Ensure you created the secret 'my-validator-validator-keys' beforehand!
```

## πŸ›  Technical Deep Dive (For Engineers)
Expand Down
31 changes: 27 additions & 4 deletions api/v1/ethereumnode_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,39 @@
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// NodeType defines the role and purpose of the Ethereum node.
// The operator infers specific configurations (like syncMode, sidecars, and API limits) based on this type.
// The possible values are:
// - full: A standard node that maintains current state and verifies blocks (implies syncMode: snap).
// - archive: A node that retains all historical state data for querying the past (implies syncMode: archive).
// - validator: A node that participates in Proof-of-Stake consensus (auto-injects the Validator Client sidecar).
// - gateway: A node optimized for high-volume JSON-RPC traffic (implies tuned API limits for dApps).
// +kubebuilder:validation:Enum=full;archive;validator;gateway
type NodeType string

const (
NodeTypeFull NodeType = "full"
NodeTypeArchive NodeType = "archive"
NodeTypeValidator NodeType = "validator"
NodeTypeGateway NodeType = "gateway"
)

// EthereumNodeSpec defines the desired state of EthereumNode
type EthereumNodeSpec struct {
// NodeType defines the type of Ethereum node.
// It determines the node's role and configuration.
// Possible values: full, archive, validator, gateway.
// +kubebuilder:validation:Enum=full;archive;validator;gateway
// +kubebuilder:default=full
NodeType NodeType `json:"nodeType"`

// Network defines the blockchain network (e.g., mainnet, sepolia).
// +kubebuilder:validation:Enum=mainnet;sepolia;holesky
Network string `json:"network"`

// SyncMode defines the synchronization strategy.
// +kubebuilder:validation:Enum=snap;full;archive
// +kubebuilder:default=snap
SyncMode string `json:"syncMode"`
// SyncMode is optional. If it's not set, the operator infers the synchronization strategy based on the NodeType.
// +optional
SyncMode string `json:"syncMode,omitempty"`

// Replicas defines how many nodes of this type we want.
// +kubebuilder:validation:Minimum=1
Expand Down Expand Up @@ -51,8 +74,8 @@
Conditions []metav1.Condition `json:"conditions,omitempty"`
}

//+kubebuilder:object:root=true

Check failure on line 77 in api/v1/ethereumnode_types.go

View workflow job for this annotation

GitHub Actions / Run on Ubuntu

comment-spacings: no space between comment delimiter and comment text (revive)

Check failure on line 77 in api/v1/ethereumnode_types.go

View workflow job for this annotation

GitHub Actions / Run on Ubuntu

comment-spacings: no space between comment delimiter and comment text (revive)
//+kubebuilder:subresource:status

Check failure on line 78 in api/v1/ethereumnode_types.go

View workflow job for this annotation

GitHub Actions / Run on Ubuntu

comment-spacings: no space between comment delimiter and comment text (revive)

Check failure on line 78 in api/v1/ethereumnode_types.go

View workflow job for this annotation

GitHub Actions / Run on Ubuntu

comment-spacings: no space between comment delimiter and comment text (revive)

// EthereumNode is the Schema for the ethereumnodes API
type EthereumNode struct {
Expand All @@ -63,7 +86,7 @@
Status EthereumNodeStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true

Check failure on line 89 in api/v1/ethereumnode_types.go

View workflow job for this annotation

GitHub Actions / Run on Ubuntu

comment-spacings: no space between comment delimiter and comment text (revive)

Check failure on line 89 in api/v1/ethereumnode_types.go

View workflow job for this annotation

GitHub Actions / Run on Ubuntu

comment-spacings: no space between comment delimiter and comment text (revive)

// EthereumNodeList contains a list of EthereumNode
type EthereumNodeList struct {
Expand Down
3 changes: 2 additions & 1 deletion api/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 21 additions & 7 deletions config/crd/bases/infra.blockchain.corp_ethereumnodes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,24 @@ spec:
- sepolia
- holesky
type: string
nodeType:
allOf:
- enum:
- full
- archive
- validator
- gateway
- enum:
- full
- archive
- validator
- gateway
default: full
description: |-
NodeType defines the type of Ethereum node.
It determines the node's role and configuration.
Possible values: full, archive, validator, gateway.
type: string
replicas:
default: 1
description: Replicas defines how many nodes of this type we want.
Expand Down Expand Up @@ -131,17 +149,13 @@ spec:
description: 'StorageSize defines the disk size. E.g.: "500Gi"'
type: string
syncMode:
default: snap
description: SyncMode defines the synchronization strategy.
enum:
- snap
- full
- archive
description: SyncMode is optional. If it's not set, the operator infers
the synchronization strategy based on the NodeType.
type: string
required:
- network
- nodeType
- replicas
- syncMode
type: object
status:
description: EthereumNodeStatus defines the observed state of EthereumNode
Expand Down
2 changes: 1 addition & 1 deletion config/manager/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ kind: Kustomization
images:
- name: controller
newName: blockchain-operator
newTag: v1
newTag: v2
1 change: 1 addition & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ rules:
- apiGroups:
- ""
resources:
- secrets
- services
verbs:
- create
Expand Down
25 changes: 25 additions & 0 deletions examples/archive-node.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
apiVersion: infra.blockchain.corp/v1
kind: EthereumNode
metadata:
name: my-archive-node
namespace: blockchain-operator-system
spec:
# Define that this node should keep the full history
nodeType: archive

network: "sepolia"
replicas: 1

# Archive nodes occupy A LOT of space.
# For Mainnet, more than 2TB would be needed. For Sepolia, 1TB is safe to start.
storageSize: "1Ti"

checkpointSyncURL: "https://sepolia.beaconstate.info"

resources:
requests:
cpu: "4000m" # Archive demands more processing for heavy queries
memory: "8Gi"
limits:
cpu: "6000m"
memory: "16Gi"
32 changes: 32 additions & 0 deletions examples/full-node.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
apiVersion: infra.blockchain.corp/v1
kind: EthereumNode
metadata:
name: my-full-node
namespace: blockchain-operator-system
spec:
# Here is the magic: we only define the INTENTION of the node.
# The operator will automatically set up Geth (snap) + Prysm.
nodeType: full

# Choose the network: mainnet, sepolia, or holesky
network: "sepolia"

# Number of replicas (Pods)
replicas: 1

# Disk size.
# For a Full Node on Sepolia or Mainnet, I recommend at least 500Gi of SSD/NVMe.
storageSize: "500Gi"

# Checkpoint Sync: Essential for the node to become "Ready" in minutes, not days.
# This endpoint is public and reliable for the Sepolia network.
checkpointSyncURL: "https://sepolia.beaconstate.info"

# Recommended resources for a stable Full Node
resources:
requests:
cpu: "2000m" # 2 vCPUs guaranteed
memory: "4Gi" # 4GB RAM guaranteed
limits:
cpu: "4000m" # Up to 4 vCPUs at peak
memory: "8Gi" # Up to 8GB RAM at peak
24 changes: 24 additions & 0 deletions examples/gateway-node.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apiVersion: infra.blockchain.corp/v1
kind: EthereumNode
metadata:
name: my-gateway-node
namespace: blockchain-operator-system
spec:
# Define that it is a node optimized for public/private RPC
nodeType: gateway

network: "sepolia"

# Gateways usually run in HA (High Availability)
replicas: 2

storageSize: "500Gi"
checkpointSyncURL: "https://sepolia.beaconstate.info"

resources:
requests:
cpu: "4000m"
memory: "8Gi"
limits:
cpu: "8000m"
memory: "16Gi" # More RAM for caching RPC responses
22 changes: 22 additions & 0 deletions examples/validator-node.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
apiVersion: infra.blockchain.corp/v1
kind: EthereumNode
metadata:
name: my-validator-node
namespace: blockchain-operator-system
spec:
# The operator will inject the 'validator-client' container and mount the secret
nodeType: validator

network: "sepolia"
replicas: 1

storageSize: "500Gi"
checkpointSyncURL: "https://sepolia.beaconstate.info"

resources:
requests:
cpu: "2500m" # A bit more CPU as it runs 3 containers
memory: "5Gi"
limits:
cpu: "5000m"
memory: "10Gi"
Loading
Loading