diff --git a/charts/astrotrek/Chart.yaml b/charts/astrotrek/Chart.yaml new file mode 100644 index 0000000000..1ab1870a06 --- /dev/null +++ b/charts/astrotrek/Chart.yaml @@ -0,0 +1,27 @@ +apiVersion: v2 +name: astrotrek +description: A Helm chart for deploying a k8s sequencer explorer for the Astria Sequencer Network. + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.0.1 +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "0.0.1" + +maintainers: + - name: quasystaty1 + url: astria.org diff --git a/charts/astrotrek/templates/_helpers.tpl b/charts/astrotrek/templates/_helpers.tpl new file mode 100644 index 0000000000..997fcfb9a7 --- /dev/null +++ b/charts/astrotrek/templates/_helpers.tpl @@ -0,0 +1,18 @@ +{{/* +Namepsace to deploy elements into. +*/}} +{{- define "astrotrek.namespace" -}} +{{- default .Release.Namespace .Values.global.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end }} + +{{- define "indexer.image" -}} +{{ .Values.images.indexer.repo }}:{{ if .Values.global.dev }}{{ .Values.images.indexer.devTag }}{{ else }}{{ .Values.images.indexer.tag }}{{ end }} +{{- end }} + +{{- define "api.image" -}} +{{ .Values.images.api.repo }}:{{ if .Values.global.dev }}{{ .Values.images.api.devTag }}{{ else }}{{ .Values.images.api.tag }}{{ end }} +{{- end }} + +{{- define "frontend.image" -}} +{{ .Values.images.frontend.repo }}:{{ if .Values.global.dev }}{{ .Values.images.frontend.devTag }}{{ else }}{{ .Values.images.frontend.tag }}{{ end }} +{{- end }} diff --git a/charts/astrotrek/templates/configmap.yaml b/charts/astrotrek/templates/configmap.yaml new file mode 100644 index 0000000000..1fba3f7804 --- /dev/null +++ b/charts/astrotrek/templates/configmap.yaml @@ -0,0 +1,29 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + app: api-env + name: env +data: + API_HOST: "{{ .Values.config.api.host }}" + API_PORT: "{{ .Values.ports.api }}" + API_PROMETHEUS_ENABLED: "{{ .Values.metrics.enabled }}" + API_RATE_LIMIT: "{{ .Values.config.api.rateLimit }}" + API_REQUEST_TIMEOUT: "{{ .Values.config.api.requestTimeout }}" + ASTRIA_ENV: "{{ .Values.config.astriaEnv }}" + INDEXER_BLOCK_PERIOD: "{{ .Values.config.indexer.indexerBlockPeriod }}" + INDEXER_SCRIPTS_DIR: "{{ .Values.config.indexer.indexerScriptDir }}" + INDEXER_THREADS_COUNT: "{{ .Values.config.indexer.indexerThreadsCount }}" + INDEXER_VIEWS_DIR: "{{ .Values.config.indexer.indexerViewsDir }}" + LOG_LEVEL: "{{ .Values.config.logLevel }}" + POSTGRES_DB: "{{ .Values.config.database.postgresDb }}" + POSTGRES_HOST: "{{ .Values.config.database.postgresHost }}" + POSTGRES_PASSWORD: "{{ .Values.config.database.postgresPassword }}" + POSTGRES_PORT: "{{ .Values.ports.db}}" + POSTGRES_USER: "{{ .Values.config.database.postgresUser }}" + PROFILER_SERVER: "{{ .Values.config.profilerServer }}" + SEQUENCER_RPC_RPS: "{{ .Values.config.sequencerRpcRps }}" + SEQUENCER_RPC_TIMEOUT: "{{ .Values.config.sequencerRpcTimeout }}" + SEQUENCER_RPC_URL: "{{ .Values.config.sequencerRpcUrl }}" + NUXT_PUBLIC_API_DEV: "{{ .Values.config.frontend.rpcApiUrl }}" + NUXT_PUBLIC_WSS_DEV: "{{ .Values.config.frontend.wsApiUrl }}" diff --git a/charts/astrotrek/templates/deployment.yaml b/charts/astrotrek/templates/deployment.yaml new file mode 100644 index 0000000000..c47c31b50f --- /dev/null +++ b/charts/astrotrek/templates/deployment.yaml @@ -0,0 +1,63 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.config.name }}-indexer + labels: + app: {{ .Values.config.name }}-indexer + namespace: {{ .Values.global.namespace }} +spec: + replicas: {{ .Values.global.replicaCount }} + selector: + matchLabels: + app: {{ .Values.config.name }}-indexer + template: + metadata: + labels: + app: {{ .Values.config.name }}-indexer + spec: + containers: + - name: {{ .Values.config.name }}-indexer + image: {{ include "indexer.image" . }} + envFrom: + - configMapRef: + name: env + restartPolicy: Always +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Values.global.namespace }} + labels: + app: {{ .Values.config.name }}-frontend + name: {{ .Values.config.name }}-frontend +spec: + replicas: 1 + selector: + matchLabels: + app: {{ .Values.config.name }}-frontend + template: + metadata: + labels: + app: {{ .Values.config.name }}-frontend + spec: + containers: + - args: + - npm + - run + - start + envFrom: + - configMapRef: + name: env + image: {{ include "frontend.image" . }} + name: {{ .Values.config.name }}-frontend + ports: + - containerPort: {{ .Values.ports.frontend }} + protocol: TCP + resources: + requests: + cpu: {{ .Values.resources.requests.cpu }} + memory: {{ .Values.resources.requests.memory }} + limits: + cpu: {{ .Values.resources.limits.cpu }} + memory: {{ .Values.resources.limits.memory }} + restartPolicy: Always diff --git a/charts/astrotrek/templates/ingress.yaml b/charts/astrotrek/templates/ingress.yaml new file mode 100644 index 0000000000..c3d084fe06 --- /dev/null +++ b/charts/astrotrek/templates/ingress.yaml @@ -0,0 +1,71 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Values.config.name }}-api-ingress + namespace: {{ .Values.global.namespace }} + annotations: + {{- with .Values.ingress.api.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.api.className }} + ingressClassName: {{ .Values.ingress.api.className }} + {{- end }} + rules: + - host: {{ .Values.ingress.api.host | quote }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ .Values.config.name }}-indexer-api-service + port: + name: indexer-api + {{- if .Values.ingress.api.tls }} + tls: + {{- range .Values.ingress.api.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Values.config.name }}-frontend-ingress + namespace: {{ .Values.global.namespace }} + annotations: + {{- with .Values.ingress.frontend.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.frontend.className }} + ingressClassName: {{ .Values.ingress.frontend.className }} + {{- end }} + rules: + - host: {{ .Values.ingress.frontend.host | quote }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ .Values.config.name }}-frontend-service + port: + number: {{ .Values.ports.frontend }} + {{- if .Values.ingress.frontend.tls }} + tls: + {{- range .Values.ingress.frontend.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/astrotrek/templates/service.yaml b/charts/astrotrek/templates/service.yaml new file mode 100644 index 0000000000..d0e630cf5e --- /dev/null +++ b/charts/astrotrek/templates/service.yaml @@ -0,0 +1,44 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ .Values.config.name }} + name: {{ .Values.config.name }}-db-service + namespace: {{ .Values.global.namespace }} +spec: + ports: + - name: "{{ .Values.ports.db }}" + port: {{ .Values.ports.db }} + targetPort: {{ .Values.ports.db }} + selector: + app: {{ .Values.config.name }}-db +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ .Values.config.name }}-indexer-api + name: {{ .Values.config.name }}-indexer-api-service + namespace: {{ .Values.global.namespace }} +spec: + ports: + - name: indexer-api + port: {{ .Values.ports.api}} + targetPort: {{ .Values.ports.api}} + selector: + app: {{ .Values.config.name }}-indexer-api +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ .Values.config.name }}-frontend + name: {{ .Values.config.name }}-frontend-service + namespace: {{ .Values.global.namespace }} +spec: + ports: + - name: "{{ .Values.ports.frontend }}" + port: {{ .Values.ports.frontend }} + targetPort: {{ .Values.ports.frontend }} + selector: + app: {{ .Values.config.name }}-frontend diff --git a/charts/astrotrek/templates/servicemonitor.yaml b/charts/astrotrek/templates/servicemonitor.yaml new file mode 100644 index 0000000000..9375cb45eb --- /dev/null +++ b/charts/astrotrek/templates/servicemonitor.yaml @@ -0,0 +1,36 @@ +{{- if .Values.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: astria-indexer-metrics + labels: + app: inderxer + {{- with .Values.serviceMonitor.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + jobLabel: astria-indexer-metrics + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + app: astria-indexer + endpoints: + - port: metrics + path: /metrics + {{- with .Values.serviceMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + - port: astria-indexer-metrics + path: /metrics + {{- with .Values.serviceMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} +{{- end }} diff --git a/charts/astrotrek/templates/statefulsets.yaml b/charts/astrotrek/templates/statefulsets.yaml new file mode 100644 index 0000000000..17d41f0887 --- /dev/null +++ b/charts/astrotrek/templates/statefulsets.yaml @@ -0,0 +1,87 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Values.global.namespace }} + labels: + app: {{ .Values.config.name }}-indexer-api + name: {{ .Values.config.name }}-indexer-api +spec: + replicas: 1 + selector: + matchLabels: + app: {{ .Values.config.name }}-indexer-api + name: {{ .Values.config.name }}-indexer-api + template: + metadata: + labels: + app: {{ .Values.config.name }}-indexer-api + name: {{ .Values.config.name }}-indexer-api + spec: + containers: + - name: {{ .Values.config.name }}-indexer-api + image: {{ include "api.image" . }} + envFrom: + - configMapRef: + name: env + ports: + - containerPort: {{ .Values.ports.api }} + name: indexer-api + protocol: TCP + resources: + requests: + cpu: {{ .Values.resources.requests.cpu }} + memory: {{ .Values.resources.requests.memory }} + limits: + cpu: {{ .Values.resources.limits.cpu }} + memory: {{ .Values.resources.limits.memory }} + restartPolicy: Always +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + namespace: {{ .Values.global.namespace }} + labels: + app: {{ .Values.config.name }}-db + name: {{ .Values.config.name }}-db +spec: + serviceName: "{{ .Values.config.name }}-db" + replicas: 1 + selector: + matchLabels: + app: {{ .Values.config.name }}-db + template: + metadata: + labels: + app: {{ .Values.config.name }}-db + spec: + containers: + - args: + - -cshared_preload_libraries=timescaledb,pg_stat_statements + - -cpg_stat_statements.track=all + envFrom: + - configMapRef: + name: env + image: timescale/timescaledb-ha:pg15-latest + livenessProbe: + exec: + command: + - pg_isready -U -d astria + failureThreshold: 5 + periodSeconds: 10 + timeoutSeconds: 5 + name: {{ .Values.config.name }}-db + ports: + - containerPort: {{ .Values.ports.db }} + protocol: TCP + volumeMounts: + - mountPath: /home/postgres/pgdata + name: db + restartPolicy: Always + volumes: + - name: db + {{- if .Values.storage.enabled }} + persistentVolumeClaim: + claimName: astrotrek-shared-local-pvc + {{- else }} + emptyDir: {} + {{- end }} diff --git a/charts/astrotrek/templates/storageclasses.yaml b/charts/astrotrek/templates/storageclasses.yaml new file mode 100644 index 0000000000..47de0dce3c --- /dev/null +++ b/charts/astrotrek/templates/storageclasses.yaml @@ -0,0 +1,14 @@ +{{/* We only want to create a storage class if we are local. */}} +{{/* For production, you need to create a StorageClass on GKE. */}} +{{- if and .Values.storage.enabled .Values.storage.local }} + {{- range $key, $value := .Values.storage.entities }} +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: astrotrek-shared-vol-local +provisioner: kubernetes.io/no-provisioner +volumeBindingMode: WaitForFirstConsumer +reclaimPolicy: Retain +--- + {{- end }} +{{- end }} diff --git a/charts/astrotrek/templates/volumes.yaml b/charts/astrotrek/templates/volumes.yaml new file mode 100644 index 0000000000..d55b538634 --- /dev/null +++ b/charts/astrotrek/templates/volumes.yaml @@ -0,0 +1,47 @@ +{{/* We need to manually create a PersistentVolume when local. */}} +{{/* In prod, a PV will be created by the StorageClass' provisioner using dynamic provisioning feature. */}} +{{- if .Values.storage.enabled }} + {{- range $key, $value := .Values.storage.entities }} + {{- if $.Values.storage.local }} +apiVersion: v1 +kind: PersistentVolume +metadata: + name: astrotrek-shared-vol-local-pv + namespace: {{ include "astrotrek.namespace" $ }} +spec: + capacity: + storage: {{ $value.size }} + volumeMode: Filesystem + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + storageClassName: astrotrek-shared-vol-local + local: + path: {{ $value.path }} + nodeAffinity: + required: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/hostname + operator: In + values: + - astria-dev-cluster-control-plane + - astria-dev-cluster-worker +--- + {{- end }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + namespace: {{ include "astrotrek.namespace" $ }} + labels: + app: {{ $.Values.config.name }}-db + name: astrotrek-shared-local-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 100Mi + {{- end}} +{{- end }} + diff --git a/charts/astrotrek/values.yaml b/charts/astrotrek/values.yaml new file mode 100644 index 0000000000..2695b33845 --- /dev/null +++ b/charts/astrotrek/values.yaml @@ -0,0 +1,97 @@ +# Default values for celestia-local. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +global: + namespaceOverride: "astria-dev-cluster" + replicaCount: 1 + +images: + indexer: + repo: ghcr.io/astriaorg/astria-indexer + tag: "0.1.0" + devTag: latest + api: + repo: ghcr.io/astriaorg/astria-indexer-api + tag: "0.1.0" + devTag: latest + frontend: + repo: ghcr.io/astriaorg/astrotrek + tag: "0.1.0" + devTag: latest + +serviceMonitor: + enabled: false + additionalLabels: {} + interval: 15s + scrapeTimeout: 10s + +storage: + enabled: false + local: true + entities: + indexerSharedStorage: + size: "1Gi" + persistentVolumeName: "indexer-shared-storage" + path: "/data/indexer-data" + +metrics: + enabled: false + +config: + name: astrotrek + astriaEnv: development + logLevel: debug + profilerServer: http://localhost:4040 + apiPrometheusEnabled: "false" + sequencerRpcUrl: http://node0-sequencer-rpc-service.astria-dev-cluster.svc.cluster.local:26657 + sequencerRpcTimeout: "10" + sequencerRpcRps: "10" + indexer: + indexerScriptDir: database + indexerThreadsCount: "10" + indexerBlockPeriod: "1" + indexerViewsDir: database/views + api: + host: 0.0.0.0 + rateLimit: 10 + requestTimeout: 10 + database: + postgresHost: astrotrek-db-service.astria-dev-cluster.svc.cluster.local + postgresUser: indexer-user + postgresPassword: indexer-user + postgresDb: astria + frontend: + rpcApiUrl: http://api.sequencer.localdev.me/v1 + wsApiUrl: ws://api.sequencer.localdev.me/v1/ws + +ingress: + enabled: true + api: + className: "nginx" + annotations: + nginx.ingress.kubernetes.io/enable-cors: "true" + nginx.ingress.kubernetes.io/cors-allow-origin: "*" + nginx.ingress.kubernetes.io/cors-allow-methods: "GET" + nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range" + nginx.ingress.kubernetes.io/cors-expose-headers: "Content-Length,Content-Range" + nginx.ingress.kubernetes.io/cors-max-age: "86400" + host: api.sequencer.localdev.me + tls: [] + frontend: + className: "nginx" + annotations: {} + host: astrotrek.sequencer.localdev.me + tls: [] + +ports: + api: "9876" + db: "5432" + frontend: "3000" + +resources: + requests: + cpu: 0.25 + memory: 100Mi + limits: + cpu: 1 + memory: 300Mi diff --git a/charts/deploy.just b/charts/deploy.just index 2ba0268968..dbaf90f284 100644 --- a/charts/deploy.just +++ b/charts/deploy.just @@ -19,7 +19,7 @@ run-smoke type *ARGS: load-image image_name tag=default_docker_tag repo=default_repo_name: kind load docker-image {{repo}}/{{image_name}}:{{tag}} --name astria-dev-cluster -deploy-all: deploy-cluster deploy-ingress-controller wait-for-ingress-controller deploy-astria-local wait-for-sequencer (deploy-chart "sequencer-faucet") deploy-rollup +deploy-all: deploy-cluster deploy-ingress-controller wait-for-ingress-controller deploy-astria-local wait-for-sequencer deploy-astrotrek (deploy-chart "sequencer-faucet") deploy-rollup delete-all: clean clean-persisted-data deploy-astria-local namespace=defaultNamespace: (deploy-chart "celestia-local" namespace) (deploy-sequencer) @@ -91,6 +91,14 @@ deploy-sequencer name=validatorName: {{name}}-sequencer-chart ./charts/sequencer deploy-sequencers: (deploy-sequencer "node0") (deploy-sequencer "node1") (deploy-sequencer "node2") +deploy-astrotrek: + helm dependency update charts/astrotrek > /dev/null + helm install astrotrek-chart ./charts/astrotrek \ + -n astria-dev-cluster \ + +delete-astrotrek: + @just delete chart astrotrek + deploy-hermes-local: helm install hermes-local-chart ./charts/hermes \ -n astria-dev-cluster \