diff --git a/charts/deploy.just b/charts/deploy.just index 08e64fe851..2ba0268968 100644 --- a/charts/deploy.just +++ b/charts/deploy.just @@ -53,6 +53,16 @@ deploy-metrics-server: deploy-ingress-controller: kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml +deploy-graph-node namespace=defaultNamespace: (deploy-chart "graph-node" namespace) +delete-graph-node namespace=defaultNamespace: (delete-chart "graph-node" namespace) +delete-graph-node-pvc namespace=defaultNamespace: + kubectl delete pvc -n namespace \ + -l 'app.kubernetes.io/instance=graph-node-chart' \ + -o name | xargs -r kubectl delete -n ${namespace} && \ + kubectl delete pvc -n namespace \ + -l 'app.kubernetes.io/managed-by=Helm' \ + --field-selector 'metadata.name in (ipfs-pvc,postgres-pvc)' + [private] deploy-celestia-local namespace=defaultNamespace: (deploy-chart "celestia-local" namespace) diff --git a/charts/graph-node/.helmignore b/charts/graph-node/.helmignore new file mode 100644 index 0000000000..0e8a0eb36f --- /dev/null +++ b/charts/graph-node/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/graph-node/Chart.yaml b/charts/graph-node/Chart.yaml new file mode 100644 index 0000000000..c7b30ada1b --- /dev/null +++ b/charts/graph-node/Chart.yaml @@ -0,0 +1,13 @@ +apiVersion: v2 +name: graph-node +description: A Helm chart for Graph Node deployment +version: 0.1.0 +appVersion: "0.0.1" + +maintainers: + - name: wafflesvonmaple + url: astria.org + - name: quasystaty1 + url: astria.org + - name: joroshiba + url: astria.org diff --git a/charts/graph-node/templates/_helpers.tpl b/charts/graph-node/templates/_helpers.tpl new file mode 100644 index 0000000000..c6aba56008 --- /dev/null +++ b/charts/graph-node/templates/_helpers.tpl @@ -0,0 +1,14 @@ +{{- define "graphnode.name" -}} +{{ .Release.Name }} +{{- end }} + +{{- define "graphnode.fullname" -}} +{{ include "graphnode.name" . }}-graph-node +{{- end }} + +{{/* +Namepsace to deploy elements into. +*/}} +{{- define "graphnode.namespace" -}} +{{- default .Release.Namespace .Values.global.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end }} diff --git a/charts/graph-node/templates/configmap.yaml b/charts/graph-node/templates/configmap.yaml new file mode 100644 index 0000000000..1d2cdfd54e --- /dev/null +++ b/charts/graph-node/templates/configmap.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: graph-node-config + namespace: {{ .Values.global.namespaceOverride | default .Release.Namespace }} +data: + postgres_host: postgres + postgres_user: {{ .Values.postgres.user }} + postgres_pass: {{ .Values.postgres.password }} + postgres_db: {{ .Values.postgres.database }} + ipfs: ipfs:{{ .Values.ipfs.ports.api }} + ethereum: {{ .Values.environment.ethereumNetwork }}:{{ .Values.environment.ethereumRPC }} + GRAPH_LOG: info diff --git a/charts/graph-node/templates/deployment.yaml b/charts/graph-node/templates/deployment.yaml new file mode 100644 index 0000000000..86bc0d135d --- /dev/null +++ b/charts/graph-node/templates/deployment.yaml @@ -0,0 +1,28 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: graph-node + namespace: {{ .Values.global.namespaceOverride | default .Release.Namespace }} +spec: + replicas: {{ .Values.graphNode.replicas }} + selector: + matchLabels: + app: graph-node + template: + metadata: + labels: + app: graph-node + spec: + containers: + - name: graph-node + envFrom: + - configMapRef: + name: graph-node-config + image: {{ .Values.graphNode.image }}:{{ .Values.graphNode.tag }} + ports: + - containerPort: {{ .Values.graphNode.ports.http }} + - containerPort: {{ .Values.graphNode.ports.jsonRpc }} + - containerPort: {{ .Values.graphNode.ports.indexNode }} + - containerPort: {{ .Values.graphNode.ports.metrics }} + - containerPort: {{ .Values.graphNode.ports.subgraphMetrics }} + diff --git a/charts/graph-node/templates/ingress.yaml b/charts/graph-node/templates/ingress.yaml new file mode 100644 index 0000000000..dfd9fe7be2 --- /dev/null +++ b/charts/graph-node/templates/ingress.yaml @@ -0,0 +1,35 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: graph-node + annotations: + {{- with .Values.ingress.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.className }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + rules: + - host: {{ .Values.ingress.host | quote }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: graph-node + port: + number: {{ .Values.graphNode.ports.http }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/graph-node/templates/servicemonitor.yaml b/charts/graph-node/templates/servicemonitor.yaml new file mode 100644 index 0000000000..088fc92ea9 --- /dev/null +++ b/charts/graph-node/templates/servicemonitor.yaml @@ -0,0 +1,36 @@ +{{- if and .Values.serviceMonitor.enabled (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1") }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: graph-node-metrics + labels: + app: graph-node + {{- with .Values.serviceMonitor.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + jobLabel: graph-node-metrics + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + app: graph-node + endpoints: + - port: metrics + path: /metrics + {{- with .Values.serviceMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + - port: subgraph-metrics + path: /metrics + {{- with .Values.serviceMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} +{{- end }} diff --git a/charts/graph-node/templates/services.yaml b/charts/graph-node/templates/services.yaml new file mode 100644 index 0000000000..54613bd4ae --- /dev/null +++ b/charts/graph-node/templates/services.yaml @@ -0,0 +1,50 @@ +apiVersion: v1 +kind: Service +metadata: + name: graph-node + namespace: {{ include "graphnode.namespace" . }} +spec: + selector: + app: graph-node + ports: + - name: http + port: {{ .Values.graphNode.ports.http }} + targetPort: {{ .Values.graphNode.ports.http }} + - name: json-rpc + port: {{ .Values.graphNode.ports.jsonRpc }} + targetPort: {{ .Values.graphNode.ports.jsonRpc }} + - name: index-node + port: {{ .Values.graphNode.ports.indexNode }} + targetPort: {{ .Values.graphNode.ports.indexNode }} + - name: metrics + port: {{ .Values.graphNode.ports.metrics }} + targetPort: {{ .Values.graphNode.ports.metrics }} + - name: subgraph-metrics + port: {{ .Values.graphNode.ports.subgraphMetrics }} + targetPort: {{ .Values.graphNode.ports.subgraphMetrics }} +--- +apiVersion: v1 +kind: Service +metadata: + name: ipfs + namespace: {{ include "graphnode.namespace" . }} +spec: + selector: + app: ipfs + ports: + - name: api + port: {{ .Values.ipfs.ports.api }} + targetPort: {{ .Values.ipfs.ports.api }} +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres + namespace: {{ include "graphnode.namespace" . }} +spec: + selector: + app: postgres + ports: + - name: postgres + port: {{ .Values.postgres.ports.postgres }} + targetPort: {{ .Values.postgres.ports.postgres }} diff --git a/charts/graph-node/templates/statefulsets.yaml b/charts/graph-node/templates/statefulsets.yaml new file mode 100644 index 0000000000..c232509ed5 --- /dev/null +++ b/charts/graph-node/templates/statefulsets.yaml @@ -0,0 +1,88 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: ipfs + namespace: {{ include "graphnode.namespace" . }} +spec: + replicas: 1 + selector: + matchLabels: + app: ipfs + template: + metadata: + labels: + app: ipfs + spec: + containers: + - name: ipfs + image: {{ .Values.ipfs.image }}:{{ .Values.ipfs.tag }} + ports: + - containerPort: {{ .Values.ipfs.ports.api }} + volumeMounts: + - name: ipfs-storage + mountPath: /data/ipfs + volumes: + - name: ipfs-storage + {{- if .Values.ipfs.storage.enabled }} + persistentVolumeClaim: + claimName: ipfs-pvc + {{- else }} + emptyDir: {} + {{- end }} +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: postgres + namespace: {{ include "graphnode.namespace" . }} +spec: + replicas: 1 + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + spec: + securityContext: + fsGroup: 999 + containers: + - name: postgres + image: {{ .Values.postgres.image }}:{{ .Values.postgres.tag }} + ports: + - containerPort: {{ .Values.postgres.ports.postgres }} + env: + - name: POSTGRES_USER + value: {{ .Values.postgres.user }} + - name: POSTGRES_PASSWORD + value: {{ .Values.postgres.password }} + - name: POSTGRES_DB + value: {{ .Values.postgres.database }} + - name: PGDATA + value: /var/lib/postgresql/data/pgdata + - name: POSTGRES_INITDB_ARGS + value: "--lc-collate=C --lc-ctype=C --encoding=UTF8" + securityContext: + runAsUser: 999 + runAsGroup: 999 + volumeMounts: + - name: postgres-storage + mountPath: /var/lib/postgresql/data + readinessProbe: + exec: + command: ["pg_isready", "-U", "{{ .Values.postgres.user }}"] + initialDelaySeconds: 10 + periodSeconds: 5 + resources: + requests: + cpu: 100m + memory: 256Mi + volumes: + - name: postgres-storage + {{- if .Values.postgres.storage.enabled }} + persistentVolumeClaim: + claimName: postgres-pvc + {{- else }} + emptyDir: {} + {{- end }} diff --git a/charts/graph-node/templates/storageclasses.yaml b/charts/graph-node/templates/storageclasses.yaml new file mode 100644 index 0000000000..3fe8ebcb13 --- /dev/null +++ b/charts/graph-node/templates/storageclasses.yaml @@ -0,0 +1,13 @@ +{{/* We only want to create a storage class if we are local. */}} +{{/* For production, you need to create a StorageClass on GKE. */}} +{{- if or (and .Values.ipfs.storage.enabled .Values.ipfs.storage.local) (and .Values.postgres.storage.enabled .Values.postgres.storage.local) }} + {{- range $key, $value := .Values.storage.entities }} +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: {{ include "graphnode.name" $ }}-{{ $value.persistentVolumeName }}-graph-node-local +provisioner: kubernetes.io/no-provisioner +volumeBindingMode: WaitForFirstConsumer +reclaimPolicy: Retain + {{- end }} +{{- end }} diff --git a/charts/graph-node/templates/volumes.yaml b/charts/graph-node/templates/volumes.yaml new file mode 100644 index 0000000000..4d82f71710 --- /dev/null +++ b/charts/graph-node/templates/volumes.yaml @@ -0,0 +1,109 @@ +{{/* 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 and .Values.ipfs.storage.enabled }} + {{- range $key, $value := .Values.storage.entities }} + {{- if $.Values.storage.local }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: ipfs-pvc +spec: + capacity: + storage: {{ $value.size }} + volumeMode: Filesystem + persistentVolumeReclaimPolicy: Retain + storageClassName: {{ .Values.persistence.storageClass }} + accessModes: + - ReadWriteOnce + local: + path: {{ $value.path }} + resources: + requests: + storage: {{ .Values.ipfs.storage.size }} + 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: + name: ipfs-pvc + namespace: {{ include "graphnode.namespace" $ }} + labels: + "app.kubernetes.io/name": "ipfs-pvc-{{ $.Chart.Name }}" + "app.kubernetes.io/managed-by": {{ $.Release.Service | quote }} + "helm.sh/chart": {{ $.Chart.Name }}-{{ $.Chart.Version | replace "+" "_" }} +spec: + {{- if $.Values.storage.local }} + storageClassName: {{ .Values.persistence.storageClass }} + {{- end }} + {{- if $value.storageClassName }} + storageClassName: {{ $value.storageClassName }} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ $value.size }} +--- + {{- end }} +{{- end }} +{{- if and .Values.postgres.storage.enabled }} + {{- range $key, $value := .Values.storage.entities }} + {{- if $.Values.storage.local }} +apiVersion: v1 +kind: PersistentVolume +metadata: + name: postgres-pvc +spec: + capacity: + storage: {{ $value.size }} + volumeMode: Filesystem + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + storageClassName: {{ .Values.persistence.storageClass }} + 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: + name: postgres-pvc + namespace: {{ include "graphnode.namespace" $ }} + labels: + "app.kubernetes.io/name": "postgres-pvc-{{ $.Chart.Name }}" + "app.kubernetes.io/managed-by": {{ $.Release.Service | quote }} + "helm.sh/chart": {{ $.Chart.Name }}-{{ $.Chart.Version | replace "+" "_" }} +spec: + {{- if $.Values.storage.local }} + storageClassName: {{ .Values.persistence.storageClass }} + {{- end }} + {{- if $value.storageClassName }} + storageClassName: {{ $value.storageClassName }} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ $value.size }} +--- + {{- end }} +{{- end }} diff --git a/charts/graph-node/values.yaml b/charts/graph-node/values.yaml new file mode 100644 index 0000000000..1fcb3146ea --- /dev/null +++ b/charts/graph-node/values.yaml @@ -0,0 +1,65 @@ +global: + namespaceOverride: "" + replicaCount: 1 + +serviceMonitor: + enabled: false + additionalLabels: {} + interval: 15s + scrapeTimeout: 10s + +graphNode: + image: graphprotocol/graph-node + tag: latest + replicas: 1 + metrics: + enabled: false + ports: + http: 8000 + jsonRpc: 8001 + indexNode: 8020 + metrics: 8030 + subgraphMetrics: 8040 + +ingress: + enabled: true + className: "nginx" + annotations: + {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + host: graph-node.localdev.me + tls: [] + # - secretName: graph-node-tls + # hosts: + # - graph-node.example.com + +ipfs: + image: ipfs/kubo + tag: v0.17.0 + storage: + enabled: false + local: true + size: 5Gi + ports: + api: 5001 + +postgres: + image: postgres + tag: latest + user: graph-node + password: let-me-in + database: graph-node + storage: + enabled: false + local: true + size: 10Gi + ports: + postgres: 5432 + +environment: + ethereumNetwork: flame-local + ethereumRPC: http://astria-evm-service.astria-dev-cluster.svc.cluster.local:8545 + +persistence: + storageClass: standard