일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- 파이썬 강좌
- 스칼라
- 파이썬 동시성
- akka 강좌
- Play2
- 플레이프레임워크
- 하이브리드앱
- 블록체인
- Actor
- 스칼라 강좌
- Play2 로 웹 개발
- Hyperledger fabric gossip protocol
- 그라파나
- 파이썬 데이터분석
- 엔터프라이즈 블록체인
- 안드로이드 웹뷰
- CORDA
- Akka
- 파이썬
- 스위프트
- 주키퍼
- play 강좌
- Golang
- 파이썬 머신러닝
- 스칼라 동시성
- play2 강좌
- 하이퍼레저 패브릭
- hyperledger fabric
- Adapter 패턴
- 이더리움
- Today
- Total
HAMA 블로그
400라인의 go코드로 구현한 하이퍼레저 패브릭 [3]- 도커로 디플로이 본문
예제로 이용된 재료는 이전에 만든 400라인의 go코드로 구현한 하이퍼레저 패브릭 [2]- 블록전파/Gossip 프로토콜 소스(앞으로는 gossip분산 서비스로 지칭)를 사용였는데 간단한 분산 네트워킹 예제이므로 도커/쿠버네이트 공부를 위한 좋은 재료가 될 것 입니다. 이 글은 그 예제의 연속성 상에서 기획된 글이며, 도커/쿠버네이트 내용을 한번 정도 읽어 봤다는 혹은 아래 참고 링크를 공부하면서 진행한다는 가정하에 실습을 위해 정리 한 포스트임을 알려드립니다. 각각의 기술에 대해 구체적으로 알고 싶은 분은 아래 레퍼런스를 참고 하시거나, 추가 구글링을 통해 확인 하십시요.
도커
아래 처럼 Dockerfile 을 만듭니다.
# Start from a Debian image with the latest version of Go installed
# and a workspace (GOPATH) configured at /go.
FROM golang
# Copy the local package files to the container's workspace.
ADD . /go/src/github.com/wowlsh93/hyperledger-fabric-400-gossip
# Build the gossip command inside the container.
# (You may fetch or manage dependencies here,
# either manually or with a tool like "godep".)
RUN go install github.com/wowlsh93/hyperledger-fabric-400-gossip/gossip
위의 도커파일을 가지고 gossip이라는 이름의 도커이미지를 만듭니다.
docker build -t gossip .
기반 이미지는 golang 을 사용하며, 빌드시 현재 프로젝트(예제를 확인하시고 github 에서 가져오세요)를 컨네이너의 /go/src/github.com/wowlsh93/hyperledger-fabric-400-gossip 위치에 복사해 놓습니다. 그리고 소스를 인스톨하여 go/src/gossip 에 실행파일을 위치 시켜 놓습니다.
docker images
만들어진 이미지를 확인 하는 명령어는 위와 같습니다.
docker run -p 28000:28000 --name gossip1 --rm gossip /go/bin/gossip -name 127.0.0.1:28000 -ip 127.0.0.1 -port 28000 -leader
실행은 run 명령어를 사용하며 옵션이 의미하는 바는
-p 옵션으로 외부포트:내부포트를 포워딩 하고
-name : 이름은 gossip1 으로 임의로 정합니다.
-rm : 옵션으로 컨테이너가 내려가면 자동으로 삭제되게 하고
컨테이너 실행시 /go/bin/gossip -name 127.0.0.1:28000 -ip 127.0.0.1 -port 28000 -leader 명령을 실행해 리더피어 서비스를 시작해 줍니다.
docker run -p 28001:28001 --net host --name gossip2 --rm gossip /go/bin/gossip -name 127.0.0.1:28001 -ip 127.0.0.1 -port 28001 -bootstrap 127.0.0.1:28000
도커 네트워킹
1) 같은 노드에 있는 컨테이너 실습 - host 방식
docker run -p 28000:28000 --net host --name gossip1 --rm gossip /go/bin/gossip -name 127.0.0.1:28000 -ip 127.0.0.1 -port 28000 -leader
위 처럼 -net host 를 각 컨테이너를 시작 할 때 넣어 주면 됩니다. 동일한 네트워크에 있기 때문에 포트만으로도 통신이 되는거죠.
2) 같은 노드에 있는 컨테이너 실습 - bridge 방식
브리지방식은 도커의 디폴트 방식이기에 -net 옵션 없으면 자동으로 선택되는데 브리지 방식으로는 각각의 컨테이너가 다른 사설IP 를 갖게 되므로 포트만을 구분하는 예제(Gossip 서비스)에서는 안되는게 당연하며 추가정보가 필요합니다.
docker network create --driver bridge gossip-network
일단 bridge형식의 네트워크를 하나 추가로 만듭니다. 이름은 gossip-network 로 하구요.
docker network ls
NETWORK ID NAME DRIVER SCOPE d87103af938c bridge bridge local 659368a11889 composer_default bridge local 17b35b1ad8c5 gossip-network bridge local 541d637a227c host host local de0e0715ded6 net_basic bridge local 6b6f56779a9a none null local
docker network ls 명령어로 gossip-network 가 만들어진것을 확인합니다.
docker run -it --network=gossip-network --name gossip1 gossip /go/bin/gossip -name gossip1:28000 -ip gossip1 -port 28000 -leader
docker run -it --network=gossip-network --name gossip2 gossip /go/bin/gossip -name gossip2:28001 -ip gossip2 -port 28001 -bootstrap gossip1:28000
docker run -it --network=gossip-network --name gossip3 gossip /go/bin/gossip -name gossip2:28002 -ip gossip3 -port 28002 -bootstrap
이제 각 도커 컨테이너를 시작시 옵션으로 -network=gossip-network 로 네트워크 설정을 하고, 불편한 IP주소 대신 gossip1~3처럼 컨네이너 명으로 컨테이너 끼리 통신 하게 할 수 있습니다. 컨테이너 끼리 NAT 테이블 안에서 브리지로 통신하기 때문에 굳이 -p 옵션으로 포트포워딩은 필요 없습니다. 참고로 다시 시작 할 때 컨네이터가 중단된 채 존재하기 때문에 안될 수 있는데 삭제 한 후에 해야합니다. 전체 컨테이너 삭제 명령어는 docker rm `docker ps -a -q` 입니다.
3) 같은 노드에 있는 컨테이너 실습 - Docker Compose
version: '2'
services:
leader:
image: gossip
container_name: gossip1
command: /go/bin/gossip -name gossip1:28000 -ip gossip1 -port 28000 -leader
restart:
on-failure
peer1:
image: gossip
container_name: gossip2
command: /go/bin/gossip -name gossip2:28001 -ip gossip2 -port 28001 -bootstrap gossip1:28000
restart:
on-failure
depends_on:
- leader
peer2:
image: gossip
container_name: gossip3
command: /go/bin/gossip -name gossip3:28002 -ip gossip3 -port 28002 -bootstrap gossip1:28000
restart:
on-failure
depends_on:
- leader
도커 컴포즈는 여러개의 컨테이너를 한방에 시작 시킬때 유용합니다. docker-compose.yaml 파일을 만들어 위의 내용을 작성합니다. 각 서비스를 구분했으며 옵션은 쉽게 이해 될 것입니다. 주의 할 점은 일반 피어는 리더피어가 생성된 후에 떠야하기때문에 depends_on옵션이 추가되었습니다.
docker-compose -p gossipnetwork up -d
-p옵션으로 네트워크를 설정해주며, -d 는 detached mode으로 로그가 안 보이기 때문에. -d 옵션을 빼거나
docker logs -t -f gossip1
같은 명령어로 각 컨테이너들의 stdout 로그를 확인합니다.
4) 다른 노드에 있는 컨테이너 실습 - Overlay Network by etcd
일단 만들어진 이미지를 도커허브에 올려서 각 노드에서 편하게 사용 하려고 합니다. 참고
이제 어디서에나 도커만 있다면 이미지를 다운로드 (이미지 이름이 gossip 에서 wowlsh93/gossip:1 로 변경됨) 받아서 실행 할 수 있습니다.
docker pull wowlsh93/gossip:1
도커(컨테이너)의 장점이 gossip 서비스를 돌리기 위한 어떤 환경(go컴파일러등)이 갖추어져 있지 않더라도, 도커만 있는 곳이라면 실행 할 수 있어서 인프라 설치를 위한 공을 들일 필요가 없는거니까요.
이제 본격적으로 여러 노드에서 gossip분산 서비스를 gossip-network 를 만들어서 실행시켜 보시면 잘 될리가 없습니다. 각 네트워크는 각 노드 내부에서만 활동하기 때문인데요. 외부 네트워크주소를 입력하는 부분도 없잖아요. 당연한거죠. 다른 방법이 필요 합니다.
여기서 다룰 오버레이 네트워크는 여러 머신에서 각각의 네트워크에서 돌아가는 서비스들이 하나의 네트워크에 있는 것 처럼 만들어 주는 방식(docker swarm, hadoop yarn, apache mesos, kubernetes 등) 으로 다양하게 이루어 질 수 있는데, 여기서는 Docker 자체에서 제공하는 방식으로 만들어 볼 예정입니다.
* 사실 우리 프로그램 경우 그냥 실행시 name 옵션에서 정확한 외부 ip 를 입력해주면 잘 동작합니다. 굳이 이딴거(오버레이/스웜/쿠버네티스) 사용 할 필요도 없긴합니다. 실제 하이퍼레저 패브릭도 마찬가지입니다. 도커,쿠버네티스 같은거 사용 안해도 돌아가는 건 상관이 없어요. 각 호스트에서 디펜던시를 따로 다 설치하는 귀찮음이 있긴 하지만 오히려 첨에 실습해보는데는 더 클리어 하구요. 다만 초기 실습이 아니라 일이 되면 여러모로 추상화/자동화가 편하겠지요.
도커 없이 ip만 입력해 주면 됨)
gossip -name 192.168.0.5:28001 -ip 192.168.0.5 -port 28001 -bootstrap 192.168.0.2:28000
도커만 사용해도 ip만 입력해 주면 됨)
docker run -p 28001:28001 --net host --name gossip1 --rm wowlsh93/gossip:1 /go/bin/gossip -name 192.168.0.5::28001 -ip 192.168.0.5 -port 28001 -bootstrap 192.168.0.2:28000
(이미지 출처: https://blog.naver.com/alice_k106/220772125819)
위 그림처럼 각각의 서버에 위치하더라도 하나의 네트워크처럼 작동하도록 하기 위해 이 글에서는 etcd (분산 key-value store로 zookeeper 같은 분산코디네이팅 역할을 함) 라는 것을 사용 할 건데요. 5개의 서버를 활용하여 3개에는 도커를 설치하여 우리가 만든 이미지를 다운로드 해주시고, 2개에는 etcd를 설치합니다. 저 같은 경우는 VirtualBox에 Host-only-adapter 방식으로 5개의 호스트 네트워크를 구성하였습니다. bridge 로 해도 되고 서로 ping 날려서 확인만 되면 됩니다.
etcd 설치 - etcd node 1
ubuntu@docker-node1:~$ wget https://github.com/coreos/etcd/releases/download/v3.0.12/etcd-v3.0.12-linux-amd64.tar.gz ubuntu@docker-node1:~$ tar zxvf etcd-v3.0.12-linux-amd64.tar.gz ubuntu@docker-node1:~$ cd etcd-v3.0.12-linux-amd64 ubuntu@docker-node1:~$ nohup ./etcd --name docker-node1 --initial-advertise-peer-urls http://192.168.205.10:2380 \ --listen-peer-urls http://192.168.205.10:2380 \ --listen-client-urls http://192.168.205.10:2379,http://127.0.0.1:2379 \ --advertise-client-urls http://192.168.205.10:2379 \ --initial-cluster-token etcd-cluster \ --initial-cluster docker-node1=http://192.168.205.10:2380,docker-node2=http://192.168.205.11:2380 \ --initial-cluster-state new&
etcd 설치 - etcd node 2
ubuntu@docker-node2:~$ wget https://github.com/coreos/etcd/releases/download/v3.0.12/etcd-v3.0.12-linux-amd64.tar.gz ubuntu@docker-node2:~$ tar zxvf etcd-v3.0.12-linux-amd64.tar.gz ubuntu@docker-node2:~$ cd etcd-v3.0.12-linux-amd64/ ubuntu@docker-node2:~$ nohup ./etcd --name docker-node2 --initial-advertise-peer-urls http://192.168.205.11:2380 \ --listen-peer-urls http://192.168.205.11:2380 \ --listen-client-urls http://192.168.205.11:2379,http://127.0.0.1:2379 \ --advertise-client-urls http://192.168.205.11:2379 \ --initial-cluster-token etcd-cluster \ --initial-cluster docker-node1=http://192.168.205.10:2380,docker-node2=http://192.168.205.11:2380 \ --initial-cluster-state new& ubuntu@docker-node2:~/etcd-v3.0.12-linux-amd64$ ./etcdctl cluster-health member 21eca106efe4caee is healthy: got healthy result from http://192.168.205.10:2379 member 8614974c83d1cc6d is healthy: got healthy result from http://192.168.205.11:2379 cluster is healthy
ondocker-node1
if docker version >= 17.09
ubuntu@docker-node1:~$ sudo service docker stop ubuntu@docker-node1:~$ sudo /usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=etcd://192.168.205.10:2379 --cluster-advertise=192.168.205.12:2375
On docker-node2
ubuntu@docker-node2:~$ sudo service docker stop ubuntu@docker-node2:~$ sudo /usr/bin/docker daemon -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=etcd://192.168.205.10:2379 --cluster-advertise=192.168.205.13:2375
On docker-node3
ubuntu@docker-node2:~$ sudo service docker stop ubuntu@docker-node2:~$ sudo /usr/bin/docker daemon -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=etcd://192.168.205.10:2379 --cluster-advertise=192.168.205.14:2375
모든 설치가 끝나고, 아무 도커호스트에서 아래처럼 오버레이 네트워크를 만듭니다.
docker network create -d overlay gossip-overlay
모든 노드에서 동일한 네트워크가 만들어 졌음을 확인합니다. 이제 해당 네트워크를 통해서 2)번의 명령어와 동일하게 실행 할 수 있습니다. 물론 네트워크이름은 바꿔야죠.
docker run -it --network=gossip-overlay --name gossip1 gossip /go/bin/gossip -name gossip1:28000 -ip gossip1 -port 28000 -leader
docker run -it --network=gossip-overlay --name gossip2 gossip /go/bin/gossip -name gossip2:28001 -ip gossip2 -port 28001 -bootstrap gossip1:28000
docker run -it --network=gossip-overlay --name gossip3 gossip /go/bin/gossip -name gossip2:28002 -ip gossip3 -port 28002 -bootstrap
5) 다른 노드에 있는 컨테이너 실습 - Docker Swarm
..진행중..
참고:
도커 / 도커허브
https://subicura.com/2017/02/10/docker-guide-for-beginners-create-image-and-deploy.html
도커 네트워크
https://mesosphere.com/blog/networking-docker-containers/
도커 컴포즈 네트워크
https://medium.com/@caysever/docker-compose-network-b86e424fad82
도커 오버레이 네트워크 by etcd
https://docker-k8s-lab.readthedocs.io/en/latest/docker/docker-etcd.html
쿠버네티스 개론 및 실습 동영상
https://www.youtube.com/watch?v=l42GttmnnZ4
'블록체인' 카테고리의 다른 글
400라인의 go코드로 구현한 하이퍼레저 패브릭 [4-1]- MSP (1) (0) | 2019.02.25 |
---|---|
CFT vs BFT (0) | 2019.02.19 |
400라인의 go코드로 구현한 하이퍼레저 패브릭 [2]- 블록전파/Gossip Protocol (0) | 2019.01.28 |
400라인의 go코드로 구현한 하이퍼레저 패브릭 [1] - 전체조망 (1) | 2019.01.24 |
[이더리움] RLPX - 메세지 read/write (0) | 2019.01.21 |