Ethereum on Google Cloud Platform

Blockchain Platforms on Google Cloud Platform

Daz Wilkin
Google Cloud - Community
8 min readMay 22, 2018

--

Google’s super-fast network, powerful VMs and SSDs coupled with its state-of-the-art container technologies make Google Cloud Platform (GCP) an unparalleled destination for Blockchain platforms.

Google could do better in ensuring that developers are aware of this.

Late last year, I wrote a story describing how to deploy Ethereum to GCP. I’d not used Ethereum between then and today. This story updates that previous post with easier ways to run Ethereum on GCP using: (a) Container-Optimized OS; (b) using Kubernetes Engine.

You’ll need a GCP Project and there are free options. You will need Cloud SDK (aka gcloud) installed. Let’s get started.

Container-Optimized OS

Container-Optimized OS permits you to deploy a Docker image to a Google Compute Engine VM. This is the simplest way to run the ethereum/client-go image:

NB To avoid exhausting disk, the container uses 500GB (the entire default Quota) of SSD Persistent Storage. Reduce the boot-disk-size or change the boot-disk-type to pd-standard as you prefer.

NB If you would prefer to use the test network add — container-arg="— testnet” before the existing — container-arg flags. If you would prefer to use Rinkeby add — container-arg=" — rinkeby" before the existing--container-arg flags.

The VM should be running in under 30 seconds, you can peek into its state with:

NB konlet-startup is the systemd service that corresponds to the Docker image deployment in the Container-Optimized OS.

Success looks like:

And you may confirm the container is running:

Then, you may use gcloud to start the ssh port-forward to the instance:

And — from a different shell — you can connect to the Ethereum node running on the instance:

Which should yield:

Running Ethereum on GCP leverages Google Cloud Logging. You will automatically be able to view and query logs.

https://console.cloud.google.com/logs/viewers

Stackdriver Logging “Global: gcplogs-docker-driver”

NB Slightly confusingly (!), you must select “Global” as the resource and you should then see “gcplogs-docker-driver” as an option. This will — as above — provide the container’s logs.

Everything you see via Cloud Console is accessible from the CLI too. In this case, you may run the following command to view the container’s logs:

You should log entries like this:

NB What you *don’t* want are log entries of the form “no space left on device” as these terminate the container. If you receive these you’ll need to increase the size of the boot-disk-size flag or grab less data.

You also get basic monitoring *but* of the VM not the container(s) specifically:

Stackriver Monitoring

You may exit the JavaScript console then delete the Ethereum VM with:

Kubernetes Engine

If you would prefer to use a Kubernetes (Engine) cluster, the commands are as straightforward.

Assuming you are authenticated against a cluster, the following steps create a namespace for Ethereum, create a disk (actually a Kubernetes PersistentVolumeClaim), deploy a single Go Ethereum (aka “geth”) node and port-forward to your local workstation so that you may attach to it:

NB If you would prefer to use the test network insert "--testnet" (including the quotation marks) between lines 33–34. If you’d prefer to use Rinkeby network insert "--rinkeby" instead.

This should result in:

And you should be able to see the Persistent Volume Claim created:

https://console.cloud.google.com/kubernetes/storage

And the Deployment:

https://console.cloud.google.com/kubernetes/workload

Running Ethereum on GCP yields some useful, automatic benefits including, Console monitoring:

Cloud Console: Kubernetes

Logging:

https://console.cloud.google.com/logs/viewer

Stackdriver Logging: GKE Container(s)

Some Stackdriver goodness (although this is even better with the recently-announced Stackdriver Kubernetes Monitoring — not enabled on this cluster). If you’ve not configured Stackdriver for the project, you’ll need to do that first and you may use the free tier:

https://console.cloud.google.com/monitoring

Stackdriver Monitoring: Kubernetes Engine cluster

We’ll use ssh port-forwarding (through gcloud) to access the Go Ethereum node from our workstation without opening a firewall.

