From a5ce7ff43e8e173b4a771d91299750d696098644 Mon Sep 17 00:00:00 2001
From: Silas Davis <silas@erisindustries.com>
Date: Tue, 4 Apr 2017 17:49:54 +0200
Subject: [PATCH] add cluster/kubernetes wrapper/templates

---
 deployment/README.md                      |  18 +++
 deployment/kubernetes/all_nodes.yaml      |  37 +++++
 deployment/kubernetes/node000-deploy.yaml |  64 ++++++++
 deployment/start_in_cluster               | 184 ++++++++++++++++++++++
 4 files changed, 303 insertions(+)
 create mode 100644 deployment/README.md
 create mode 100644 deployment/kubernetes/all_nodes.yaml
 create mode 100644 deployment/kubernetes/node000-deploy.yaml
 create mode 100755 deployment/start_in_cluster

diff --git a/deployment/README.md b/deployment/README.md
new file mode 100644
index 00000000..61e4a0cc
--- /dev/null
+++ b/deployment/README.md
@@ -0,0 +1,18 @@
+### Deployment
+Included in this directory are some template files for running Burrow in a 
+cluster orchestration environment. [start_in_cluster](start_in_cluster) 
+is a general purpose script and the files in [kubernetes](kubernetes) are some
+example Service and Deployment files that illustrates its possible usage.
+
+#### start_in_cluster
+[start_in_cluster](start_in_cluster) takes its parameters as environment variables.
+
+You can find the variables used at the top of the file along with their defaults.
+
+#### Kubernetes
+[all_nodes.yml](kubernetes/all_nodes.yaml) is a Kubernetes Service definition
+that launches an entire network of nodes based on Deployment definitions like the
+example [node000-deploy.yaml](kubernetes/node000-deploy.yaml). Each validating
+node should have it's own Deployment defintion like the one found in 
+[node000-deploy.yaml](kubernetes/node000-deploy.yaml)
+
diff --git a/deployment/kubernetes/all_nodes.yaml b/deployment/kubernetes/all_nodes.yaml
new file mode 100644
index 00000000..91a73702
--- /dev/null
+++ b/deployment/kubernetes/all_nodes.yaml
@@ -0,0 +1,37 @@
+# All Nodes - Load balanced API ports
+kind: Service
+apiVersion: v1
+metadata:
+  name: your-app-chain-api
+  labels:
+    app: your-app
+    tier: chain
+    chain_name: your-chain
+    vendor: monax
+spec:
+  sessionAffinity: ClientIP
+  selector:
+    app: your-app
+    tier: chain
+    # node_number: "001"
+  ports:
+    - protocol: TCP
+      port: 1337
+      targetPort: 1337
+      name: your-app-chain-api
+
+# All Nodes - genesis.json as ConfigMap
+---
+kind: ConfigMap
+apiVersion: v1
+metadata:
+  name: your-app-ecosystem-chain-genesis
+  labels:
+    app: your-app-ecosystem
+    tier: chain
+    chain_name: your-app
+    vendor: monax
+data:
+  chain-genesis: |
+    {"chain_id":"your-chain","accounts":[{"address":"BD1EA8ABA4B44094A406092922AF7CD92E01E5FE","amount":99999999999999,"name":"your-app_root_000","permissions":{"base":{"perms":16383,"set":16383},"roles":[]}},{"address":"E69B68990FECA85E06421859DBD4B2958C80A0D5","amount":9999999999,"name":"your-app_participant_000","permissions":{"base":{"perms":2118,"set":16383},"roles":[]}},{"address":"15416FC158C2D106B2994C82724B3DBBA47CDF79","amount":9999999999,"name":"your-app_participant_001","permissions":{"base":{"perms":2118,"set":16383},"roles":[]}},{"address":"EA6EBC0569495F98F159D533E8DD7D1D3DCFC80C","amount":9999999999,"name":"your-app_participant_002","permissions":{"base":{"perms":2118,"set":16383},"roles":[]}},{"address":"242075F27576B80F2A2805488E23203CBCBCBDFB","amount":99999999999999,"name":"your-app_validator_000","permissions":{"base":{"perms":16383,"set":16383},"roles":[]}},{"address":"8B84E223A42DEDC8C62A19F99C45C94B807BDFB6","amount":9999999999,"name":"your-app_validator_001","permissions":{"base":{"perms":32,"set":16383},"roles":[]}},{"address":"68AFC7ADB01A8CF8F9B93166D749F0067D250981","amount":9999999999,"name":"your-app_validator_002","permissions":{"base":{"perms":32,"set":16383},"roles":[]}},{"address":"443BAD24961BEE41F052C6B55AF58BDE9A4DB75F","amount":9999999999,"name":"your-app_validator_003","permissions":{"base":{"perms":32,"set":16383},"roles":[]}}],"validators":[{"pub_key":[1,"ED3EAEAAA735EC41A3625BB8AAC754A381A5726269E584B77A594E4197F2B516"],"name":"your-app_validator_000","amount":9999999998,"unbond_to":[{"address":"242075F27576B80F2A2805488E23203CBCBCBDFB","amount":9999999998}]},{"pub_key":[1,"F8F98DE0E65FBF8FBA5CE0813898F4E2FAFC34DD37FDB45B58D73B6D75DCB9AE"],"name":"your-app_validator_001","amount":9999999998,"unbond_to":[{"address":"8B84E223A42DEDC8C62A19F99C45C94B807BDFB6","amount":9999999998}]},{"pub_key":[1,"31D592F81F688AEE06B3124CBAC5AE3E04B5398A34325D4D32A25105B9588385"],"name":"your-app_validator_002","amount":9999999998,"unbond_to":[{"address":"68AFC7ADB01A8CF8F9B93166D749F0067D250981","amount":9999999998}]},{"pub_key":[1,"A1562215F9025DAA180B06C4DD9254D6B92C9F6C19219A359956941EB5924148"],"name":"your-app_validator_003","amount":9999999998,"unbond_to":[{"address":"443BAD24961BEE41F052C6B55AF58BDE9A4DB75F","amount":9999999998}]}]}
+
diff --git a/deployment/kubernetes/node000-deploy.yaml b/deployment/kubernetes/node000-deploy.yaml
new file mode 100644
index 00000000..b1d0dad5
--- /dev/null
+++ b/deployment/kubernetes/node000-deploy.yaml
@@ -0,0 +1,64 @@
+# Node 000 - Deployment
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: your-app-ecosystem-chain-000
+spec:
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: your-app-ecosystem
+        tier: chain
+        node_number: "000"
+        chain_name: your-app
+        vendor: monax
+    spec:
+      containers:
+      - name: your-app-ecosystem-chain-000
+        image: "your-app-ecosystem-chain:latest"
+        imagePullPolicy: IfNotPresent
+        env:
+        - name: CHAIN_NAME
+          value: your-chain
+        - name: CHAIN_NODE_NUMBER
+          value: "000"
+        - name: CHAIN_SEEDS
+          value: "your-app-chain-000:46656,your-app-chain-001:46656,your-app-chain-002:46656,your-app-chain-003:46656"
+        - name: CHAIN_API_PORT
+          value: "1337"
+        - name: CHAIN_PEER_PORT
+          value: "46656"
+        - name: CHAIN_RPC_PORT
+          value: "46657"
+        - name: CHAIN_LOG_LEVEL
+          value: notice
+        - name: CHAIN_GENESIS
+          valueFrom:
+            configMapKeyRef:
+              name: your-app-ecosystem-chain-genesis
+              key: chain-genesis
+        - name: KEY_ADDRESS
+          valueFrom:
+            secretKeyRef:
+              name: your-app-ecosystem-chain-000-keys
+              key: address
+        - name: KEY_PUBLIC
+          valueFrom:
+            secretKeyRef:
+              name: your-app-ecosystem-chain-000-keys
+              key: public-key
+        - name: KEY_PRIVATE
+          valueFrom:
+            secretKeyRef:
+              name: your-app-ecosystem-chain-000-keys
+              key: private-key
+        - name: ORGANIZATION_NAME
+          value: allianz
+        ports:
+        - containerPort: 46656
+        - containerPort: 46657
+        - containerPort: 1337
+      restartPolicy: Always
+
diff --git a/deployment/start_in_cluster b/deployment/start_in_cluster
new file mode 100755
index 00000000..29b29fdd
--- /dev/null
+++ b/deployment/start_in_cluster
@@ -0,0 +1,184 @@
+#!/usr/bin/env bash
+set -e
+
+# This script is a wrapper for running burrow in a cluster, that is by a cluster
+# orchestration environment like Kubernetes or Mesos
+
+# For why this is necessary see ->
+# https://github.com/kubernetes/kubernetes/issues/23404
+CHAIN_NAME=$(echo $CHAIN_NAME | tr -d '\n')
+CHAIN_NODE_NUMBER=$(echo $CHAIN_NODE_NUMBER | tr -d '\n')
+CHAIN_SEEDS=$(echo $CHAIN_SEEDS | tr -d '\n')
+ERIS=${ERIS:-$HOME/.eris}
+ERIS=$(echo $ERIS | tr -d '\n')
+KEY_ADDRESS=$(echo $KEY_ADDRESS | tr -d '\n')
+KEY_PUBLIC=$(echo $KEY_PUBLIC | tr -d '\n')
+KEY_PRIVATE=$(echo $KEY_PRIVATE | tr -d '\n')
+ORG_NAME=$(echo $ORG_NAME | tr -d '\n')
+
+# Normal var setting
+CHAIN_DIR=$ERIS/chains/$CHAIN_NAME
+CHAIN_ID=${CHAIN_ID:-$CHAIN_NAME}
+CHAIN_API_PORT=${CHAIN_API_PORT:-1337}
+CHAIN_PEER_PORT=${CHAIN_PEER_PORT:-46656}
+CHAIN_RPC_PORT=${CHAIN_RPC_PORT:-46657}
+CHAIN_NODE_NUMBER=${CHAIN_NODE_NUMBER:-"000"}
+CHAIN_SEEDS=${CHAIN_SEEDS:-""}
+ORG_NAME=${ORG_NAME:-"myGreatOrg"}
+
+# All known variables should either have defaults set above, or checks here.
+check() {
+  echo -e "\tChecking address of key."
+  [ -z "$KEY_ADDRESS" ] && { echo "Sad marmot face. Please set KEY_ADDRESS and re-run me."; exit 1; }
+  echo -e "\tChecking public key."
+  [ -z "$KEY_PUBLIC" ] && { echo "Sad marmot face. Please set KEY_PUBLIC and re-run me."; exit 1; }
+  echo -e "\tChecking private key."
+  [ -z "$KEY_PRIVATE" ] && { echo "Sad marmot face. Please set KEY_PRIVATE and re-run me."; exit 1; }
+  echo -e "\tChecking chain name."
+  [ -z "$CHAIN_NAME" ] && { echo "Sad marmot face. Please set CHAIN_NAME and re-run me."; exit 1; }
+  echo -e "\tChecking genesis."
+  if [ -z "$CHAIN_GENESIS" ]
+  then
+    if [ ! -e "$CHAIN_DIR"/genesis.json ]
+    then
+      echo "Sad marmot face. Please set CHAIN_GENESIS and re-run me."
+      exit 1
+    fi
+  fi
+  echo -e "\tChecks complete."
+}
+
+setup_dir() {
+  if [ ! -d "$CHAIN_DIR" ]
+  then
+    echo -e "\tChain dir does not exist. Creating."
+    mkdir -p $CHAIN_DIR
+  else
+    echo -e "\tChain dir exists. Not creating."
+  fi
+  cd $CHAIN_DIR
+  echo -e "\tChain dir setup."
+}
+
+write_config() {
+  cat <<EOF > config.toml
+[chain]
+assert_chain_id = "$CHAIN_ID"
+major_version = 0
+minor_version = 12
+genesis_file = "genesis.json"
+  [chain.consensus]
+  name = "tendermint"
+  major_version = 0
+  minor_version = 6
+  relative_root = "tendermint"
+  [chain.manager]
+  name = "erismint"
+  major_version = 0
+  minor_version = 12
+  relative_root = "erismint"
+[servers]
+  [servers.bind]
+  address = ""
+  port = $CHAIN_API_PORT
+  [servers.tls]
+  tls = false
+  cert_path = ""
+  key_path = ""
+  [servers.cors]
+  enable = false
+  allow_origins = []
+  allow_credentials = false
+  allow_methods = []
+  allow_headers = []
+  expose_headers = []
+  max_age = 0
+  [servers.http]
+  json_rpc_endpoint = "/rpc"
+  [servers.websocket]
+  endpoint = "/socketrpc"
+  max_sessions = 50
+  read_buffer_size = 4096
+  write_buffer_size = 4096
+  [servers.tendermint]
+  rpc_local_address = "0.0.0.0:$CHAIN_RPC_PORT"
+  endpoint = "/websocket"
+[tendermint]
+private_validator_file = "priv_validator.json"
+  [tendermint.configuration]
+  moniker = "$CHAIN_NAME-$ORG_NAME-validator-$CHAIN_NODE_NUMBER"
+  seeds = "$CHAIN_SEEDS"
+  fast_sync = false
+  db_backend = "leveldb"
+  log_level = "$CHAIN_LOG_LEVEL"
+  node_laddr = "0.0.0.0:$CHAIN_PEER_PORT"
+  rpc_laddr = "0.0.0.0:$CHAIN_RPC_PORT"
+  proxy_app = "tcp://127.0.0.1:46658"
+    [tendermint.configuration.p2p]
+    dial_timeout_seconds = 3
+    handshake_timeout_seconds = 20
+    max_num_peers = 20
+    authenticated_encryption = true
+    send_rate = 512000
+    recv_rate = 512000
+    fuzz_enable = false # use the fuzz wrapped conn
+    fuzz_active = false # toggle fuzzing
+    fuzz_mode = "drop"  # eg. drop, delay
+    fuzz_max_delay_milliseconds = 3000
+    fuzz_prob_drop_rw = 0.2
+    fuzz_prob_drop_conn = 0.00
+    fuzz_prob_sleep = 0.00
+[erismint]
+db_backend = "leveldb"
+tendermint_host = "0.0.0.0:$CHAIN_RPC_PORT"
+EOF
+  echo -e "\tConfig file written."
+}
+
+write_key_file() {
+  cat <<EOF > priv_validator.json
+{
+  "address": "$KEY_ADDRESS",
+  "pub_key": [
+    1,
+    "$KEY_PUBLIC"
+  ],
+  "priv_key": [
+    1,
+    "$KEY_PRIVATE"
+  ],
+  "last_height": 0,
+  "last_round": 0,
+  "last_step": 0
+}
+EOF
+  echo -e "\tKey file written."
+}
+
+write_genesis_file() {
+  [ -z "$CHAIN_GENESIS" ] && echo -e "\tUsing preloaded genesis file." && return 0
+  echo -e "\tWriting genesis file from environment variables."
+  echo $CHAIN_GENESIS > genesis.json
+}
+
+main() {
+  echo "Running pre-boot checks."
+  check
+
+  echo "Setting up chain directory."
+  setup_dir
+
+  echo "Writing config file."
+  write_config
+
+  echo "Writing key file."
+  write_key_file
+
+  echo "Writing genesis file."
+  write_genesis_file
+
+  sleep 2 # hack to let the cluster provision echo "Starting eris-db"
+  eris-db serve
+}
+
+main $@
\ No newline at end of file
-- 
GitLab