Skip to content

Cassandra 설치 및 실행 – Creating a multinode cluster

2012/02/13

Cassandra 설치 및 실행 – Creating a multinode cluster

지난 포스트에 이어서 간단하게 multinode cluster를 만드는 방법을 살펴보겠습니다.

1. Multi Node 구성하기 위한 최소 환경 옵션

cassandra.yaml 설정

1. cluster_name: ‘Test Cluster’

cluster의 이름으로 multi node 구성시 다른 node와 이름이 틀리면 아래와 같은 경고메시지가 계속해서 발생하게 됩니다.

WARN 17:38:39,930 ClusterName mismatch from /211.xxx.xxx.2 Test Cluster!=Tera Cluster

또는 기존에 Test Cluster로 구성했던 node에서 Tera Cluster라고 변경후 구동할려고 하면 다음과 같은 오류가 발생하게 됩니다.

ERROR 17:35:11,393 Fatal exception during initialization
org.apache.cassandra.config.ConfigurationException: Saved cluster name Test Cluster != configured name Tera Cluster
at org.apache.cassandra.db.SystemTable.checkHealth(SystemTable.java:296)
at org.apache.cassandra.service.AbstractCassandraDaemon.setup(AbstractCassandraDaemon.java:169)
at org.apache.cassandra.service.AbstractCassandraDaemon.activate(AbstractCassandraDaemon.java:356)
at org.apache.cassandra.thrift.CassandraDaemon.main(CassandraDaemon.java:107)

2. seeds: xxx.xxx.xxx.xxx

seed란 cluster에서 node의 추가/삭제가 되었을때 특정 node에게 등록하면 다른 모든 node에게 이를 알려주는 역할을 하는 node입니다.
즉, contact points라고 생각하면 됩니다. seed는 1개 이상이 될수있고 콤마<,> 로 구분됩니다.(ex : seeds: 211.xxx.xxx.1,211.xxx.xxx.2)

3. listen_address: 211.xxx.xxx.1

cassandra 서버간에 통신하기 위한 ip address 입니다. 자신의 ip를 넣으면 됩니다. 0.0.0.0 은 사용할수 없습니다.

4. rpc_address: xxx.xxx.xxx.xxx

Thrift를 이용한 클라이언트 접속을 허용하는 설정입니다. 0.0.0.0으로 설정할 경우 모든 원격지 접속을 허용하게 됩니다.

cassandra-env.sh 설정

모니터링 툴들에서  RMI을 이용해서 원격지 서버에 접속하기 때문에 hostname에 자신의 ip를 넣어주어야 합니다.

JVM_OPTS="$JVM_OPTS -Djava.rmi.server.hostname=xxx.xxx.xxx.xxx"

위와 같이 설정하지 않으면 원격 서버를 이용할려고 하면 다음과 같은 에러가 나옵니다.

Error connection to remote JMX agent!
java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is:
java.net.ConnectException: Connection refused
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:601)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:198)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:110)
at javax.management.remote.rmi.RMIServerImpl_Stub.newClient(Unknown Source)
at javax.management.remote.rmi.RMIConnector.getConnection(RMIConnector.java:2327)
at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:279)
at javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:248)
at org.apache.cassandra.tools.NodeProbe.connect(NodeProbe.java:144)
at org.apache.cassandra.tools.NodeProbe.<init>(NodeProbe.java:114)
at org.apache.cassandra.tools.NodeCmd.main(NodeCmd.java:623)
Caused by: java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
at java.net.Socket.connect(Socket.java:519)
at java.net.Socket.connect(Socket.java:469)
at java.net.Socket.<init>(Socket.java:366)
at java.net.Socket.<init>(Socket.java:180)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:22)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:128)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:595)
… 10 more

2. Node 구성 및 실행

Node 1(ip:211.xxx.xxx.1) 의 cassandra.yaml 설정 
cluster_name: 'Test Cluster'
seeds: 211.xxx.xxx.1
listen_address: 211.xxx.xxx.1
rpc_address: 211.xxx.xxx.1

