Skip to content

Commit 0535ee5

Browse files
committed
feat(network-nodes): add reliability controls
1 parent 312a1b8 commit 0535ee5

5 files changed

Lines changed: 229 additions & 1 deletion

File tree

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,5 +147,6 @@
147147
"workbench.editor.revealIfOpen": true,
148148
"workbench.fontAliasing": "auto",
149149
"workbench.tips.enabled": false,
150-
"workbench.tree.enableStickyScroll": true
150+
"workbench.tree.enableStickyScroll": true,
151+
"chatgpt.openOnStartup": false
151152
}

charts/network/charts/network-nodes/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ A Helm chart for Kubernetes
8888
| livenessProbe.periodSeconds | int | `10` | Frequency of liveness checks in seconds. |
8989
| livenessProbe.timeoutSeconds | int | `2` | Timeout in seconds before marking the probe as failed. |
9090
| nameOverride | string | `""` | Override for the short chart name used in resource naming. |
91+
| networkPolicy.annotations | object | `{}` | Additional annotations to add to the NetworkPolicy metadata. |
92+
| networkPolicy.egress | list | `[{"ports":[{"port":53,"protocol":"UDP"}],"to":[{"namespaceSelector":{},"podSelector":{"matchLabels":{"k8s-app":"kube-dns"}}}]},{"ports":[{"port":30303,"protocol":"TCP"}],"to":[{"podSelector":{"matchLabels":{"app.kubernetes.io/name":"besu-statefulset"}}}]},{"ports":[{"port":30303,"protocol":"TCP"}],"to":[{"namespaceSelector":{}}]}]` | NetworkPolicy egress rules. Leave empty to deny all egress when enabled. |
93+
| networkPolicy.enabled | bool | `false` | Create a NetworkPolicy restricting Besu pod ingress and egress. |
94+
| networkPolicy.ingress | list | `[{"from":[{"podSelector":{"matchLabels":{"app.kubernetes.io/name":"txsigner"}}},{"podSelector":{"matchLabels":{"app.kubernetes.io/name":"erpc"}}},{"podSelector":{"matchLabels":{"app.kubernetes.io/name":"blockscout-stack"}}},{"podSelector":{"matchLabels":{"app.kubernetes.io/name":"graph-node"}}},{"podSelector":{}}],"ports":[{"port":8545,"protocol":"TCP"},{"port":8546,"protocol":"TCP"},{"port":8547,"protocol":"TCP"},{"port":9545,"protocol":"TCP"}]},{"from":[{"podSelector":{"matchLabels":{"app.kubernetes.io/name":"besu-statefulset"}}}],"ports":[{"port":30303,"protocol":"TCP"}]}]` | NetworkPolicy ingress rules. Leave empty to deny all ingress when enabled. |
95+
| networkPolicy.labels | object | `{}` | Additional labels to add to the NetworkPolicy metadata. |
96+
| networkPolicy.podSelector | object | `{}` | Optional override for the default pod selector; defaults to Besu workload labels when empty. |
97+
| networkPolicy.policyTypes | list | `[]` | Policy types enforced by the NetworkPolicy. When empty, inferred from ingress/egress rules or defaults to both. |
9198
| nodeSelector | object | `{}` | |
9299
| openShiftRoute.alternateBackends | list | `[]` | Additional backend references to balance traffic across services. |
93100
| openShiftRoute.annotations | object | `{}` | |
@@ -116,6 +123,20 @@ A Helm chart for Kubernetes
116123
| podAnnotations."prometheus.io/port" | string | `"9545"` | Container port value used by Prometheus to scrape metrics. |
117124
| podAnnotations."prometheus.io/scheme" | string | `"http"` | HTTP scheme (http or https) used for metrics scraping. |
118125
| podAnnotations."prometheus.io/scrape" | string | `"true"` | Enables Prometheus scraping of the Besu metrics endpoint. |
126+
| podDisruptionBudgets.rpc | object | `{"annotations":{},"enabled":false,"labels":{},"maxUnavailable":null,"minAvailable":1,"unhealthyPodEvictionPolicy":""}` | PodDisruptionBudget governing RPC pods. |
127+
| podDisruptionBudgets.rpc.annotations | object | `{}` | Additional annotations applied to the RPC PodDisruptionBudget. |
128+
| podDisruptionBudgets.rpc.enabled | bool | `false` | Enable the RPC PodDisruptionBudget. |
129+
| podDisruptionBudgets.rpc.labels | object | `{}` | Additional labels applied to the RPC PodDisruptionBudget. |
130+
| podDisruptionBudgets.rpc.maxUnavailable | string | `nil` | Maximum RPC pods that can be disrupted at once. Accepts integers or percentages. |
131+
| podDisruptionBudgets.rpc.minAvailable | int | `1` | Minimum RPC pods that must remain available; ignored when maxUnavailable is set. |
132+
| podDisruptionBudgets.rpc.unhealthyPodEvictionPolicy | string | `""` | Optional unhealthy pod eviction policy (Default or AlwaysAllow). |
133+
| podDisruptionBudgets.validator | object | `{"annotations":{},"enabled":false,"labels":{},"maxUnavailable":null,"minAvailable":1,"unhealthyPodEvictionPolicy":""}` | PodDisruptionBudget controlling voluntary disruptions for validator pods. |
134+
| podDisruptionBudgets.validator.annotations | object | `{}` | Additional annotations applied to the validator PodDisruptionBudget. |
135+
| podDisruptionBudgets.validator.enabled | bool | `false` | Enable the validator PodDisruptionBudget. |
136+
| podDisruptionBudgets.validator.labels | object | `{}` | Additional labels applied to the validator PodDisruptionBudget. |
137+
| podDisruptionBudgets.validator.maxUnavailable | string | `nil` | Maximum validator pods that can be disrupted at once. Accepts integers or percentages. |
138+
| podDisruptionBudgets.validator.minAvailable | int | `1` | Minimum validator pods that must remain available; ignored when maxUnavailable is set. |
139+
| podDisruptionBudgets.validator.unhealthyPodEvictionPolicy | string | `""` | Optional unhealthy pod eviction policy (Default or AlwaysAllow). |
119140
| podLabels | object | `{}` | |
120141
| podSecurityContext | object | `{}` | |
121142
| readinessProbe | string | `nil` | |
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{{- if .Values.networkPolicy.enabled }}
2+
{{- $root := . -}}
3+
{{- $np := .Values.networkPolicy | default (dict) -}}
4+
{{- $labels := get $np "labels" | default (dict) -}}
5+
{{- $annotations := get $np "annotations" | default (dict) -}}
6+
{{- $podSelector := get $np "podSelector" | default (dict) -}}
7+
{{- $hasCustomSelector := gt (len $podSelector) 0 -}}
8+
{{- $ingress := get $np "ingress" | default (list) -}}
9+
{{- $egress := get $np "egress" | default (list) -}}
10+
{{- $policyTypes := get $np "policyTypes" | default (list) -}}
11+
{{- if not $policyTypes }}
12+
{{- if gt (len $ingress) 0 }}
13+
{{- $policyTypes = append $policyTypes "Ingress" -}}
14+
{{- end }}
15+
{{- if gt (len $egress) 0 }}
16+
{{- $policyTypes = append $policyTypes "Egress" -}}
17+
{{- end }}
18+
{{- if eq (len $policyTypes) 0 }}
19+
{{- $policyTypes = list "Ingress" "Egress" -}}
20+
{{- end }}
21+
{{- end }}
22+
---
23+
apiVersion: networking.k8s.io/v1
24+
kind: NetworkPolicy
25+
metadata:
26+
name: {{ include "nodes.fullname" $root }}
27+
labels:
28+
{{- include "nodes.labels" $root | nindent 4 }}
29+
{{- with $labels }}
30+
{{- toYaml . | nindent 4 }}
31+
{{- end }}
32+
{{- with $annotations }}
33+
annotations:
34+
{{- toYaml . | nindent 4 }}
35+
{{- end }}
36+
spec:
37+
podSelector:
38+
{{- if $hasCustomSelector }}
39+
{{- toYaml $podSelector | nindent 4 }}
40+
{{- else }}
41+
matchLabels:
42+
{{- include "nodes.selectorLabels" $root | nindent 6 }}
43+
{{- end }}
44+
policyTypes:
45+
{{- toYaml $policyTypes | nindent 4 }}
46+
{{- if gt (len $ingress) 0 }}
47+
ingress:
48+
{{- toYaml $ingress | nindent 4 }}
49+
{{- end }}
50+
{{- if gt (len $egress) 0 }}
51+
egress:
52+
{{- toYaml $egress | nindent 4 }}
53+
{{- end }}
54+
{{- end }}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{{- $root := . -}}
2+
{{- $pdbValues := .Values.podDisruptionBudgets | default (dict) -}}
3+
{{- $components := list
4+
(dict "name" "validator" "config" (default (dict) (get $pdbValues "validator")))
5+
(dict "name" "rpc" "config" (default (dict) (get $pdbValues "rpc")))
6+
-}}
7+
{{- range $component := $components }}
8+
{{- $cfg := $component.config -}}
9+
{{- if and $cfg (get $cfg "enabled") }}
10+
{{- $minRaw := get $cfg "minAvailable" -}}
11+
{{- $hasMin := and (hasKey $cfg "minAvailable") (ne $minRaw nil) (not (and (kindIs "string" $minRaw) (eq $minRaw ""))) -}}
12+
{{- $maxRaw := get $cfg "maxUnavailable" -}}
13+
{{- $hasMax := and (hasKey $cfg "maxUnavailable") (ne $maxRaw nil) (not (and (kindIs "string" $maxRaw) (eq $maxRaw ""))) -}}
14+
{{- if not (or $hasMin $hasMax) }}
15+
{{- fail (printf "podDisruptionBudgets.%s requires minAvailable or maxUnavailable" $component.name) -}}
16+
{{- end }}
17+
---
18+
apiVersion: policy/v1
19+
kind: PodDisruptionBudget
20+
metadata:
21+
name: {{ include "nodes.fullname" $root }}-{{ $component.name }}
22+
labels:
23+
{{- include "nodes.labels" $root | nindent 4 }}
24+
app.kubernetes.io/component: {{ $component.name }}
25+
{{- with (get $cfg "labels") }}
26+
{{- toYaml . | nindent 4 }}
27+
{{- end }}
28+
{{- with (get $cfg "annotations") }}
29+
annotations:
30+
{{- toYaml . | nindent 4 }}
31+
{{- end }}
32+
spec:
33+
{{- if $hasMin }}
34+
minAvailable: {{ $minRaw }}
35+
{{- end }}
36+
{{- if $hasMax }}
37+
maxUnavailable: {{ $maxRaw }}
38+
{{- end }}
39+
{{- $policy := get $cfg "unhealthyPodEvictionPolicy" -}}
40+
{{- if and $policy (ne $policy "") }}
41+
unhealthyPodEvictionPolicy: {{ $policy }}
42+
{{- end }}
43+
selector:
44+
matchLabels:
45+
{{- include "nodes.selectorLabels" $root | nindent 6 }}
46+
app.kubernetes.io/component: {{ $component.name }}
47+
{{- end }}
48+
{{- end }}

