mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-12 04:41:22 +00:00
mv tools files to tools repo
This commit is contained in:
192
tools/mintnet-kubernetes/LICENSE
Normal file
192
tools/mintnet-kubernetes/LICENSE
Normal file
@ -0,0 +1,192 @@
|
||||
Copyright (C) 2017 Tendermint
|
||||
|
||||
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
290
tools/mintnet-kubernetes/README.rst
Normal file
290
tools/mintnet-kubernetes/README.rst
Normal file
@ -0,0 +1,290 @@
|
||||
Using Kubernetes
|
||||
================
|
||||
|
||||
.. figure:: assets/t_plus_k.png
|
||||
:alt: Tendermint plus Kubernetes
|
||||
|
||||
Tendermint plus Kubernetes
|
||||
|
||||
This should primarily be used for testing purposes or for
|
||||
tightly-defined chains operated by a single stakeholder (see `the
|
||||
security precautions <#security>`__). If your desire is to launch an
|
||||
application with many stakeholders, consider using our set of Ansible
|
||||
scripts.
|
||||
|
||||
Quick Start
|
||||
-----------
|
||||
|
||||
For either platform, see the `requirements <https://github.com/kubernetes/minikube#requirements>`__
|
||||
|
||||
MacOS
|
||||
^^^^^
|
||||
|
||||
::
|
||||
|
||||
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/kubectl
|
||||
curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.18.0/minikube-darwin-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/
|
||||
minikube start
|
||||
|
||||
git clone https://github.com/tendermint/tools.git && cd tools/mintnet-kubernetes/examples/basecoin && make create
|
||||
|
||||
Linux
|
||||
^^^^^
|
||||
|
||||
::
|
||||
|
||||
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/kubectl
|
||||
curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.18.0/minikube-linux-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/
|
||||
minikube start
|
||||
|
||||
git clone https://github.com/tendermint/tools.git && cd tools/mintnet-kubernetes/examples/basecoin && make create
|
||||
|
||||
Verify it worked
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
**Using a shell:**
|
||||
|
||||
First wait until all the pods are ``Running``:
|
||||
|
||||
``kubectl get pods -w -o wide -L tm``
|
||||
|
||||
then query the Tendermint app logs from the first pod:
|
||||
|
||||
``kubectl logs -c tm -f tm-0``
|
||||
|
||||
finally, use our `Rest API <../specification/rpc.html>`__ to fetch the status of the second pod's Tendermint app.
|
||||
|
||||
Note we are using ``kubectl exec`` because pods are not exposed (and should not be) to the
|
||||
outer network:
|
||||
|
||||
``kubectl exec -c tm tm-0 -- curl -s http://tm-1.basecoin:26657/status | json_pp``
|
||||
|
||||
**Using the dashboard:**
|
||||
|
||||
::
|
||||
|
||||
minikube dashboard
|
||||
|
||||
Clean up
|
||||
~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
make destroy
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Setup a Kubernetes cluster
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- locally using `Minikube <https://github.com/kubernetes/minikube>`__
|
||||
- on GCE with a single click in the web UI
|
||||
- on AWS using `Kubernetes
|
||||
Operations <https://github.com/kubernetes/kops/blob/master/docs/aws.md>`__
|
||||
- on Linux machines (Digital Ocean) using
|
||||
`kubeadm <https://kubernetes.io/docs/getting-started-guides/kubeadm/>`__
|
||||
- on AWS, Azure, GCE or bare metal using `Kargo
|
||||
(Ansible) <https://kubernetes.io/docs/getting-started-guides/kargo/>`__
|
||||
|
||||
Please refer to `the official
|
||||
documentation <https://kubernetes.io/docs/getting-started-guides/>`__
|
||||
for overview and comparison of different options.
|
||||
|
||||
Kubernetes on Digital Ocean
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Available options:
|
||||
|
||||
- `kubeadm (alpha) <https://kubernetes.io/docs/getting-started-guides/kubeadm/>`__
|
||||
- `kargo <https://kubernetes.io/docs/getting-started-guides/kargo/>`__
|
||||
- `rancher <http://rancher.com/>`__
|
||||
- `terraform <https://github.com/hermanjunge/kubernetes-digitalocean-terraform>`__
|
||||
|
||||
As you can see, there is no single tool for creating a cluster on DO.
|
||||
Therefore, choose the one you know and comfortable working with. If you know
|
||||
and used `terraform <https://www.terraform.io/>`__ before, then choose it. If you
|
||||
know Ansible, then pick kargo. If none of these seem familiar to you, go with
|
||||
``kubeadm``. Rancher is a beautiful UI for deploying and managing containers in
|
||||
production.
|
||||
|
||||
Kubernetes on Google Cloud Engine
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Review the `Official Documentation <https://kubernetes.io/docs/getting-started-guides/gce/>`__ for Kubernetes on Google Compute
|
||||
Engine.
|
||||
|
||||
**Create a cluster**
|
||||
|
||||
The recommended way is to use `Google Container
|
||||
Engine <https://cloud.google.com/container-engine/>`__. You should be able
|
||||
to create a fully fledged cluster with just a few clicks.
|
||||
|
||||
**Connect to it**
|
||||
|
||||
Install ``gcloud`` as a part of `Google Cloud SDK <https://cloud.google.com/sdk/>`__.
|
||||
|
||||
Make sure you have credentials for GCloud by running ``gcloud auth login``.
|
||||
|
||||
In order to make API calls against GCE, you must also run ``gcloud auth
|
||||
application-default login``.
|
||||
|
||||
Press ``Connect``:
|
||||
|
||||
.. figure:: assets/gce1.png
|
||||
|
||||
and execute the first command in your shell. Then start a proxy by
|
||||
executing ``kubectl` proxy``.
|
||||
|
||||
.. figure:: assets/gce2.png
|
||||
|
||||
Now you should be able to run ``kubectl`` command to create resources, get
|
||||
resource info, logs, etc.
|
||||
|
||||
**Make sure you have Kubernetes >= 1.5, because you will be using
|
||||
StatefulSets, which is a beta feature in 1.5.**
|
||||
|
||||
Create a configuration file
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Download a template:
|
||||
|
||||
::
|
||||
|
||||
curl -Lo app.yaml https://github.com/tendermint/tools/raw/master/mintnet-kubernetes/app.template.yaml
|
||||
|
||||
Open ``app.yaml`` in your favorite editor and configure your app
|
||||
container (navigate to ``- name: app``). Kubernetes DSL (Domain Specific
|
||||
Language) is very simple, so it should be easy. You will need to set
|
||||
Docker image, command and/or run arguments. Replace variables prefixed
|
||||
with ``YOUR_APP`` with corresponding values. Set genesis time to now and
|
||||
preferable chain ID in ConfigMap.
|
||||
|
||||
Please note if you are changing ``replicas`` number, do not forget to
|
||||
update ``validators`` set in ConfigMap. You will be able to scale the
|
||||
cluster up or down later, but new pods (nodes) won't become validators
|
||||
automatically.
|
||||
|
||||
Deploy your application
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
kubectl create -f ./app.yaml
|
||||
|
||||
Observe your cluster
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
`web UI <https://github.com/kubernetes/dashboard>`__
|
||||
|
||||
The easiest way to access Dashboard is to use ``kubectl``. Run the following
|
||||
command in your desktop environment:
|
||||
|
||||
::
|
||||
|
||||
kubectl proxy
|
||||
|
||||
``kubectl`` will handle authentication with apiserver and make Dashboard
|
||||
available at http://localhost:8001/ui
|
||||
|
||||
**shell**
|
||||
|
||||
List all the pods:
|
||||
|
||||
::
|
||||
|
||||
kubectl get pods -o wide -L tm
|
||||
|
||||
StatefulSet details:
|
||||
|
||||
::
|
||||
|
||||
kubectl describe statefulsets tm
|
||||
|
||||
First pod details:
|
||||
|
||||
::
|
||||
|
||||
kubectl describe pod tm-0
|
||||
|
||||
Tendermint app logs from the first pod:
|
||||
|
||||
::
|
||||
|
||||
kubectl logs tm-0 -c tm -f
|
||||
|
||||
App logs from the first pod:
|
||||
|
||||
::
|
||||
|
||||
kubectl logs tm-0 -c app -f
|
||||
|
||||
Status of the second pod's Tendermint app:
|
||||
|
||||
::
|
||||
|
||||
kubectl exec -c tm tm-0 -- curl -s http://tm-1.<YOUR_APP_NAME>:26657/status | json_pp
|
||||
|
||||
Security
|
||||
--------
|
||||
|
||||
Due to the nature of Kubernetes, where you typically have a single
|
||||
master, the master could be a SPOF (Single Point Of Failure). Therefore,
|
||||
you need to make sure only authorized people can access it. And these
|
||||
people themselves had taken basic measures in order not to get hacked.
|
||||
|
||||
These are the best practices:
|
||||
|
||||
- all access to the master is over TLS
|
||||
- access to the API Server is X.509 certificate or token based
|
||||
- etcd is not exposed directly to the cluster
|
||||
- ensure that images are free of vulnerabilities
|
||||
(`1 <https://github.com/coreos/clair>`__)
|
||||
- ensure that only authorized images are used in your environment
|
||||
- disable direct access to Kubernetes nodes (no SSH)
|
||||
- define resource quota
|
||||
|
||||
Resources:
|
||||
|
||||
- https://kubernetes.io/docs/admin/accessing-the-api/
|
||||
- http://blog.kubernetes.io/2016/08/security-best-practices-kubernetes-deployment.html
|
||||
- https://blog.openshift.com/securing-kubernetes/
|
||||
|
||||
Fault tolerance
|
||||
---------------
|
||||
|
||||
Having a single master (API server) is a bad thing also because if
|
||||
something happens to it, you risk being left without an access to the
|
||||
application.
|
||||
|
||||
To avoid that you can `run Kubernetes in multiple
|
||||
zones <https://kubernetes.io/docs/admin/multiple-zones/>`__, each zone
|
||||
running an `API
|
||||
server <https://kubernetes.io/docs/admin/high-availability/>`__ and load
|
||||
balance requests between them. Do not forget to make sure only one
|
||||
instance of scheduler and controller-manager are running at once.
|
||||
|
||||
Running in multiple zones is a lightweight version of a broader `Cluster
|
||||
Federation feature <https://kubernetes.io/docs/admin/federation/>`__.
|
||||
Federated deployments could span across multiple regions (not zones). We
|
||||
haven't tried this feature yet, so any feedback is highly appreciated!
|
||||
Especially, related to additional latency and cost of exchanging data
|
||||
between the regions.
|
||||
|
||||
Resources:
|
||||
|
||||
- https://kubernetes.io/docs/admin/high-availability/
|
||||
|
||||
Starting process
|
||||
----------------
|
||||
|
||||
.. figure:: assets/statefulset.png
|
||||
:alt: StatefulSet
|
||||
|
||||
StatefulSet
|
||||
|
||||
Init containers (``tm-gen-validator``) are run before all other
|
||||
containers, creating public-private key pair for each pod. Every ``tm``
|
||||
container then asks other pods for their public keys, which are served
|
||||
with nginx (``pub-key`` container). When ``tm`` container have all the
|
||||
keys, it forms a genesis file and starts the Tendermint process.
|
265
tools/mintnet-kubernetes/app.template.yaml
Normal file
265
tools/mintnet-kubernetes/app.template.yaml
Normal file
@ -0,0 +1,265 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
annotations:
|
||||
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
|
||||
name: YOUR_APP_NAME
|
||||
labels:
|
||||
app: YOUR_APP_NAME
|
||||
spec:
|
||||
ports:
|
||||
- port: 26656
|
||||
name: p2p
|
||||
- port: 26657
|
||||
name: rpc
|
||||
clusterIP: None
|
||||
selector:
|
||||
app: tm
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: tm-config
|
||||
data:
|
||||
seeds: "tm-0,tm-1,tm-2,tm-3"
|
||||
validators: "tm-0,tm-1,tm-2,tm-3"
|
||||
validator.power: "10"
|
||||
genesis.json: |-
|
||||
{
|
||||
"genesis_time": "2017-01-02T10:10:10.164Z",
|
||||
"chain_id": "chain-B5XXm5",
|
||||
"validators": [],
|
||||
"app_hash": ""
|
||||
}
|
||||
pub_key_nginx.conf: |-
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server ipv6only=on;
|
||||
location /pub_key.json { root /usr/share/nginx/; }
|
||||
}
|
||||
---
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: tm-budget
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: tm
|
||||
minAvailable: 2
|
||||
---
|
||||
apiVersion: apps/v1beta1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: tm
|
||||
spec:
|
||||
serviceName: YOUR_APP_NAME
|
||||
replicas: 4
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: tm
|
||||
version: v1
|
||||
annotations:
|
||||
pod.beta.kubernetes.io/init-containers: '[{
|
||||
"name": "tm-gen-validator",
|
||||
"image": "tendermint/tendermint:0.10.0",
|
||||
"imagePullPolicy": "IfNotPresent",
|
||||
"command": ["bash", "-c", "
|
||||
set -ex\n
|
||||
if [ ! -f /tendermint/priv_validator.json ]; then\n
|
||||
tendermint gen_validator > /tendermint/priv_validator.json\n
|
||||
# pub_key.json will be served by pub-key container\n
|
||||
cat /tendermint/priv_validator.json | jq \".pub_key\" > /tendermint/pub_key.json\n
|
||||
fi\n
|
||||
"],
|
||||
"volumeMounts": [
|
||||
{"name": "tmdir", "mountPath": "/tendermint"}
|
||||
]
|
||||
}]'
|
||||
spec:
|
||||
containers:
|
||||
- name: tm
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: tendermint/tendermint:0.10.0
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
ports:
|
||||
- containerPort: 26656
|
||||
name: p2p
|
||||
- containerPort: 26657
|
||||
name: rpc
|
||||
env:
|
||||
- name: SEEDS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: seeds
|
||||
- name: VALIDATOR_POWER
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: validator.power
|
||||
- name: VALIDATORS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: validators
|
||||
- name: TMHOME
|
||||
value: /tendermint
|
||||
command:
|
||||
- bash
|
||||
- "-c"
|
||||
- |
|
||||
set -ex
|
||||
|
||||
# copy template
|
||||
cp /etc/tendermint/genesis.json /tendermint/genesis.json
|
||||
|
||||
# fill genesis file with validators
|
||||
IFS=',' read -ra VALS_ARR <<< "$VALIDATORS"
|
||||
fqdn_suffix=$(hostname -f | sed 's#[^.]*\.\(\)#\1#')
|
||||
for v in "${VALS_ARR[@]}"; do
|
||||
# wait until validator generates priv/pub key pair
|
||||
set +e
|
||||
|
||||
curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null
|
||||
ERR=$?
|
||||
while [ "$ERR" != 0 ]; do
|
||||
sleep 5
|
||||
curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null
|
||||
ERR=$?
|
||||
done
|
||||
set -e
|
||||
|
||||
# add validator to genesis file along with its pub_key
|
||||
curl -s "http://$v.$fqdn_suffix/pub_key.json" | jq ". as \$k | {pub_key: \$k, amount: $VALIDATOR_POWER, name: \"$v\"}" > pub_validator.json
|
||||
cat /tendermint/genesis.json | jq ".validators |= .+ [$(cat pub_validator.json)]" > tmpgenesis && mv tmpgenesis /tendermint/genesis.json
|
||||
rm pub_validator.json
|
||||
done
|
||||
|
||||
# construct seeds
|
||||
IFS=',' read -ra SEEDS_ARR <<< "$SEEDS"
|
||||
seeds=()
|
||||
for s in "${SEEDS_ARR[@]}"; do
|
||||
seeds+=("$s.$fqdn_suffix:26656")
|
||||
done
|
||||
seeds=$(IFS=','; echo "${seeds[*]}")
|
||||
|
||||
tendermint node --p2p.seeds="$seeds" --moniker="`hostname`" --proxy_app="unix:///socks/app.sock"
|
||||
volumeMounts:
|
||||
- name: tmdir
|
||||
mountPath: /tendermint
|
||||
- mountPath: /etc/tendermint/genesis.json
|
||||
name: configdir
|
||||
subPath: genesis.json
|
||||
- name: socksdir
|
||||
mountPath: /socks
|
||||
|
||||
- name: app
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: YOUR_APP_IMAGE
|
||||
args: ["--addr=\"unix:///socks/app.sock\""]
|
||||
volumeMounts:
|
||||
- name: socksdir
|
||||
mountPath: /socks
|
||||
|
||||
######## OR ########
|
||||
#
|
||||
# - name: app
|
||||
# imagePullPolicy: IfNotPresent
|
||||
# image: golang:1.7.5
|
||||
# resources:
|
||||
# requests:
|
||||
# cpu: YOUR_APP_CPU_REQ
|
||||
# memory: YOUR_APP_MEM_REQ
|
||||
# limits:
|
||||
# cpu: YOUR_APP_CPU_LIMIT
|
||||
# memory: YOUR_APP_MEM_LIMIT
|
||||
# command:
|
||||
# - bash
|
||||
# - "-c"
|
||||
# - |
|
||||
# set -ex
|
||||
|
||||
# go get -d YOUR_APP_PACKAGE
|
||||
# cd $GOPATH/YOUR_APP_PACKAGE
|
||||
# make install
|
||||
#
|
||||
# rm -f /socks/app.sock # remove old socket
|
||||
|
||||
# YOUR_APP_EXEC --addr="unix:///socks/app.sock"
|
||||
# volumeMounts:
|
||||
# - name: socksdir
|
||||
# mountPath: /socks
|
||||
|
||||
######## OPTIONALLY ########
|
||||
#
|
||||
# - name: data
|
||||
# imagePullPolicy: IfNotPresent
|
||||
# image: golang:1.7.5
|
||||
# command:
|
||||
# - bash
|
||||
# - "-c"
|
||||
# - |
|
||||
# set -ex
|
||||
# go get github.com/tendermint/merkleeyes/cmd/merkleeyes
|
||||
# rm -f /socks/data.sock # remove old socket
|
||||
# merkleeyes server --address="unix:///socks/data.sock"
|
||||
# volumeMounts:
|
||||
# - name: socksdir
|
||||
# mountPath: /socks
|
||||
|
||||
- name: pub-key
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: nginx:1.11.9
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 12Mi
|
||||
limits:
|
||||
cpu: 20m
|
||||
memory: 24Mi
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: pub-key
|
||||
command:
|
||||
- bash
|
||||
- "-c"
|
||||
- |
|
||||
set -ex
|
||||
# fixes 403 Permission Denied (open() "/tendermint/pub_key.json" failed (13: Permission denied))
|
||||
# => we cannot serve from /tendermint, so we copy the file
|
||||
mkdir -p /usr/share/nginx
|
||||
cp /tendermint/pub_key.json /usr/share/nginx/pub_key.json
|
||||
nginx -g "daemon off;"
|
||||
volumeMounts:
|
||||
- name: tmdir
|
||||
mountPath: /tendermint
|
||||
- mountPath: /etc/nginx/conf.d/pub_key.conf
|
||||
name: configdir
|
||||
subPath: pub_key_nginx.conf
|
||||
|
||||
volumes:
|
||||
- name: configdir
|
||||
configMap:
|
||||
name: tm-config
|
||||
- name: socksdir
|
||||
emptyDir: {}
|
||||
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: tmdir
|
||||
annotations:
|
||||
volume.alpha.kubernetes.io/storage-class: anything
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
BIN
tools/mintnet-kubernetes/assets/gce1.png
Normal file
BIN
tools/mintnet-kubernetes/assets/gce1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
tools/mintnet-kubernetes/assets/gce2.png
Normal file
BIN
tools/mintnet-kubernetes/assets/gce2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
BIN
tools/mintnet-kubernetes/assets/statefulset.png
Normal file
BIN
tools/mintnet-kubernetes/assets/statefulset.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
BIN
tools/mintnet-kubernetes/assets/t_plus_k.png
Normal file
BIN
tools/mintnet-kubernetes/assets/t_plus_k.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
10
tools/mintnet-kubernetes/examples/basecoin/Makefile
Normal file
10
tools/mintnet-kubernetes/examples/basecoin/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
create:
|
||||
@echo "==> Creating deployment"
|
||||
@kubectl create -f app.yaml
|
||||
|
||||
destroy:
|
||||
@echo "==> Destroying deployment"
|
||||
@kubectl delete -f app.yaml
|
||||
@kubectl delete pvc -l app=tm
|
||||
|
||||
.PHONY: create destroy
|
42
tools/mintnet-kubernetes/examples/basecoin/README.md
Normal file
42
tools/mintnet-kubernetes/examples/basecoin/README.md
Normal file
@ -0,0 +1,42 @@
|
||||
# Basecoin example
|
||||
|
||||
This is an example of using [basecoin](https://github.com/tendermint/basecoin).
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
make create
|
||||
```
|
||||
|
||||
### Check account balance and send a transaction
|
||||
|
||||
1. wait until all the pods are `Running`.
|
||||
|
||||
```
|
||||
kubectl get pods -w -o wide -L tm
|
||||
```
|
||||
|
||||
2. wait until app starts.
|
||||
|
||||
```
|
||||
kubectl logs -c app -f tm-0
|
||||
```
|
||||
|
||||
3. get account's address of the second pod
|
||||
|
||||
```
|
||||
ADDR=`kubectl exec -c app tm-1 -- cat /app/key.json | jq ".address" | tr -d "\""`
|
||||
```
|
||||
|
||||
4. send 5 coins to it from the first pod
|
||||
|
||||
```
|
||||
kubectl exec -c app tm-0 -- basecoin tx send --to "0x$ADDR" --amount 5mycoin --from /app/key.json --chain_id chain-tTH4mi
|
||||
```
|
||||
|
||||
|
||||
## Clean up
|
||||
|
||||
```
|
||||
make destroy
|
||||
```
|
334
tools/mintnet-kubernetes/examples/basecoin/app.yaml
Normal file
334
tools/mintnet-kubernetes/examples/basecoin/app.yaml
Normal file
@ -0,0 +1,334 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
annotations:
|
||||
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
|
||||
name: basecoin
|
||||
labels:
|
||||
app: basecoin
|
||||
spec:
|
||||
ports:
|
||||
- port: 26656
|
||||
name: p2p
|
||||
- port: 26657
|
||||
name: rpc
|
||||
clusterIP: None
|
||||
selector:
|
||||
app: tm
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: tm-config
|
||||
data:
|
||||
seeds: "tm-0,tm-1,tm-2,tm-3"
|
||||
validators: "tm-0,tm-1,tm-2,tm-3"
|
||||
validator.power: "10"
|
||||
genesis.json: |-
|
||||
{
|
||||
"genesis_time": "2016-02-05T06:02:31.526Z",
|
||||
"chain_id": "chain-tTH4mi",
|
||||
"validators": [],
|
||||
"app_hash": ""
|
||||
}
|
||||
pub_key_nginx.conf: |-
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server ipv6only=on;
|
||||
location /pub_key.json { root /usr/share/nginx/; }
|
||||
location /app_pub_key.json { root /usr/share/nginx/; }
|
||||
}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config
|
||||
data:
|
||||
genesis.json: |-
|
||||
{
|
||||
"chain_id": "chain-tTH4mi",
|
||||
"app_options": {
|
||||
"accounts": [
|
||||
{
|
||||
"pub_key": "tm-0",
|
||||
"coins": [
|
||||
{
|
||||
"denom": "mycoin",
|
||||
"amount": 1000000000
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"pub_key": "tm-1",
|
||||
"coins": [
|
||||
{
|
||||
"denom": "mycoin",
|
||||
"amount": 1000000000
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"pub_key": "tm-2",
|
||||
"coins": [
|
||||
{
|
||||
"denom": "mycoin",
|
||||
"amount": 1000000000
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"pub_key": "tm-3",
|
||||
"coins": [
|
||||
{
|
||||
"denom": "mycoin",
|
||||
"amount": 1000000000
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
---
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: tm-budget
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: tm
|
||||
minAvailable: 2
|
||||
---
|
||||
apiVersion: apps/v1beta1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: tm
|
||||
spec:
|
||||
serviceName: basecoin
|
||||
replicas: 4
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: tm
|
||||
annotations:
|
||||
pod.beta.kubernetes.io/init-containers: '[{
|
||||
"name": "tm-gen-validator",
|
||||
"image": "tendermint/tendermint:0.10.0",
|
||||
"imagePullPolicy": "IfNotPresent",
|
||||
"command": ["bash", "-c", "
|
||||
set -ex\n
|
||||
if [ ! -f /tendermint/priv_validator.json ]; then\n
|
||||
tendermint gen_validator > /tendermint/priv_validator.json\n
|
||||
# pub_key.json will be served by pub-key container\n
|
||||
cat /tendermint/priv_validator.json | jq \".pub_key\" > /tendermint/pub_key.json\n
|
||||
fi\n
|
||||
"],
|
||||
"volumeMounts": [
|
||||
{"name": "tmdir", "mountPath": "/tendermint"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "app-gen-key",
|
||||
"image": "tendermint/basecoin:0.5.1",
|
||||
"imagePullPolicy": "IfNotPresent",
|
||||
"command": ["bash", "-c", "
|
||||
set -ex\n
|
||||
if [ ! -f /app/key.json ]; then\n
|
||||
basecoin key new > /app/key.json\n
|
||||
# pub_key.json will be served by app-pub-key container\n
|
||||
cat /app/key.json | jq \".pub_key\" > /app/pub_key.json\n
|
||||
fi\n
|
||||
"],
|
||||
"volumeMounts": [
|
||||
{"name": "appdir", "mountPath": "/app"}
|
||||
]
|
||||
}]'
|
||||
spec:
|
||||
containers:
|
||||
- name: tm
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: tendermint/tendermint:0.10.0
|
||||
ports:
|
||||
- containerPort: 26656
|
||||
name: p2p
|
||||
- containerPort: 26657
|
||||
name: rpc
|
||||
env:
|
||||
- name: SEEDS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: seeds
|
||||
- name: VALIDATOR_POWER
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: validator.power
|
||||
- name: VALIDATORS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: validators
|
||||
- name: TMHOME
|
||||
value: /tendermint
|
||||
command:
|
||||
- bash
|
||||
- "-c"
|
||||
- |
|
||||
set -ex
|
||||
|
||||
# copy template
|
||||
cp /etc/tendermint/genesis.json /tendermint/genesis.json
|
||||
|
||||
# fill genesis file with validators
|
||||
IFS=',' read -ra VALS_ARR <<< "$VALIDATORS"
|
||||
fqdn_suffix=$(hostname -f | sed 's#[^.]*\.\(\)#\1#')
|
||||
for v in "${VALS_ARR[@]}"; do
|
||||
# wait until validator generates priv/pub key pair
|
||||
set +e
|
||||
|
||||
curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null
|
||||
ERR=$?
|
||||
while [ "$ERR" != 0 ]; do
|
||||
sleep 5
|
||||
curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null
|
||||
ERR=$?
|
||||
done
|
||||
set -e
|
||||
|
||||
# add validator to genesis file along with its pub_key
|
||||
curl -s "http://$v.$fqdn_suffix/pub_key.json" | jq ". as \$k | {pub_key: \$k, amount: $VALIDATOR_POWER, name: \"$v\"}" > pub_validator.json
|
||||
cat /tendermint/genesis.json | jq ".validators |= .+ [$(cat pub_validator.json)]" > tmpgenesis && mv tmpgenesis /tendermint/genesis.json
|
||||
rm pub_validator.json
|
||||
done
|
||||
|
||||
# construct seeds
|
||||
IFS=',' read -ra SEEDS_ARR <<< "$SEEDS"
|
||||
seeds=()
|
||||
for s in "${SEEDS_ARR[@]}"; do
|
||||
seeds+=("$s.$fqdn_suffix:26656")
|
||||
done
|
||||
seeds=$(IFS=','; echo "${seeds[*]}")
|
||||
|
||||
tendermint node --p2p.seeds="$seeds" --moniker="`hostname`" --proxy_app="unix:///socks/app.sock"
|
||||
volumeMounts:
|
||||
- name: tmdir
|
||||
mountPath: /tendermint
|
||||
- mountPath: /etc/tendermint/genesis.json
|
||||
name: tmconfigdir
|
||||
subPath: genesis.json
|
||||
- name: socksdir
|
||||
mountPath: /socks
|
||||
|
||||
- name: app
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: tendermint/basecoin:0.5.1
|
||||
env:
|
||||
- name: BCHOME
|
||||
value: /app
|
||||
workingDir: /app
|
||||
command:
|
||||
- bash
|
||||
- "-c"
|
||||
- |
|
||||
set -ex
|
||||
|
||||
# replace "tm-N" with public keys in genesis file
|
||||
cp /etc/app/genesis.json genesis.json
|
||||
fqdn_suffix=$(hostname -f | sed 's#[^.]*\.\(\)#\1#')
|
||||
# for every "base/account"
|
||||
i=0
|
||||
length=$(cat genesis.json | jq ".app_options.accounts | length")
|
||||
while [[ $i -lt $length ]]; do
|
||||
# extract pod name ("tm-0")
|
||||
pod=$(cat genesis.json | jq -r ".app_options.accounts[$i].pub_key")
|
||||
|
||||
# wait until pod starts to serve its pub_key
|
||||
set +e
|
||||
|
||||
curl -s --fail "http://$pod.$fqdn_suffix/app_pub_key.json" > /dev/null
|
||||
ERR=$?
|
||||
while [ "$ERR" != 0 ]; do
|
||||
sleep 5
|
||||
curl -s --fail "http://$pod.$fqdn_suffix/app_pub_key.json" > /dev/null
|
||||
ERR=$?
|
||||
done
|
||||
set -e
|
||||
|
||||
# get its pub_key
|
||||
curl -s "http://$pod.$fqdn_suffix/app_pub_key.json" | jq "." > k.json
|
||||
|
||||
# replace pod name with it ("tm-0" => "{"type": ..., "data": ...}")
|
||||
cat genesis.json | jq ".app_options.accounts[$i].pub_key = $(cat k.json | jq '.')" > tmpgenesis && mv tmpgenesis genesis.json
|
||||
rm -f k.json
|
||||
|
||||
i=$((i+1))
|
||||
done
|
||||
|
||||
rm -f /socks/app.sock # remove old socket
|
||||
|
||||
basecoin start --address="unix:///socks/app.sock" --without-tendermint
|
||||
volumeMounts:
|
||||
- name: appdir
|
||||
mountPath: /app
|
||||
- mountPath: /etc/app/genesis.json
|
||||
name: appconfigdir
|
||||
subPath: genesis.json
|
||||
- name: socksdir
|
||||
mountPath: /socks
|
||||
|
||||
- name: pub-key
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: nginx:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
command:
|
||||
- bash
|
||||
- "-c"
|
||||
- |
|
||||
set -ex
|
||||
# fixes 403 Permission Denied (open() "/tendermint/pub_key.json" failed (13: Permission denied))
|
||||
# => we cannot serve from /tendermint, so we copy the file
|
||||
mkdir -p /usr/share/nginx
|
||||
cp /tendermint/pub_key.json /usr/share/nginx/pub_key.json
|
||||
cp /app/pub_key.json /usr/share/nginx/app_pub_key.json
|
||||
nginx -g "daemon off;"
|
||||
volumeMounts:
|
||||
- name: tmdir
|
||||
mountPath: /tendermint
|
||||
- name: appdir
|
||||
mountPath: /app
|
||||
- mountPath: /etc/nginx/conf.d/pub_key.conf
|
||||
name: tmconfigdir
|
||||
subPath: pub_key_nginx.conf
|
||||
|
||||
volumes:
|
||||
- name: tmconfigdir
|
||||
configMap:
|
||||
name: tm-config
|
||||
- name: appconfigdir
|
||||
configMap:
|
||||
name: app-config
|
||||
- name: socksdir
|
||||
emptyDir: {}
|
||||
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: tmdir
|
||||
annotations:
|
||||
volume.alpha.kubernetes.io/storage-class: anything
|
||||
spec:
|
||||
accessModes: [ "ReadWriteOnce" ]
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
||||
- metadata:
|
||||
name: appdir
|
||||
annotations:
|
||||
volume.alpha.kubernetes.io/storage-class: anything
|
||||
spec:
|
||||
accessModes: [ "ReadWriteOnce" ]
|
||||
resources:
|
||||
requests:
|
||||
storage: 12Mi
|
100
tools/mintnet-kubernetes/examples/basecoin/lightclient.md
Normal file
100
tools/mintnet-kubernetes/examples/basecoin/lightclient.md
Normal file
@ -0,0 +1,100 @@
|
||||
**OUTDATED**
|
||||
|
||||
# Using with lightclient
|
||||
|
||||
We have an awesome cluster running, let's try to test this out without
|
||||
relying on executing commands on the cluster. Rather, we can connect to the
|
||||
rpc interface with the `light-client` package and execute commands locally,
|
||||
or even proxy our webapp to the kubernetes backend.
|
||||
|
||||
## Setup
|
||||
|
||||
In order to get this working, we need to know a few pieces of info,
|
||||
the chain id of tendermint, the chain id of basecoin, and an account
|
||||
with a bit of cash....
|
||||
|
||||
### Tendermint Chain ID
|
||||
|
||||
`kubectl exec -c tm tm-0 -- curl -s http://tm-1.basecoin:26657/status | json_pp | grep network`
|
||||
|
||||
set TM_CHAIN with the value there
|
||||
|
||||
### Basecoin Chain ID
|
||||
|
||||
`kubectl exec -c app tm-1 -- grep -A1 chainID /app/genesis.json`
|
||||
|
||||
set BC_CHAIN with the value there
|
||||
|
||||
### Expose tendermint rpc
|
||||
|
||||
We need to be able to reach the tendermint rpc interface from our shell.
|
||||
|
||||
`kubectl port-forward tm-0 26657:26657`
|
||||
|
||||
### Start basecoin-proxy
|
||||
|
||||
Using this info, let's connect our proxy and get going
|
||||
|
||||
`proxy-basecoin -tmchain=$TM_CHAIN -chain=$BC_CHAIN -rpc=localhost:26657`
|
||||
|
||||
## Basecoin accounts
|
||||
|
||||
Well, we can connect, but we don't have a registered account yet...
|
||||
Let's look around, then use the cli to send some money from one of
|
||||
the validators to our client's address so we can play.
|
||||
|
||||
**TODO** we can add some of our known accounts (from `/keys`) into
|
||||
the genesis file, so we can skip all the kubectl money fiddling here.
|
||||
We will want to start with money on some known non-validators.
|
||||
|
||||
### Getting validator info (kubectl)
|
||||
|
||||
The basecoin app deployment starts with 1000 "blank" coin in an account of
|
||||
each validator. Let's get the address of the first validator
|
||||
|
||||
`kubectl exec -c app tm-1 -- grep address /app/key.json`
|
||||
|
||||
Store this info as VAL1_ADDR
|
||||
|
||||
### Querying state (proxy)
|
||||
|
||||
The proxy can read any public info via the tendermint rpc, so let's check
|
||||
out this account.
|
||||
|
||||
`curl localhost:8108/query/account/$VAL1_ADDR`
|
||||
|
||||
Now, let's make out own account....
|
||||
|
||||
`curl -XPOST http://localhost:8108/keys/ -d '{"name": "k8demo", "passphrase": "1234567890"}'`
|
||||
|
||||
(or pick your own user and password). Remember the address you get here. You can
|
||||
always find it out later by calling:
|
||||
|
||||
`curl http://localhost:8108/keys/k8demo`
|
||||
|
||||
and store it in DEMO_ADDR, which is empty at first
|
||||
|
||||
`curl localhost:8108/query/account/$DEMO_ADDR`
|
||||
|
||||
|
||||
### "Stealing" validator cash (kubectl)
|
||||
|
||||
Run one command, that will be signed, now we have money
|
||||
|
||||
`kubectl exec -c app tm-0 -- basecoin tx send --to <k8demo-address> --amount 500`
|
||||
|
||||
### Using our money
|
||||
|
||||
Returning to our remote shell, we have a remote account with some money.
|
||||
Let's see that.
|
||||
|
||||
`curl localhost:8108/query/account/$DEMO_ADDR`
|
||||
|
||||
Cool. Now we need to send it to a second account.
|
||||
|
||||
`curl -XPOST http://localhost:8108/keys/ -d '{"name": "buddy", "passphrase": "1234567890"}'`
|
||||
|
||||
and store the resulting address in BUDDY_ADDR
|
||||
|
||||
**TODO** finish this
|
||||
|
10
tools/mintnet-kubernetes/examples/counter/Makefile
Normal file
10
tools/mintnet-kubernetes/examples/counter/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
create:
|
||||
@echo "==> Creating deployment"
|
||||
@kubectl create -f app.yaml
|
||||
|
||||
destroy:
|
||||
@echo "==> Destroying deployment"
|
||||
@kubectl delete -f app.yaml
|
||||
@kubectl delete pvc -l app=tm
|
||||
|
||||
.PHONY: create destroy
|
214
tools/mintnet-kubernetes/examples/counter/app.yaml
Normal file
214
tools/mintnet-kubernetes/examples/counter/app.yaml
Normal file
@ -0,0 +1,214 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
annotations:
|
||||
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
|
||||
name: counter
|
||||
labels:
|
||||
app: counter
|
||||
spec:
|
||||
ports:
|
||||
- port: 26656
|
||||
name: p2p
|
||||
- port: 26657
|
||||
name: rpc
|
||||
clusterIP: None
|
||||
selector:
|
||||
app: tm
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: tm-config
|
||||
data:
|
||||
seeds: "tm-0,tm-1,tm-2,tm-3"
|
||||
validators: "tm-0,tm-1,tm-2,tm-3"
|
||||
validator.power: "10"
|
||||
genesis.json: |-
|
||||
{
|
||||
"genesis_time": "2016-02-05T23:17:31.164Z",
|
||||
"chain_id": "chain-B5XXm5",
|
||||
"validators": [],
|
||||
"app_hash": ""
|
||||
}
|
||||
pub_key_nginx.conf: |-
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server ipv6only=on;
|
||||
location /pub_key.json { root /usr/share/nginx/; }
|
||||
}
|
||||
---
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: tm-budget
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: tm
|
||||
minAvailable: 2
|
||||
---
|
||||
apiVersion: apps/v1beta1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: tm
|
||||
spec:
|
||||
serviceName: counter
|
||||
replicas: 4
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: tm
|
||||
annotations:
|
||||
pod.beta.kubernetes.io/init-containers: '[{
|
||||
"name": "tm-gen-validator",
|
||||
"image": "tendermint/tendermint:0.10.0",
|
||||
"imagePullPolicy": "IfNotPresent",
|
||||
"command": ["bash", "-c", "
|
||||
set -ex\n
|
||||
if [ ! -f /tendermint/priv_validator.json ]; then\n
|
||||
tendermint gen_validator > /tendermint/priv_validator.json\n
|
||||
# pub_key.json will be served by pub-key container\n
|
||||
cat /tendermint/priv_validator.json | jq \".pub_key\" > /tendermint/pub_key.json\n
|
||||
fi\n
|
||||
"],
|
||||
"volumeMounts": [
|
||||
{"name": "tmdir", "mountPath": "/tendermint"}
|
||||
]
|
||||
}]'
|
||||
spec:
|
||||
containers:
|
||||
- name: tm
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: tendermint/tendermint:0.10.0
|
||||
ports:
|
||||
- containerPort: 26656
|
||||
name: p2p
|
||||
- containerPort: 26657
|
||||
name: rpc
|
||||
env:
|
||||
- name: SEEDS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: seeds
|
||||
- name: VALIDATOR_POWER
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: validator.power
|
||||
- name: VALIDATORS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: validators
|
||||
- name: TMHOME
|
||||
value: /tendermint
|
||||
command:
|
||||
- bash
|
||||
- "-c"
|
||||
- |
|
||||
set -ex
|
||||
|
||||
# copy template
|
||||
cp /etc/tendermint/genesis.json /tendermint/genesis.json
|
||||
|
||||
# fill genesis file with validators
|
||||
IFS=',' read -ra VALS_ARR <<< "$VALIDATORS"
|
||||
fqdn_suffix=$(hostname -f | sed 's#[^.]*\.\(\)#\1#')
|
||||
for v in "${VALS_ARR[@]}"; do
|
||||
# wait until validator generates priv/pub key pair
|
||||
set +e
|
||||
|
||||
curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null
|
||||
ERR=$?
|
||||
while [ "$ERR" != 0 ]; do
|
||||
sleep 5
|
||||
curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null
|
||||
ERR=$?
|
||||
done
|
||||
set -e
|
||||
|
||||
# add validator to genesis file along with its pub_key
|
||||
curl -s "http://$v.$fqdn_suffix/pub_key.json" | jq ". as \$k | {pub_key: \$k, amount: $VALIDATOR_POWER, name: \"$v\"}" > pub_validator.json
|
||||
cat /tendermint/genesis.json | jq ".validators |= .+ [$(cat pub_validator.json)]" > tmpgenesis && mv tmpgenesis /tendermint/genesis.json
|
||||
rm pub_validator.json
|
||||
done
|
||||
|
||||
# construct seeds
|
||||
IFS=',' read -ra SEEDS_ARR <<< "$SEEDS"
|
||||
seeds=()
|
||||
for s in "${SEEDS_ARR[@]}"; do
|
||||
seeds+=("$s.$fqdn_suffix:26656")
|
||||
done
|
||||
seeds=$(IFS=','; echo "${seeds[*]}")
|
||||
|
||||
tendermint node --p2p.seeds="$seeds" --moniker="`hostname`" --proxy_app="unix:///socks/app.sock"
|
||||
volumeMounts:
|
||||
- name: tmdir
|
||||
mountPath: /tendermint
|
||||
- mountPath: /etc/tendermint/genesis.json
|
||||
name: tmconfigdir
|
||||
subPath: genesis.json
|
||||
- name: socksdir
|
||||
mountPath: /socks
|
||||
|
||||
- name: app
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: golang:latest
|
||||
command:
|
||||
- bash
|
||||
- "-c"
|
||||
- |
|
||||
set -ex
|
||||
|
||||
go get github.com/tendermint/abci/cmd/counter
|
||||
|
||||
rm -f /socks/app.sock # remove old socket
|
||||
|
||||
counter --serial --addr="unix:///socks/app.sock"
|
||||
volumeMounts:
|
||||
- name: socksdir
|
||||
mountPath: /socks
|
||||
|
||||
- name: pub-key
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: nginx:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: pub-key
|
||||
command:
|
||||
- bash
|
||||
- "-c"
|
||||
- |
|
||||
set -ex
|
||||
# fixes 403 Permission Denied (open() "/tendermint/pub_key.json" failed (13: Permission denied))
|
||||
# => we cannot serve from /tendermint, so we copy the file
|
||||
mkdir -p /usr/share/nginx
|
||||
cp /tendermint/pub_key.json /usr/share/nginx/pub_key.json
|
||||
nginx -g "daemon off;"
|
||||
volumeMounts:
|
||||
- name: tmdir
|
||||
mountPath: /tendermint
|
||||
- mountPath: /etc/nginx/conf.d/pub_key.conf
|
||||
name: tmconfigdir
|
||||
subPath: pub_key_nginx.conf
|
||||
|
||||
volumes:
|
||||
- name: tmconfigdir
|
||||
configMap:
|
||||
name: tm-config
|
||||
- name: socksdir
|
||||
emptyDir: {}
|
||||
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: tmdir
|
||||
annotations:
|
||||
volume.alpha.kubernetes.io/storage-class: anything
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
17
tools/mintnet-kubernetes/examples/dummy/Makefile
Normal file
17
tools/mintnet-kubernetes/examples/dummy/Makefile
Normal file
@ -0,0 +1,17 @@
|
||||
create:
|
||||
@echo "==> Creating deployment"
|
||||
@kubectl create -f app.yaml
|
||||
@echo "==> Waiting 10s until it is probably ready"
|
||||
@sleep 10
|
||||
@echo "==> Creating monitor and transacter pods"
|
||||
@kubectl create -f tm-monitor-pod.yaml
|
||||
@kubectl create -f transacter-pod.yaml
|
||||
|
||||
destroy:
|
||||
@echo "==> Destroying deployment"
|
||||
@kubectl delete -f transacter-pod.yaml
|
||||
@kubectl delete -f tm-monitor-pod.yaml
|
||||
@kubectl delete -f app.yaml
|
||||
@kubectl delete pvc -l app=tm
|
||||
|
||||
.PHONY: create destroy
|
196
tools/mintnet-kubernetes/examples/dummy/app.yaml
Normal file
196
tools/mintnet-kubernetes/examples/dummy/app.yaml
Normal file
@ -0,0 +1,196 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
annotations:
|
||||
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
|
||||
name: dummy
|
||||
labels:
|
||||
app: dummy
|
||||
spec:
|
||||
ports:
|
||||
- port: 26656
|
||||
name: p2p
|
||||
- port: 26657
|
||||
name: rpc
|
||||
clusterIP: None
|
||||
selector:
|
||||
app: tm
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: tm-config
|
||||
data:
|
||||
seeds: "tm-0,tm-1,tm-2,tm-3"
|
||||
validators: "tm-0,tm-1,tm-2,tm-3"
|
||||
validator.power: "10"
|
||||
genesis.json: |-
|
||||
{
|
||||
"genesis_time": "2016-02-05T23:17:31.164Z",
|
||||
"chain_id": "chain-B5XXm5",
|
||||
"validators": [],
|
||||
"app_hash": ""
|
||||
}
|
||||
pub_key_nginx.conf: |-
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server ipv6only=on;
|
||||
location /pub_key.json { root /usr/share/nginx/; }
|
||||
}
|
||||
---
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: tm-budget
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: tm
|
||||
minAvailable: 2
|
||||
---
|
||||
apiVersion: apps/v1beta1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: tm
|
||||
spec:
|
||||
serviceName: dummy
|
||||
replicas: 4
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: tm
|
||||
annotations:
|
||||
pod.beta.kubernetes.io/init-containers: '[{
|
||||
"name": "tm-gen-validator",
|
||||
"image": "tendermint/tendermint:0.10.0",
|
||||
"imagePullPolicy": "IfNotPresent",
|
||||
"command": ["bash", "-c", "
|
||||
set -ex\n
|
||||
if [ ! -f /tendermint/priv_validator.json ]; then\n
|
||||
tendermint gen_validator > /tendermint/priv_validator.json\n
|
||||
# pub_key.json will be served by pub-key container\n
|
||||
cat /tendermint/priv_validator.json | jq \".pub_key\" > /tendermint/pub_key.json\n
|
||||
fi\n
|
||||
"],
|
||||
"volumeMounts": [
|
||||
{"name": "tmdir", "mountPath": "/tendermint"}
|
||||
]
|
||||
}]'
|
||||
spec:
|
||||
containers:
|
||||
- name: tm
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: tendermint/tendermint:0.10.0
|
||||
ports:
|
||||
- containerPort: 26656
|
||||
name: p2p
|
||||
- containerPort: 26657
|
||||
name: rpc
|
||||
env:
|
||||
- name: SEEDS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: seeds
|
||||
- name: VALIDATOR_POWER
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: validator.power
|
||||
- name: VALIDATORS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: validators
|
||||
- name: TMHOME
|
||||
value: /tendermint
|
||||
command:
|
||||
- bash
|
||||
- "-c"
|
||||
- |
|
||||
set -ex
|
||||
|
||||
# copy template
|
||||
cp /etc/tendermint/genesis.json /tendermint/genesis.json
|
||||
|
||||
# fill genesis file with validators
|
||||
IFS=',' read -ra VALS_ARR <<< "$VALIDATORS"
|
||||
fqdn_suffix=$(hostname -f | sed 's#[^.]*\.\(\)#\1#')
|
||||
for v in "${VALS_ARR[@]}"; do
|
||||
# wait until validator generates priv/pub key pair
|
||||
set +e
|
||||
|
||||
curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null
|
||||
ERR=$?
|
||||
while [ "$ERR" != 0 ]; do
|
||||
sleep 5
|
||||
curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null
|
||||
ERR=$?
|
||||
done
|
||||
set -e
|
||||
|
||||
# add validator to genesis file along with its pub_key
|
||||
curl -s "http://$v.$fqdn_suffix/pub_key.json" | jq ". as \$k | {pub_key: \$k, amount: $VALIDATOR_POWER, name: \"$v\"}" > pub_validator.json
|
||||
cat /tendermint/genesis.json | jq ".validators |= .+ [$(cat pub_validator.json)]" > tmpgenesis && mv tmpgenesis /tendermint/genesis.json
|
||||
rm pub_validator.json
|
||||
done
|
||||
|
||||
# construct seeds
|
||||
IFS=',' read -ra SEEDS_ARR <<< "$SEEDS"
|
||||
seeds=()
|
||||
for s in "${SEEDS_ARR[@]}"; do
|
||||
seeds+=("$s.$fqdn_suffix:26656")
|
||||
done
|
||||
seeds=$(IFS=','; echo "${seeds[*]}")
|
||||
|
||||
tendermint node --p2p.seeds="$seeds" --moniker="`hostname`" --proxy_app="dummy"
|
||||
volumeMounts:
|
||||
- name: tmdir
|
||||
mountPath: /tendermint
|
||||
- mountPath: /etc/tendermint/genesis.json
|
||||
name: tmconfigdir
|
||||
subPath: genesis.json
|
||||
- name: socksdir
|
||||
mountPath: /socks
|
||||
|
||||
- name: pub-key
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: nginx:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: pub-key
|
||||
command:
|
||||
- bash
|
||||
- "-c"
|
||||
- |
|
||||
set -ex
|
||||
# fixes 403 Permission Denied (open() "/tendermint/pub_key.json" failed (13: Permission denied))
|
||||
# => we cannot serve from /tendermint, so we copy the file
|
||||
mkdir -p /usr/share/nginx
|
||||
cp /tendermint/pub_key.json /usr/share/nginx/pub_key.json
|
||||
nginx -g "daemon off;"
|
||||
volumeMounts:
|
||||
- name: tmdir
|
||||
mountPath: /tendermint
|
||||
- mountPath: /etc/nginx/conf.d/pub_key.conf
|
||||
name: tmconfigdir
|
||||
subPath: pub_key_nginx.conf
|
||||
|
||||
volumes:
|
||||
- name: tmconfigdir
|
||||
configMap:
|
||||
name: tm-config
|
||||
- name: socksdir
|
||||
emptyDir: {}
|
||||
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: tmdir
|
||||
annotations:
|
||||
volume.alpha.kubernetes.io/storage-class: anything
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
13
tools/mintnet-kubernetes/examples/dummy/tm-monitor-pod.yaml
Normal file
13
tools/mintnet-kubernetes/examples/dummy/tm-monitor-pod.yaml
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: monitor
|
||||
spec:
|
||||
containers:
|
||||
- name: monitor
|
||||
image: tendermint/monitor
|
||||
args: ["-listen-addr=tcp://0.0.0.0:26670", "tm-0.dummy:26657,tm-1.dummy:26657,tm-2.dummy:26657,tm-3.dummy:26657"]
|
||||
ports:
|
||||
- containerPort: 26670
|
||||
name: rpc
|
19
tools/mintnet-kubernetes/examples/dummy/transacter-pod.yaml
Normal file
19
tools/mintnet-kubernetes/examples/dummy/transacter-pod.yaml
Normal file
@ -0,0 +1,19 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: transacter
|
||||
spec:
|
||||
containers:
|
||||
- name: transacter
|
||||
image: tendermint/transacter
|
||||
command:
|
||||
- bash
|
||||
- "-c"
|
||||
- |
|
||||
set -ex
|
||||
while true
|
||||
do
|
||||
./transact 100 "tm-0.dummy:26657"
|
||||
sleep 1
|
||||
done
|
Reference in New Issue
Block a user