Running Chainlink Nodes on Kubernetes and the Google Cloud Platform
In order to ensure our nodes have optimal uptime, the team at Secure Data Links is currently utilising Kubernetes alongside Google Cloud Platform (GCP) to run our Chainlink oracle. In this article we’ll be walking you through the process of setting up infrastructure that mimics our own, allowing you to run your nodes with consistent uptime on GCP.
In this tutorial we use Kubernetes to setup two Chainlink nodes which connect to an external database all within GCP. Running the nodes with Kubernetes allows them to automatically restart should they crash, and since both the database and nodes are run internally on Google Cloud, all traffic is conveniently routed internally between them and never exposed to public networks.
We aim to make this tutorial as friendly as possible to all, with minimum pre-requisite knowledge required. However some knowledge of the unix command line is assumed.
We recommend running a Chainlink node locally following the official Chainlink guide (https://docs.chain.link/docs/running-a-chainlink-node) just to get a feel for the process, however this isn’t completely necessary.
You will however need to install the following dependencies on whatever machine you are using
- Kubectl command line tool (https://kubernetes.io/docs/tasks/tools/install-kubectl/)
- Google cloud command line tool (https://cloud.google.com/sdk/docs/#install_the_latest_cloud_tools_version_cloudsdk_current_version)
- A Google cloud account (you can sign up for one free and get $300 worth of free credit at https://cloud.google.com)
- A Copy of our Chainlink Kubernetes deployment (https://github.com/securedatalinks/ChainlinkKubernetes)
I would also recommend creating a new directory to work in, and pull the files from our ChainlinkKubernetes Github into this directory.
Part 1 — Creating the Kubernetes Cluster and Postgres DB
The first part of the process is to create a new Kubernetes cluster in GCP. To do this simply navigate to the Kubernetes Engine tab and hit create cluster. Then set up a standard cluster with 2vCPU’s and a single node, which should look as follows. Feel free to place the cluster in any region.
While your cluster is starting up, we can create a Postgres DB. Head to the SQL tab under storage, hit create instance and select Postgresql. Give the instance a name and a password (make sure you write down the password as you will need it later). Place the database in the same region as your Kubernetes cluster.
Congratulations, you now have a Kubernetes cluster and Postgres database running on GCP. Time to configure the database.
Part 2 — Database Configuration
Once your database is setup, you will be able to access it via the SQL tab. Once you click on your newly setup database, you should be presented with a screen similar to the one below. The first thing we are going to do is create a new table for our nodes data.
Head to the databases tab, hit create database and name your new database “chainlink”. This will hold all the data your node needs to operate.
Next we are going to configure a private IP. The private IP allows your Chainlink nodes to communicate with the database privately on the internal GCP network. This means you are not required to set up any firewall rules for our database.
Simply head to the connections tab, and change connectivity from public IP to private IP.
Once complete, you should be able to navigate back to the database’s homepage and see a private IP listed. From this we can now construct our database URL (that we will need later to configure our node). The database URL for our postgres database is as follows, where PASSWORD is replaced by the password you used to create the database in step 1, and IP is the private IP listed in the database dashboard.
Part 3 — Creating the Nodes
We are now ready to start creating our Chainlink nodes through Kubernetes. The first step in this process is to configure kubectl to connect to your GCP Kubernetes cluster. Navigate to the Kubernetes Engine tab and select connect. You should now be able to copy the gcloud container command listed under “command line access” as seen below. By running this in any unix terminal, kubectl will be configured to access your GCP cluster.
The next steps are setting up some variables needed by your Chainlink node. The first of these are the api file and the password file. These files are needed to allow the Chainlink node to startup with a given api user name, password, and node password. To setup these files, run the following commands and provide your own email, and passwords. Ensure your passwords are strong.
echo "firstname.lastname@example.org" > .apiecho "password" > .apiecho "my_wallet_password" > .password
You should now have a directory that looks similar to this.
Now you need to turn these files into secrets to be used by Kubernetes. This is made very simple with the kubectl command line, simply run:
kubectl create secret generic api-env --from-file=.apikubectl create secret generic password-env --from-file=.password
This will create two new secrets within Kubernetes that can be used by your cluster later on. Next up you need to create a configMap to hold your environment variables for the Chainlink node. In both of the below examples, ensure you replace the DATABASE_URL with your database URL that we constructed above, and replace the ETH_URL with the URL of your Ethereum web-sockets endpoint.
kubectl create configmap node-env --from-literal ROOT=/chainlink --from-literal LOG_LEVEL=debug --from-literal ETH_CHAIN_ID=3 --from-literal MIN_OUTGOING_CONFIRMATIONS=2 --from-literal LINK_CONTRACT_ADDRESS=0x20fe562d797a42dcb3399062ae9546cd06f63280 --from-literal CHAINLINK_TLS_PORT=0 --from-literal SECURE_COOKIES=false --from-literal ALLOW_ORIGINS=* --from-literal ETH_URL=<INSERT-ETH-WSS> --from-literal DATABASE_URL=<INSERT-DATBASE-URL> --from-literal DATABASE_TIMEOUT=0
kubectl create configmap node-env --from-literal ROOT=/chainlink --from-literal LOG_LEVEL=debug --from-literal ETH_CHAIN_ID=1 --from-literal CHAINLINK_TLS_PORT=0 --from-literal SECURE_COOKIES=false --from-literal ALLOW_ORIGINS=* --from-literal ETH_URL=<INSERT-ETH-WSS> --from-literal DATABASE_URL=<INSERT-DATBASE-URL> --from-literal DATABASE_TIMEOUT=0
Running the following should now list one configMap named node-env
kubectl get configMaps
While the following command should show two secrets called api-env and password-env
kubectl get secrets
We are now ready to launch our deployment. Simply run
kubectl apply -f deploy.yaml
and Kubernetes will start up our two Chainlink nodes. You should now be able to run the following command and get a similar output to below. If so, you now successfully have two Chainlink nodes up and running with the help of Kubernetes.
kubectl get all
To check that the nodes are operating as they should be, you may run
kubectl logs <NAME>
where name is replaced by the name of either of your deployed pods. One pod should output a locking message as this is our redundant node, while the other node should output some basic setup lines and then the block headers it is currently receiving (similar to below)
Part 4 — Operator GUI Access
Now that you have two nodes running, you need some way of accessing the operator GUI so you can add jobs to our nodes. There are two main ways of doing this. You can either use port forwarding, or add a load balancer to your cluster. As per the Chainlink guide, port forwarding is the preferred option as it does not expose the Operator GUI to the public internet, however should you want/need to do this, the option is there through the use of a node balancer.
Method 1 — Port Forwarding (Recommended)
To port forward from your pod to localhost, first identify which pod is currently running the Chainlink node. This can be done by running
kubectl logs <POD-NAME> --tail 10
The node that is currently running should have logs showing it receiving block headers from your Ethereum client. This is the pod we will want to port forward from. Next, simply run
kubectl port-forward <POD-NAME> 6688:6688
You will now be able to access the operator GUI at localhost:6688
Method 2 — Load Balancer (Not Recommended)
Another method for accessing the operator GUI is to simply create a new Kubernetes load balancer service, which will expose our cluster to a public IP, allowing us to get access to the nodes.
To do this, navigate to the Kubernetes Engine panel, click connect next to the cluster you setup in this tutorial, and then hit open workloads dashboard. You should now see a large list of Kubernetes workloads, and one should be titled chainlink-deployment. Click on that to access our deployments page.
Scroll down until you see exposing services and click expose. Next, you want to set both the port and target port to 6688, and ensure the type is set to load balancer as seen below.
Clicking expose should then start up the service. Once the service is started, on the service page you will see a public IP. This is where you can now access your newly deployed node.