Running CRATE with Docker on Google Cloud Platform (3)

Running CRATE with Docker on Google Cloud Platform (3)

  • Sample 데이타를 이용한 실습
  • 테스트 마무리

Sample 데이타를 이용한 실습

이제 Twitter 에서 데이터를 가져오자.
두 번째 메뉴인 GET STARTED 로 가서 제일 밑의 “Import tweets for testing.” 을 클릭하자.

  • Twitter 에서 가져온 tweets 는 tweets 라는 TABLE 에 데이터를 저장한다.
  • TABLES 메뉴를 클릭하면 테이블 상태와 저장된 레코드 수를 확인할 수 있다.
  • CONSOLE 메뉴를 클릭해서 직접 SQL 을 입력할 수 있다.

어느 정도 데이타를 가져왔으면 “SELECT text FROM tweets LIMIT 100” 을 입력해서 결과를 확인해보자.
100만건 이상이 저장된 상태에서 조회한 결과로써 상당히 빠른 속도를 보여주고 있다.

Limit 100 Query 결과
< 그림6. Limit 100 Query 결과 > [ 출처: Flickr, gongjak1 ]

Limit 1000 Query 결과
< 그림7. Limit 1000 Query 결과 > [ 출처: Flickr, gongjak1 ]

Limit 10000 Query 결과
< 그림8. Limit 10000 Query 결과 > [ 출처: Flickr, gongjak1 ]


테스트 마무리

지금까지 지내오면서 Database 를 선택함에 있어서 대부분 선택의 폭이 없는 경우를 많이 봤다. 이유라면…

  1. database 는 무조건 Oracle 이다.
  2. 개발자가 알고 있고 사용할 수 있는 database 가 xxxx 뿐이다.
  3. dba 가 다른 database 는 모른다.
  4. 지금까지 사용해온 것을 그냥 사용하겠다.
  5. 이미 개발이 끝나서 이제는 못 바꾼다.

본인은 Database 를 선택함에 있어서 서비스에 맞춰서 골라야 한다고 생각하는데, 이런 현실적인 이유로 인해 서비스 성격에 맞지 않게 database 를 사용하는 경우를 많이 봤다.
물론 서비스는 잘 운영될 리가 없다. 종종 장애가 발생하고, 서비스 로직이 복잡해져 성능이 떨어지고, 담당자는 뒤처리를 위해 사무실에서 떠날 수 있는 날이 없는 경우를 많이 봤다.

요즘의 추세로 본다면 RDBMS + NoSQL 의 조합으로 사용해야 할 서비스들이 많을 것이다. RDBMS 운영이 결코 쉽지만은 않다는 것은 잘 알 것이고, DBA 들이 NoSQL 까지 운영하기에는 지금까지의 NoSQL 들이 너무 복잡하고, 표준 SQL 이 아닌 나름의 방식을 다시 배워야 했다. 또한 많은 NoSQL 들이 시스템과 직접적으로 연관되어 있고, DBA 들이 할 일은 많이 없었다. 하지만 CRATE 는 매우 쉽게 배울 수 있어서 NoSQL 을 서비스에 사용함에 있어 조금은 거리감을 줄일 수 있으리라 생각한다.

DB의 노드 증설 작업은 매우 어려운 일인데, NoSQL 장점을 최대한 살려서 서비스에서 필요에 따라 container 로 database node 를 쉽게 늘리고 줄이는 모습을 조만간 볼 수 있기를 기대해 본다.

Running CRATE with Docker on Google Cloud Platform (2)

Running CRATE with Docker on Google Cloud Platform (2)

  • STEP 4. 환경 설정을 위한 startup 스크립트
  • STEP 5. CRATE 실행
  • STEP 6. CRATE Cluster 에 접속하기

STEP 4. 환경 설정을 위한 startup 스크립트

인스턴스에 접속하여 실행해준다.
정상적으로 잘 실행이 된다면 crate 도커 최신버전이 설치되었을 것이다.

startup.sh

#!/bin/bash
# Update the instances:
#yum update
apt-get -y update
# Crate the filesystems for Crate's data storage
mkfs.ext4 /dev/sdb
mkfs.ext4 /dev/sdc
# Make the directories to mount the drives
mkdir /data
mkdir /data/data{1,2}
# Mount the drives to the data directories
mount /dev/sdb /data/data1
mount /dev/sdc /data/data2
# Add a crate user and give it ownership of the data directories
useradd -s /sbin/nologin crate
chown -R crate.crate /data
# Install and start Docker
#yum install -y docker
apt-get purge "docker.io*"
apt-get install apt-transport-https ca-certificates
apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
echo "deb https://apt.dockerproject.org/repo debian-jessie main" > /etc/apt/sources.list.d/docker.list
apt-get update
apt-get install docker-engine
service docker start
# Get the latest Crate container for Docker
docker pull crate:latest

