diff --git a/.github/ct.yaml b/.github/ct.yaml index 13ab7ac5..91e0a02e 100644 --- a/.github/ct.yaml +++ b/.github/ct.yaml @@ -13,3 +13,4 @@ check-version-increment: true validate-chart-schema: true validate-maintainers: true validate-yaml: true +helm-extra-args: --timeout 600s diff --git a/dysnix/arbitrum/Chart.yaml b/dysnix/arbitrum/Chart.yaml new file mode 100644 index 00000000..e3073ad1 --- /dev/null +++ b/dysnix/arbitrum/Chart.yaml @@ -0,0 +1,20 @@ +apiVersion: v2 +name: arbitrum +description: Arbitrum nitro-node Helm Chart + +version: 0.1.0 +appVersion: v2.3.0-3e14543 + +keywords: + - rollup + - arbitrum + - nitro + - cryptocurrency + - blockchain + +sources: + - https://github.com/dysnix/charts + +maintainers: + - name: VladStarr + email: vlad.derigin@dysnix.com diff --git a/dysnix/arbitrum/ci/ct-values.yaml b/dysnix/arbitrum/ci/ct-values.yaml new file mode 100644 index 00000000..5f96b702 --- /dev/null +++ b/dysnix/arbitrum/ci/ct-values.yaml @@ -0,0 +1,15 @@ +readinessProbe: + enabled: false + +livenessProbe: + enabled: false + +config: + init: + empty: true + url: "" + parent-chain: + connection: + url: https://ethereum-rpc.publicnode.com + blob-client: + beacon-url: https://ethereum-beacon-api.publicnode.com diff --git a/dysnix/arbitrum/templates/NOTES.txt b/dysnix/arbitrum/templates/NOTES.txt new file mode 100644 index 00000000..691bbd57 --- /dev/null +++ b/dysnix/arbitrum/templates/NOTES.txt @@ -0,0 +1,12 @@ +arbitrum RPC can be accessed via port {{ .Values.config.http.port }} on the following DNS name from within your cluster: +{{ template "arbitrum.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + +To connect to arbitrum RPC: + +1. Forward the port for the node: + + $ kubectl port-forward --namespace {{ .Release.Namespace }} $(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath='{ .items[0].metadata.name }') {{ .Values.config.http.port }} + +2. Try basic RPC method: + + $ curl -X POST http://localhost:{{ .Values.config.http.port }} --data '{"jsonrpc":"2.0","method":"net_version","params":[],"id":1}' diff --git a/dysnix/arbitrum/templates/_helpers.tpl b/dysnix/arbitrum/templates/_helpers.tpl new file mode 100644 index 00000000..b6b97529 --- /dev/null +++ b/dysnix/arbitrum/templates/_helpers.tpl @@ -0,0 +1,76 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "arbitrum.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "arbitrum.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "arbitrum.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "arbitrum.labels" -}} +helm.sh/chart: {{ include "arbitrum.chart" . }} +{{ include "arbitrum.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "arbitrum.selectorLabels" -}} +app.kubernetes.io/name: {{ include "arbitrum.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "arbitrum.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "arbitrum.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{- define "arbitrum.healthcheck" -}} +{{- $context := index . 0 }} +{{- $root := index . 1 }} +{{- if and $root.exec (kindIs "string" $root.exec.command) }} +{{- omit $root "enabled" "exec" | toYaml }} +exec: + command: + {{- tpl $root.exec.command $context | nindent 4 }} +{{- else }} +{{- omit $root "enabled" | toYaml }} +{{- end }} +{{- end }} diff --git a/dysnix/arbitrum/templates/configmap-scripts.yaml b/dysnix/arbitrum/templates/configmap-scripts.yaml new file mode 100644 index 00000000..49efd3d1 --- /dev/null +++ b/dysnix/arbitrum/templates/configmap-scripts.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "arbitrum.fullname" . }}-scripts + labels: + {{- include "arbitrum.labels" . | nindent 4 }} +data: + readiness.sh: |- + {{- include (print $.Template.BasePath "/scripts/_readiness.tpl") . | nindent 4 }} + liveness.sh: |- + {{- include (print $.Template.BasePath "/scripts/_liveness.tpl") . | nindent 4 }} + {{- if or .Values.syncToS3.enabled .Values.initFromS3.enabled }} + init-from-s3.sh: |- + {{- include (print $.Template.BasePath "/scripts/_init-from-s3.tpl") . | nindent 4 }} + sync-to-s3.sh: |- + {{- include (print $.Template.BasePath "/scripts/_sync-to-s3.tpl") . | nindent 4 }} + s3-env.sh: |- + {{- include (print $.Template.BasePath "/scripts/_s3-env.tpl") . | nindent 4 }} + s3-cron.sh: |- + {{- include (print $.Template.BasePath "/scripts/_s3-cron.tpl") . | nindent 4 }} + {{- end }} diff --git a/dysnix/arbitrum/templates/configmap.yaml b/dysnix/arbitrum/templates/configmap.yaml new file mode 100644 index 00000000..a3663295 --- /dev/null +++ b/dysnix/arbitrum/templates/configmap.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "arbitrum.fullname" . }} + labels: + {{- include "arbitrum.labels" . | nindent 4 }} +data: + config.json: | + {{- .Values.config | toPrettyJson | replace "\\u0026" "&" | replace "\\u003c" "<" | replace "\\u003e" ">" | nindent 4 }} diff --git a/dysnix/arbitrum/templates/ingress-http.yaml b/dysnix/arbitrum/templates/ingress-http.yaml new file mode 100644 index 00000000..492c0f66 --- /dev/null +++ b/dysnix/arbitrum/templates/ingress-http.yaml @@ -0,0 +1,61 @@ +{{- if and .Values.services.rpc.enabled .Values.ingress.http.enabled -}} +{{- $fullName := include "arbitrum.fullname" . -}} +{{- $svcPort := .Values.services.rpc.httpPort -}} +{{- if and .Values.ingress.http.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.http.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.http.annotations "kubernetes.io/ingress.class" .Values.ingress.http.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }}-http + labels: + {{- include "arbitrum.labels" . | nindent 4 }} + {{- with .Values.ingress.http.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.http.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.http.className }} + {{- end }} + {{- if .Values.ingress.http.tls }} + tls: + {{- range .Values.ingress.http.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.http.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }}-rpc + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }}-rpc + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/dysnix/arbitrum/templates/ingress-ws.yaml b/dysnix/arbitrum/templates/ingress-ws.yaml new file mode 100644 index 00000000..e2ddbb37 --- /dev/null +++ b/dysnix/arbitrum/templates/ingress-ws.yaml @@ -0,0 +1,61 @@ +{{- if and .Values.services.rpc.enabled .Values.ingress.ws.enabled -}} +{{- $fullName := include "arbitrum.fullname" . -}} +{{- $svcPort := .Values.services.rpc.wsPort -}} +{{- if and .Values.ingress.ws.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.ws.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.ws.annotations "kubernetes.io/ingress.class" .Values.ingress.ws.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }}-ws + labels: + {{- include "arbitrum.labels" . | nindent 4 }} + {{- with .Values.ingress.ws.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.ws.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.ws.className }} + {{- end }} + {{- if .Values.ingress.ws.tls }} + tls: + {{- range .Values.ingress.ws.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.ws.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }}-rpc + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }}-rpc + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/dysnix/arbitrum/templates/rbac.yaml b/dysnix/arbitrum/templates/rbac.yaml new file mode 100644 index 00000000..ad649409 --- /dev/null +++ b/dysnix/arbitrum/templates/rbac.yaml @@ -0,0 +1,31 @@ +{{- if and .Values.syncToS3.enabled .Values.serviceAccount.create }} +{{- $fullName := include "arbitrum.fullname" . }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ $fullName }} + labels: {{ include "arbitrum.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: + - configmaps + resourceNames: + - {{ $fullName }}-s3-config + verbs: + - get + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ $fullName }} + labels: {{ include "arbitrum.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ $fullName }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: {{ $fullName }} + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/dysnix/arbitrum/templates/s3-configmap.yaml b/dysnix/arbitrum/templates/s3-configmap.yaml new file mode 100644 index 00000000..a0881d7c --- /dev/null +++ b/dysnix/arbitrum/templates/s3-configmap.yaml @@ -0,0 +1,11 @@ +{{- if or .Values.initFromS3.enabled .Values.syncToS3.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "arbitrum.fullname" . }}-s3-config +data: + DATA_DIR: {{ .Values.config.persistent.chain }} + SYNC_TO_S3: "False" + S3_BASE_URL: {{ tpl .Values.s3config.baseUrl . }} + FORCE_INIT: {{ ternary "True" "False" .Values.initFromS3.force | quote }} +{{- end }} diff --git a/dysnix/arbitrum/templates/s3-cronjob-rbac.yaml b/dysnix/arbitrum/templates/s3-cronjob-rbac.yaml new file mode 100644 index 00000000..e8be5b3e --- /dev/null +++ b/dysnix/arbitrum/templates/s3-cronjob-rbac.yaml @@ -0,0 +1,45 @@ +{{- if .Values.syncToS3.cronjob.enabled -}} +{{- $fullName := print (include "arbitrum.fullname" .) "-s3-cronjob" }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ $fullName }} + labels: {{ include "arbitrum.labels" . | nindent 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ $fullName }} + labels: {{ include "arbitrum.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: + - pods + verbs: + - get + - list + - watch + - delete + - apiGroups: [""] + resources: + - configmaps + resourceNames: + - {{ include "arbitrum.fullname" . }}-s3-config + verbs: + - get + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ $fullName }} + labels: {{ include "arbitrum.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ $fullName }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: {{ $fullName }} + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/dysnix/arbitrum/templates/s3-cronjob.yaml b/dysnix/arbitrum/templates/s3-cronjob.yaml new file mode 100644 index 00000000..87e2eeb3 --- /dev/null +++ b/dysnix/arbitrum/templates/s3-cronjob.yaml @@ -0,0 +1,71 @@ +{{- if .Values.syncToS3.cronjob.enabled }} +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ include "arbitrum.fullname" . }}-sync-to-s3 + labels: + {{- include "arbitrum.labels" . | nindent 4 }} +spec: + {{- with .Values.syncToS3.cronjob }} + schedule: "{{ .schedule }}" + concurrencyPolicy: Forbid + startingDeadlineSeconds: 300 + jobTemplate: + metadata: + name: {{ include "arbitrum.fullname" $ }}-sync-to-s3 + spec: + activeDeadlineSeconds: 60 + backoffLimit: 0 + template: + metadata: + labels: + {{- include "arbitrum.labels" $ | nindent 12 }} + spec: + restartPolicy: OnFailure + {{- with .imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 12 }} + {{- end }} + serviceAccountName: {{ include "arbitrum.fullname" $ }}-s3-cronjob + {{- with .podSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .affinity }} + affinity: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .tolerations }} + tolerations: + {{- toYaml . | nindent 12 }} + {{- end }} + containers: + - name: enable-sync-to-s3 + image: "{{ .image.repository }}:{{ .image.tag }}" + imagePullPolicy: {{ .image.pullPolicy | quote }} + {{- with .securityContext }} + securityContext: + {{- toYaml . | nindent 14 }} + {{- end }} + command: + - /bin/sh + - /scripts/s3-cron.sh + - enable_sync + - 5s + volumeMounts: + - name: scripts + mountPath: /scripts + {{- with .resources }} + resources: + {{- toYaml . | nindent 14 }} + {{- end }} + volumes: + - name: scripts + configMap: + name: {{ include "arbitrum.fullname" $ }}-scripts + {{- end }} +{{- end }} diff --git a/dysnix/arbitrum/templates/s3-secret.yaml b/dysnix/arbitrum/templates/s3-secret.yaml new file mode 100644 index 00000000..60ad9c2a --- /dev/null +++ b/dysnix/arbitrum/templates/s3-secret.yaml @@ -0,0 +1,14 @@ +{{- if or .Values.initFromS3.enabled .Values.syncToS3.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "arbitrum.fullname" . }}-s3-secret +data: + {{- with .Values.s3config }} + {{- if .endpointUrl }} + S3_ENDPOINT_URL: {{ .endpointUrl | toString | b64enc }} + {{- end }} + AWS_ACCESS_KEY_ID: {{ .accessKeyId | toString | b64enc }} + AWS_SECRET_ACCESS_KEY: {{ .secretAccessKey | toString | b64enc }} + {{- end }} +{{- end }} diff --git a/dysnix/arbitrum/templates/scripts/_init-from-s3.tpl b/dysnix/arbitrum/templates/scripts/_init-from-s3.tpl new file mode 100644 index 00000000..d36892b4 --- /dev/null +++ b/dysnix/arbitrum/templates/scripts/_init-from-s3.tpl @@ -0,0 +1,85 @@ +#!/usr/bin/env sh +# shellcheck disable=SC2086,SC3037 + +set -e + +. /scripts/s3-env.sh + +process_inputs() { + # download even if already initialized + if [ "$FORCE_INIT" = "True" ]; then + echo "Force init enabled, existing data will be deleted." + rm -f "$INITIALIZED_FILE" + fi + # check for S3 credentials + if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then + echo "S3 credentials are not provided, exiting"; exit 1 + fi +} + +progress() { + remote_stats=$("$S5CMD" cat "s3://${STATS_URL}") + case $1 in + "start") + while true; do + inodes=$(df -Phi "$DATA_DIR" | tail -n 1 | awk '{print $3}') + size=$(df -P -BG "$DATA_DIR" | tail -n 1 | awk '{print $3}')G + echo -e "$(date -Iseconds) | SOURCE TOTAL ${remote_stats} | DST USED Inodes:\t${inodes} Size:\t${size}" + sleep 2 + done & + progress_pid=$! ;; + "stop") + kill "$progress_pid" + progress_pid=0 ;; + "*") + echo "Unknown arg" ;; + esac +} + +check_lockfile() { + if "$S5CMD" cat "s3://${LOCKFILE_URL}" >/dev/null 2>&1; then + echo "Found existing lockfile, snapshot might be corrupted. Aborting download.." + exit 1 + fi +} + +# stop all background tasks +interrupt() { + echo "Got interrupt signal, stopping..." + for i in "$@"; do kill $i; done +} + +sync() { + # check if we are already initialized + if [ -f "$INITIALIZED_FILE" ]; then + echo "Blockchain already initialized. Exiting..." + exit 0 + fi + # s5cmd does not support "true" sync, it does not save object's timestamps + # https://github.com/peak/s5cmd/issues/532 + echo "Cleaning up local data..." + rm -rf "${DATA_DIR}" + mkdir -p "${DATA_DIR}" + + echo "Starting download data from S3..." + + # handle interruption / termination + trap 'interrupt ${progress_pid}' INT TERM + progress start + + # perform remote snapshot download and remove local objects which don't exist in snapshot + time "$S5CMD" --stat --log error sync "s3://${S3_DATA_DIR}/*" "${DATA_DIR}/" + progress stop + + # all done, mark as initialized + touch "$INITIALIZED_FILE" +} + + +main() { + process_inputs + check_lockfile + sync +} + +main \ No newline at end of file diff --git a/dysnix/arbitrum/templates/scripts/_liveness.tpl b/dysnix/arbitrum/templates/scripts/_liveness.tpl new file mode 100644 index 00000000..7903afea --- /dev/null +++ b/dysnix/arbitrum/templates/scripts/_liveness.tpl @@ -0,0 +1,52 @@ +#!/usr/bin/env sh +# shellcheck disable=SC3040 + +# Node is alive when new blocks are being imported. +# We are checking the age when last block import event occured. + +set -e + +AGE_THRESHOLD=$1 +STATE_FILE=${2:-"{{ .Values.config.persistent.chain }}/saved_block_number.txt"} +HTTP_PORT="{{ .Values.config.http.port }}" + +if [ -z "${AGE_THRESHOLD}" ] || [ -z "${STATE_FILE}" ]; then + echo "Usage: $0 [state file]" 1>&2; exit 1 +fi + + +# expected output format: 0x50938d +get_block_number() { + curl -s "http://localhost:$HTTP_PORT" \ + -H 'Content-Type: application/json' \ + -d '{"jsonrpc":"2.0","method":"eth_blockNumber","id":1}' \ + | jq -r .result +} + +# using $(()) converts hex string to number +block_number=$(($(get_block_number))) +saved_block_number="" + +if ! echo "$block_number" | grep -qE '^[0-9]+$'; then + echo "Error reading block number"; exit 1 +fi + +if [ -f "${STATE_FILE}" ]; then + saved_block_number=$(cat "${STATE_FILE}") +fi + +if [ "${block_number}" != "${saved_block_number}" ]; then + mkdir -p "$(dirname "${STATE_FILE}")" + echo "${block_number}" > "${STATE_FILE}" +fi + +current_timestamp=$(date +%s) +last_import_timestamp=$(date -r "${STATE_FILE}" +%s) + +age=$((current_timestamp - last_import_timestamp)) + +if [ $age -lt $AGE_THRESHOLD ]; then + exit 0 +else + echo "Last block import event was $age seconds ago. Threshold is $AGE_THRESHOLD seconds"; exit 1 +fi \ No newline at end of file diff --git a/dysnix/arbitrum/templates/scripts/_readiness.tpl b/dysnix/arbitrum/templates/scripts/_readiness.tpl new file mode 100644 index 00000000..0497ebaa --- /dev/null +++ b/dysnix/arbitrum/templates/scripts/_readiness.tpl @@ -0,0 +1,38 @@ +#!/usr/bin/env sh +# shellcheck disable=SC3040 + +# Node is ready when the latest block is fresh enough. +# We are checking the timestamp of the latest block and compare it to current local time. + +set -e + +HTTP_PORT="{{ .Values.config.http.port }}" +AGE_THRESHOLD=$1 + +if [ -z "$AGE_THRESHOLD" ]; then + echo "Usage: $0 "; exit 1 +fi + +# expected output format: 0x65cb8ca8 +get_block_timestamp() { + curl -s "http://localhost:$HTTP_PORT" \ + -H 'Content-Type: application/json' \ + -d '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest", false],"id":1}' \ + | jq -r .result.timestamp +} + +# using $(()) converts hex string to number +block_timestamp=$(($(get_block_timestamp))) +current_timestamp=$(date +%s) + +if ! echo "$block_timestamp" | grep -qE '^[0-9]+$'; then + echo "Error reading block timestamp"; exit 1 +fi + +age=$((current_timestamp - block_timestamp)) + +if [ $age -le $AGE_THRESHOLD ]; then + exit 0 +else + echo "Latest block is $age seconds old. Threshold is $AGE_THRESHOLD seconds" && exit 1 +fi \ No newline at end of file diff --git a/dysnix/arbitrum/templates/scripts/_s3-cron.tpl b/dysnix/arbitrum/templates/scripts/_s3-cron.tpl new file mode 100644 index 00000000..83ae67d4 --- /dev/null +++ b/dysnix/arbitrum/templates/scripts/_s3-cron.tpl @@ -0,0 +1,81 @@ +#!/usr/bin/env sh +# shellcheck disable=SC1083 + +MODE="$1" +WAIT_TIMEOUT="$2" +CONFIGMAP_NAME={{ include "arbitrum.fullname" . }}-s3-config +KUBECTL=$(which kubectl) +PATCH_DATA="" +POD_NAME={{ include "arbitrum.fullname" . }}-0 + +check_ret(){ + ret="$1" + msg="$2" + # allow to override exit code, default value is ret + exit_code=${3:-${ret}} + if [ ! "$ret" -eq 0 ]; then + echo "$msg" + echo "return code ${ret}, exit code ${exit_code}" + exit "$exit_code" + fi +} + +check_pod_readiness() { + # wait for pod to become ready + echo "$(date -Iseconds) Waiting ${WAIT_TIMEOUT} for pod ${1} to become ready ..." + "$KUBECTL" wait --timeout="$WAIT_TIMEOUT" --for=condition=Ready pod "$1" + check_ret $? "$(date -Iseconds) Pod ${1} is not ready, nothing to do, exiting" 0 + + # ensuring pod is not terminating now + # https://github.com/kubernetes/kubernetes/issues/22839 + echo "$(date -Iseconds) Checking for pod ${1} to not terminate ..." + deletion_timestamp=$("$KUBECTL" get -o jsonpath='{.metadata.deletionTimestamp}' pod "$1") + check_ret $? "$(date -Iseconds) Cannot get pod ${1}, abort" + + [ -z "$deletion_timestamp" ] + check_ret $? "$(date -Iseconds) Pod ${1} is terminating now, try another time" 1 +} + +enable_sync() { + echo "$(date -Iseconds) Patching configmap ${CONFIGMAP_NAME} to enable sync" + PATCH_DATA='{"data":{"SYNC_TO_S3":"True"}}' +} + +disable_sync() { + echo "$(date -Iseconds) Patching configmap ${CONFIGMAP_NAME} to disable sync" + PATCH_DATA='{"data":{"SYNC_TO_S3":"False"}}' +} + +patch_configmap() { + "$KUBECTL" patch configmap "$CONFIGMAP_NAME" --type merge --patch "$PATCH_DATA" + check_ret $? "$(date -Iseconds) Fatal: cannot patch configmap ${CONFIGMAP_NAME}, abort" +} + +delete_pod() { + echo "$(date -Iseconds) Deleting pod ${1} to trigger action inside init container ..." + # delete the pod to trigger action inside init container + "$KUBECTL" delete pod "$1" --wait=false + check_ret $? "$(date -Iseconds) Fatal: cannot delete pod ${1}, abort" + echo "$(date -Iseconds) Pod ${1} deleted successfully, exiting. Check pod logs after restart." +} + +main() { + case "$MODE" in + "enable_sync") + check_pod_readiness "$POD_NAME" + enable_sync + patch_configmap + delete_pod "$POD_NAME" + ;; + # intended to be run inside initContainer after successful sync + "disable_sync") + disable_sync + patch_configmap + ;; + "*") + check_ret 1 "$(date -Iseconds) Mode value \"$MODE\" is incorrect, abort" + ;; + esac +} + +main \ No newline at end of file diff --git a/dysnix/arbitrum/templates/scripts/_s3-env.tpl b/dysnix/arbitrum/templates/scripts/_s3-env.tpl new file mode 100644 index 00000000..a67293a9 --- /dev/null +++ b/dysnix/arbitrum/templates/scripts/_s3-env.tpl @@ -0,0 +1,20 @@ +#!/usr/bin/env sh + +export S5CMD=/s5cmd + +# local directory structure config +export DATA_DIR="${DATA_DIR:-{{ .Values.config.persistent.chain }}}/nitro" +export INITIALIZED_FILE="{{ .Values.config.persistent.chain }}/.initialized" + +# s3 directory structure config +export S3_BASE_URL="${S3_BASE_URL?S3_BASE_URL not provided.}" +export S3_DATA_DIR="${S3_BASE_URL}/nitro" +export S_COMPLETED="/completed" +export S_STATS="/stats" +export S_LOCKFILE="/lockfile" +export COMPLETED_URL="${S3_BASE_URL}${S_COMPLETED}" +export LOCKFILE_URL="${S3_BASE_URL}${S_LOCKFILE}" +export STATS_URL="${S3_BASE_URL}${S_STATS}" + +# download/upload options +export FORCE_INIT="${FORCE_INIT:-False}" diff --git a/dysnix/arbitrum/templates/scripts/_sync-to-s3.tpl b/dysnix/arbitrum/templates/scripts/_sync-to-s3.tpl new file mode 100644 index 00000000..a158616e --- /dev/null +++ b/dysnix/arbitrum/templates/scripts/_sync-to-s3.tpl @@ -0,0 +1,56 @@ +#!/usr/bin/env sh +# shellcheck disable=SC2086,SC3037 + +set -e + +. /scripts/s3-env.sh + +process_inputs() { + # enable sync via env variable + if [ "$SYNC_TO_S3" != "True" ]; then + echo "Sync is not enabled in config, exiting" + exit 0 + fi + # check for S3 credentials + if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then + echo "S3 credentials are not provided, exiting" + exit 1 + fi +} + +check_recent_init() { + # if node has been initialized from snapshot <30 mins ago, skip upload + is_recent=$(find "$INITIALIZED_FILE" -type f -mmin +30 | wc -l | tr -d '[:blank:]') + + if [ -f "$INITIALIZED_FILE" ] && [ "$is_recent" -eq 0 ]; then + echo "Node has been initialized recently, skipping the upload. Exiting..."; exit 0 + fi +} + +sync() { + # add lockfile while uploading + # shellcheck disable=SC3028 + echo "${HOSTNAME} $(date +%s)" | "$S5CMD" pipe "s3://${LOCKFILE_URL}" + + # perform upload of local data and remove destination objects which don't exist locally + time "$S5CMD" --stat sync --delete "${DATA_DIR}/" "s3://${S3_DATA_DIR}/" + + # mark upload as completed + date +%s | "$S5CMD" pipe "s3://${COMPLETED_URL}" + "$S5CMD" rm "s3://${LOCKFILE_URL}" +} + +update_stats() { + inodes=$(df -Phi "${DATA_DIR}" | tail -n 1 | awk '{print $3}') + size=$(df -P -BG "${DATA_DIR}" | tail -n 1 | awk '{print $3}')G + echo -ne "Inodes:\t${inodes} Size:\t${size}" | "$S5CMD" pipe "s3://${STATS_URL}" +} + +main() { + process_inputs + check_recent_init + sync + update_stats +} + +main \ No newline at end of file diff --git a/dysnix/arbitrum/templates/service-metrics.yaml b/dysnix/arbitrum/templates/service-metrics.yaml new file mode 100644 index 00000000..61f51034 --- /dev/null +++ b/dysnix/arbitrum/templates/service-metrics.yaml @@ -0,0 +1,38 @@ +{{- with .Values.services.metrics }} +{{- if .enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "arbitrum.fullname" $ }}-metrics + {{- with .annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + service-type: metrics + {{- include "arbitrum.labels" $ | nindent 4 }} +spec: + type: {{ .type }} + {{- with .loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + {{- with .clusterIP }} + clusterIP: {{ . }} + {{- end }} + {{- with .externalTrafficPolicy }} + externalTrafficPolicy: {{ . }} + {{- end }} + {{- with .internalTrafficPolicy }} + internalTrafficPolicy: {{ . }} + {{- end }} + {{- with .publishNotReadyAddresses }} + publishNotReadyAddresses: {{ . }} + {{- end }} + ports: + - name: metrics + port: {{ .port }} + targetPort: metrics + selector: + {{- include "arbitrum.selectorLabels" $ | nindent 4 }} +{{- end }} +{{- end }} diff --git a/dysnix/arbitrum/templates/service-rpc.yaml b/dysnix/arbitrum/templates/service-rpc.yaml new file mode 100644 index 00000000..292eaf88 --- /dev/null +++ b/dysnix/arbitrum/templates/service-rpc.yaml @@ -0,0 +1,46 @@ +{{- with .Values.services.rpc }} +{{- if .enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "arbitrum.fullname" $ }}-rpc + {{- with .annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + service-type: rpc + {{- include "arbitrum.labels" $ | nindent 4 }} +spec: + type: {{ .type }} + {{- with .loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + {{- with .clusterIP }} + clusterIP: {{ . }} + {{- end }} + {{- with .externalTrafficPolicy }} + externalTrafficPolicy: {{ . }} + {{- end }} + {{- with .internalTrafficPolicy }} + internalTrafficPolicy: {{ . }} + {{- end }} + {{- with .publishNotReadyAddresses }} + publishNotReadyAddresses: {{ . }} + {{- end }} + ports: + - name: http + port: {{ .http.port }} + targetPort: http + {{- if .ws.enabled }} + - name: ws + port: {{ .ws.port }} + targetPort: ws + {{- end }} + selector: + {{- include "arbitrum.selectorLabels" $ | nindent 4 }} + {{- with $.Values.podStatusLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/dysnix/arbitrum/templates/serviceaccount.yaml b/dysnix/arbitrum/templates/serviceaccount.yaml new file mode 100644 index 00000000..ab575864 --- /dev/null +++ b/dysnix/arbitrum/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "arbitrum.serviceAccountName" . }} + labels: + {{- include "arbitrum.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/dysnix/arbitrum/templates/servicemonitor.yaml b/dysnix/arbitrum/templates/servicemonitor.yaml new file mode 100644 index 00000000..4503b9d9 --- /dev/null +++ b/dysnix/arbitrum/templates/servicemonitor.yaml @@ -0,0 +1,22 @@ +{{- if and .Values.services.metrics.enabled .Values.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "arbitrum.fullname" . }} + labels: + {{- include "arbitrum.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + service-type: metrics + {{- include "arbitrum.selectorLabels" . | nindent 6 }} + endpoints: + - port: metrics + path: /debug/metrics/prometheus + {{- with (omit .Values.serviceMonitor "enabled") }} + {{- toYaml . | nindent 6 }} + {{- end }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace | quote }} +{{- end }} diff --git a/dysnix/arbitrum/templates/statefulset.yaml b/dysnix/arbitrum/templates/statefulset.yaml new file mode 100644 index 00000000..48acf194 --- /dev/null +++ b/dysnix/arbitrum/templates/statefulset.yaml @@ -0,0 +1,235 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "arbitrum.fullname" . }} + labels: + {{- include "arbitrum.labels" . | nindent 4 }} +spec: + serviceName: {{ include "arbitrum.name" . }} + updateStrategy: + {{- toYaml .Values.updateStrategy | nindent 4 }} + selector: + matchLabels: + {{- include "arbitrum.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + checksum/scripts: {{ include (print $.Template.BasePath "/configmap-scripts.yaml") . | sha256sum }} + labels: + {{- include "arbitrum.selectorLabels" . | nindent 8 }} + {{- with .Values.podStatusLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + enableServiceLinks: {{ .Values.enableServiceLinks }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + serviceAccountName: {{ include "arbitrum.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + initContainers: + {{- if .Values.initFromS3.enabled }} + {{- with .Values.s3config }} + - name: init-from-s3 + image: "{{ .image.repository }}:{{ .image.tag }}" + imagePullPolicy: {{ .image.pullPolicy | quote }} + {{- with .securityContext }} + securityContext: + {{- toYaml . | nindent 10 }} + {{- end }} + command: + - sh + - /scripts/init-from-s3.sh + envFrom: + - configMapRef: + name: {{ include "arbitrum.fullname" $ }}-s3-config + - secretRef: + name: {{ include "arbitrum.fullname" $ }}-s3-secret + volumeMounts: + - name: scripts + mountPath: /scripts + - name: data + mountPath: {{ $.Values.config.persistent.chain }} + {{- end }} + {{- end }} + {{- if .Values.syncToS3.enabled }} + {{- with .Values.s3config }} + - name: sync-to-s3 + image: "{{ .image.repository }}:{{ .image.tag }}" + imagePullPolicy: {{ .image.pullPolicy | quote }} + {{- with .securityContext }} + securityContext: + {{- toYaml . | nindent 10 }} + {{- end }} + command: + - /bin/sh + - /scripts/sync-to-s3.sh + envFrom: + - configMapRef: + name: {{ include "arbitrum.fullname" $ }}-s3-config + - secretRef: + name: {{ include "arbitrum.fullname" $ }}-s3-secret + volumeMounts: + - name: scripts + mountPath: /scripts + - name: data + mountPath: {{ $.Values.config.persistent.chain }} + {{- end }} + {{- with .Values.syncToS3.cronjob }} + {{- if .enabled }} + - name: disable-sync-to-s3 + image: "{{ .image.repository }}:{{ .image.tag }}" + imagePullPolicy: {{ .image.pullPolicy | quote }} + {{- with .securityContext }} + securityContext: + {{- toYaml . | nindent 10 }} + {{- end }} + command: + - /bin/sh + - /scripts/s3-cron.sh + - disable_sync + - 5s + volumeMounts: + - name: scripts + mountPath: /scripts + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.extraInitContainers }} + {{- tpl (toYaml . | nindent 6) $ }} + {{- end }} + containers: + {{- with .Values.sidecarContainers }} + {{- tpl (toYaml . | nindent 6) $ }} + {{- end }} + - name: {{ include "arbitrum.name" . }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.command }} + command: + {{- tpl (toYaml .) $ | nindent 10 }} + {{- end }} + args: + {{- if .Values.config.metrics }} + - --metrics + {{- end }} + {{- if .Values.config.pprof }} + - --pprof + {{- end }} + - --conf.file=/config/config.json + {{- with .Values.extraArgs }} + {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.config.http.port }} + protocol: TCP + - name: ws + containerPort: {{ .Values.config.ws.port }} + protocol: TCP + {{- if .Values.config.metrics }} + - name: metrics + containerPort: {{ index .Values "config" "metrics-server" "port" }} + protocol: TCP + {{- end }} + {{- if .Values.config.pprof }} + - name: pprof + containerPort: {{ index .Values "config" "pprof-cfg" "port" }} + protocol: TCP + {{- end }} + {{- if .Values.livenessProbe.enabled }} + livenessProbe: + {{- include "arbitrum.healthcheck" (list $ .Values.livenessProbe) | nindent 10 }} + {{- end }} + {{- if .Values.readinessProbe.enabled }} + readinessProbe: + {{- include "arbitrum.healthcheck" (list $ .Values.readinessProbe) | nindent 10 }} + {{- end }} + {{- if .Values.startupProbe.enabled }} + startupProbe: + {{- include "arbitrum.healthcheck" (list $ .Values.startupProbe) | nindent 10 }} + {{- end }} + volumeMounts: + - name: config + mountPath: /config + - name: scripts + mountPath: /scripts + - name: data + mountPath: {{ .Values.config.persistent.chain }} + {{- if .Values.extraVolumeMounts }} + {{- range .Values.extraVolumeMounts }} + - name: {{ .name }} + mountPath: {{ tpl .mountPath $ }} + {{- end }} + {{- end }} + {{- if and .Values.config.init.url (index .Values "config" "init" "download-path") }} + - name: download + mountPath: {{ index .Values "config" "init" "download-path" }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 10 }} + volumes: + - name: config + configMap: + name: {{ include "arbitrum.fullname" . }} + - name: scripts + configMap: + name: {{ include "arbitrum.fullname" . }}-scripts + {{- if eq .Values.persistence.type "hostPath" }} + - name: data + hostPath: + path: {{ .Values.persistence.hostPath.path }} + type: {{ .Values.persistence.hostPath.type }} + {{- end }} + {{- with .Values.extraVolumes }} + {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + volumeClaimTemplates: + {{- if eq .Values.persistence.type "pvc" }} + - metadata: + name: data + labels: + {{- include "arbitrum.selectorLabels" . | nindent 8 }} + {{- with .Values.persistence.pvc.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + accessModes: + - {{ .Values.persistence.pvc.accessMode }} + {{- if .Values.persistence.pvc.storageClass }} + {{- if eq .Values.persistence.pvc.storageClass "-" }} + storageClassName: "" + {{- else }} + storageClassName: {{ .Values.persistence.pvc.storageClass | quote }} + {{- end }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.pvc.size | quote }} + {{- end }} + {{- with .Values.extraVolumeClaimTemplates }} + {{- tpl (toYaml .) $ | nindent 2 }} + {{- end }} diff --git a/dysnix/arbitrum/values.yaml b/dysnix/arbitrum/values.yaml new file mode 100644 index 00000000..e061925e --- /dev/null +++ b/dysnix/arbitrum/values.yaml @@ -0,0 +1,325 @@ +image: + repository: offchainlabs/nitro-node + pullPolicy: IfNotPresent + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +updateStrategy: + type: RollingUpdate + +## Ensure we shut down gracefully +terminationGracePeriodSeconds: 300 + +## Extra pod labels +podLabels: {} + # environment: production + +## This labels mark arbitrum node as ready to serve the traffic. +## Used as selector for RPC service together with `.Values.podLabels` and default labels. +podStatusLabels: {} + # manualstatus: in-service + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # runAsNonRoot: true + # runAsUser: 1000 + # runAsGroup: 1000 + +## By disabling we fix "Unknown config environment variable envvar=GETH_" +## Enable if your workload depends on this functionality +enableServiceLinks: false + +## Override arbitrum container command (can be templated) +command: [] + +## Extra container arguments (can be templated) +extraArgs: [] + +## Extra init containers, can be templated +extraInitContainers: [] + # - name: init + # image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + # imagePullPolicy: "{{ .Values.image.pullPolicy }}" + # args: + # - --init.then-quit + # - '--init.url={{ .Values.config.init.url }}' + # - '--init.download-path={{ index .Values "config" "init" "download-path" }}' + # - --parent-chain.connection.url=https://mock.mock + # - --parent-chain.blob-client.beacon-url=http://mock.mock + # volumeMounts: + # - name: config + # mountPath: /config + # - name: download + # mountPath: '{{ index .Values "config" "init" "download-path" }}' + +## Sidecar containers, can be templated +sidecarContainers: [] + # - name: exporter + # image: ethpandaops/ethereum-metrics-exporter:latest + # imagePullPolicy: Always + # args: + # - --execution-url=http://localhost:{{ .Values.config.http.port }} + # ports: + # - name: exporter + # containerPort: 9090 + +extraVolumeMounts: [] + # - name: download + # mountPath: '{{ index .Values "config" "init" "download-path" }}' + +extraVolumes: [] + # - name: download + # claimName: '{{ include "arbitrum.fullname" . }}-download-pvc' + +extraVolumeClaimTemplates: [] + # - metadata: + # name: download + # labels: + # app.kubernetes.io/name: arbitrum + # app.kubernetes.io/instance: arbitrum + # spec: + # accessModes: + # - ReadWriteOnce + # resources: + # requests: + # storage: 512Gi + +## Services config +services: + rpc: + enabled: true + type: ClusterIP + http: + port: 8545 + ws: + enabled: false + port: 8546 + annotations: {} + metrics: + enabled: false + type: ClusterIP + port: 6070 + annotations: {} + publishNotReadyAddresses: true + +ingress: + http: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + # cert-manager.io/cluster-issuer: letsencrypt-prod + hosts: [] + # - host: arbitrum.local + # paths: + # - path: / + # pathType: ImplementationSpecific + tls: [] + # - secretName: arbitrum-tls + # hosts: + # - arbitrum.local + ws: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + # cert-manager.io/cluster-issuer: letsencrypt-prod + hosts: + # - host: arbitrum-ws.local + # paths: + # - path: / + # pathType: ImplementationSpecific + tls: [] + # - secretName: arbitrum-ws-tls + # hosts: + # - arbitrum-ws.local + +persistence: + type: pvc + # type: hostPath + pvc: + size: 1280Gi # full node occupies ~600GB state + 500GB for snapshot download + accessMode: ReadWriteOnce + storageClass: "" # set to "-" if you want to manually create persistent volume + annotations: {} + hostPath: + path: /mnt/disks/raid0/arb + type: Directory # assume that path is already created, otherwise set to "DirectoryOrCreate" + +affinity: {} + +nodeSelector: {} + +tolerations: [] + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +# Create Prometheus Operator serviceMonitor +serviceMonitor: + enabled: false + # interval: 10s + # scrapeTimeout: 2s + # honorLabels: true + # relabelings: [] + # metricRelabelings: [] + +# .startupProbe.exec.command can also be in a templated string format +# using startupProbe we can cover cases when node is downloading initial snapshot +startupProbe: + enabled: true + periodSeconds: 5 + successThreshold: 1 + failureThreshold: 518400 + timeoutSeconds: 2 + tcpSocket: + port: http + +# .livenessProbe.exec.command can also be in a templated string format +livenessProbe: + enabled: true + initialDelaySeconds: 120 + periodSeconds: 60 + successThreshold: 1 + failureThreshold: 10 + timeoutSeconds: 10 + exec: + command: + - sh + - /scripts/liveness.sh + - "300" + +# .readinessProbe.exec.command can also be in a templated string format +readinessProbe: + enabled: true + initialDelaySeconds: 60 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 2 + timeoutSeconds: 5 + exec: + command: + - sh + - /scripts/readiness.sh + - "60" + +## Main nitro config section +config: + chain: + name: arb1 + + parent-chain: + id: 1 + blob-client: + beacon-url: http://lighthouse:5052 + connection: + url: http://geth:8545 + + persistent: + chain: /home/user/.arbitrum/arb1 + + init: + url: https://snapshot.arbitrum.foundation/arb1/nitro-pruned.tar + ## HINT: use together with extraVolumes if you want to save some space, i.e. when running on local SSDs + download-path: "" + + metrics: true + + metrics-server: + addr: 0.0.0.0 + port: 6070 + + pprof: false + + pprof-cfg: + addr: 0.0.0.0 + port: 6071 + + http: + addr: 0.0.0.0 + port: 8545 + api: ["eth", "net", "web3", "arb"] + vhosts: ["*"] + corsdomain: ["*"] + server-timeouts: + idle-timeout: 60m + read-header-timeout: 60m + read-timeout: 60m + write-timeout: 60m + + ws: + addr: 0.0.0.0 + port: 8546 + api: ["eth", "net", "web3", "arb"] + origins: ["*"] + +## S3 snapshot sync config +s3config: + image: + repository: peakcom/s5cmd + tag: v2.2.2 + pullPolicy: IfNotPresent + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + runAsNonRoot: true + capabilities: + drop: + - ALL + # Any S3-compatible object storage service should be supported, but has only been tested with GCS. + # I.e. Amazon S3, MinIO, DigitalOcean Spaces, CloudFlare R2. + # endpointUrl: https://storage.googleapis.com + endpointUrl: "" + # Assuming your S3 bucket name is `my-snapshot-bucket` and base directory name is Helm release name + baseUrl: my-snapshot-bucket/{{ .Release.Name }} + # How to create access key + # AWS S3 https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html + # GCS https://cloud.google.com/storage/docs/authentication/managing-hmackeys#create + accessKeyId: REPLACEME + secretAccessKey: REPLACEME + +initFromS3: + # enable initContainer + enabled: false + # download snapshot from S3 on every pod start + force: false + +syncToS3: + # enable initContainer (won't enable actual sync) + enabled: false + # restart pod and trigger sync to S3 inside initContainer by schedule + cronjob: + enabled: false + image: + repository: dysnix/kubectl + tag: v1.27 + pullPolicy: IfNotPresent + schedule: "0 2 * * *"