charts/network/charts/network-nodes/values.yaml

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,110 @@ podAnnotations:
4949
# Additional labels applied to all Besu pods.
5050
podLabels: {}
5151

52+
# PodDisruptionBudget configuration for validator and RPC workloads.
53+
podDisruptionBudgets:
54+
# -- PodDisruptionBudget controlling voluntary disruptions for validator pods.
55+
validator:
56+
# -- Enable the validator PodDisruptionBudget.
57+
enabled: false
58+
# -- Minimum validator pods that must remain available; ignored when maxUnavailable is set.
59+
minAvailable: 1
60+
# -- Maximum validator pods that can be disrupted at once. Accepts integers or percentages.
61+
maxUnavailable:
62+
# -- Optional unhealthy pod eviction policy (Default or AlwaysAllow).
63+
unhealthyPodEvictionPolicy: ""
64+
# -- Additional annotations applied to the validator PodDisruptionBudget.
65+
annotations: {}
66+
# -- Additional labels applied to the validator PodDisruptionBudget.
67+
labels: {}
68+
# -- PodDisruptionBudget governing RPC pods.
69+
rpc:
70+
# -- Enable the RPC PodDisruptionBudget.
71+
enabled: false
72+
# -- Minimum RPC pods that must remain available; ignored when maxUnavailable is set.
73+
minAvailable: 1
74+
# -- Maximum RPC pods that can be disrupted at once. Accepts integers or percentages.
75+
maxUnavailable:
76+
# -- Optional unhealthy pod eviction policy (Default or AlwaysAllow).
77+
unhealthyPodEvictionPolicy: ""
78+
# -- Additional annotations applied to the RPC PodDisruptionBudget.
79+
annotations: {}
80+
# -- Additional labels applied to the RPC PodDisruptionBudget.
81+
labels: {}
82+
83+
# NetworkPolicy configuration applied to Besu pods.
84+
networkPolicy:
85+
# -- Create a NetworkPolicy restricting Besu pod ingress and egress.
86+
enabled: false
87+
# -- Optional override for the default pod selector; defaults to Besu workload labels when empty.
88+
podSelector: {}
89+
# -- Policy types enforced by the NetworkPolicy. When empty, inferred from ingress/egress rules or defaults to both.
90+
policyTypes: []
91+
# -- Additional labels to add to the NetworkPolicy metadata.
92+
labels: {}
93+
# -- Additional annotations to add to the NetworkPolicy metadata.
94+
annotations: {}
95+
# -- NetworkPolicy ingress rules. Leave empty to deny all ingress when enabled.
96+
ingress:
97+
# Allow blockchain clients to reach RPC, WS, GraphQL, and metrics endpoints.
98+
- from:
99+
- podSelector:
100+
matchLabels:
101+
app.kubernetes.io/name: txsigner
102+
- podSelector:
103+
matchLabels:
104+
app.kubernetes.io/name: erpc
105+
- podSelector:
106+
matchLabels:
107+
app.kubernetes.io/name: blockscout-stack
108+
- podSelector:
109+
matchLabels:
110+
app.kubernetes.io/name: graph-node
111+
- podSelector: {}
112+
ports:
113+
- protocol: TCP
114+
port: 8545
115+
- protocol: TCP
116+
port: 8546
117+
- protocol: TCP
118+
port: 8547
119+
- protocol: TCP
120+
port: 9545
121+
# Permit intra-cluster P2P traffic among Besu nodes.
122+
- from:
123+
- podSelector:
124+
matchLabels:
125+
app.kubernetes.io/name: besu-statefulset
126+
ports:
127+
- protocol: TCP
128+
port: 30303
129+
130+
# -- NetworkPolicy egress rules. Leave empty to deny all egress when enabled.
131+
egress:
132+
# Allow DNS resolution for outbound hosts.
133+
- to:
134+
- namespaceSelector: {}
135+
podSelector:
136+
matchLabels:
137+
k8s-app: kube-dns
138+
ports:
139+
- protocol: UDP
140+
port: 53
141+
# Permit Besu pods to speak to peers inside the namespace.
142+
- to:
143+
- podSelector:
144+
matchLabels:
145+
app.kubernetes.io/name: besu-statefulset
146+
ports:
147+
- protocol: TCP
148+
port: 30303
149+
# Allow outbound P2P connections to external peers (public networks).
150+
- to:
151+
- namespaceSelector: {}
152+
ports:
153+
- protocol: TCP
154+
port: 30303
155+
52156
# Pod-level security context shared by all containers.
53157
podSecurityContext:
54158
{}

0 commit comments

Comments
 (0)