STEP 5. CRATE 실행

이 스크립트를 실행하면 crate 라는 이름으로 container 가 생성되고 실행된다.

crate-start.sh

#!/bin/bash

# 인스턴스에 할당된 내부 IP 정보를 PRIVATE_IP 변수에 저장한다.
PRIVATE_IP=$(curl "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip" -H "Metadata-Flavor: Google")
echo "PRIVATE_IP = "$PRIVATE_IP

docker run -d -p 4200:4200 -p 4300:4300 \
--name crate \
--volume /data:/data \
--env CRATE_HEAP_SIZE=8g \
crate crate \
-Des.cluster.name="my_cluster" \
-Des.path.data="/data/data1,/data/data2" \
-Des.discovery.zen.minimum_master_nodes=2 \
-Des.gateway.expected_nodes=3 \
-Des.gateway.recover_after_nodes=3 \
-Des.discovery.zen.ping.multicast.enabled=false \
-Des.network.publish_host=$PRIVATE_IP \
-Des.discovery.zen.ping.unicast.hosts=crate-1-sjyun:4300 \
-Des.discovery.zen.ping.unicast.hosts=crate-2-sjyun:4300 \
-Des.discovery.zen.ping.unicast.hosts=crate-3-sjyun:4300

sleep 5
docker ps

Google Compute Engine 의 생성된 인스턴스들은 http://metadata.google.internal/computeMetadata/v1/ 을 통해 Metadata 정보를 얻을 수 있다.
자세한 내용은 [GCP Tip] Metadata of Instance 를 보라.

  • docker run <옵션> <이미지 이름> <실행할 파일> 형식으로 도커를 실행합니다.
옵션 설명
run Run a command in a new container
-d Run container in background and print container ID
-p Publish a container’s port(s) to the host
–name string Assign a name to the container
–volume value Bind mount a volume
–env value Set environment variables
-Des.cluster.name CRATE 클러스터의 이름을 정한다.
-Des.path.data data를 저장할 위치를 지정한다.
-Des.discovery.zen.minimum_master_nodes=2 3 노드 클러스터 에 그들이 마스터 를 선출 하도록 허용 하기 전에 적어도 2 노드가 서로 를 볼 필요가 있음을 의미한다.
-Des.gateway.expected_nodes=3 클러스터의 상태가 즉시 복구 될 때까지 기다려야 하는 노드 수를 정의한다. 모든 노드가 시작된 후 클러스터 상태를 복구하고 싶어하기 때문에 이 값은 클러스터의 노드 수와 같아야 한다.
-Des.gateway.recover_after_nodes=3 모든 클러스터 상태 복구가 시작 되기 전에 시작 해야하는 노드의 수를 정의한다. 모든 노드가 시작될 때 한번에 복구되어지는 클러스터의 상태를 원하기 때문에 이상적으로 이 값은 모든 클러스터 노드의 수와 일치해야만 한다.
-Des.discovery.zen.ping.multicast.enabled=false Multicast를 지원하지 않는 일부 환경(Amazon EC2, Google Compute Engine or Docker 등)에서 클러스터를 배포 할 경우 multicast 를 사용하지 않도록 하고 대신 unicast 를 사용해야 한다.
-Des.network.publish_host=$PRIVATE_IP 특정 경우에 CRATE를 실행하는 노드의 주소가 다른 노드가 접속하는 주소와 다를 수가 있다. CRATE가 Docker 내에서 실행될 결우가 이러한 예이다. 따라서 CRATE는 이를 위한 호스트와 포트를 지정할 수 있다. 이 설정은 실제 호스트의 주소와 다를 수 있다.
-Des.discovery.zen.ping.unicast.hosts=crate-1-sjyun:4300 클러스터 노드를 지정한다.

STEP 6. CRATE Cluster 에 접속하기

CRATE Cluster 에 접속 할 수 있는 방법은 3가지 이다.

Docker 로 실행된 CRATE Cluster 는 CLI tool 을 사용할 수 없다. 때문에 나머지 2가지 방법을 이용해야만 한다.
개발자가 아니라면 REST API 는 사용하기가 좀 번잡하다.
때문에 일반적으로 보기 쉬운 Admin UI 로 접속해보자.

