Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
We've extended Kubernetes with Node custom resource which can be used to create Filecoin nodes across different filecoin networks like Mainnet or calibration using lotus client from a given spec.
Here's an example of a Filecoin node that syncs calibration chain:
apiVersion: filecoin.kotal.io/v1alpha1
kind: Node
metadata:
name: calibration-node
spec:
network: calibrationFor all the fields associated with the Node API resource:
kubectl explain node --api-version filecoin.kotal.io/v1alpha1
kubectl explain node.spec --api-version filecoin.kotal.io/v1alpha1Full filecoin node reference is documented here.
You can support us by donating Eth or any token to our ENS address farghaly.eth or directly to the following Ethereum address:
Thank you!
Polkadot is a sharded protocol that enables blockchain networks to operate together seamlessly. Polkadot is a 100% open-source project created to enable a decentralized web and better society.
We've extended Kubernetes with Node custom resource which can be used to Polkadot, Kusama, Rococo, and substrate-based chains from the given spec.
Node is Polkadot node using client, connecting to and syncing a specific chain, and optionally validating blocks.
For all the fields associated with the Node API resource:
Full polkadot node reference is documented .
IPFS is a distributed system for storing and accessing files, websites, applications, and data.
We've extended Kubernetes with Peer and ClusterPeer custom resources which can be used to deploy IPFS peers, swarms, and clusters from the given spec.
Peer is an ipfs peer running go-ipfs client and connecting to the public ipfs swarm or a private swarm secured by swarm key. Here's an example of a very basic ipfs peer connecting to the public ipfs swarm.
For all the fields associated with the Peer API resource:
Full ipfs peer reference is documented .
ClusterPeer is an ipfs cluster peer running ipfs-cluster-service client, connecting to ipfs peer and optional bootstrap cluster peer(s). ClusterPeers provide data orchestration across a swarm of IPFS daemons by allocating, replicating and tracking a global pinset distributed among multiple peers. Here's an example of cluster peer connecting to ipfs peer.
For all the fields associated with the ClusterPeer API resource:
Full ipfs cluster peer reference is documented .
0x5dfA5dB515748f3E2BCc8677A9332f4aFFad5A5EapiVersion: polkadot.kotal.io/v1alpha1
kind: Node
metadata:
Name: kusama-node
spec:
network: kusama
rpc: truekubectl explain nodes --api-version polkadot.kotal.io/v1alpha1
kubectl explain nodes.spec --api-version polkadot.kotal.io/v1alpha1apiVersion: ipfs.kotal.io/v1alpha1
kind: Peer
metadata:
Name: simple-peer
spec: {}kubectl explain peers --api-version ipfs.kotal.io/v1alpha1
kubectl explain peers.spec --api-version ipfs.kotal.io/v1alpha1apiVersion: ipfs.kotal.io/v1alpha1
kind: ClusterPeer
metadata:
Name: simple-cluster-peer
spec:
peerEndpoint: /dns4/simple-peer/tcp/5001kubectl explain clusterpeers --api-version ipfs.kotal.io/v1alpha1
kubectl explain clusterpeers.spec --api-version ipfs.kotal.io/v1alpha1apiVersion: bitcoin.kotal.io/v1alpha1
kind: Node
metadata:
Name: bitcoin-node
spec:
network: mainnet
rpc: true
...kubectl explain nodes --api-version bitcoin.kotal.io/v1alpha1
kubectl explain nodes.spec --api-version bitcoin.kotal.io/v1alpha1Kotal is an open source alternative to centralized API gateway, Node as a service, and Staking service providers. Like Infura in Ethereum ecosystem, Onfinality in Polkadot ecosystem, and Hiro in Stacks ecosystem.
Kotal is multi-client, protocol-agnostic, and cloud-agnostic Blockchain Kubernetes Operator that makes it easy to deploy highly-available self-managing self-healing blockchain infrastructure on any cloud.
Kotal has been tested on Amazon Web Service, Google Cloud Platform, Microsoft Azure, DigitalOcean, Alibab Cloud, Tencent cloud 🤯.
Deploy nodes across 10 Blockchain protocols (Aptos, Bitcoin, Chainkstack, Ethereum, Filecoin, IPFS, NEAR, Polkadot, Stacks)
Upgrade and Downgrade node client software
Load validator keys and start producing blocks
Manage storage and resources (CPU & Memory) allocated to the node
Manage Secrets (private keys, passwords, tokens, certificates)
Monitor resources utilization
Fetch real time logs
Create TLS-secure API endpoints
View API endpoints usage
Create workspaces of nodes and resources
Invite members to workspaces and assign roles
Create rinkeby.yaml manifest that describes an Ethereum node which uses go-ethereum client, connecting to rinkeby network, and enabling JSON-RPC server:
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
name: rinkeby-geth-node
spec:
network: rinkeby
client: geth
rpc: trueDeploy the node using kubectl:
kubectl apply -f rinkeby.yamlWithin a couple of seconds, the node will be up and running. You can get the node using:
kubectl get nodes.ethereumIt will return an output similar to the following:
NAME CLIENT Network Consensus
rinkeby-geth-node geth rinkeby poaKotal will create all the necessary pods, volumes, services for the node. Get the pods by:
kubectl get podsIt will return an output similar to the following:
NAME READY STATUS RESTARTS AGE
rinkeby-geth-node-0 1/1 Running 0 1mFinally delete the node by:
kubectl delete -f rinkeby.yamlCongratulations!
We've extended Kubernetes with Node custom resource which can be used to deploy Chainlink nodes from the given spec.
apiVersion: chainlink.kotal.io/v1alpha1
kind: Node
metadata:
name: my-node
spec:
# your node spec goes hereUsing Chainlink Node custom resource, you can describe any chainlink node, connect to EVM chain node, add jobs and satisfy requests, and Kotal will create all the necessary Kubernetes resources like pods, persistent volumes, services, configmaps, and secrets for you.
If you want to get all the deployted chainlink Node(s):
kubectl get nodes.chainlinkWhich will report node name, client, Ethereum chain ID, and Link contract address.
If you want to get all the fields associated with chainlink Node:
kubectl explain nodes --api-version chainlink.kotal.io/v1alpha1For a comprehensive reference on Chainlink Node, check our chainlink reference
We've extended Kubernetes with Node custom resource which can be used to deploy Ethereum nodes from the given spec.
Using Ethereum Node custom resource, you can describe any public or private network node you want, and Kotal will create all the necessary Kubernetes resources like pods, persistent volumes, services, configmaps, and secrets for you.
If you want to get all the deployted ethereum Node(s):
Which will report node name, client, network, and consensus.
If you want to get all the fields associated with ethereum Node:
For a comprehensive reference on Ethereum Node, check our
Support for OpenEthereum (parity) client has been deprecated. OpenEthereum team is working with Erigon on a smooth transition path for users. More information can be found
Kotal supports the following Ethereum 1 clients:
We've extended Kubernetes with BeaconNode and Validator custom resources which can be used to deploy Ethereum 2.0 beacon nodes and validator clients from the given spec.
BeaconNode is Ethereum 2.0 beacon node -optionally- connecting to Ethereum 1 endpoint and syncing the beacon chain.
Here's an example of ConsenSys Teku beacon node BeaconNode syncing mainnet beacon chain, connecting to Ethereum 1 JSON RPC endpoint, enabling REST API server which is listening at port 8888:
For all the fields associated with the BeaconNode API resource:
Full beacon node reference is documented .
Validator is Ethereum 2.0 validator client connecting to beacon node endpoint and validating blocks using the loaded keystores.
Here's an example of ConsenSys Teku validator client connecting to beacon node endpoint, validating pyrmont blocks using 1 loaded validator keystore from its secret:
For all the fields associated with the Validator API resource:
Full validator client reference is documented .
Kotal supports the following Ethereum 2.0 beacon node and validator clients:
by ConsenSys.
by Sigma Prime.
by Prysmatic Labs.
by Status.im.
Setting validator or beacon node client is as simple as changing the spec.client to the desired client.
We've extended Kubernetes with Node custom resource which can be used to deploy NEAR nodes from the given spec.
Node is NEAR node using client, connecting to and syncing a specific chain, and optionally validating blocks.
For all the fields associated with the Node API resource:
Full NEAR node reference is documented .
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
name: my-node
spec:
# your node spec goes here$ kubectl get nodes.ethereum$ kubectl explain nodes --api-version ethereum.kotal.io/v1alpha1apiVersion: ethereum2.kotal.io/v1alpha1
kind: BeaconNode
metadata:
name: teku-beacon-node
spec:
network: mainnet
client: teku
rest: true
restPort: 8888
eth1Endpoints:
- http://besu-mainnet-node:8545kubectl explain beaconnode --api-version ethereum2.kotal.io/v1alpha1
kubectl explain beaconnode.spec --api-version ethereum2.kotal.io/v1alpha1apiVersion: ethereum2.kotal.io/v1alpha1
kind: Validator
metadata:
name: teku-validator
spec:
network: pyrmont
client: teku
beaconEndpoints:
- http://teku-beacon-node:8888
graffiti: Validated by Kotal
keystores:
- secretName: my-validatorkubectl explain validator --api-version ethereum2.kotal.io/v1alpha1
kubectl explain validator.spec --api-version ethereum2.kotal.io/v1alpha1
kubectl explain validator.spec.keystores --api-version ethereum2.kotal.io/v1alpha1apiVersion: near.kotal.io/v1alpha1
kind: Node
metadata:
Name: near-node
spec:
network: mainnet
rpc: truekubectl explain nodes --api-version near.kotal.io/v1alpha1
kubectl explain nodes.spec --api-version near.kotal.io/v1alpha1Staking is the act of depositing 32 ETH to activate validator software. As a validator you’ll be responsible for storing data, processing transactions, and adding new blocks to the blockchain. This will keep Ethereum secure for everyone and earn you new ETH in the process. This process, known as proof-of-stake, is being introduced by the Beacon Chain. source
apiVersion: ethereum2.kotal.io/v1alpha1
kind: Validator
metadata:
name: teku-validator
spec:
client: teku
network: pyrmont
beaconEndpoints:
- http://teku-beacon-node:9999
graffiti: Validated by Kotal
keystores:
- secretName: my-validatorIn this validator client, we're using ConsenSys Teku Ethereum 2.0 client client: teku, validating pyrmont network blockchain network: pyrmont, connecting to beacon node endpoint using beaconEndpoints: ..., setting the graffiti text to include in the propsed blocks graffiti: validated by Kotal, and loading a validator keystore using keystores: ... from a kubernetes secret called my-validator.
The keystores loaded using spec.keystores[].secretName from kubernetes secret, must contain two data keys:
keystore key hodling the BLS12-381 keystore JSON file
password key holding the encryption key of the keystore.
Let's deploy the validator client:
kubectl apply -f validator.yamlKotal operator will notice your teku-validator and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.
You can fetch the deployed Ethereum 2.0 Validator using:
kubectl get validatorsIt will return an output similar to the following:
NAME CLIENT NETWORK AGE
teku-validator teku pyrmont 1mGet the pods created for the validator client:
kubectl get podsIt will return an output similar to the following:
NAME READY STATUS RESTARTS AGE
teku-validator-0 1/1 Running 0 1mGet the logs of the running validator pod:
kubectl logs -f teku-validator-0You'll get an output similar to the following:
...
21:21:30.668 INFO - Storing validator data in: /opt/teku/kotal-data/validator
21:21:30.751 INFO - Loading 1 validator keys...
21:21:31.759 INFO - Loaded 1 Validators: 83dbb18
...Finally delete the validator client:
kubectl delete validator teku-validatorKubernetes garbage collector will delete all the resources that has been created by Kotal Ethereum 2.0 Validator controller.
The following manifest describes a NEAR node that syncs NEAR mainnet network: mainnet, enables HTTP JSON-RPC server rpc: true and uses NEAR Core client:
apiVersion: near.kotal.io/v1alpha1
kind: Node
metadata:
name: near-node
spec:
network: mainnet
rpc: trueApply near.yaml manifest:
kubectl apply -f near.yamlKotal operator will notice your near-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.
You can fetch the deployed NEAR Node using:
kubectl get nodes.nearIt will return an output similar to the following:
NAME NETWORK CLIENT VALIDATOR
near-node mainnet nearcore fasleGet the pods that has been created by Kotal for the node:
kubectl get podsIt will return an output similar to the following:
NAME READY STATUS RESTARTS AGE
near-node-0 1/1 Running 0 1mGet the logs of the running node:
kubectl logs -f near-node-0It will return node logs similar to the following:
Apr 07 12:18:33.280 INFO neard: Version: 1.23.1, Build: 1.23.0-9-gc0551c84b-modified, Latest Protocol: 50
Apr 07 12:18:33.287 INFO near: Did not find "/home/near/kotal-data/data" path, will be creating new store database
Apr 07 12:18:33.806 INFO stats: Server listening at ed25519:[email protected]:24567
Apr 07 12:18:43.816 INFO stats: # 9820210 Downloading headers 0.00% (53203932) 5/3/40 peers ⬇ 7.2kiB/s ⬆ 0.4kiB/s 0.00 bps 0 gas/s CPU: 0%, Mem: 0 B
Apr 07 12:18:53.819 INFO stats: # 9820210 Downloading headers 0.00% (53203933) 5/3/40 peers ⬇ 7.2kiB/s ⬆ 0.5kiB/s 0.00 bps 0 gas/s CPU: 10%, Mem: 134.4 MiB
Apr 07 12:19:03.787 INFO stats: # 9820210 Downloading headers 0.00% (53203933) 5/3/40 peers ⬇ 7.2kiB/s ⬆ 0.5kiB/s 0.00 bps 0 gas/s CPU: 24%, Mem: 165.9 MiB
Apr 07 12:19:13.790 INFO stats: # 9820210 Downloading headers 0.00% (53203933) 5/3/40 peers ⬇ 7.2kiB/s ⬆ 0.5kiB/s 0.00 bps 0 gas/s CPU: 9%, Mem: 175.0 MiB
...By default, NEAR node JSON-RPC server port is 3030, which can be changed using rpcPort.
Forward localhost:3030 calls to the node pod:
kubectl port-forward near-node-0 3030In another terminal window call status JSON-RPC method to get the general status of our node (sync status, nearcore node version, protocol version) and the current set of validators:
curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "status"}' 0.0.0.0:3030You will get JSON result similar to the following:
{
"jsonrpc": "2.0",
"result": {
"version": {
"version": "1.23.1",
"build": "1.23.0-9-gc0551c84b-modified"
},
"chain_id": "mainnet",
"protocol_version": 29,
"latest_protocol_version": 50,
"rpc_addr": "0.0.0.0:3030",
"validators": [
{
"account_id": "nfvalidator2.near",
"is_slashed": false
},
{
"account_id": "nfvalidator1.near",
"is_slashed": false
},
{
"account_id": "nfvalidator4.near",
"is_slashed": false
},
{
"account_id": "nfvalidator3.near",
"is_slashed": false
}
],
"sync_info": {
"latest_block_hash": "EPnLgE7iEq9s7yTkos96M3cWymH5avBAPm3qx3NXqR8H",
"latest_block_height": 9820210,
"latest_state_root": "5o1trt9N9YgDL4xeY33z9adS5Ub3jMmuyQpWM7UHowrq",
"latest_block_time": "2020-07-21T16:55:51.591948Z",
"syncing": true,
"earliest_block_hash": "EPnLgE7iEq9s7yTkos96M3cWymH5avBAPm3qx3NXqR8H",
"earliest_block_height": 9820210,
"earliest_block_time": "2020-07-21T16:55:51.591948Z"
},
"validator_account_id": "validator"
},
"id": 53
}Finally you can delete the node by:
kubectl delete -f near.yamlKubernetes garbage collector will delete all the resources that has been created by Kotal NEAR Node controller.
Rinkeby is a Proof of Authority public Ethereum test network, used by developers to test their dApps.
The following manifest describes an Ethereum node that joins rinkeby network network: rinkeby, and uses Hyperledger Besu client client: besu:
Apply rinkeby.yaml manifest:
Kotal operator will notice your rinkeby-besu-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.
You can fetch the deployed Ethereum Node using:
It will return an output similar to the following:
Get the pods that has been created by Kotal for the node:
It will return an output similar to the following:
Get the logs of the running node:
Let's update our node by enabling JSON-RPC HTTP server:
Apply the new version of rinkeby.yaml:
Forward localhost:8545 calls to the node pod:
In another terminal window call eth_syncing JSON-RPC method
You will get JSON result similar to the following:
Finally you can delete the node by:
Kubernetes garbage collector will delete all the resources that has been created by Kotal Ethereum Node controller.
Bitcoin nodes that enable JSON-RPC server are required to use basic authentication while calling JSON-RPC methods.
Apply rpc-user-password.yaml to create the password secret:
The following manifest describes a Bitcoin node that syncs Bitcoin mainnet network: mainnet, enables HTTP JSON-RPC server rpc: true, defines JSON-RPC user credentials rpcUsers: ... and uses client:
Apply bitcoin.yaml manifest:
Kotal operator will notice your bitcoin-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.
You can fetch the deployed Bitcoin Node using:
It will return an output similar to the following:
Get the pods that has been created by Kotal for the node:
It will return an output similar to the following:
Get the logs of the running node:
It will return node logs similar to the following:
By default, Bitcoin node JSON-RPC server port is 8332, which can be changed using rpcPort.
Forward localhost:8332 calls to the node pod:
In another terminal window call getblockhash JSON-RPC method to get the genesis block hash:
You will get JSON result similar to the following:
Finally you can delete the node by:
Kubernetes garbage collector will delete all the resources that has been created by Bitcoin Node controller.
The Beacon Chain is the coordination mechanism of the new network, responsible for creating new blocks, making sure those new blocks are valid, and rewarding validators with ETH for keeping the network secure.
In this beacon node, we're using ConsenSys Teku Ethereum 2.0 client client: teku, and syncing the pyrmont network beacon chain network: pyrmont. We also enable REST API server rest: true at port 8888 restPort: 8888. We're connecting to Ethereum 1 endpoint eth1Endpoints: .... Check Ethereum on how to deploy an Ethereum node.
Let's deploy the beacon node:
Kotal operator will notice your teku-beacon-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.
You can fetch the deployed Ethereum 2.0 BeaconNode using:
It will return an output similar to the following:
Get the pods created for the beacon node:
It will return an output similar to the following:
Get the logs of the running beacon node:
/eth/v1/beacon/genesis REST APIGet the service created for the beacon node:
It will return an output similar to the following:
Forward the localhost:8888 calls to the beacon node
In another terminal window, send REST API call to get chain genesis details:
You'll get a result similar to the following:
Finally delete the beacon node:
Kubernetes garbage collector will delete all the resources that has been created by Kotal Ethereum 2.0 BeaconNode controller.
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
name: rinkeby-besu-node
spec:
network: rinkeby
client: besukubectl apply -f rinkeby.yamlkubectl get nodes.ethereumNAME CLIENT Consensus Network
rinkeby-besu-node besu poa rinkebykubectl get podsNAME READY STATUS RESTARTS AGE
rinkeby-besu-node-0 1/1 Running 0 1mkubectl logs -f rinkeby-besu-node-0apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
name: rinkeby-besu-node
spec:
network: rinkeby
client: besu
rpc: truekubectl apply -f rinkeby.yamlkubectl port-forward rinkeby-besu-node-0 8545curl -X POST -H 'content-type: application/json' --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":32}' http://127.0.0.1:8545{
"jsonrpc" : "2.0",
"id" : 32,
"result" : {
"startingBlock" : "0x0",
"currentBlock" : "0x1518",
"highestBlock" : "0x9567a3",
"pulledStates" : "0x203ca",
"knownStates" : "0x200636"
}
}kubectl delete -f rinkeby.yaml
node.ethereum.kotal.io "rinkeby-besu-node" deleted# WARNING: DON'T use the following secret in production
apiVersion: v1
kind: Secret
metadata:
name: kotal-rpc-user-password
stringData:
password: s3cr3tkubectl apply -f rpc-user-password.yamlapiVersion: bitcoin.kotal.io/v1alpha1
kind: Node
metadata:
name: bitcoin-node
spec:
network: mainnet
rpc: true
rpcUsers:
- username: kotal
passwordSecretName: kotal-rpc-user-passwordkubectl apply -f bitcoin.yamlkubectl get nodes.bitcoinNAME NETWORK CLIENT
bitcoin-node mainnet bitcoincorekubectl get podsNAME READY STATUS RESTARTS AGE
bitcoin-node-0 1/1 Running 0 1mkubectl logs -f bitcoin-node-02022-04-09T18:26:45Z Bitcoin Core version v22.0.0 (release build)
2022-04-09T18:26:45Z InitParameterInteraction: parameter interaction: -bind set -> setting -listen=1
2022-04-09T18:26:45Z Assuming ancestors of block 00000000000000000008a89e854d57e5667df88f1cdef6fde2fbca1de5b639ad have valid signatures.
2022-04-09T18:26:45Z Setting nMinimumChainWork=00000000000000000000000000000000000000001fa4663bbbe19f82de910280
2022-04-09T18:26:45Z Using the 'sse4(1way),sse41(4way),avx2(8way)' SHA256 implementation
2022-04-09T18:26:45Z Using RdRand as an additional entropy source
2022-04-09T18:26:45Z Wallet disabled!
...
2022-04-09T18:27:02Z Synchronizing blockheaders, height: 9999 (~1.44%)
2022-04-09T18:27:02Z Synchronizing blockheaders, height: 11999 (~1.73%)
2022-04-09T18:27:02Z Synchronizing blockheaders, height: 13999 (~2.02%)
2022-04-09T18:27:02Z Synchronizing blockheaders, height: 15999 (~2.31%)
2022-04-09T18:27:02Z Synchronizing blockheaders, height: 17999 (~2.61%)
2022-04-09T18:27:03Z Synchronizing blockheaders, height: 19999 (~2.90%)
2022-04-09T18:27:03Z Synchronizing blockheaders, height: 21999 (~3.21%)
2022-04-09T18:27:03Z Synchronizing blockheaders, height: 23999 (~3.51%)
2022-04-09T18:27:04Z Synchronizing blockheaders, height: 25999 (~3.82%)
2022-04-09T18:27:04Z Synchronizing blockheaders, height: 27999 (~4.13%)
2022-04-09T18:27:04Z Synchronizing blockheaders, height: 29999 (~4.43%)
...kubectl port-forward bitcoin-node-0 8332curl --user "kotal:s3cr3t" --data-binary '{"jsonrpc": "1.0", "id": 1, "method": "getblockhash", "params": [0]}' -H 'content-type: text/plain;' http://0.0.0.0:8332{
"result":"000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
"error":null,
"id":1
}kubectl delete -f bitcoin.yamlapiVersion: ethereum2.kotal.io/v1alpha1
kind: BeaconNode
metadata:
name: teku-beacon-node
spec:
network: pyrmont
client: teku
rest: true
restPort: 8888
eth1Endpoints:
- http://goerli-besu-node:8545kubectl apply -f beacon.yamlkubectl get beaconnodesNAME CLIENT Network AGE
teku-beacon-node teku pyrmont 1mkubectl get podsNAME READY STATUS RESTARTS AGE
teku-beacon-node-0 1/1 Running 0 1mkubectl logs -f teku-beacon-node-0kubectl get servicesNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
teku-beacon-node ClusterIP 10.96.197.218 <none> 9000/UDP,9000/TCP,8888/TCP 7skubectl port-forward teku-beacon-node-0 8888curl localhost:8888/eth/v1/beacon/genesis{
"data": {
"genesis_time": "1606824023",
"genesis_validators_root": "0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95",
"genesis_fork_version": "0x00000000"
}
}kubectl delete beaconnode teku-beacon-nodeThe following manifest describes a Polkadot node that syncs Polkadot relay chain network: polkadot, enables HTTP JSON-RPC server rpc: true on custom port rpcPort: 8888, and uses Parity Polkadot client:
apiVersion: polkadot.kotal.io/v1alpha1
kind: Node
metadata:
name: polkadot-node
spec:
network: polkadot
rpc: true
rpcPort: 8888Apply polkadot.yaml manifest:
kubectl apply -f polkadot.yamlKotal operator will notice your polkadot-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.
You can fetch the deployed Polkadot Node using:
kubectl get nodes.polkadotIt will return an output similar to the following:
NAME NETWORK VALIDATOR
polkadot-node polkadot fasleGet the pods that has been created by Kotal for the node:
kubectl get podsIt will return an output similar to the following:
NAME READY STATUS RESTARTS AGE
polkadot-node-0 1/1 Running 0 1mGet the logs of the running node:
kubectl logs -f polkadot-node-0It will return node logs similar to the following:
2021-10-17 22:15:12 Parity Polkadot
2021-10-17 22:15:12 ✌️ version 0.9.11-bfd38ed62-x86_64-linux-gnu
2021-10-17 22:15:12 ❤️ by Parity Technologies <[email protected]>, 2017-2021
2021-10-17 22:15:12 📋 Chain specification: Polkadot
2021-10-17 22:15:12 🏷 Node name: polkadot-node
2021-10-17 22:15:12 👤 Role: FULL
2021-10-17 22:15:12 💾 Database: RocksDb at /polkadot/kotal-data/chains/polkadot/db/full
2021-10-17 22:15:12 ⛓ Native runtime: polkadot-9110 (parity-polkadot-0.tx8.au0)
2021-10-17 22:15:12 🔨 Initializing Genesis block/state (state: 0x29d0…4e17, header-hash: 0x91b1…90c3)
2021-10-17 22:15:12 👴 Loading GRANDPA authority set from genesis on what appears to be first startup.
2021-10-17 22:15:13 ⏱ Loaded block-time = 6s from block 0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3
2021-10-17 22:15:13 👶 Creating empty BABE epoch changes on what appears to be first startup.
2021-10-17 22:15:13 🏷 Local node identity is: 12D3KooWRo3vvfgPdsJ44tXu1Y2GeFNmC9ror2HsdJjvSjEcfZdw
2021-10-17 22:15:13 📦 Highest known block at #0
2021-10-17 22:15:13 Listening for new connections on 127.0.0.1:9944.
2021-10-17 22:15:13 🔍 Discovered new external address for our node: /ip4/102.189.29.174/tcp/30333/ws/p2p/12D3KooWRo3vvfgPdsJ44tXu1Y2GeFNmC9ror2HsdJjvSjEcfZdw
2021-10-17 22:15:18 ⚙️ Syncing, target=#7304424 (1 peers), best: #64 (0x4983…1114), finalized #0 (0x91b1…90c3), ⬇ 37.0kiB/s ⬆ 17.6kiB/sForward localhost:8888 calls to the node pod because rpcPort: 8888:
kubectl port-forward polkadot-node-0 8888In another terminal window call eth_getBlock JSON-RPC method to get the latest synced block:
curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "chain_getBlock", "params": []}' 0.0.0.0:8888You will get JSON result similar to the following:
{
"jsonrpc": "2.0",
"result": {
"block": {
"extrinsics": [
"0x280403000be06ab2527201",
"0x14040a00912e",
"0x1004140000"
],
"header": {
"digest": {
"logs": [
"0x0642414245b501030000000042eacc0f00000000f414617b1dbce8671e029af90ae45c4b51d2f8d77d7876ae5f19dd42b7cb213775f40642dc2d86dd0a16169008e2d8735c849d7113da468be33b1c85819310024daffbee165156a2c17919fdc592754960a5587b6affc81f3e9c260364da2200",
"0x054241424501019243678a110c1271c784ba9abaf03e08ae635ea766ce953853bfb1e3c0f70b5c95907240de74e57aa379c8428cd9933f097e32f9ef82caf261277ba4dc573b8b"
]
},
"extrinsicsRoot": "0xd9c14a96f36005ef6487ff56cb4722ff64afa3535cb1464c988767084094566c",
"number": "0xba7",
"parentHash": "0xcfb74aa6750036482897f63806191b3b14447186e45f69c43fcb72e02b57871f",
"stateRoot": "0x5116aa11f10b1b1ce7c05ea85de08238b7db4c2c485bc88a9167e3b0a153368b"
}
},
"justifications": null
},
"id": 1
}Finally you can delete the node by:
kubectl delete -f polkadot.yaml
node.polkadot.kotal.io "polkadot-node" deletedKubernetes garbage collector will delete all the resources that has been created by Kotal Polkadot Node controller.
apiVersion: ipfs.kotal.io/v1alpha1
kind: Peer
metadata:
name: simple-peer
spec: {}This is a simple ipfs peer that joins the public ipfs swarm, and will starts with the all default settings that's similar to running ipfs init then ipfs daemon on your machine.
Let's deploy the peer:
kubectl apply -f peer.yamlKotal operator will notice your simple-peer and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.
kubectl get peersIt will return an output similar to the following:
NAME CLIENT
simple-peer go-ipfsGet the pods created for the peer:
kubectl get podsIt will return an output similar to the following:
NAME READY STATUS RESTARTS AGE
simple-peer-0 1/1 Running 0 5mCheck the logs of the running peer:
kubectl logs -f simple-peer-0You'll get output similar to the following:
Initializing daemon...
go-ipfs version: 0.8.0-ce693d7
Repo version: 11
System version: amd64/linux
Golang version: go1.14.4
Swarm listening on /ip4/10.244.0.6/tcp/4001
Swarm listening on /ip4/10.244.0.6/udp/4001/quic
Swarm listening on /ip4/127.0.0.1/tcp/4001
Swarm listening on /ip4/127.0.0.1/udp/4001/quic
Swarm listening on /ip6/::1/tcp/4001
Swarm listening on /ip6/::1/udp/4001/quic
Swarm listening on /p2p-circuit
Swarm announcing /ip4/10.244.0.6/tcp/4001
Swarm announcing /ip4/10.244.0.6/udp/4001/quic
Swarm announcing /ip4/127.0.0.1/tcp/4001
Swarm announcing /ip4/127.0.0.1/udp/4001/quic
Swarm announcing /ip6/::1/tcp/4001
Swarm announcing /ip6/::1/udp/4001/quic
API server listening on /ip4/0.0.0.0/tcp/5001
WebUI: http://0.0.0.0:5001/webui
Gateway (readonly) server listening on /ip4/0.0.0.0/tcp/8080
Daemon is readyYour peer is up and running and ready to receive api calls.
Let's forward localhost:5001 calls to simple-peer:5001
kubectl port-forward simple-peer-0 5001In another terminal window, send http api call using cURL:
curl -X POST "http://127.0.0.1:5001/api/v0/cat?arg=QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/readme"You'll get the following output:
Hello and Welcome to IPFS!
██╗██████╗ ███████╗███████╗
██║██╔══██╗██╔════╝██╔════╝
██║██████╔╝█████╗ ███████╗
██║██╔═══╝ ██╔══╝ ╚════██║
██║██║ ██║ ███████║
╚═╝╚═╝ ╚═╝ ╚══════╝
If you're seeing this, you have successfully installed
IPFS and are now interfacing with the ipfs merkledag!
-------------------------------------------------------
| Warning: |
| This is alpha software. Use at your own discretion! |
| Much is missing or lacking polish. There are bugs. |
| Not yet secure. Read the security notes for more. |
-------------------------------------------------------
Check out some of the other files in this directory:
./about
./help
./quick-start <-- usage examples
./readme <-- this file
./security-notesYou can also view ipfs webui by visiting http://0.0.0.0:5001/webui
Finally, delete the ipfs peer:
kubectl delete -f peer.yamlKubernetes garbage collector will delete all the resources that has been created by Kotal IPFS Peer controller.
Stacks node requires a Bitcoin node to connect to on the back-end for Proof of Transfer. You can deploy a Bitcoin node using Kotal operator like we did in this guide. In this tutorial, we will be using Bitcoin node hosted by Stacks Foundation.
Make sure Bitcoin node is fully synced before deploying your Stacks node.
Let's store Stacks Foundation Bitcoin node JSON-RPC password in a Kubernetes secret to be used by our node:
apiVersion: v1
kind: Secret
metadata:
name: bitcoin-node-rpc-password
stringData:
password: blockstacksystemApply bitcoin-node-rpc-password.yaml to create the password secret:
kubectl apply -f bitcoin-node-rpc-password.yamlThe following manifest describes a Stacks node that syncs Stacks mainnet network: mainnet, and connects to the bitcoin node using configurations in bitcoinNode: ... for Proof of Transfer:
apiVersion: stacks.kotal.io/v1alpha1
kind: Node
metadata:
name: stacks-node
spec:
network: mainnet
bitcoinNode:
endpoint: bitcoin.blockstack.com
rpcPort: 8332
p2pPort: 8333
rpcUsername: blockstack
rpcPasswordSecretName: bitcoin-node-rpc-passwordApply stacks.yaml manifest:
kubectl apply -f stacks.yamlKotal operator will notice your stacks-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.
You can fetch the deployed Stacks Node using:
kubectl get nodes.stacksIt will return an output similar to the following:
NAME NETWORK CLIENT MINER
stacks-node mainnet stacks falseGet the pods that has been created by Kotal for the node:
kubectl get podsIt will return an output similar to the following:
NAME READY STATUS RESTARTS AGE
stacks-node-0 1/1 Running 0 1mGet the logs of the running node:
kubectl logs -f stacks-node-0It will return node logs similar to the following:
INFO [1649597250.010714] [testnet/stacks-node/src/main.rs:113] [main] Loading config at path /home/stacks/kotal-config/config.toml
INFO [1649597250.599067] [testnet/stacks-node/src/run_loop/neon.rs:341] [main] Start syncing Bitcoin headers, feel free to grab a cup of coffee, this can take a while
INFO [1649597251.949664] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 0.3% (2000 out of 731268)
INFO [1649597253.010039] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 0.5% (4000 out of 731268)
INFO [1649597254.019798] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 0.8% (6000 out of 731268)
INFO [1649597254.992070] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 1.1% (8000 out of 731268)
INFO [1649597256.214756] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 1.4% (10000 out of 731268)
INFO [1649597257.276950] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 1.6% (12000 out of 731268)
INFO [1649597258.383248] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 1.9% (14000 out of 731268)
...By default, Stacks node JSON-RPC server port is 20443, which can be changed using rpcPort.
Forward localhost:20443 calls to the node pod:
kubectl port-forward bitcoin-node-0 20443HTTP server will start after Bitcoin headers sync, till then you will get the following error if you tried to send JSON-RPC calls:
curl: (52) Empty reply from serverIn another terminal window call info JSON-RPC method to retrieve information about the Core API including the server version:
curl localhost:20443/v2/infoYou will get JSON result similar to the following:
{
"peer_version": 402653189,
"pox_consensus": "9bed78c9f02d2ba5a5950fe88c4746436b47c730",
"burn_block_height": 666051,
"stable_pox_consensus": "0000000000000000000000000000000000000000",
"stable_burn_block_height": 666050,
"server_version": "stacks-node No Version Info (No Branch Info:No Commit Info, release build, linux [x86_64])",
"network_id": 1,
"parent_network_id": 3652501241,
"stacks_tip_height": 0,
"stacks_tip": "0000000000000000000000000000000000000000000000000000000000000000",
"stacks_tip_consensus_hash": "0000000000000000000000000000000000000000",
"genesis_chainstate_hash": "74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b",
"unanchored_tip": null,
"unanchored_seq": null,
"exit_at_block_height": null
}Finally you can delete the node by:
kubectl delete -f stacks.yamlKubernetes garbage collector will delete all the resources that has been created by Stacks Node controller.
In this tutorial we will use the following private keys and their corresponding addresses.
DON'T use these keys in production.
Let's describe an Ethereum Node that uses a custom genesis block to join a private Proof of Authority network using Clique consensus configuration in the genesis block.
In this node, we're using Hyperledger besu client client: besu, enabling JSON-RPC server rpc: true so we can query number of peers later in this tutorial, and we're loading the node private key from Kubernetes secretd called besu-clique-nodekey.
The node private key will give the node a unique identity and node URL, and will allow the node to generate blocks, because the address 0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa that's corresponding to the node private key is in the initial block signers.
We're defining a genesis block that uses the value 4444 as network and chain identifier, and we start the chain with 3 signers as defined by spec.genesis.clique.signers.
This node private key secret can be created by:
Let's deploy the node:
Kotal operator will notice your besu-clique-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.
You can fetch the deployed Ethereum Node using:
It will return an output similar to the following:
Get the pods that has been created by Kotal for the node:
It will return an output similar to the following:
Get the logs of the running node:
Let's deploy another go-ethereum node, and connect it to the previous node in our private proof of authority network.
In this node, we're using go-ethereum client client: geth, starting the PoA consensus engine miner: true, setting the second address in the genesis signers list spec.genesis.clique.signers as the coinbase coinbase: "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d", and loading the signer account private key and password from kubernetes secrets privateKeySecretName: ... and passwordSecretName: .... We're connecting to the first node using staticNodes option which accepts Node name or enode url.
You can create the private key and password secrets using:
Deploy the second node using:
Kotal operator will notice your second geth-clique-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.
You can fetch the deployed Ethereum Nodes using:
It will return an output similar to the following:
net_peerCountGet the pods that has been created by Kotal for the node:
It will return an output similar to the following:
Forward localhost:8545 calls to the node pod:
In another terminal window call net_peerCount JSON-RPC method
You will get JSON result similar to the following:
Deploy a third node that uses Nethermind client, and signing blocks using the third key in the signers list spec.genesis.clique.signers. Nethermind client is similar to geth, you will import signer account private key and password from kubernetes secrets, and use the same genesis as the other nodes.
Finally you can delete all the nodes by:
Kubernetes garbage collector will delete all the resources that has been created by Kotal Ethereum Node controller.
In this tutorial we will use the following private keys and their corresponding addresses.
DON'T use these keys in production.
Let's describe an Ethereum Node that uses a custom genesis block to join a private Proof of Work network using Ethash consensus configuration in the genesis block.
In this node, we're using Hyperledger besu client client: besu, enabling JSON-RPC server rpc: true so we can query number of peers later in this tutorial, turning on Proof of Work mining miner: true, setting the address that will collect block reward using coinbase, and we're loading the node private key from Kubernetes secretd called besu-ethash-nodekey, this is the private from which the coinbase address is derived.
We're defining a genesis block that uses the value 4444 as network and chain identifier, and used ethash proof of work consensus engine.
This node private key secret can be created by:
Let's deploy the node:
Kotal operator will notice your besu-ethash-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.
You can fetch the deployed Ethereum Node using:
It will return an output similar to the following:
Get the pods that has been created by Kotal for the node:
It will return an output similar to the following:
Get the logs of the running node:
Let's deploy another go-ethereum node, and connect it to the previous node in our private proof of work network.
In this node, we're using go-ethereum client client: geth, turning on Proof of Work mining miner: true, setting the address that will collect block reward using coinbase, and loading the miner account private key and password from kubernetes secrets privateKeySecretName: ... and passwordSecretName: .... We're connecting to the first node using staticNodes option which accepts Node name or enode url.
You can create the private key and password secrets using:
Deploy the second node using:
Kotal operator will notice your second geth-ethash-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.
You can fetch the deployed Ethereum Nodes using:
It will return an output similar to the following:
net_peerCountGet the pods that has been created by Kotal for the node:
It will return an output similar to the following:
Forward localhost:8545 calls to the node pod:
In another terminal window call net_peerCount JSON-RPC method
You will get JSON result similar to the following:
Deploy a third node that uses Nethermind client, and use the third private key and address from the table above. Nethermind client is similar to geth, you will import signer account private key and password from kubernetes secrets, and use the same genesis as the other nodes.
Finally you can delete all the nodes by:
Kubernetes garbage collector will delete all the resources that has been created by Kotal Ethereum Node controller.
0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa
fb5411342ae51291447515c89bcf6a057e3dbd0b51e060c45cb73406c38f851d
0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d
153b174f5e9948ae4678baed54f88244cc9c39d56b9f17ecef93d7ede633f56b
0x7DE985E2f878c83C4e91b6B1312c0f63A56C844a
89b03c4de62d61be16d22e09c8a48929a9bccd11fa6b37809cfef290292bcba3
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
name: besu-clique-node
spec:
client: besu
nodePrivateKeySecretName: besu-clique-nodekey
rpc: true
genesis:
chainId: 4444
networkId: 4444
clique:
signers:
- "0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa"
- "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d"
- "0x7DE985E2f878c83C4e91b6B1312c0f63A56C844a"kubectl create secret generic besu-clique-nodekey --from-literal=key=fb5411342ae51291447515c89bcf6a057e3dbd0b51e060c45cb73406c38f851dkubectl apply -f besu-clique-node.yamlkubectl get nodes.ethereumNAME CLIENT Consensus Network
besu-clique-node besu poa privatekubectl get podsNAME READY STATUS RESTARTS AGE
besu-clique-node-0 1/1 Running 0 1mkubectl logs -f besu-clique-node-0apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
name: geth-clique-node
spec:
client: geth
miner: true
coinbase: "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d"
import:
privateKeySecretName: geth-clique-account-key
passwordSecretName: geth-clique-account-password
staticNodes:
- besu-clique-node
genesis:
chainId: 4444
networkId: 4444
clique:
signers:
- "0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa"
- "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d"
- "0x7DE985E2f878c83C4e91b6B1312c0f63A56C844a"kubectl create secret generic geth-clique-account-key --from-literal=key=153b174f5e9948ae4678baed54f88244cc9c39d56b9f17ecef93d7ede633f56b
kubectl create secret generic geth-clique-account-password --from-literal=password=s3cr3tkubectl apply -f geth-clique-node.yamlkubectl get nodes.ethereumNAME CLIENT Consensus Network
besu-clique-node besu poa private
geth-clique-node geth poa privatekubectl get podsNAME READY STATUS RESTARTS AGE
besu-clique-node-0 1/1 Running 0 1m
geth-clique-node-0 1/1 Running 0 1mkubectl port-forward besu-clique-node-0 8545curl -X POST -H 'content-type: application/json' --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":32}' http://127.0.0.1:8545{
"jsonrpc" : "2.0",
"id" : 32,
"result" : "0x1"
}kubectl delete nodes.ethereum --all0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa
fb5411342ae51291447515c89bcf6a057e3dbd0b51e060c45cb73406c38f851d
0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d
153b174f5e9948ae4678baed54f88244cc9c39d56b9f17ecef93d7ede633f56b
0x7DE985E2f878c83C4e91b6B1312c0f63A56C844a
89b03c4de62d61be16d22e09c8a48929a9bccd11fa6b37809cfef290292bcba3
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
name: besu-ethash-node
spec:
client: besu
nodePrivateKeySecretName: besu-ethash-nodekey
rpc: true
miner: true
coinbase: "0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa"
genesis:
chainId: 4444
networkId: 4444
ethash: {}kubectl create secret generic besu-ethash-nodekey --from-literal=key=fb5411342ae51291447515c89bcf6a057e3dbd0b51e060c45cb73406c38f851dkubectl apply -f besu-ethash-node.yamlkubectl get nodes.ethereumNAME CLIENT Consensus Network
besu-ethash-node besu pow privatekubectl get podsNAME READY STATUS RESTARTS AGE
besu-ethash-node-0 1/1 Running 0 1mkubectl logs -f besu-ethash-node-0apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
name: geth-ethash-node
spec:
client: geth
rpc: true
miner: true
coinbase: "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d"
import:
privateKeySecretName: geth-ethash-account-key
passwordSecretName: geth-ethash-account-password
staticNodes:
- besu-ethash-node
genesis:
chainId: 4444
networkId: 4444
ethash: {}kubectl create secret generic geth-ethash-account-key --from-literal=key=153b174f5e9948ae4678baed54f88244cc9c39d56b9f17ecef93d7ede633f56b
kubectl create secret generic geth-ethash-account-password --from-literal=password=s3cr3tkubectl apply -f geth-ethash-node.yamlkubectl get nodes.ethereumNAME CLIENT Consensus Network
besu-ethash-node besu pow private
geth-ethash-node geth pow privatekubectl get podsNAME READY STATUS RESTARTS AGE
besu-ethash-node-0 1/1 Running 0 1m
geth-ethash-node-0 1/1 Running 0 1mkubectl port-forward besu-ethash-node-0 8545curl -X POST -H 'content-type: application/json' --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":32}' http://127.0.0.1:8545{
"jsonrpc" : "2.0",
"id" : 32,
"result" : "0x1"
}kubectl delete nodes.ethereum --allKubernetes cluster
Cert Manager
For development and testing purposes we recommend using kind (Kubernetes in Docker), it's an easy way to create and tear down kubernetes clusters in seconds. For staging and production purposes you can use any public cloud kubernetes as a service like Amazon EKS, Azure AKS or Google GKE.
kind installation guide can be found here.
Cert Manager is a native Kubernetes certificate management controller. It can help with issuing certificates from a variety of sources, such as Let’s Encrypt, HashiCorp Vault, a simple signing key pair, or self-signed. It will ensure certificates are valid and up to date, and attempt to renew certificates at a configured time before expiry.
Kotal webhook component uses cert-manager for issuing certificates to default and validate your Blockchain resources such as nodes, beacon nodes, ipfs peers ... etc.
cert-manager installation guide can be found here.
The latest version of Kotal operator v0.3.0 can be installed into your Kubernetes cluster simply by:
kubectl apply -f https://github.com/kotalco/kotal/releases/download/v0.3.0/kotal.yamlrequired
string
NEAR network to join and sync
string
Kubernetes secret name holding node Ed25519 private key
string
Kubernetes secret name holding node Ed25519 validator key
number
Minimum number of peers to start syncing/producing blocks
5
boolean
Keeps old blocks in the storage
false
number
p2p protocol tcp port
24567
string
p2p host
0.0.0.0
boolean
Enables JSON-RPC server
false
number
JSON-RPC server listening port
3030
string
JSON-RPC server listening host
0.0.0.0
number
Prometheus exporter port
9615
string
Prometheus exporter host
0.0.0.0
string
Telemetry service URL
array
Boot nodes to bootstrap network from
object
node compute and storage resources to alloacte
network is NEAR network to join and sync. Possible values are mainnet, testnet, and betanet.
network is immutable, it can't be changed after node is created.
nodePrivateKeySecretName is Kubernetes secret name holding node Ed25519 private key in data field key, from which node public key is generated, and p2p messages are signed.
validatorSecretName is Kubernetes secret name holding node Ed25519 validator key in data field key.
minPeers is the minimum number of peers to start syncing/producing blocks.
archive keeps old blocks in the storage.
p2pPort is p2p protocol tcp port.
p2pHost is p2p host address.
rpc enables JSON-RPC server.
rpcPort is JSON-RPC server listening port.
rpcHost is JSON-RPC server listening host address.
prometheusPort is Prometheus exporter port.
prometheusHost is Prometheus exporter host address.
telemetryURL is Telemetry service URL.
bootnodes is a list of boot nodes to bootstrap network from
resources allocates compute and storage resources to the node.
cpu
string
number of cpu cores this node requires
4
cpuLimit
string
number of cpu cores this node is limited to
8
memory
string
memory this node requires
4Gi
memoryLimit
string
memory this node is limited to
8Gi
storage
string
disk space this node requires
250Gi for non archival node, 4Ti for archive node
storageClass
string
Node volume storage class
Cluster's default storage class will be used as defined by cluster admin or cloud provider
memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.
cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1), 1500m, 2, and 4.
cpuLimit can't be less than cpu.
memoryLimit can't be less than or equal to memory.
storageClass field is immutable, it cannot be changed after creation.
network is Bitcoin network to join and sync. Possible values are mainnet and testnet.
network is immutable, can't be changed after node is created.
p2pPort is p2p communications port.
p2pHost is p2p communications host.
rpc enables JSON-RPC server.
rpcPort is JSON-RPC server port.
rpcHost is JSON-RPC server host.
rpcUsers is a list of JSON-RPC users credentials:
wallet loads local wallet and enables wallet RPC calls.
txIndex maintains a full transaction index.
resources allocates compute and storage resources to the node.
memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.
cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1), 1500m, 2, and 4.
cpuLimit can't be less than cpu.
memoryLimit can't be less than or equal to memory.
storageClass field is immutable, it cannot be changed after creation.
network required
string
Bitcoin network to join and sync
number
p2p communications port
8333 for mainnet, 18333 for testnet
string
p2p communication host
0.0.0.0
boolean
Enables JSON-RPC server
false
number
JSON-RPC server port
8332 for mainnet, 18332 for testnet
string
JSON-RPC server host
0.0.0.0
array
JSON-RPC users credentials
boolean
Load local wallet and enables wallet RPC calls
false
boolean
Maintains a full transaction index
false
object
node compute and storage resources to alloacte
username
string
JSON-RPC user name
passwordSecretName
string
Kubernetes secret name holding JSON-RPC user password
cpu
string
number of cpu cores this node requires
2
cpuLimit
string
number of cpu cores this node is limited to
4
memory
string
memory this node requires
4Gi
memoryLimit
string
memory this node is limited to
8Gi
storage
string
disk space this node requires
100Gi
storageClass
string
Node volume storage class
Cluster's default storage class will be used as defined by cluster admin or cloud provider
IPFS Cluster provides data orchestration across a swarm of IPFS daemons by allocating, replicating and tracking a global pinset distributed among multiple peers. Source
Before we start, you need to:
Deploy an ipfs peer Peer because it's required by ClusterPeer. Check our Deploy IPFS Peer tutorial.
Create a cluster secret which secures access to the cluster:
CLUSTER_SECRET=$(openssl rand -hex 32)
kubectl create secret generic cluster-secret --from-literal=secret=$CLUSTER_SECRETCluster secret must be 32-byte hex-encoded (64 characters) without the leading 0x. It must be hold in data field called secret in the Kubernetes secret.
Create cluster peer ID and private key using ipfs-key
ipfs-key -type ed25519 | base64It will return an output similar to the following:
Generating a 2048 bit ed25519 key...
Success!
ID for generated key: 12D3KooWBcEtY8GH4mNkri9kM3haeWhEXtQV7mi81ErWrqLYGuiq
CAESQOH/DvUJmeJ9z6m3wAStpkrlBwJQxIyNSK0YGf0EI5ZRGpwsWxl4wmgReqmHl8LQjTC2iPM0QbYAjeY3Z63AFnI=create Kubernetes secret from the generated private key in step(3) above.
CLUSTER_PEER_PRIVATEKEY=CAESQOH/DvUJmeJ9z6m3wAStpkrlBwJQxIyNSK0YGf0EI5ZRGpwsWxl4wmgReqmHl8LQjTC2iPM0QbYAjeY3Z63AFnI=
kubectl create secret generic cluster-peer-privatekey --from-literal=key=$CLUSTER_PEER_PRIVATEKEYNow we're ready to deploy the cluster peer and connect it to the peer we've deployed in step(1)
apiVersion: ipfs.kotal.io/v1alpha1
kind: ClusterPeer
metadata:
Name: cluster-peer
spec:
consensus: crdt
# from step(3)
id: "12D3KooWBcEtY8GH4mNkri9kM3haeWhEXtQV7mi81ErWrqLYGuiq"
# from step(4)
privateKeySecretName: cluster-peer-privatekey
# from step(1)
peerEndpoint: /dns4/peer-sample/tcp/5001
# from step(2)
clusterSecretName: cluster-secretLet's deploy cluster peer manifest file:
kubectl apply -f cluster-peer.yamlKotal operator will notice your cluster-peer and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.
You can fetch the deployed IPFS ClusterPeer using:
kubectl get clusterpeersIt will return an output similar to the following:
NAME CLIENT CONSENSUS
cluster-peer ipfs-cluster-service crdtGet the pods created for our cluster peer:
kubectl get podsIt will return an output similar to the following:
NAME READY STATUS RESTARTS AGE
cluster-peer-0 1/1 Running 0 2mCheck the logs of the running cluster peer:
kubectl logs -f cluster-peer-0It will return an output similar to the following:
2021-04-30T00:31:24.109Z INFO service ipfs-cluster-service/daemon.go:46 Initializing. For verbose output run with "-l debug". Please wait...
2021-04-30T00:31:24.133Z INFO cluster ipfs-cluster/cluster.go:136 IPFS Cluster v0.13.2+git812c8e3631d4d6771a6e04112e12cd7726e23f7a listening on:
/ip4/10.244.0.8/tcp/9096/p2p/12D3KooWBcEtY8GH4mNkri9kM3haeWhEXtQV7mi81ErWrqLYGuiq
/ip4/127.0.0.1/tcp/9096/p2p/12D3KooWBcEtY8GH4mNkri9kM3haeWhEXtQV7mi81ErWrqLYGuiq
2021-04-30T00:31:24.134Z INFO ipfsproxy ipfsproxy/ipfsproxy.go:320 IPFS Proxy: /ip4/127.0.0.1/tcp/9095 -> /ip4/127.0.0.1/tcp/5001
2021-04-30T00:31:24.134Z INFO restapi rest/restapi.go:521 REST API (HTTP): /ip4/127.0.0.1/tcp/9094
2021-04-30T00:31:24.134Z INFO crdt [email protected]/crdt.go:278 crdt Datastore created. Number of heads: 0. Current max-height: 0
2021-04-30T00:31:24.136Z INFO cluster ipfs-cluster/cluster.go:651 Cluster Peers (without including ourselves):
2021-04-30T00:31:24.136Z INFO cluster ipfs-cluster/cluster.go:653 - No other peers
2021-04-30T00:31:24.136Z INFO cluster ipfs-cluster/cluster.go:666 ** IPFS Cluster is READY **As you can see from the logs that our cluster peer is up and running as indicated by the healthy logs IPFS Cluster is READY.
Let's add some content to the pinset by executing commands inside cluster peer container:
$ kubectl exec -it cluster-peer-0 -- sh
# now we're inside cluster-peer container
$ echo "kotal simplifies Blockchain DevOps" > kotal.txt
# add kotal.txt to the pinset
$ ipfs-cluster-ctl add kotal.txt
added QmUiwYtz1VxeryVCpTLWqrbeUi9HyGH4AnpSG6BrmdMhzL kotal.txt
# leave cluster-peer container
$ exitLet's fetch the pinset of the ipfs peer by executing commands inside peer -created in step(1)- container:
$ kubectl exec -it peer-sample-0 -- sh
# now we're inside peer-sample container
# List objects pinned to local storage
$ ipfs pin ls
QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn recursive
QmUiwYtz1VxeryVCpTLWqrbeUi9HyGH4AnpSG6BrmdMhzL recursive
$ ipfs cat QmUiwYtz1VxeryVCpTLWqrbeUi9HyGH4AnpSG6BrmdMhzL
kotal simplifies Blockchain DevOps
# leave ipfs peer container
$ exitAs you can see, content pinned by the cluster peer, has been added to the pinset of the ipfs peer and available in its local storage.
The only prerequisite to the second cluster peer is to:
Deploy an ipfs peer Peer, and name it peer-sample-two. Check our Deploy IPFS Peer tutorial.
We will reuse cluster secret that was generated in step(2) during deploying first cluster peer above.
apiVersion: ipfs.kotal.io/v1alpha1
kind: ClusterPeer
metadata:
Name: cluster-peer-two
spec:
# from step(1)
peerEndpoint: /dns4/peer-sample-twp/tcp/5001
# generated during deploying first cluster peer in step(2)
clusterSecretName: cluster-secret
# first cluster peer listening address
bootstrapPeers:
- /ip4/cluster-peer/tcp/9096/p2p/12D3KooWBcEtY8GH4mNkri9kM3haeWhEXtQV7mi81ErWrqLYGuiqDeploying this cluster manifest will deploy a cluster peer that connects to the first cluster peer and will connect to its own ipfs peer peer-sample-two instance.
kubectl apply -f cluster-peer-two.yamlYou can fetch the deployed cluster peers by:
kubectl get clusterpeersIt will return an output similar to the following:
NAME CLIENT CONSENSUS
cluster-peer ipfs-cluster-service crdt
cluster-peer-two ipfs-cluster-service crdtGet the pods created by our cluster peer:
kubectl get podsIt will return an output similar to the following:
NAME READY STATUS RESTARTS AGE
cluster-peer-0 1/1 Running 0 10m
cluster-peer-two-0 1/1 Running 0 2mCheck the logs of cluster peer two:
kubectl logs -f cluster-peer-two-0It will return an output similar to the following:
2021-05-01T19:17:12.043Z INFO service ipfs-cluster-service/daemon.go:46 Initializing. For verbose output run with "-l debug". Please wait...
2021-05-01T19:17:12.352Z INFO cluster ipfs-cluster/cluster.go:136 IPFS Cluster v0.13.2+git812c8e3631d4d6771a6e04112e12cd7726e23f7a listening on:
/ip4/10.244.0.35/tcp/9096/p2p/12D3KooWGVZek7gdarvj7gePvnV9x8ekSeSdruYojgj5dmU466Wv
/ip4/127.0.0.1/tcp/9096/p2p/12D3KooWGVZek7gdarvj7gePvnV9x8ekSeSdruYojgj5dmU466Wv
2021-05-01T19:17:12.441Z INFO restapi rest/restapi.go:521 REST API (HTTP): /ip4/127.0.0.1/tcp/9094
2021-05-01T19:17:12.441Z INFO ipfsproxy ipfsproxy/ipfsproxy.go:320 IPFS Proxy: /ip4/127.0.0.1/tcp/9095 -> /ip4/127.0.0.1/tcp/5001
2021-05-01T19:17:12.441Z INFO service ipfs-cluster-service/daemon.go:218 Bootstrapping to /dns4/cluster-peer/tcp/9096/p2p/12D3KooWBcEtY8GH4mNkri9kM3haeWhEXtQV7mi81ErWrqLYGuiq
2021-05-01T19:17:12.442Z INFO crdt [email protected]/crdt.go:278 crdt Datastore created. Number of heads: 0. Current max-height: 0
2021-05-01T19:17:12.442Z INFO crdt crdt/consensus.go:277 'trust all' mode enabled. Any peer in the cluster can modify the pinset.
2021-05-01T19:17:12.447Z INFO cluster ipfs-cluster/cluster.go:651 Cluster Peers (without including ourselves):
2021-05-01T19:17:12.447Z INFO cluster ipfs-cluster/cluster.go:653 - No other peers
2021-05-01T19:17:12.448Z INFO cluster ipfs-cluster/cluster.go:666 ** IPFS Cluster is READY **
2021-05-01T19:17:12.551Z INFO cluster ipfs-cluster/cluster.go:1020 12D3KooWGVZek7gdarvj7gePvnV9x8ekSeSdruYojgj5dmU466Wv: joined 12D3KooWBcEtY8GH4mNkri9kM3haeWhEXtQV7mi81ErWrqLYGuiq's clusterAs you can see cluster peer two is up and running as indicated by the healthy logs and IPFS Cluster is READY.
Cluster peer two has joined the first cluster peer as indicated by the highlighted log line joined 12D...uiq's cluster
Finally, delete all peers and cluster peers:
kubectl delete peers --all
kubectl delete clusterpeers --allKubernetes garbage collector will delete all the resources that has been created by Kotal IPFS Peer and ClusterPeer controllers.
number
Ethereum chain id
string
Link contract address
string
Ethereum node WebSocket server endpoint
array
Ethereum HTTP endpoints
string
Postgres database connection URL
string
k8s secret name that holds keystore password
object
API credentials
array
Domains from which to accept cross origin requests
*
string
k8s secret name that holds tls.key and tls.crt
number
Port used for node API and GUI
6688
number
Port used for HTTPS connections
6689
number
Port used for p2p communcations
30303
boolean
Enable secure cookies for authentication
false
string
Logging verbosity level
info
object
node compute and storage resources to alloacte
ethereumChainId is ethereum chain id.
linkContractAddress is Link contract address.
ethereumWsEndpoint is Ethereum node's WebSocket server endpoint.
ethereumHttpEndpoints is array of Ethereum HTTP endpoints used for heavy requests and as fallback in case of Ethereum node bug or failure.
databaseURL is Postgres database connection URL.
keystorePasswordSecretName is k8s secret name that holds keystore (wallet) password in data field called password.
apiCredentials is the credetials used to access Chainlink node UI:
string
User email
passwordSecretName
string
k8s secret name that holds password in data field called password
corsDomains is a list of domains from which to accept cross origin requests.
certSecretName is k8s secret name that holds TLS private key in tls.key data field and TLS certificate in tls.crt data field.
apiPort is the port used for node API and GUI.
tlsPort is the port used for HTTPS connections.
p2pPort is the port used for p2p communcations.
secureCookies enables secure cookies for authentication.
logging is logging verbosity level. Possible values are debug, info, warn, error, and panic.
resources allocates compute and storage resources to the node.
cpu
string
number of cpu cores this node requires
2
cpuLimit
string
number of cpu cores this node is limited to
4
memory
string
memory this node requires
2Gi
memoryLimit
string
memory this node is limited to
4Gi
storage
string
disk space this node requires
20Gi
storageClass
string
Node volume storage class
Cluster's default storage class will be used as defined by cluster admin or cloud provider
memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.
cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1), 1500m, 2, and 4.
cpuLimit can't be less than cpu.
memoryLimit can't be less than or equal to memory.
storageClass field is immutable, it cannot be changed after creation.
required
string
Stacks network to join and sync
number
JSON-RPC server port
20443
string
JSON-RPC server host
0.0.0.0
number
p2p bind port
20444
string
p2p bind host
0.0.0.0
object
Bitcoin node details
boolean
Enables mining
false
string
Kubernetes secret name holding seed private key used for mining
boolean
Mines Stacks micro blocks
false
string
Kubernetes secret name holding node private key
object
node compute and storage resources to alloacte
network is Stacks network to join and sync. Possible values are mainnet and testnet.
network is immutable, can't be changed after node is created.
rpcPort is JSON-RPC server port.
rpcHost is JSON-RPC server host.
p2pPort is p2p bind port.
p2pHost is p2p bind host.
bitcoinNode is Bitcoin node details for Stacks node to connect and query:
endpoint
string
Stacks network to join and sync
p2pPort
number
p2p bind port
rpcPort
number
JSON-RPC server host
rpcUsername
string
Bitcoin node JSON-RPC username
rpcPasswordSecretName
string
Kubernetes secret name holding bitcoin node JSON-RPC password
miner enables mining.
seedPrivateKeySecretName is Kubernetes secret name holding seed private key used for mining.
mineMicroblocks enables mining Stacks micro blocks.
nodePrivateKeySecretName is Kubernetes secret name holding node private key.
resources allocates compute and storage resources to the node.
cpu
string
number of cpu cores this node requires
2
cpuLimit
string
number of cpu cores this node is limited to
4
memory
string
memory this node requires
4Gi
memoryLimit
string
memory this node is limited to
8Gi
storage
string
disk space this node requires
100Gi
storageClass
string
Node volume storage class
Cluster's default storage class will be used as defined by cluster admin or cloud provider
memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.
cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1), 1500m, 2, and 4.
cpuLimit can't be less than cpu.
memoryLimit can't be less than or equal to memory.
storageClass field is immutable, it cannot be changed after creation.
Stacks node requires a Bitcoin node to connect to on the back-end for . You can deploy a Bitcoin node using Kotal operator like we did in this . In this tutorial, we will be using Bitcoin node hosted by Stacks Foundation.
Make sure Bitcoin node is fully synced before deploying your Stacks node.
Don't use the following Miner private key in production!
Generate Key chain using tool. Stacks CLI can be installed using:
Generate key chain using:
It will return an output similar to the following
Store privateKey from the output above into a Kubernetes secret in data field called key:
Let's store Stacks Foundation Bitcoin node JSON-RPC password in a Kubernetes secret to be used by our node:
Apply bitcoin-node-rpc-password.yaml to create the password secret:
The following manifest describes a Stacks node that syncs Stacks mainnet network: mainnet, and connects to the bitcoin node using configurations in bitcoinNode: ... for Proof of Transfer, and loading miner private key using seedPrivateKeySecretName:
Apply stacks.yaml manifest:
Kotal operator will notice your stacks-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.
You can fetch the deployed Stacks Node using:
It will return an output similar to the following:
Note Miner is true in the previous output 🔥
Get the pods that has been created by Kotal for the node:
It will return an output similar to the following:
Get the logs of the running node:
It will return node logs similar to the following:
Finally you can delete the node by:
Kubernetes garbage collector will delete all the resources that has been created by Stacks Node controller.
We've extended Kubernetes with Node custom resource which can be used to deploy Stacks rpc and miner nodes from the given spec.
Node is Stacks node using client, connecting to and syncing a specific chain, optionally mining or exposing JSON-RPC server to be used by clients.
For all the fields associated with the Node API resource:
Full Stacks node reference is documented .
npm install -g @stacks/clistx make_keychain{
"mnemonic": "blue news bid also tell vault blame tonight crumble history tribe anxiety arch stove usage eight stick firm weapon wet chapter gravity seat idle",
"keyInfo": {
"privateKey": "7a3ef70a4a3ff3c389818ac11abec24b20ffbe3fb2cf6f71e947367a4ddbec6601",
"address": "SPQG93WFTVV6GA4AEDMS18ZCSTKMKFHWEHEXQAJJ",
"btcAddress": "15HcDuW1W2TqEe9mVER9ceJYtqMAED26jp",
"wif": "L1KLjY5xMGUSSV9cfE9VoKRdVt3D1zJxoJwPVLHfgRNS1ETGUSvr",
"index": 0
}
}kubectl create secret generic seed-private-key --from-literal=key=7a3ef70a4a3ff3c389818ac11abec24b20ffbe3fb2cf6f71e947367a4ddbec6601apiVersion: v1
kind: Secret
metadata:
name: bitcoin-node-rpc-password
stringData:
password: blockstacksystemkubectl apply -f bitcoin-node-rpc-password.yamlapiVersion: stacks.kotal.io/v1alpha1
kind: Node
metadata:
name: stacks-node
spec:
network: mainnet
seedPrivateKeySecretName: seed-private-key
bitcoinNode:
endpoint: bitcoin.blockstack.com
rpcPort: 8332
p2pPort: 8333
rpcUsername: blockstack
rpcPasswordSecretName: bitcoin-node-rpc-passwordkubectl apply -f stacks.yamlkubectl get nodes.stacksNAME NETWORK CLIENT MINER
stacks-node mainnet stacks truekubectl get podsNAME READY STATUS RESTARTS AGE
stacks-node-0 1/1 Running 0 1mkubectl logs -f stacks-node-0INFO [1649610683.233993] [testnet/stacks-node/src/main.rs:113] [main] Loading config at path /home/stacks/kotal-config/config.toml
INFO [1649610683.795606] [testnet/stacks-node/src/run_loop/neon.rs:341] [main] Start syncing Bitcoin headers, feel free to grab a cup of coffee, this can take a while
INFO [1649610686.606279] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 0.3% (2000 out of 731294)
INFO [1649610687.625014] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 0.5% (4000 out of 731294)
INFO [1649610688.634560] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 0.8% (6000 out of 731294)
INFO [1649610689.677533] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 1.1% (8000 out of 731294)
INFO [1649610690.737928] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 1.4% (10000 out of 731294)
INFO [1649610691.745002] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 1.6% (12000 out of 731294)
INFO [1649610692.789689] [src/burnchains/bitcoin/spv.rs:923] [main] Syncing Bitcoin headers: 1.9% (14000 out of 731294)
...kubectl delete -f stacks.yamlapiVersion: stacks.kotal.io/v1alpha1
kind: Node
metadata:
Name: stacks-node
spec:
network: mainnet
...kubectl explain nodes --api-version stacks.kotal.io/v1alpha1
kubectl explain nodes.spec --api-version stacks.kotal.io/v1alpha1In this tutorial, we will learn how to deploy a NEAR validator node, and load a validator key into it.
Generate validator account using NEAR CLI tool. Which can be installed using:
npm install -g near-cliValidator account must have the name validator.
near generate-key validatorAn ed25519 private key will be generated and saved in current user home directory under .near-credentials/testnet
cat ~/.near-credentials/testnet/validator.jsonIt will return an output similar to the following
{
"account_id": "validator",
"public_key": "ed25519:CdTBLXMmu9gzoCbNKdUnej1tJNMz5tzRjJF2a9DwAgUr",
"private_key": "ed25519:4k83DwbSpD3zzai4ZPdeRJcfXttU3Uq68mWWhni6ra2RKnG3jyVKEZyP14gDJZ9W1oqFujpAkidoNrYY4TLqijsG"
}Change private_key field to secret_key.
Create a Kubernetes secret from the generated private key in the previous step:
kubectl create secret generic validator-key --from-file=key=$HOME/.near-credentials/testnet/validator.jsonThe following manifest describes a NEAR node that syncs NEAR testnet network: testnet, enables HTTP JSON-RPC server rpc: true, loads validator key from the Kubernetes secret that we've created in the previous step, and uses NEAR Core client:
apiVersion: near.kotal.io/v1alpha1
kind: Node
metadata:
name: near-node
spec:
network: testnet
validatorSecretName: validator-key
rpc: trueApply near.yaml manifest:
kubectl apply -f near.yamlKotal operator will notice your near-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.
You can fetch the deployed NEAR Node using:
kubectl get nodes.nearIt will return an output similar to the following:
NAME NETWORK CLIENT VALIDATOR
near-node testnet nearcore trueNote that validator is true in the prevous output 😇
Get the pods that has been created by Kotal for the node:
kubectl get podsIt will return an output similar to the following:
NAME READY STATUS RESTARTS AGE
near-node-0 1/1 Running 0 1mGet the logs of the running node:
kubectl logs -f near-node-0It will return node logs similar to the following:
Apr 08 12:24:09.930 INFO neard: Version: 1.23.1, Build: 1.23.0-9-gc0551c84b-modified, Latest Protocol: 50
Apr 08 12:24:09.937 INFO near: Did not find "/home/near/kotal-data/data" path, will be creating new store database
Apr 08 12:24:10.438 INFO stats: Server listening at ed25519:[email protected]:24567
Apr 08 12:24:20.444 INFO stats: # 9820210 Downloading headers 0.00% (53273496) 5/3/40 peers ⬇ 0.7kiB/s ⬆ 0.2kiB/s 0.00 bps 0 gas/s CPU: 0%, Mem: 0 B
Apr 08 12:24:30.447 INFO stats: # 9820210 Downloading headers 0.00% (53273498) 5/3/40 peers ⬇ 0.7kiB/s ⬆ 0.2kiB/s 0.00 bps 0 gas/s CPU: 4%, Mem: 78.4 MiB
Apr 08 12:24:40.417 INFO stats: # 9820210 Downloading headers 0.00% (53273497) 5/3/40 peers ⬇ 0.7kiB/s ⬆ 0.2kiB/s 0.00 bps 0 gas/s CPU: 10%, Mem: 99.6 MiB
...Finally you can delete the node by:
kubectl delete -f near.yamlKubernetes garbage collector will delete all the resources that has been created by Kotal NEAR Node controller.
apiVersion: filecoin.kotal.io/v1alpha1
kind: Node
metadata:
name: calibration-node
spec:
network: calibrationThis is a simple filecoin Node that joins calibration test network.
Let's deploy the node:
kubectl apply -f calibration.yamlKotal operator will notice your calibration-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.
kubectl get peersIt will return an output similar to the following:
NAME NETWORK CLIENT
calibration-node calibration lotusGet the pods created for the node:
kubectl get podsIt will return an output similar to the following:
NAME READY STATUS RESTARTS AGE
calibration-node-0 1/1 Running 0 5mCheck the logs of the running node:
kubectl logs -f calibration-node-0Finally you can delete the filecoin node and all its resources by
kubectl delete -f calibration.yamland kubernetes garbage collector will delete all resources created by the node controller.
Array
List of initial configuration profiles
default-datastore
Array
List of configuration profiles to apply after peer initialization
string
API server host
0.0.0.0
number
API server port
5001
string
Local ipfs gateway host
0.0.0.0
number
Local ipfs gateway port
8080
string
Content routing mechanism
dht
string
Name of the k8s secret holding swarm secret key
object
Compute and storage resources
initProfiles is al list of initial ipfs configuration profile.
initialProfiles available values are server, randomports, default-datastore, local-discovery, test, default-networking, flatfs, badgerds, and lowpower.
initProfiles can't be updated (immutable).
profiles is the list of configuration profiles to apply after peer initialization.
profiles available values are server, randomports, default-datastore, local-discovery, test, default-networking, flatfs, badgerds, and lowpower.
apiHost is API server host.
apiPort is API server port.
gatewayHost is local ipfs gateway host.
gatewayPort is API server port.
routing is the content routing mechanism.
routing available values are none, dht, dhtclient, dhtserver.
swarmKeySecretName is the kubernetes secret name that's holding the swarm key in a key called secret.
kubectl create secret generic swarm-key --from-literal=secret=$w@rmk3yresources allocates compute and storage resources to the peer.
resources object has the following fields:
cpu
string
number of cpu cores this peer requires
1
cpuLimit
string
number of cpu cores this peer is limited to
2
memory
string
memory this peer requires
2Gi
memoryLimit
string
memory this peer is limited to
4Gi
storage
string
disk space this peer requires
10Gi
storageClass
string
Node volume storage class
Cluster's default storage class will be used as defined by cluster admin or cloud provider
Memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.
cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1 core), 1500m which is 1.5 core, 2 cores, and 4 cores.
cpuLimit can't be less than cpu.
memoryLimit can't be less than or equal to memory.
storageClass field is immutable, it cannot be changed after creation.
string
Cluster peer ID
string
Name of the k8s secret holding cluster peer privatekey
* if consensus is crdt
array
Peer IDs that can manage the pinset in crdt consensus
array
Peers to connect to on startup
string
Cluster consensus algorithm
crdt
required
string
ipfs peer http API endpoint
required
string
Name of the k8s secret holding cluster secret
object
Compute and storage resources
id is cluster peer id derived from private key.
id is required if privateKeySecretName is provided.
id can be generated using ipfs-key tool.
ipfs-key -type ed25519 | base64It will return an output similar to the following:
Generating a 2048 bit ed25519 key...
Success!
ID for generated key: 12D3KooWT2bqgwZPxHthAGBV9Ut8ZLraz1LARtB7vG3mF26Mtof1
CAESQLepaunFGa/PI0oNS3plrbVSInqab/X/U1laEDe2V2cL/7kbF9H6x3xBiwpbVnYT/jDA8EhAznXALlbwzEsuKaw=privateKeySecretName is the name of the k8s secret holding base64 cluster peer privatekey in a key called key.
privateKeySecretName is required if id is provided.
privateKeySecretName can be generated using ipfs-key tool.
ipfs-key -type ed25519 | base64It will return an output similar to the following:
Generating a 2048 bit ed25519 key...
Success!
ID for generated key: 12D3KooWT2bqgwZPxHthAGBV9Ut8ZLraz1LARtB7vG3mF26Mtof1
CAESQLepaunFGa/PI0oNS3plrbVSInqab/X/U1laEDe2V2cL/7kbF9H6x3xBiwpbVnYT/jDA8EhAznXALlbwzEsuKaw=trustedPeers is a list of peer IDs that can manage the cluster pinset in crdt consensus clusters.
trustedPeers is ignored in raft consensus clusters.
trustedPeers default value is * which is trust all peers.
bootstrapPeers is a list of peers to connect to on startup.
bootstrapPeers will be trusted peers in crdt clusters.
consensus is the cluster consensus algorithm.
peerEndpoint id ipfs peer http API endpoint.
peerEndpoint is required for the cluster peer to function correctly.
clusterSecretName is the k8s secret name holding 32-bit hex-encoded (without 0x) cluster secret in a key called secret.
clusterSecretName can be generated using openssl tool:
CLUSTER_SECRET=$(openssl rand -hex 32)
kubectl create secret generic cluster-secret --from-literal=secret=$CLUSTER_SECRETresources allocates compute and storage resources to the peer.
resources object has the following fields:
cpu
string
number of cpu cores this peer requires
1
cpuLimit
string
number of cpu cores this peer is limited to
2
memory
string
memory this peer requires
2Gi
memoryLimit
string
memory this peer is limited to
4Gi
storage
string
disk space this peer requires
10Gi
Memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.
cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1 core), 1500m which is 1.5 core, 2 cores, and 4 cores.
cpuLimit can't be less than cpu.
memoryLimit can't be less than or equal to memory.
In this tutorial we will use the following private keys and their corresponding addresses.
DON'T use these keys in production.
Let's describe an Ethereum Node that uses a custom genesis block to join a private Proof of Authority network using ibft2 consensus configuration in the genesis block.
In this node, we're using Hyperledger besu client client: besu, enabling JSON-RPC server rpc: true so we can query number of peers later in this tutorial, and we're loading the node private key from Kubernetes secretd called besu-ibft2-nodekey.
The node private key will give the node a unique identity and node URL, and will allow the node to generate blocks, because the address 0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa that's corresponding to the node private key is in the initial block validators.
We're defining a genesis block that uses the value 4444 as network and chain identifier, and we start the chain with 3 validators as defined by spec.genesis.ibft2.validators.
This node private key secret can be created by:
Let's deploy the node:
Kotal operator will notice your besu-ibft2-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.
You can fetch the deployed Ethereum Node using:
It will return an output similar to the following:
Get the pods that has been created by Kotal for the node:
It will return an output similar to the following:
Get the logs of the running node:
Let's deploy another go-ethereum node, and connect it to the previous node in our private proof of authority network.
In this node, we're using go-ethereum client client: geth, starting the PoA consensus engine miner: true, setting the second address in the genesis validators list spec.genesis.ibft2.validators as the coinbase coinbase: "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d", and loading the validator account private key and password from kubernetes secrets privateKeySecretName: ... and passwordSecretName: .... We're connecting to the first node using staticNodes option which accepts Node name or enode url.
You can create the private key and password secrets using:
Deploy the second node using:
Kotal operator will notice your second geth-ibft2-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.
You can fetch the deployed Ethereum Nodes using:
It will return an output similar to the following:
net_peerCountGet the pods that has been created by Kotal for the node:
It will return an output similar to the following:
Forward localhost:8545 calls to the node pod:
In another terminal window call net_peerCount JSON-RPC method
You will get JSON result similar to the following:
Deploy a third node that uses Nethermind client, and signing blocks using the third key in the validators list spec.genesis.ibft2.validators. Nethermind client is similar to geth, you will import validator account private key and password from kubernetes secrets, and use the same genesis as the other nodes.
Finally you can delete all the nodes by:
Kubernetes garbage collector will delete all the resources that has been created by Kotal Ethereum Node controller.
network is the network this node should join and sync its blockchain data.
network possible values are mainnet, and calibration.
butterfly and nerpa networks have been deprecated 🥺
api enables API server.
apiPort is API server listening port.
apiHost is API server host.
apiRequestTimeout is API request timeout in seconds.
disableMetadataLog disables metadata logging.
p2pPort is p2p port.
p2pHost is p2p host.
ipfsPeerEndpoint ipfs peer endpoint.
ipfsOnlineMode sets sets ipfs online mode.
ipfsForRetrieval uses ipfs for retrieval.
resources allocates compute and storage resources to the node.
memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.
cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1), 1500m, 2, and 4.
cpuLimit can't be less than cpu.
memoryLimit can't be less than or equal to memory.
storageClass field is immutable, it cannot be changed after creation.
0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa
fb5411342ae51291447515c89bcf6a057e3dbd0b51e060c45cb73406c38f851d
0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d
153b174f5e9948ae4678baed54f88244cc9c39d56b9f17ecef93d7ede633f56b
0x7DE985E2f878c83C4e91b6B1312c0f63A56C844a
89b03c4de62d61be16d22e09c8a48929a9bccd11fa6b37809cfef290292bcba3
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
name: besu-ibft2-node
spec:
client: besu
nodePrivateKeySecretName: besu-ibft2-nodekey
rpc: true
genesis:
chainId: 4444
networkId: 4444
ibft2:
validators:
- "0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa"
- "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d"
- "0x7DE985E2f878c83C4e91b6B1312c0f63A56C844a"kubectl create secret generic besu-ibft2-nodekey --from-literal=key=fb5411342ae51291447515c89bcf6a057e3dbd0b51e060c45cb73406c38f851dkubectl apply -f besu-ibft2-node.yamlkubectl get nodes.ethereumNAME CLIENT Consensus Network
besu-ibft2-node besu ibft2 privatekubectl get podsNAME READY STATUS RESTARTS AGE
besu-ibft2-node-0 1/1 Running 0 1mkubectl logs -f besu-ibft2-node-0apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
name: geth-ibft2-node
spec:
client: geth
miner: true
coinbase: "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d"
import:
privateKeySecretName: geth-ibft2-account-key
passwordSecretName: geth-ibft2-account-password
staticNodes:
- besu-ibft2-node
genesis:
chainId: 4444
networkId: 4444
ibft2:
validators:
- "0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa"
- "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d"
- "0x7DE985E2f878c83C4e91b6B1312c0f63A56C844a"kubectl create secret generic geth-ibft2-account-key --from-literal=key=153b174f5e9948ae4678baed54f88244cc9c39d56b9f17ecef93d7ede633f56b
kubectl create secret generic geth-ibft2-account-password --from-literal=password=s3cr3tkubectl apply -f geth-ibft2-node.yamlkubectl get nodes.ethereumNAME CLIENT Consensus Network
besu-ibft2-node besu poa private
geth-ibft2-node geth poa privatekubectl get podsNAME READY STATUS RESTARTS AGE
besu-ibft2-node-0 1/1 Running 0 1m
geth-ibft2-node-0 1/1 Running 0 1mkubectl port-forward besu-ibft2-node-0 8545curl -X POST -H 'content-type: application/json' --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":32}' http://127.0.0.1:8545{
"jsonrpc" : "2.0",
"id" : 32,
"result" : "0x1"
}kubectl delete nodes.ethereum --allstring
network to join and sync
boolean
enables API server
false
number
API server listening port
1234
string
API server host
0.0.0.0
number
API request timeout in seconds
30
boolean
disables metadata logging
false
string
p2p port
4444
string
p2p host
0.0.0.0
string
ipfs peer endpoint
boolean
ipfs online mode
false
boolean
use ipfs for retrieval
false
object
node compute and storage resources to alloacte
cpu
string
number of cpu cores this node requires
4 in nerpa, 8 in other networks
cpuLimit
string
number of cpu cores this node is limited to
8 in nerpa, 16 in other networks
memory
string
memory this node requires
8Gi in nerpa, 16Gi in other networks
memoryLimit
string
memory this node is limited to
16Gi in nerpa, 32Gi in other networks
storage
string
disk space this node requires
100Gi in nerpa, 200Gi in other networks
storageClass
string
Node volume storage class
Cluster's default storage class will be used as defined by cluster admin or cloud provider
The following manifest describes Kusama node that syncs Kusama relay chain network: kusama, in archive mode pruning: false, and uses Parity Polkadot client:
apiVersion: polkadot.kotal.io/v1alpha1
kind: Node
metadata:
name: kusama-node
spec:
network: kusama
pruning: falseApply kusama.yaml manifest:
kubectl apply -f kusama.yamlKotal operator will notice your kusama-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.
You can fetch the deployed Polkadot Node using:
kubectl get nodes.polkadotIt will return an output similar to the following:
NAME NETWORK VALIDATOR
kusama-node kusama fasleGet the pods that has been created by Kotal for the node:
kubectl get podsIt will return an output similar to the following:
NAME READY STATUS RESTARTS AGE
kusama-node-0 1/1 Running 0 1mGet the logs of the running node:
kubectl logs -f kusama-node-0It will return node logs similar to the following:
2021-10-18 15:32:38 ----------------------------
2021-10-18 15:32:38 This chain is not in any way
2021-10-18 15:32:38 endorsed by the
2021-10-18 15:32:38 KUSAMA FOUNDATION
2021-10-18 15:32:38 ----------------------------
2021-10-18 15:32:38 Parity Polkadot
2021-10-18 15:32:38 ✌️ version 0.9.11-bfd38ed62-x86_64-linux-gnu
2021-10-18 15:32:38 ❤️ by Parity Technologies <[email protected]>, 2017-2021
2021-10-18 15:32:38 📋 Chain specification: Kusama
2021-10-18 15:32:38 🏷 Node name: validator-node-sample
2021-10-18 15:32:38 👤 Role: AUTHORITY
2021-10-18 15:32:38 💾 Database: RocksDb at /polkadot/kotal-data/chains/ksmcc3/db/full
2021-10-18 15:32:38 ⛓ Native runtime: kusama-9110 (parity-kusama-0.tx7.au2)
2021-10-18 15:32:38 🔨 Initializing Genesis block/state (state: 0xb000…ef6b, header-hash: 0xb0a8…dafe)
2021-10-18 15:32:38 👴 Loading GRANDPA authority set from genesis on what appears to be first startup.
2021-10-18 15:32:39 ⏱ Loaded block-time = 6s from block 0xb0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe
2021-10-18 15:32:39 👶 Creating empty BABE epoch changes on what appears to be first startup.
2021-10-18 15:32:39 🏷 Local node identity is: 12D3KooWFEHU9FXqGCL6ify4rqcon31WYViCnUfA6aVYTjRXqJ5F
2021-10-18 15:32:39 📦 Highest known block at #0
2021-10-18 15:32:39 〽️ Prometheus exporter started at 0.0.0.0:9615
2021-10-18 15:32:39 Listening for new connections on 127.0.0.1:9944.
2021-10-18 15:32:39 👶 Starting BABE Authorship worker
...Once the node is fully synced, enable validator by updating the node with validator: true:
apiVersion: polkadot.kotal.io/v1alpha1
kind: Node
metadata:
name: kusama-node
spec:
network: kusama
pruning: false
validator: trueApply the updated kusama.yaml Node manifest:
kubectl apply -f kusama.yamlFetch the deployed Polkadot Node using:
kubectl get nodes.polkadotIt will return an output similar to the following:
NAME NETWORK VALIDATOR
kusama-node kusama trueNote that validator has changed from false to true.
The remainig steps in setting up a validator are:
Bonding KSM
Generating Session Keys
Setting Session Keys by signing and submitting an extrinsic
Relax 🏝️
These steps are documented in Polkadot Wiki.
We will cover next how to generate a session key.
Validator nodes can't enable external HTTP or WS JSON-RPC servers.
Session key can be generated by calling author_rotateKeys JSON-RPC method.
Forward localhost:9933 calls to the node pod because rpcPort: 9933:
kubectl port-forward polkadot-node-0 9933In another terminal window call author_rotateKeys JSON-RPC method to get a new session key:
curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "author_rotateKeys", "params":[]}' http://127.0.0.1:9933You will get JSON result similar to the following:
{
"jsonrpc": "2.0",
"result": "0x159256d69a61b523a211d7845a92d5a238f6a97b53627c4aa92665eb6bc2959dc88c9c279ad01b8acf90573ca005f6565c4a0d88d19951740b8f8ec38c63b344b2c186e703ce88f0f4b628263265ffefa1cdc148c79a5608ccc7734e6a0bfb077076c5f370491331819d17884b9aa4e41d4e2bec774b5c31251203266c446a2ec02d89f5ecefcc75777d4de74766a57fbafe65b1850500875e8cf2fed3325f65",
"id": 1
}You can set the sesison key as documented in Polkadot Wiki.
Finally you can delete the node by:
kubectl delete -f kusama.yaml
node.polkadot.kotal.io "kusama-node" deletedKubernetes garbage collector will delete all the resources that has been created by Kotal Polkadot Node controller.
Chainlink node requires access to an EVM chain node with WebSocket server enabled. Here's how to deploy a simple Ethereum Rinkeby node with WebSocket server enabled:
After deploying this node, it can be accessed in-cluster using ws://besu-rinkeby-node:8546 🔥. Read for more details on how to deploy public and private network nodes.
Chainlink requires access to database instance.
You can use a hosted database a service to obtain PostgreSQL database:
You can also deploy your own PostgreSQL database instance from official PostgreSQL .
Chainlink node requires a strong password for securing access to keystore (wallet) and API. We will store this password in Kubernetes secret my-password:
Chainlink optionally requires TLS certificate to secure access to the node API. Using we can issue a simple self-signed certificate and store it in a Kubernetes secret:
With access to Ethereum Rinkeby node, PostgreSQL database, tls certificate and a strong password. We're ready to deploy our Chainlink node to create jobs and satisfy requests:
In this manifest, we're describing Chainlink node that connects to Ethereum Rinkeby node using ethereumWsEndpoint, setting ethereum chain ID using ethereumChainId, setting link contract address using linkContractAddress, connecting to postgress database instance using databaseURL, setting wallet password using keystorePasswordSecretName which accepts a name of k8s secret, setting tls configuration using certSecretName which accepts k8s secret name that holds tls.key and tls.crt, and finally setting API credentials using apiCredentials.
Apply chainlink.yaml manifest:
Kotal operator will notice your chainlink-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets neccessary.
You can fetch the deployed Chainlink Node using:
It will return an output similar to the following:
If you added -o wide it will return more info like link contract address
Get the pods that has been created by Kotal for the node:
It will return an output similar to the following:
Get the logs of the running node:
Chainlink node comes with a user interface for managing the node, and it's being served by default on port 6688.
Forward localhost:6688 calls to the node pod:
Open https://localhost:6688 and it will take you to Chainlink node UI. It will ask you for API credentials. Enter the email address in your node's .spec.apiCredentials.email, and in the password field, enter fE2xXKDnR3ns489X.
🔥🔥🔥
Finally you can delete the node by:
Kubernetes garbage collector will delete all the resources that has been created by Kotal Chainlink Node controller.
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
name: besu-rinkeby-node
spec:
network: rinkeby
client: besu
ws: trueapiVersion: v1
kind: Secret
metadata:
name: my-password
stringData:
password: fE2xXKDnR3ns489X# create self-signed certificate issuer
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: self-signed-issuer
spec:
selfSigned: {}
---
# create certificate for chainlink node
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: chainlink-node-cert
spec:
dnsNames:
- "chainlink-node.svc"
- "chainlink-node.svc.cluster.local"
# store tls.crt and tls.key in this kubernetes secret
secretName: chainlink-node-cert
issuerRef:
name: self-signed-issuerapiVersion: chainlink.kotal.io/v1alpha1
kind: Node
metadata:
name: chainlink-node
spec:
ethereumChainId: 4
ethereumWsEndpoint: "ws://besu-rinkeby-node:8546"
linkContractAddress: "0x01BE23585060835E02B77ef475b0Cc51aA1e0709"
databaseURL: "postgresql://username:password@server:port/name"
keystorePasswordSecretName: "my-password"
certSecretName: "chainlink-node-cert"
apiCredentials:
email: "[email protected]"
passwordSecretName: "my-password"kubectl apply -f chainlink.yamlkubectl get nodes.chainlinkNAME CLIENT EthereumChainId
chainlink-node chainlink 4NAME CLIENT EthereumChainId LinkContractAddress
chainlink-node chainlink 4 0x01BE23585060835E02B77ef475b0Cc51aA1e0709kubectl get podsNAME READY STATUS RESTARTS AGE
chainlink-node-0 1/1 Running 0 1mkubectl logs -f chainlink-node-0kubectl port-forward chainlink-node-0 6688kubectl delete -f chainlink.yaml
node.chainlink.kotal.io "chainlink-node" deletedstring
Polkadot node client image
last stable and tested client
array
Extra arguments to pass down to the node client
number
number of replicas
1
required
string
polkadot network/chain to join and sync
string
p2p protocol tcp port
30333
string
Kubernetes secret name holding node Ed25519 private key
boolean
enables validator
false
string
blockchain synchronization mode
full
boolean
whether to keep only recent or all blocks
false
number
number of blocks to keep state for
256
string
database backend
auto
string
logging verboisty level
info
boolean
enables connecting to telemetry server
false
string
telemetry service URL
wss://telemetry.polkadot.io/submit/ 0
string
exposes prometheus exporter endpoint
false
number
prometheus exporter port
9615
boolean
enables JSON-RPC server
false
number
JSON-RPC server port
9933
boolean
enables Websocket server
false
number
Websocket server port
9944
array
browser origins allowed to access the JSON-RPC HTTP and WS servers
all
object
node compute and storage resources to alloacte
image is polkadot node client image. Kotal dashboard uses image information published here.
extraArgs are extra arguments to pass down to the node client. This can be useful if kotal doesn't support something you're inttersted in.
# these extra arguments will be passed as follow to the client
# --arg1 val1 --toggle --arg2 val2
extraArgs:
"--arg1": val1
"--toggle": ""
"--arg2": val2replicas is number of replicas. Accepted values are 0 and 1 only.
network is the polkadot network/chain to join and sync. Possible values are polkadot, kusama, rococo, westend and other chains supported by Parity Polkadot client.
p2pPort is p2p protocol tcp port.
nodePrivateKeySecretName is Kubernetes secret name holding node Ed25519 private key in data field called key.
Node private can be generated using subkey tool from Parity Substrate.
# generate binary node key and save it in node.key file
subkey generate-node-key node.key
# convert node.key binary file into hexadecimal node.key.hex file
xxd -p -c 32 node.key > node.key.hexCreate node private key secret:
kubectl create secret generic polkadot-node-key --from-file=key=node.key.hexpolkadot-node-key secret can be used in your polkadot Node by updating .spec with nodePrivateKeySecretName: polkadot-node-key.
validator enables validator.
Node must sync blocks in archive mode pruning: false if validator is enabled.
syncMode is blockchain synchronization mode. Available values are fast and full.
pruning controls whether to keep only recent or all blocks. Setting pruning to false runs the node in archive mode.
retainedBlocks is the number of blocks to keep state for. It's only considered if .spec.pruning is set to true.
database is database backend. Possible values are auto, paritydb or rocksdb.
logging is logging verboisty level. Available logging levels are error, warn, info, debug, and trace.
telemetry enables connecting to telemetry server.
telemetryURL is telemetry service URL. It's only considered if .spec.telemetry is set to true.
prometheus exposes prometheus exporter endpoint.
prometheusPort is prometheus exporter port
rpc enables JSON-RPC server.
rpcPort is JSON-RPC server port.
ws enables Websocket server.
wsPort is Websocket server port.
corsDomains is browser origins allowed to access the JSON-RPC HTTP and WS servers.
resources allocates compute and storage resources to the node.
cpu
string
number of cpu cores this node requires
4
cpuLimit
string
number of cpu cores this node is limited to
8
memory
string
memory this node requires
4Gi
memoryLimit
string
memory this node is limited to
8Gi
storage
string
disk space this node requires
80Gi
storageClass
string
Node volume storage class
Cluster's default storage class will be used as defined by cluster admin or cloud provider
memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.
cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1), 1500m, 2, and 4.
cpuLimit can't be less than cpu.
memoryLimit can't be less than or equal to memory.
storageClass field is immutable, it cannot be changed after creation.
string
Network to join
string
Ethereum 2.0 client to use
array
Ethereum 1 JSON RPC endpoints
array
hostnames to whitelist for RPC access
*
array
domains from which to accept cross origin requests
*
bool
Enable REST API server
false
string
REST API server host
0.0.0.0
number
REST API server port
5051
bool
Enables JSON RPC server
false
string
JSON RPC server host
0.0.0.0
number
JSON RPC server port
4000
bool
GRPC gateway server
false
string
GRPC gateway server host
0.0.0.0
number
GRPC gateway server port
3500
number
p2p and discovery port
9000
string
k8s secret name that holds tls.key and tls.crt
string
logging verbosity level
info
object
Node compute and storage resources
network is Ethereum 2.0 network to join and sync its beacon chain.
client is the Ethereum 2.0 client to use.
client possible values are teku,prysm,lighthouse, and nimbus.
eth1Endpoints is array of Ethereum 1 JSON RPC endpoints.
hosts is a list of host names to whitelist for RPC access (server enforced).
corsDomains is a list of domains from which to accept cross-origin requests (browser enforced).
rest enables REST API server.
restHost is the REST API server host.
restPort is the REST API server port.
rpc enables JSON RPC server.
rpcHost is the JSON RPC server host.
rpcPort is the JSON RPC server port.
grpc enables GRPC gateway server.
grpcHost is the GRPC gateway server host.
grpcPort is the GRPC gateway server port.
p2pPort is the p2p and discovery port.
certSecretName is k8s secret name that holds TLS private key in data field called tls.key and TLS certificate in data field called tls.crt.
certSecretName is supported only by prysm client.
logging is logging verbosity level.
Different levels are supported by different Ethereum 2.0 beacon node clients.
off
✔️
❌
❌
❌
fatal
✔️
❌
✔️
✔️
none
❌
❌
❌
✔️
notice
❌
❌
❌
✔️
error
✔️
✔️
✔️
✔️
warn
✔️
✔️
✔️
✔️
info
✔️
✔️
✔️
✔️
debug
✔️
✔️
✔️
✔️
trace
✔️
❌
✔️
✔️
all
✔️
❌
❌
❌
critical
❌
✔️
❌
❌
panic
❌
❌
✔️
❌
resources allocates compute and storage resources to the node.
resources object has the following fields:
cpu
string
number of cpu cores this node requires
4
cpuLimit
string
number of cpu cores this node is limited to
8
memory
string
memory this node requires
8Gi
memoryLimit
string
memory this node is limited to
16Gi
storage
string
disk space this node requires
200Gi
storageClass
string
Node volume storage class
Cluster's default storage class will be used as defined by cluster admin or cloud provider
memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.
cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1 core), 1500m which is 1.5 core, 2 cores, and 4 cores.
cpuLimit can't be less than cpu.
memoryLimit can't be less than or equal to memory.
storageClass field is immutable, it cannot be changed after creation.
string
Network to validate blocks for
string
Ethereum 2.0 client to use
array
List of beacon node endpoints
string
k8s secret name that holds tls.crt
string
Text to include in proposed blocks
Powered by Kotal
string
Wallet password kubernetes secret
array
Validator keystores
string
logging verbosity level
info
object
Validator compute and storage resources
network is the Network to validate blocks for.
client is the Ethereum 2.0 client to use.
beaconEndpoints is a list of beacon node endpoints.
certSecretName is k8s secret name that holds TLS certificate in data field called tls.crt.
certSecretName is supported only by prysm client.
graffiti is the text to include in proposed blocks.
walletPasswordSecretName is prysm wallet password kubernetes secret.
Wallet password secret must be deployed before deploying the validator.
Wallet password secret must contain the password in key named password.
# create k8s secret from password value
kubectl create secret wallet-password --from-literal=password=<actual-password>
# create k8s secret from password file
kubectl create secret wallet-password --from-file=password=<password-file-path>keystores is array of keystore objects.
secretName
string
kubernetes secret name holding keystore and password
publicKey
string
Validator public key in hexadecimal
Keystore secret must be deployed before deploying the validator.
Keystore secret must contain the BLS12-381 keystore JSON file in data field key called keystore key, and password in password key.
# create k8s secret from keystore and password file
kubectl create secret my-validator --from-file=keystore=/path/to/keystore.json --from-file=password=/path/to/password.txtlogging is logging verbosity level.
Different levels are supported by different Ethereum 2.0 beacon node clients.
Teku validator client doesn't support logging. Verbosity level will be ignored 🙈
off
❌
❌
❌
fatal
❌
✔️
✔️
none
❌
❌
✔️
notice
❌
❌
✔️
error
✔️
✔️
✔️
warn
✔️
✔️
✔️
info
✔️
✔️
✔️
debug
✔️
✔️
✔️
trace
❌
✔️
✔️
all
❌
❌
❌
critical
✔️
❌
❌
panic
❌
✔️
❌
resources allocates compute and storage resources to the node.
resources object has the following fields:
cpu
string
number of cpu cores this node requires
4
cpuLimit
string
number of cpu cores this node is limited to
8
memory
string
memory this node requires
8Gi
memoryLimit
string
memory this node is limited to
16Gi
storage
string
disk space this node requires
200Gi
memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.
cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1 core), 1500m which is 1.5 core, 2 cores, and 4 cores.
cpuLimit can't be less than cpu.
memoryLimit can't be less than or equal to memory.
string
Public network name to join, like mainnet, rinkeby, and goerli
boolean
Ethereum nodes will be scheduled on different kubernetes nodes
false
string
kubernetes node label key used to distribute ethereum nodes
topology.kubernetes.io/zone
object
Genesis block configuration
array
ethereum node URLs for p2p discovery bootstrap
string
ethereum client powering the node
string
ethereum account to which mining rewards are paid
array
domains from which to accept cross origin requests (browser enforced)
*
boolean
enable GraphQL server
false
number
GraphQL server listening port
8547
array
hostnames to whitelist for RPC access (server enforced)
*
object
ethereum account to import for geth node
string
node logging verbosity level
info
boolean
node is mining or signing blocks ?
false
string
name of kubernetes secret holding node private key
string
node p2p port
30303
object
node compute and storage resources to alloacte
boolean
enable HTTP RPC server
false
number
HTTP RPC server listening port
8545
array
services to enable
web3, eth, and net
array
set of trusted ethereum nodes to maintain connection to
string
blockchain synchronization mode
fast in public, full in private
boolean
enable web socket server
false
number
web socket server listening port
8546
array
services to enable
web3, eth, and net
network is the public network name to join, like rinkeby.
network can't be provided in private networks, where .spec.genesis is not null.
network can't be updated (immutable).
highlyAvailable controls if Ethereum nodes will be scheduled on different Kubernetes nodes.
topologyKey is Kubernetes node label key used to distribute ethereum nodes pods on different kubernetes nodes.
bootnodes is ethereum node URLs for p2p network discovery and bootstraping.
bootnodes accepts ethereum node URL enodeURL or a reference to kotal Node in the form of name.namespace where namespace is optional if referenced node is in the same namespace.
Ethereum clients have hardcoded bootnodes for public main and test networks. bootnodes will override these bootnodes.
Support for OpenEthereum (parity) client has been deprecated. OpenEthereum team is working with Erigon on a smooth transition path for users. More information can be found here
client is the Ethereum client name powering the node.
client possible values are besu, geth, nethermind.
Only besu client can be used if network consensus is ibft2.
Only besu can be used in fixed difficulty proof of work networks, where spec.genesis.ethash.fixedDifficulty is not null.
coinbase is ethereum account to which mining rewards are paid.
coinbase is required if the node is mining miner: true.
corsDomains is a list of domains from which to accept cross-origin requests (browser enforced).
Default value * will be used if HTTP RPC server is enabled rpc: true or web socket server is enabled ws: true or graphQL server is enabled graphql: true.
graphql enables the GraphQL server.
Nethermind client doesn't support GraphQL.
Geth (Go-Ethereum) GraphQL server can be used only if RPC is enabled as of geth v1.9.19 release notes
graphqlPort GraphQL server listening port.
The default value 8547 will be used if the graphQL server is enabled graphql: true.
hosts is a list of host names to whitelist for RPC access (server enforced).
import is the ethereum account to import. Only for nodes running with geth or nethermind.
During account creation, it will be encrypted with the password, and during import it will be unlocked using the same password.
Nodes that import accounts can't enable HTTP RPC server, web socket server, or GraphQL server to prevent funds drainage if exposed to the internet.
Account must be imported if the node is running with geth or nethermind clients wants to be a signer or miner.
privateKeySecretName
string
name of the k8s secret holding account private key in hexadecimal (without 0x) in data field called key
passwordSecretName
string
name of the k8s secret holding encryption secret in data field called password
logging is Ethereum node logging verbosity level.
logging possible values are off, fatal, error, warn, debug, info, trace and all.
Different clients support different logging vrbosity levels as shown in the following table:
off
✔️
✔️
❌
fatal
✔️
❌
❌
error
✔️
✔️
✔️
warn
✔️
✔️
✔️
debug
✔️
✔️
✔️
info
✔️
✔️
✔️
trace
✔️
❌
✔️
all
✔️
✔️
❌
miner enables node mining or signing blocks.
nodePrivateKeySecretName is the node private key.
nodePrivateKeySecretName is required if the node is a boot node bootnode: true, or if besu node with client: besu is a signer in proof of authority clique network or validator in ibft2 network.
p2pPort is node p2p port for communication (TCP) and discovery (UDP).
resources allocates compute and storage resources to the node.
cpu
string
number of cpu cores this node requires
2 in private, 4 in public
cpuLimit
string
number of cpu cores this node is limited to
3 in private, 6 in public
memory
string
memory this node requires
4Gi in private, 8Gi in public
memoryLimit
string
memory this node is limited to
8Gi in private, 16Gi in public
storage
string
disk space this node requires
100Gi in private, 6Ti in mainnet with full sync, 750Gi in mainnet wit fast sync, 25Gi in public test networks
storageClass
string
Node volume storage class
Cluster's default storage class will be used as defined by cluster admin or cloud provider
memory and storage requests and limits must use the pattern ^[1-9][0-9]*[KMGTPE]i$ for example 1500Mi, 30Gi, and 1Ti.
cpu requests and limits must use the pattern ^[1-9][0-9]*m?$ for example 1000m (which is equal to 1), 1500m, 2, and 4.
cpuLimit can't be less than cpu.
memoryLimit can't be less than or equal to memory.
storageClass field is immutable, it cannot be changed after creation.
rpc enables the HTTP RPC server.
rpcPort is the HTTP RPC server listening port.
Default value 8545 will be used if the HTTP RPC server is enabled with rpc: true.
rpcAPI is a list of RPC services to enable.
Default value ["web3", "eth", "net] will be used if HTTP RPC server is enabeld with rpc: true.
staticNodes is a set of trusted ethereum nodes to maintain connection to.
staticNodes accepts ethereum node URL enodeURL or a reference to kotal Node in the form of name.namespace where namespace is optional if referenced node is in the same namespace.
Nethermind client removed support for beam sync which was activated by syncMode: light.
syncMode is Blockchain synchronization mode.
syncMode possible values are light, full, snap or fast.
light and snap sync modes are only supported by go-ethereum client.
ws enables the web socket server.
wsPort is the web socket server listening port.
The default value 8546 is used if the web socket server is enabled with ws: true.
wsAPI is a list of rpc services to enable.
the default value ["web3", "eth", "net] will be used if the web socket server is enabeld with ws: true.
genesis is the genesis block configuration.
Genesis block configuration genesis is required in private networks.
number
used in transaction signature to prevent transactions reply
number
used in network p2p communications
string
benefeciary (ethereum address) of mining reward
address(0)
string
difficulty (hexadecimal number) of the genesis block
0x1
string
hash (hexadecimal) combined with nonce to prove effort spent to create block
0x00..00
string
total gas limit (hexadecimal number) for all transactions in a block
0x47b760
string
random hexadecimal number used in block computation
0x0
string
genesis block creation date (hexadecimal)
0x0
Array
array of accounts to prefund and store code
object
supported forks and corresponding block number
object
Proof of Work consensus configuration
object
Proof of Authority consensus configuration
object
IBFT2 consensus configuration
chainId is the chain id value used in transaction signature to prevent transactions reply eip155
chainId is required.
chainId can't reuse existing public network chain id to avoid transaction replay.
mainnet
1
ropsten
3
rinkeby
4
goerli
5
kotti
6
ethereum classic
61
Mordor
63
development
2018
id is the network id used for p2p communications between network nodes in private networks.
id is required in private networks.
id can't be provided while joining a public network.
id can't be updated (immutable).
coinbase is the beneficiary (ethereum address) of mining reward.
coinbase is optional.
difficulty is the difficulty of the genesis block.
difficulty is optional.
mixHash is combined with the nonce to prove the effort spent to create a block.
mixHash is optional.
gasLimit is the total gas limit for all transactions in a block.
gasLimit is optional.
nonce is a random number used in block computation.
nonce is optional.
timestamp is block creation date.
timestamp is optional.
forks is an object, where the key is fork name and the value is the block number at which to activate this fork.
forks is optional.
if forks is missing, all forks will be activated at block 0 (genesis block) except DAO.
Later forks like muirglacier can't be activated before earlier forks like homestead. They must be ordered as in the following table:
homestead
number
fork activation block number
dao
number
fork activation block number
eip150
number
fork activation block number
eip155
number
fork activation block number
eip158
number
fork activation block number
byzantium
number
fork activation block number
constantinople
number
fork activation block number
petersburg
number
fork activation block number
istanbul
number
fork activation block number
muirglacier
number
fork activation block number
berlin
number
fork activation block number
london
number
fork activation block number
arrowGlacier
number
fork activation block number
accounts is an array of accounts to fund or store code.
accounts is optional.
accounts is recommended for networks where signers or validators are not rewarded with eth.
a single account has no defaults.
address
string
ethereum address
balance
string
account balance in hexadecimal
code
string
bytecode in hexadecimal
storage
map
key is the storage location in hexadecimal, and value in hexadecimal is the storage value
ethash is Proof of Work consensus engine configuration.
ethash is optional.
ethash can be set only in proof of work private networks.
ethash.fixedDifficulty has no default value.
ethash.fixedDifficulty is only supported by Hyperledger Besu Client client: besu
fixedDifficulty
number
fixed difficulty used in block computation
clique is Proof of Authority clique consensus engine configuration.
clique is optional.
clique can be set only in proof of authority clique private networks.
At least one signer in clique.signers is required.
blockPeriod
number
block time in seconds
15
epochLength
number
number of blocks after which to reset all votes
1000
signers
Array
array of ethereum addresses
ibft2 is IBFT2 engine configuration.
ibft2 is optional.
ibft2 can be set only in IBFT2 private networks.
At least one validator in ibft2.validators is required.
blockPeriod
number
block time in seconds
15
epochLength
number
number of blocks after which to reset all votes
1000
validators
array
array of ethereum addresses
requestTimeout
number
timeout for each consensus round in seconds
10
messageQueueLimit
number
message queue limit
1000
duplicateMessageLimit
number
duplicate messages limit
100
futureMessagesLimit
number
future messages buffer limit
1000
futureMessagesMaxDistance
number
maximum height from current chain height for buffering future messages
10