Skip to content

Commit ce6ecfd

Browse files
authored
Add support for exporter/indexer/explorer stack deployment (#4850)
## Motivation Deploying the exporter/indexer/explorer stack requires careful dependency ordering and runtime checks: 1. **Exporters need database to exist** before starting (ScyllaDB must be initialized) 2. **Exporters need indexer to be ready** before attempting connections 3. **Indexer image needs linera CLI** to perform database checks 4. **Configuration needs flexibility** to support both internal cluster DNS and external endpoints with TLS Without these capabilities, deployments fail with race conditions where exporters start before dependencies are ready, causing crash loops and manual intervention. ## Proposal Add comprehensive deployment support through init containers that wait for dependencies, include linera CLI in the indexer image for database checks, and make indexer endpoints configurable to support both internal and external deployments with automatic TLS handling. ## Test Plan 1. Deploy fresh network with exporter/indexer/explorer stack: - Verify ScyllaDB init container waits for database - Verify indexer readiness init container waits for indexer - Confirm exporters start only after both checks pass 2. Test with external indexer endpoint: - Configure `blockExporter.indexerEndpoint` with external URL - Verify TLS configuration is applied - Confirm connectivity works 3. Test failure scenarios: - Deploy without indexer, verify exporter init container retries indefinitely - Kill indexer, verify exporters restart and wait for it to return ## Release Plan - These changes should be backported to the latest `testnet` branch, then - be released in a validator hotfix.
1 parent 755514b commit ce6ecfd

File tree

5 files changed

+113
-7
lines changed

5 files changed

+113
-7
lines changed

docker/Dockerfile.indexer

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ ENV GIT_COMMIT=${git_commit}
7373
ENV RUSTFLAGS=${rustflags}
7474

7575

76-
# Build block exporter with scylladb and metrics features
76+
# Build linera CLI and block exporter with scylladb and metrics features
7777
RUN cargo build ${build_flag:+"$build_flag"} \
78-
-p linera-service \
78+
--bin linera \
7979
--bin linera-exporter \
8080
--features $build_features
8181

@@ -86,6 +86,7 @@ RUN cargo build ${build_flag:+"$build_flag"} \
8686

8787
# Move binaries to avoid directory conflicts and clean up to save space
8888
RUN mv \
89+
target/"$build_folder"/linera \
8990
target/"$build_folder"/linera-exporter \
9091
target/"$build_folder"/linera-indexer-grpc \
9192
./
@@ -94,6 +95,7 @@ RUN mv \
9495
FROM scratch AS builder_copy
9596
ARG binaries
9697
COPY \
98+
"$binaries"/linera \
9799
"$binaries"/linera-exporter \
98100
"$binaries"/linera-indexer-grpc \
99101
./
@@ -121,8 +123,9 @@ RUN update-ca-certificates
121123

122124
ARG target
123125

124-
# Copy only indexer and exporter binaries
126+
# Copy linera CLI, indexer and exporter binaries
125127
COPY --from=binaries \
128+
linera \
126129
linera-indexer-grpc \
127130
linera-exporter \
128131
./

kubernetes/linera-validator/Chart.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ dependencies:
1212
repository: https://grafana.github.io/helm-charts
1313
version: 1.3.1
1414
digest: sha256:295a8fc7b332a0b3c3223c2192ee1dbff016f8707760c5b4b22d76403d6d7af4
15-
generated: "2025-10-21T02:26:24.01435788+02:00"
15+
generated: "2025-10-28T00:45:17.142689-03:00"

kubernetes/linera-validator/exporter-config.toml.tpl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,15 @@ kind = "Logging"
1515

1616
[[destination_config.destinations]]
1717
kind = "Indexer"
18+
{{- if .Values.blockExporter.indexerEndpoint }}
19+
tls = "Tls"
20+
port = 443
21+
endpoint = "{{ .Values.blockExporter.indexerEndpoint }}"
22+
{{- else }}
1823
tls = "ClearText"
19-
port = {{ .Values.indexer.port }}
20-
endpoint = "linera-indexer"
24+
port = {{ .Values.blockExporter.indexerPort }}
25+
endpoint = "linera-indexer-{{ .Values.networkName }}.linera-indexer.svc.cluster.local"
26+
{{- end }}
2127

2228
[limits]
2329
persistence_period_ms = 299000

kubernetes/linera-validator/templates/block-exporter.yaml

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,44 @@ spec:
4949
effect: NoSchedule
5050
{{- end }}
5151
initContainers:
52+
- name: linera-exporter-initializer
53+
image: {{ .Values.indexer.image }}
54+
imagePullPolicy: {{ .Values.indexer.imagePullPolicy }}
55+
securityContext:
56+
runAsNonRoot: true
57+
runAsUser: 65534
58+
allowPrivilegeEscalation: false
59+
capabilities:
60+
drop:
61+
- ALL
62+
resources:
63+
requests:
64+
memory: "64Mi"
65+
cpu: "50m"
66+
limits:
67+
memory: "128Mi"
68+
cpu: "100m"
69+
command:
70+
- sh
71+
- -c
72+
- |
73+
set -euo pipefail
74+
while true; do
75+
output=$(./linera storage check-existence --storage "{{ .Values.storage }}" 2>&1)
76+
status=$?
77+
if [ "$status" -eq 0 ]; then
78+
echo "Database already exists, no need to initialize."
79+
exit 0
80+
else
81+
if [ "$status" -eq 1 ]; then
82+
echo "Database does not exist, retrying in {{ .Values.blockExporter.initRetryIntervalSeconds | default 5 }} seconds..."
83+
else
84+
echo "An unexpected error occurred (status: $status): $output"
85+
echo "Retrying in {{ .Values.blockExporter.initRetryIntervalSeconds | default 5 }} seconds..."
86+
fi
87+
sleep {{ .Values.blockExporter.initRetryIntervalSeconds | default 5 }}
88+
fi
89+
done
5290
- name: config-selector
5391
image: busybox
5492
command:
@@ -62,6 +100,65 @@ spec:
62100
mountPath: /configmap
63101
- name: config
64102
mountPath: /config
103+
- name: indexer-readiness-check
104+
image: curlimages/curl:latest
105+
securityContext:
106+
runAsNonRoot: true
107+
runAsUser: 65534
108+
allowPrivilegeEscalation: false
109+
readOnlyRootFilesystem: true
110+
capabilities:
111+
drop:
112+
- ALL
113+
resources:
114+
requests:
115+
memory: "32Mi"
116+
cpu: "25m"
117+
limits:
118+
memory: "64Mi"
119+
cpu: "50m"
120+
env:
121+
- name: INDEXER_ENDPOINT
122+
value: {{ if .Values.blockExporter.indexerEndpoint }}"{{ .Values.blockExporter.indexerEndpoint }}"{{ else }}"linera-indexer-{{ .Values.networkName }}.linera-indexer.svc.cluster.local"{{ end }}
123+
- name: INDEXER_PORT
124+
value: {{ if .Values.blockExporter.indexerEndpoint }}"443"{{ else }}"{{ .Values.blockExporter.indexerPort }}"{{ end }}
125+
- name: INDEXER_TLS
126+
value: {{ if .Values.blockExporter.indexerEndpoint }}"true"{{ else }}"false"{{ end }}
127+
command:
128+
- sh
129+
- -c
130+
- |
131+
set -euo pipefail
132+
# Validate extracted values
133+
if [ -z "$INDEXER_ENDPOINT" ] || [ -z "$INDEXER_PORT" ]; then
134+
echo "Error: INDEXER_ENDPOINT or INDEXER_PORT is empty"
135+
exit 1
136+
fi
137+
138+
if [ "$INDEXER_TLS" = "true" ]; then
139+
INDEXER_URL="https://${INDEXER_ENDPOINT}:${INDEXER_PORT}"
140+
else
141+
INDEXER_URL="http://${INDEXER_ENDPOINT}:${INDEXER_PORT}"
142+
fi
143+
144+
echo "Checking indexer readiness at ${INDEXER_URL}..."
145+
146+
while true; do
147+
# Try to connect to the indexer (just check if it's listening)
148+
# Using --insecure for init container readiness check only
149+
# This is acceptable because:
150+
# 1. Only checking if service is reachable, not exchanging sensitive data
151+
# 2. External endpoints may use self-signed certs in dev/staging
152+
# 3. Actual exporter traffic uses proper TLS validation
153+
if curl --max-time 5 --connect-timeout 5 --silent --fail --insecure "${INDEXER_URL}" > /dev/null 2>&1 || \
154+
curl --max-time 5 --connect-timeout 5 --silent --head --insecure "${INDEXER_URL}" > /dev/null 2>&1; then
155+
echo "Indexer is reachable, exporter can start."
156+
exit 0
157+
else
158+
echo "Indexer not ready yet, retrying in {{ .Values.blockExporter.initRetryIntervalSeconds | default 5 }} seconds..."
159+
sleep {{ .Values.blockExporter.initRetryIntervalSeconds | default 5 }}
160+
fi
161+
done
65162
containers:
66163
- name: linera-block-exporter
67164
image: {{ .Values.indexer.image }}

kubernetes/linera-validator/templates/proxy.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ spec:
1616
name: metrics
1717
selector:
1818
app: proxy
19-
clusterIp: None
19+
clusterIP: None
2020

2121
---
2222
apiVersion: v1

0 commit comments

Comments
 (0)