http://SERVER_IP:4200/admin

SERVER_IP 는 당연하겠지만 Cluster 노드들 중에서 External IP 주소이다.

Cluster 가 정상적으로 동작한다면 그림1 과 같은 화면을 볼 수 있을 것이다.
현재 클러스터의 전반적인 상태를 보여주고 있다. 주의해서 볼 부분은 당연히 녹색으로 표시되어 있는 “HEALTH” 이다.
문제가 발생한다면 녹색이 빨간색으로 변하고 그에 대한 내용을 화면에 보여준다.

Overview
< 그림1. Overview > [ 출처: Flickr, gongjak1 ]

두 번째 메뉴는 “GET STARTED” 이다. 여기에서 Twitter 로 부터 실제 데이터를 import 하여 Sample Data 로 저장하고 테스트해볼 수 있다.

GET STARTED
< 그림2. GET STARTED > [ 출처: Flickr, gongjak1 ]

다음 메뉴는 “CONSOLE” 로서 직접 Query 를 날려서 결과를 확인할 수 있다.

CONSOLE
< 그림3. CONSOLE > [ 출처: Flickr, gongjak1 ]

“TABLE” 메뉴 에서는 현재 DB 의 TABLE 들과 그에 대한 정보를 보여주고 있다. 테이블을 클릭하면 Schema 정보도 나온다.

TABLE
< 그림4. TABLE > [ 출처: Flickr, gongjak1 ]

마지막 “CLUSTER” 에서는 현재 노드들의 정보를 보여준다. 여기에서 보여주는 Name 은 Node.name 으로 지정하지 않으면 임의의 값을 생성한다. Hostname 은 Docker 로 실행했기 때문에 CONTAINER ID 를 보여주고 있다.

CLUSTER
< 그림5. CLUSTER > [ 출처: Flickr, gongjak1 ]

모든 화면의 오른쪽 하단에는 하늘색 원에 ‘?’ 가 들어가 있는 아이콘이 있는데, 클릭하면 Crate.IO Team 과 대화를 할 수도 있다. 팀원이 근무중일 때에는 실시간으로 대화도 가능하고, 메일 주소를 남겨놓으면 채팅 내용이 메일로도 전달 된다.
사용하다 궁금한 점이 있으면 그냥 메시지를 남겨 놓자.


To be continue …

Running CRATE with Docker on Google Cloud Platform (1)

Running CRATE with Docker on Google Cloud Platform (1)

  • CRATE 란 ?
        – 주요 특징 요약
        – 테스트 설명
  • STEP 1. GCP 에서 방화벽 룰 추가
  • STEP 2. 인스턴스에서 사용할 추가 디스크 생성
  • STEP 3. 인스턴스 3개 생성

CRATE 란 ?

Homepage: CRATE.io

CRATE(크레이트) 는 오픈 소스이고, 확장성이 뛰어난 비공유 분산 SQL 데이터베이스입니다.
CRATE 는 표준 SQL 의 강력함을 가진 최신 No-SQL 데이터베이스로서 높은 확장성과 성능을 제공합니다.

CRATE 를 테스트하면서 DBMS가 이렇게 가볍게 동작할 수도 있구나라는 생각을 할 수 있었는데, JAVA로 만들어졌음에도 불구하고 가볍고 쉽게 작동 시킬 수 있었다.
물론 장시간에 걸쳐 서비스에 적용해보거나 하지는 않았기에 CRATE를 실제 상용 서비스에 적용하여 운영할 때에는 어떤 이슈가 생길수 있을지 알 수가 없다.
오랜시간 DBA로 일을 해오고 있는 사람들은 실제 DB서버의 운영에 많은 노하우들이 필요하다는 것을 알고 있을 것이다.
이 때문에 한 번 선택한 DB는 쉽게 바꾸지 못한다.

하지만 CRATE는 No-SQL이다. 전에 사용해봤던 Riak, Cassandra, MongoDB에 비하면 설정이 매우 쉽다.
거의 모든 운영체제를 지원하고, Docker를 사용할 수도 있고, 여러 클라우드 서비스에서도 사용할 수 있다. (설치 참조)
그리고 무엇보다 표준 SQL을 지원하는 No-SQL이다. DBA든 개발자든 표준 SQL만 알면 바로 사용할 수 있는 No-SQL 이다는 점이 가장 매력적이다.