Node 2(ip:211.xxx.xxx.2) 의 cassandra.yaml 설정 
cluster_name: 'Test Cluster'
seeds: 211.xxx.xxx.1
listen_address: 211.xxx.xxx.2
rpc_address: 211.xxx.xxx.2

Node 1(ip:211.xxx.xxx.1) 의 구동시 로그

INFO 17:13:36,400 Listening for thrift clients…                   // Node 1 구동완료
INFO 17:10:51,584 Node /211.xxx.xxx.xx2 is now part of the cluster       // Node 2 구동되어 cluster에 등록시작
INFO 17:10:51,584 InetAddress /211.xxx.xxx.xx2 is now UP                 // Node 2 등록 완료

만약 Node 1과 Node 2를 둘다 seed로 등록한다면(seeds: 211.xxx.xxx.xx1,211.xxx.xxx.xx2) Node 2의 구동시 다음과 같은 로그가 발생합니다.

INFO 17:13:36,155 This node will not auto bootstrap because it is configured to be a seed node.

카산드라에서 bootstrap이란 자신이 부족한 데이터를 주변의 노드들로부터 가져오는 과정(동기화)을 말합니다. 
새롭게 참가하는 노드들은 클러스터의 데이터들을 동기화하면서 참여하여야 합니다.
하지만 seed node는 auto bootstrap을 실행하지 않습니다.

INFO 17:13:36,286 Node /211.xxx.xxx.xx1 is now part of the cluster
INFO 17:13:36,289 InetAddress /211..xxx.xxx.xx1 is now UP
INFO 17:13:36,359 Node /211.xxx.xxx.xx2 state jump to normal
INFO 17:13:36,360 Bootstrap/Replace/Move completed! Now serving reads.
INFO 17:13:36,394 Binding thrift service to /211.xxx.xxx.xx2:9160
INFO 17:13:36,397 Using TFastFramedTransport with a max frame size of 15728640 bytes.
INFO 17:13:36,399 Using synchronous/threadpool thrift server on /211.xxx.xxx.xx2 : 9160
INFO 17:13:36,400 Listening for thrift clients…

그리고 Node 1만 seed로 등록해 두었다면 Node 2를 구동시 다음과 같은 로그가 Node 2에 찍히게 됩니다.

INFO 17:30:41,302 JOINING: waiting for ring and schema information
INFO 17:30:42,699 Node /211.xxx.xxx.xx1 is now part of the cluster
INFO 17:30:42,700 InetAddress /211.xxx.xxx.xx1 is now UP
INFO 17:31:11,303 JOINING: schema complete, ready to bootstrap

seed가 아니기 때문에 다른 node에서 데이터를 받아오는 bootstarp 과정을 시작합니다.

INFO 17:31:11,304 JOINING: getting bootstrap token
INFO 17:31:11,315 New token will be 83588448613386206109030975344773549004 to assume load from /211.xxx.xxx.xx1
INFO 17:31:11,470 JOINING: sleeping 30000 ms for pending range setup
INFO 17:31:41,472 JOINING: Starting to bootstrap…
INFO 17:31:41,645 Node /211.xxx.xxx.xx2 state jump to normal
INFO 17:31:41,645 Bootstrap/Replace/Move completed! Now serving reads.
INFO 18:34:48,011 Binding thrift service to /211.113.70.172:9160
INFO 18:34:48,015 Using TFastFramedTransport with a max frame size of 15728640 bytes.
INFO 18:34:48,018 Using synchronous/threadpool thrift server on /211.113.70.172 : 9160
INFO 18:34:48,019 Listening for thrift clients…

참고로 bootstrap 과정은 시간이 걸리기 때문에 "Listening for thrift clients"라는 message가 올라오기 까지는 시간이 걸립니다.

만약 Node 2가 죽는다면 Node 1에는 다음과 같은 메시지가 남습니다.

INFO 17:27:56,672 InetAddress /211.xxx.xxx.xx2 is now dead.

3. 노드 상태 확인