NB These nebulous looking commands grab one of the Kubernetes cluster’s node names; determine which NodePort the Ethereum Service is being served on; and then uses gcloud to port-forward that node’s port to the localhost’s (same) port. If you prefer you could use — ssh-flag=“-L 8545:localhost:${PORT}” and then in the subsequent command replace ${PORT} with 8545 too. Your choice!

NB In my case echo ${PORT} (this time) returned 30873.

Then, from your local workstation, run the geth JavaScript client and attach to the node running on the Kubernetes cluster:

NB In my case, the value of ${PORT} is 30873.

And you should then be put in the Ethereum JavaScript console:

When you’re done, it’s simplest to whack the Kubernetes namespace which will delete the Deployment, the Service and the PeristentVolumeClaim:

18–05–25 Aside: Wallets

I uncovered an issue using Wallets passed to Kubernetes (Engine) as Secrets. Providing data to Pods using Secrets (and ConfigMaps) is considered a good practice with Kubernetes. However, the implementation of both Secrets and ConfigMaps when (volume) mounted into Pods is to present file content as symbolic links. This appears to be a problem with Wallets and Ethereum:

https://github.com/ethereum/go-ethereum/issues/16793

If you’d like to use existing wallet file(s) when you deploy to Kubernetes, this should be as simple as creating a Secret (you may use ConfigMaps similarly but Secrets provide opacity for… secrets and other confidential info) and then mounting the Secret as a volume mount for the Ethereum node to access. However, as above, this does not work correctly with Ethereum. So, you will need the additional step in the ‘hacky workaround’ below.

First, create the Secret:

NB Your path should end in a directory called keystore and this directory and its wallet(s) will be encoded in the Secret.

My hacky workaround is to use init containers to copy the wallet(s) from the Secret (called /keystore) into an emptyDir (called /cache) volume *before* the Ethereum node starts and configure Ethereum to look for the wallet in /cache rather than /keystore (because this doesn’t work). This works because copying the symbolic link duplicates the underlying file.

NB See the next section ‘SSD’ to configure the datadir as SSD rather than HDD.

NB Line #31–39 create an init container called init-service. init-service uses Alpine to copy files of the form UTC* from /keystore to /cache. These directories are volume mounted. The volumes are defined (for the Pod not specific containers) in lines #66–75. keystore is the Secret containing wallet file(s) mounted as symbolic link(s) that do not appear to work with Ethereum if used directly. cache is an emptyDir volume and, if Ethereum uses the wallet(s) when copied here, it does work!

NB In line #46, Ethereum is configured to use the /cache directory for wallets with --keystore=/cache.

SSD

The Kubernetes Deployment used above includes a PersistentVolumeClaim spec and line #7 defines storageClassName of standard. This corresponds to regular Persistent Disk.

If you’d prefer to use faster SSD, we must first register the new Storage class in Kubernetes Engine:

and:

Now, when you query the Kubernetes Engine storage classes, a new type pd-ssd called ssd should be added:

Then, we can revise the Deployment file’s line #7 and change storageClassName: standard to storageClassName: ssd.

NB Default “Persistent Disk SSD (GB)” Quotas for GCP Projects are 500 GB (gigabytes) per zone. If you’ve not increased these quotas, you will be unable to provision a 500 GiB (!) disk when you Apply the Deployment. For this reason, please also *reduce* the value of line #12 in the Deployment to e.g. 400Gi (~429GB) which should be sufficient *unless* you have other SSD PD in your Project in the zone. Or, request a Quota increase:

https://console.cloud.google.com/iam-admin/quotas?project=${PROJECT}&service=compute.googleapis.com&metric=Persistent%20Disk%20SSD%20(GB)

Quota: Persistent Disks SSD (GB)

To effect this change we must delete and recreate the Deployment:

Compute Engine: Disks

NB There are 4 Compute Engine Disks: 3 are “Standard Persistent disk” one for each of the 3 Nodes in the Kubernetes cluster. The 4th disk is 430GB (==400GiB) and is of type “SSD persistent disk”. It was created by the PersistentVolumeClaim when we applied the Deployment.

Conclusion

In this post, I’ve provided two straightforward ways to run a single Ethereum node on Google Cloud Platform.

Feedback is always welcome.

That’s all!

--

--