주요 특징 요약

  1. Open Source
  2. Highly Scalable
  3. Shared-nothing distributed SQL
  4. Standard SQL을 지원
  5. masterless and simple to install, operate and use
  6. Transactional & Analytical need 를 하나의 Database 에서 처리할 수 있다.
  7. Web, mobile 그리고 IoT 같은 대용량을 지원하기 위해 디자인 되었다.
  8. Container 지원

테스트 설명

이번 테스트는 다음의 목적으로 진행했다. 또한 모든 작업은 웹 콘솔에서도 동일하게 작업할 수 있으나 설명의 편의성으로 CLI를 이용한 방법으로 정리한다.

  1. DB 서버의 운영을 간소화하기 위해 시스템에 직접 설치가 아닌 Docker를 이용하고 싶다.
  2. 시스템의 운영 환경을 관리자가 어느 정도 관리하면서 운영하고 싶다.
  3. Kubernetes와 같은 자동화 툴에서 DB는 운영하고 싶지 않다.

시스템 환경

  • Cloud Service : Google Cloud Platform 의 Compute Engine 을 사용
  • Instance Type : n1-standard-4 (4 vCPUs, 15 GB) * 3대
  • Disk : SSD Type, 100GB 용량의 추가 디스크 서버당 2개씩
  • 운영체계 : Debian 8 (Jessie), Debian 3.16.7-ckt25-2+deb8u3 (2016-07-02) x86_64 GNU/Linux

STEP 1. GCP 에서 방화벽 룰 추가

CRATE는 4200번 포트를 통해 admin 화면에 접속 할 수 있다. 나중에 admin 화면에 접속해보면 알 수 있지만 할 수 있는 일은 많지 않다.
그냥 모니터링을 위한 화면으로 생각하면 될 거 같다.

gcloud compute --project "" firewall-rules create "default-crate-allow" --allow tcp:4200 --network "default" --source-ranges "0.0.0.0/0" --target-tags "crate-admin"

STEP 2. 인스턴스에서 사용할 추가 디스크 생성

PROJECT_NAME=""

gcloud compute --project "${PROJECT_NAME}" disks create "crate-1-sjyun-disk-1" --size "100" --zone "us-central1-f" --type "pd-ssd"
gcloud compute --project "${PROJECT_NAME}" disks create "crate-1-sjyun-disk-2" --size "100" --zone "us-central1-f" --type "pd-ssd"

gcloud compute --project "${PROJECT_NAME}" disks create "crate-2-sjyun-disk-1" --size "100" --zone "us-central1-f" --type "pd-ssd"
gcloud compute --project "${PROJECT_NAME}" disks create "crate-2-sjyun-disk-2" --size "100" --zone "us-central1-f" --type "pd-ssd"

gcloud compute --project "${PROJECT_NAME}" disks create "crate-2-sjyun-disk-1" --size "100" --zone "us-central1-f" --type "pd-ssd"
gcloud compute --project "${PROJECT_NAME}" disks create "crate-2-sjyun-disk-2" --size "100" --zone "us-central1-f" --type "pd-ssd"

STEP 3. 인스턴스 3개 생성

클러스터로 동작하기 위해서 필요한 최소 노드 수는 3대이기에 다음 명령어로 생성해준다.

PROJECT_NAME=""

# instance #1
gcloud compute --project "${PROJECT_NAME}" instances create "crate-1-sjyun" --zone "us-central1-f" \
--machine-type "n1-standard-4" --network "default" --maintenance-policy "MIGRATE" \
--scopes default="https://www.googleapis.com/auth/devstorage.read_only","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring.write","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly" \
--tags "crate-admin" \
--disk "name=crate-1-sjyun-disk-1,device-name=crate-1-sjyun-disk-1,mode=rw,boot=no" \
--disk "name=crate-1-sjyun-disk-2,device-name=crate-1-sjyun-disk-2,mode=rw,boot=no" \
--image "/debian-cloud/debian-8-jessie-v20160803" \
--boot-disk-size "10" --boot-disk-type "pd-standard" \
--boot-disk-device-name "crate-1-sjyun"