아래와 같은 명령어로 node 들의 상태를 볼수 있습니다.

[/home/teragoon/cassandra/apache-cassandra-1.0.7/bin]$ ./nodetool -h localhost ring 
Address         DC          Rack   Status State   Load     Owns     Token
                                                                   869521
211.xxx.xxx.xx1  datacenter1 rack1  Up    Normal  29.4 KB  50.00%  188156
211.xxx.xxx.xx2  datacenter1 rack1  Up    Normal  15.69 KB 50.00%  869521

Status는 up/down 이 있고 State에는 Normal/Leaving이 있습니다. 그리고 Owns은 데이터를 나눠가진 정도입니다.
down 상태는 데이터를 가지고 있지만 node가 죽은 상태로 살려내거나 cluster에서 제거하여 다른 node에 데이터를 다시 분산해야합니다.

4. 노드 제거

운영중인 Node 2(211.xxx.xxx.xx2)를 cluster에서 빼기 위해서는 다음과 같은 명령어를 사용합니다.

[211.xxx.xxx.xx2:/home/teragoon/cassandra/apache-cassandra-1.0.7/bin]$ ./nodetool -h 211.xxx.xxx.xx2 decommission

위와 같이 명령을 내리면 화면에 아무런 표시없이 한참 있다가(기존에 Node 2가 가지고 있던 데이터를 다른 Node들에 재분배함) 끝나게 됩니다.

Node 1에서 확인해보면 다음과 같이 Node 2가 없어지고 Node 1의 Owns=100%가 됩니다.

Address         DC          Rack   Status State   Load     Owns    Token
211.xxx.xxx.xx1  datacenter1 rack1  Up    Normal  24.61 KB 100.00% 869521

또는 강제로 제거하기 위해서는 removetoken 을 사용할수 있습니다.

./nodetool -h xxx.xxx.xxx removetoken 토큰

5. 업그래이드를 위한 노드 정지방법

Cassandra는 새로운 버전이 자주 출시되며 Thrift도 가끕씩 업그래이드해줄 필요가 있습니다.
그래서 cluster에서 완전히 제거하는것이 아니라 일시적으로 안정적으로 멈추는 방법을 살펴보겠습니다.

우선 Thrift 서비스를 중단하여 클라이언트 들로 부터 접속을 차단합니다.

./nodetool -h xxx.xxx.xxx disablethrift

그리고 노드간의 통신(gossip)을 종료합니다.

./nodetool -h xxx.xxx.xxx disablegossip

Thrift와 gossip을 종료하면 다른 노드에서는 이 노드가 죽어있는 것으로 판단합니다.

 이때 node 2를 위의 방법으로 죽였지만 node 2에서 자신의 상태는 아래와 같이 up 상태로 남아있지만

./nodetool -h 211.xxx.xxx.xx2 ring
Address             DC              Rack        Status   State     Load     Owns     Token
211.xxx.xxx.xx2  datacenter1 rack1  Up   Normal  17.65 KB   50.00%  188156
211.xxx.xxx.xx1  datacenter1 rack1  Up   Normal  15.69 KB   50.00%  869521

node 1에서 보면 node 2가 down 상태인것을 확인할 수 있습니다.

./nodetool -h 211.xxx.xxx.xx1 ring
Address            DC              Rack         Status   State      Load     Owns    Token
211.xxx.xxx.xx2 datacenter1 rack1   Down Normal 17.65 KB 50.00% 188156
211.xxx.xxx.xx1 datacenter1 rack1   Up       Normal 15.69 KB 50.00% 869521

이후 cluster에 문제가 없다면 해당 장비의 메모리에 있는 모든 정보를 SSTable에 강제 쓰기를 하도록 합니다.

./nodetool -h xxx.xxx.xxx drain

마지막으로 cassandra의 프로세스를 종료합니다.

kill -9 pid

경우에 따라서는 위에 두단계를 생략하고 kill -9 pid 만 할 수도 있습니다.

No comments yet

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

%s에 연결하는 중

%d 블로거가 이것을 좋아합니다: