Installs the Hedera Mirror Node Helm wrapper chart. This chart will install the mirror node components:
- Hedera Mirror GraphQL API
- Hedera Mirror GRPC API
- Hedera Mirror Importer
- Hedera Mirror Monitor
- Hedera Mirror REST API
- Hedera Mirror Java REST API
- Hedera Mirror Rosetta API
- Hedera Mirror Web3 API
Set environment variables that will be used for the remainder of the document:
export RELEASE="mirror1"To install the wrapper chart:
$ helm repo add hedera https://hiero-ledger.github.io/hiero-mirror-node/charts
$ helm upgrade --install "${RELEASE}" hedera/hedera-mirrorThis chart supports automatic generation of random passwords. On initial installation, a secure, random password for
each chart component will be generated and stored into a Kubernetes secret. During upgrades, Helm
will lookup the existing
secret and ensure the passwords stay the same between upgrades. You can retrieve the generated passwords in
the mirror-passwords Kubernetes secret. It's recommended to use ksd to
automatically base64 decode secrets.
kubectl get password mirror-passwords -o yaml | ksdWhen running against a network other than a public network (e.g., demo, previewnet, testnet, or mainnet), the network must be updated with an initial address book file prior to deploying the chart.
- First acquire the address book file and encode its contents to Base64:
$ base64 --input ~/addressbook.bin- Then populate the importer's
addressBookproperty in the customvalues.yamlwith the Base64 output:
importer:
addressBook: CtYGGgUwLjAuN...The mirror node chart uses the Traefik chart to manage access to cluster services through an Ingress and to route traffic through a load balancer. The implemented configuration uses a default self-signed certificate to secure traffic over TLS.
In production, it is advised to use a certificate authority signed certificate, and an external load balancer to allow for more secure and intricate load balancing needs. The following diagram illustrates a high level overview of the resources utilized in the recommended traffic flow.
When deploying in GCP, the following steps may be taken to use a container-native load balancer through a Standalone NEG.
-
Create a Kubernetes cluster utilizing a custom subnet.
This can be done by setting a unique name for the subnet in the UI or through the console with the following command
gcloud container clusters create mirror-node \ --enable-ip-alias \ --create-subnetwork="" \ --network=default \ --zone=us-central1-a \ --cluster-version=1.34 \ --machine-type=n2-custom-6-15360 -
Configure Traefik to use the external load balancer.
The following default production setup configures the Standalone NEG. It exposes port 443 for HTTPS based traffic. This load balancer is a GCP container-native load balancer through standalone NEG. Please modify for other cloud providers. Apply this config to your local values file (i.e.
custom.yaml) for use in helm deployment:traefik: service: annotations: cloud.google.com/neg: '{"exposed_ports": {"443": {"name": "<tls_neg_name>"}}}'
Note: Ensure the NEG names are cluster unique to support shared NEGs across separate globally distributed clusters
The annotation will ensure that a NEG is created for each name specified, with the endpoints pointing to the Traefik pod IPs in your cluster on the configured port. These ports should match the ports exposed by Traefik in the common chart
.Values.traefik.ports. -
Create a Google Managed Certificate for use by the Load Balancer
-
Create an External HTTPS load balancer and create a Backend Service(s) that utilizes the automatically created NEGs pointing to the traffic pods.
To verify the chart installation is successful, you can run the helm tests. These tests are not automatically executed
by helm on install/upgrade, they have to be executed manually. The tests require the operatorId,
and operatorKey properties be set in a local values file in order to execute, as well as network if using an
environment other than testnet, and nodes if using a custom environment.
To configure:
test:
config:
hiero:
mirror:
test:
acceptance:
network:
operatorId:
operatorKey:To execute:
helm test "${RELEASE}" --timeout 10mAll the public APIs can be accessed via a single IP. First, get the load balancer IP address:
export SERVICE_IP=$(kubectl get service "${RELEASE}-traefik" -o jsonpath="{.status.loadBalancer.ingress[0].ip}")To access the GraphQL API:
curl --location --request POST "http://${SERVICE_IP}/graphql/alpha" \
--header 'Content-Type: application/json' \
--data-raw '{"query":"{ account(input: {entityId: {shard: 0, realm: 0, num: 98}}) {alias autoRenewPeriod createdTimestamp declineReward createdTimestamp}}"}'To access the GRPC API (using grpcurl):
grpcurl -plaintext ${SERVICE_IP}:80 listTo access the REST API:
curl -s "http://${SERVICE_IP}/api/v1/transactions?limit=1"To access the Java REST API:
curl -s "http://${SERVICE_IP}/api/v1/accounts/{id}/allowances/nfts"To access the Rosetta API:
curl -sL -d '{"metadata":{}}' "http://${SERVICE_IP}/network/list"To access the Web3 API:
curl -sL -H "Content-Type: application/json" -X POST -d '{"from": "0x0000000000000000000000000000000002edec80","to": "0x0000000000000000000000000000000002edec81","value": 500,"gas": 0,"gasPrice": 0}' "http://${SERVICE_IP}/api/v1/contracts/call"To view the Grafana dashboard:
kubectl port-forward service/${RELEASE}-grafana 8080:80 &
open "http://localhost:8080"To view the Stackgres UI:
kubectl get secret ${RELEASE}-restapi --template '{{ printf "%s / %s\n" (.data.k8sUsername | base64decode) (.data.clearPassword | base64decode) }}'
kubectl port-forward service/${RELEASE}-restapi 8443:443 &
open https://localhost:8443To remove all the Kubernetes components associated with the chart and delete the release:
helm delete "${RELEASE}"The above command does not delete any of the underlying persistent volumes. To delete all the data associated with this release:
kubectl delete $(kubectl get pvc -o name)The Helm charts use Bitnami for various chart components. Newer Bitnami images are no longer freely available, so we
need to periodically build their images from source and publish them to our own registry. After building the images
using the below steps, update the values.yaml to use the newly built images.
export REDIS_VERSION="8.2.2"
git checkout https://github.com/bitnami/containers.git
cd containers/bitnami/
docker buildx build --platform linux/amd64,linux/arm64 -t gcr.io/mirrornode/redis:${REDIS_VERSION} --provenance false --push redis/8.2/debian-12
docker buildx build --platform linux/amd64,linux/arm64 -t gcr.io/mirrornode/redis-sentinel:${REDIS_VERSION} --provenance false --push redis-sentinel/8.2/debian-12To troubleshoot a pod, you can view its log and describe the pod to see its status. See the kubectl documentation for more commands.
kubectl describe pod "${POD_NAME}"
kubectl logs -f --tail=100 "${POD_NAME}"
kubectl logs -f --prefix --tail=10 -l app.kubernetes.io/name=importerTo change an application's properties, create
a ConfigMap
and mount it into the container by specifying volumes
and volumeMounts in your custom values.yaml. Create the ConfigMap from a properties file:
echo "logging.level.org.hiero.mirror.grpc=TRACE" > application.properties
kubectl create configmap grpc --from-file=application.propertiesAdd the following to your values.yaml to mount it:
volumes:
custom:
configMap:
name: grpc
defaultMode: 420
volumeMounts:
custom:
mountPath: /custom
readOnly: trueDashboard, metrics and alerts can be viewed via Grafana. See the Using section for how to connect to Grafana.
To connect to the database and run queries:
V1:
kubectl exec -it "${RELEASE}-postgres-postgresql-0" -c postgresql -- psql -d mirror_node -U mirror_nodeV2:
DB_PASSWORD="$(kubectl get secrets -o yaml ${RELEASE}-passwords |ksd | yq '.stringData.HIERO_MIRROR_REST_DB_PASSWORD')"
kubectl run psql-util -it --rm --image=bitnami/postgresql:16 --env="PGPASSWORD=${DB_PASSWORD}" --command -- psql -h "${RELEASE}-citus-reads" -U mirror_rest -d mirror_nodeThe Stackgres Admin UI can be exposed to monitor and troubleshoot problems with Citus.
A thread dump can be taken by sending a QUIT signal to the java process inside the container. The thread dump output
will be visible via container logs.
kubectl exec "${POD_NAME}" -- kill -QUIT 1
kubectl logs -f "${POD_NAME}"Prometheus AlertManager is used to monitor and alert for ongoing issues in the cluster. If an alert is received via a
notification mechanism like Slack or PagerDuty, it should contain enough details to know where to start the
investigation. Active alerts can be viewed via the AlertManager dashboard in Grafana. To see further details or to
silence or suppress the alert it will need to be done via the AlertManager UI. To access the AlertManager UI, expose it
via kubectl:
kubectl port-forward service/${RELEASE}-prometheus-alertmanager 9093:9093 &
open http://localhost:9093