# instance #2
gcloud compute --project "${PROJECT_NAME}" instances create "crate-2-sjyun" --zone "us-central1-f" \
--machine-type "n1-standard-4" --network "default" --maintenance-policy "MIGRATE" \
--scopes default="https://www.googleapis.com/auth/devstorage.read_only","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring.write","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly" \
--tags "crate-admin" \
--disk "name=crate-2-sjyun-disk-1,device-name=crate-2-sjyun-disk-1,mode=rw,boot=no" \
--disk "name=crate-2-sjyun-disk-2,device-name=crate-2-sjyun-disk-2,mode=rw,boot=no" \
--image "/debian-cloud/debian-8-jessie-v20160803" \
--boot-disk-size "10" --boot-disk-type "pd-standard" \
--boot-disk-device-name "crate-2-sjyun"

# instance #3
gcloud compute --project "${PROJECT_NAME}" instances create "crate-3-sjyun" --zone "us-central1-f" \
--machine-type "n1-standard-4" --network "default" --maintenance-policy "MIGRATE" \
--scopes default="https://www.googleapis.com/auth/devstorage.read_only","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring.write","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly" \
--tags "crate-admin" \
--disk "name=crate-3-sjyun-disk-1,device-name=crate-3-sjyun-disk-1,mode=rw,boot=no" \
--disk "name=crate-3-sjyun-disk-2,device-name=crate-3-sjyun-disk-2,mode=rw,boot=no" \
--image "/debian-cloud/debian-8-jessie-v20160803" \
--boot-disk-size "10" --boot-disk-type "pd-standard" \
--boot-disk-device-name "crate-3-sjyun"

서버를 하나씩 모두 생성하지 않고, 한 대만 생성하여 셋팅을 완료하고 이를 이용하여 나머지 서버를 만들수도 있다.
여러 대의 서버를 생성하고자 할 때에는 이 방법이 훨씬 수월하다.

우선 1번 서버만 만들고 설정을 완료한 후 boot 디스크의 snapshot 을 생성한다. (snapshot 이름 : crate-1-snapshot-sjyun)
아래 명령어를 이용하여 하나씩 서버를 생성하면 된다.

PROJECT_NAME=""

# instance #2
gcloud compute --project "${PROJECT_NAME}" disks create "crate-2-sjyun-disk-1" --size "100" --zone "us-central1-f" --type "pd-ssd"
gcloud compute --project "${PROJECT_NAME}" disks create "crate-2-sjyun-disk-2" --size "100" --zone "us-central1-f" --type "pd-ssd"

gcloud compute --project "${PROJECT_NAME}" disks create "crate-2-sjyun" --size "10" --zone "us-central1-f" --source-snapshot "crate-1-snapshot-sjyun" --type "pd-standard"

gcloud compute --project "${PROJECT_NAME}" instances create "crate-2-sjyun" --zone "us-central1-f" \
--machine-type "n1-standard-4" \
--network "default" --maintenance-policy "MIGRATE" \
--scopes default="https://www.googleapis.com/auth/devstorage.read_only","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring.write","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly" \
--tags "crate-admin" \
--disk "name=crate-2-sjyun,device-name=crate-2-sjyun,mode=rw,boot=yes,auto-delete=yes" \
--disk "name=crate-2-sjyun-disk-1,device-name=crate-2-sjyun-disk-1,mode=rw,boot=no" \
--disk "name=crate-2-sjyun-disk-2,device-name=crate-2-sjyun-disk-2,mode=rw,boot=no"

# instance #3
gcloud compute --project "${PROJECT_NAME}" disks create "crate-3-sjyun-disk-1" --size "100" --zone "us-central1-f" --type "pd-ssd"
gcloud compute --project "${PROJECT_NAME}" disks create "crate-3-sjyun-disk-2" --size "100" --zone "us-central1-f" --type "pd-ssd"

gcloud compute --project "${PROJECT_NAME}" disks create "crate-3-sjyun" --size "10" --zone "us-central1-f" --source-snapshot "crate-1-snapshot-sjyun" --type "pd-standard"

gcloud compute --project "${PROJECT_NAME}" instances create "crate-2-sjyun" --zone "us-central1-f" \
--machine-type "n1-standard-4" \
--network "default" --maintenance-policy "MIGRATE" \
--scopes default="https://www.googleapis.com/auth/devstorage.read_only","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring.write","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly" \
--tags "crate-admin" \
--disk "name=crate-3-sjyun,device-name=crate-3-sjyun,mode=rw,boot=yes,auto-delete=yes" \
--disk "name=crate-3-sjyun-disk-1,device-name=crate-3-sjyun-disk-1,mode=rw,boot=no" \
--disk "name=crate-3-sjyun-disk-2,device-name=crate-3-sjyun-disk-2,mode=rw,boot=no"

To be continue …