Collo를 좀 더 알기쉽게 전달하기 위해 개요 및 샘플들을 제작하여 SlideShare에 공유 중입니다. 

 

이 글에서도 링크를 추가하여 계속 업데이트 하도록 하겠습니다.

 

https://www.slideshare.net/winninghabit/collo-01-kr

 

Collo -01 , kr

Collo를 소개합니다! https://github.com/blackwitch/Collo

www.slideshare.net

https://www.slideshare.net/winninghabit/collo-02-kr

불러오는 중입니다...

 

'개발 이야기 > Collo' 카테고리의 다른 글

Collo - slideshare 링크 공유  (0) 2019.11.05
Collo - 실시간 마이그레이션 툴  (0) 2019.09.30

한동안 회사에서 진행한 Data Warehouse(이하 DW) 및 통계시스템 구축이 최근 완료되었습니다. 

 

그리고 데이타를 저장한 Database(이하 DB) 종류, 저장된 로그의 파일 포멧 그리고 서버 위치도 다른 데이터들을 한 곳으로 손쉽게 모으기 위해 만들었던 천 줄 내외의 Javascript 코드를 정리해서 Collo라는 이름으로 github에 며칠 전 공개하게 되었습니다.

 

Collo의 주 목표는 실시간으로 누적되는 데이터를 해당 시스템의 부하없이 DW로 가져오는 것이었으며, 마이그레이션에 대한 모든 기능을 포함한 솔루션이 아닌 손쉽게 수정, 조작 가능한 작은 유틸리티 제작을 목표로 한 프로젝트였습니다. 그리고 데이타를 가져오는 성능 보다는 안정성에 더 중점을 두어 제작하였습니다. 그리고 유지보수를 위해서도 언제든, 누구든 분석하기 쉽게 가능한 작은 코드 수를 유지하려고 노력했습니다. 혼자 개발을 했기 때문에 개발 시간 단축, 각 저장소에 대한 안정된 연결을 유지하기 위해 공개된 npm들을 최대한 활용하였습니다.

 

제작 중간부터는 사용 가능한 저장소를 하나 둘 늘리면서 내가 다뤄보지 않은 저장소에 대해서도 지원하면 좋겠다는 생각을 했고, 이 작은 프로젝트가 같은 고민과 과제를 안고 있는 누군가에게 도움이 되었으면 했습니다. 이때부터 오픈소스로 공개를 목표로 하게 되었습니다. 게다가 관리툴의 UI도 엉망이어서 누군가의 도움을 받길 원했습니다. (첫번째 목표였을지도... -_-a)

 

이 카테고리에는 Collo에 대한 활용 방법, 예시들을 올릴 예정입니다. 

 

https://github.com/blackwitch/Collo

 

 

 

 

'개발 이야기 > Collo' 카테고리의 다른 글

Collo - slideshare 링크 공유  (0) 2019.11.05
Collo - 실시간 마이그레이션 툴  (0) 2019.09.30

(* 이 글은 NodeJS 10.15.1 을 기준으로 작성되었습니다. )

한국은 GMT +9 를 기준으로 시간을 사용하며, 데이터를 다룰때도 일반적으로는 GMT +9 기준을 사용합니다. 단일 솔루션만 다룰 때는 거의 신경쓰지 않겠지만, 이기종 혹은 여러 솔루션을 한번에 컨트롤 할 때는 상당히 거슬리는 문제가 됩니다. 특히 월드 와이드 서비스를 하고 있다면요. 대부분의 DB에서 UTC 기준으로 값을 저장하기 때문에 큰 문제는 없지만, 간혹 일부 npm에서 datetime 자료형을 다룰 때 미묘한 차이가 있습니다.

node-mysql(구분을 위해 임시로 node-를 붙였습니다)의 경우, 저장된 datetime 값을 그대로 가져오기 때문에 전혀 문제가 없는데 반해, node-mssql은 useUTC옵션을 제대로 설정하지 않으면 잘못된 날짜 정보를 가져오게 되어 문제가 발생합니다. 

예를 들면 아래와 같습니다. 
(아래 테스트는 DB : MSSQL/2008R2, MySQL/MariaDB10.4, npm package version : node-mssql/4.2.0, node-mysql/2.16.0 하에서 진행되었습니다.)

MSSQL과 MySQL의 어떤 테이블의 datetime 컬럼에 "2019-01-01 00:00:00" 라는 값을 넣어보겠습니다. 이 값은 UTC 기준으로 값이 저장됩니다. string 형태로 출력해보면 "Mon, 31 Dec 2018 15:00:00 GMT", 실제 저장된 값은 "15462684000000"입니다.

이 값을 MSSQL의 management studio, MySQL는 prompt 혹은 HeidiSQL 모두에서 현지 시간으로 보입니다. 즉 "2019-01-01 00:00:00"으로 보이게 됩니다.

이제 node-mssql/node-mysql로 값을 읽어보면 아래와 같은 결과가 나옵니다.

2019-01-01 09:00:00  (MSSQL NPM으로 읽어온 경우) 
2019-01-01 00:00:00  (MySQL NPM으로 읽어온 경우) 

node-mssql으로 얻은 결과값이 이상한 것을 보실 수 있습니다. node-mssql에는 useUTC 옵션이 있습니다. default 갑이 true로 되어 있어, DB의 datetime이 어디를 기준으로 되어 있던 무조건 UTC 기준값으로 인지합니다. 그래서 최종 출력시에는 Asia/Seoul 의 시간대인 +9시간이 되어 출력된 것이죠. 

 

connection에 사용되는 config값에 useUTC 옵션값을 추가하고 값을 false로 설정하면 현지 시간값으로 읽어옵니다. 사용에 주의 하세요. 

 


이상입니다. 좋은 하루 되세요. :)





JavaScript의 Date 객체는 아래의 특징을 가지고 있습니다. 다른 언어에서도 크게 다르지 않습니다.

- Date 객체는 UTC, 1970년 1월 1일 0시를 기준으로 하며, 밀리세컨트로 시간값을 기록합니다. 
- 만약 입력된 값이 유효하지 않다면 NaN값이 반환됩니다.
- 월은 0부터 시작하며 11이 12월이 됩니다.
- 요일은 0부터 시작하며 0이 일요일, 6일 토요일이 됩니다. 
* 크로스 브라우징 문제가 일부 있습니다. 작성 전 이에 대한 문제를 검토해 보시기 바랍니다. (https://www.google.com/search?q=js+date+cross+browser+format) 보다 상세한 내용은 이 곳(https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Date)을 참고하세요.

아래 예제에서는 JavaScript Date 객체 사용법을 알아보겠습니다.

var date1 = new Date('2019-01-01T00:00:00.000Z'); 
var date2 = new Date('2019-01-01T00:00:00'); 

console.log( "RAW DATE = ",date1, " / ", date2);  
// 결과 (1) : RAW DATE = 2019-01-01T00:00:00.000Z / 2018-12-31T15:00:00.000Z 
console.log( "toString = ",date1.toString(), " / ", date2.toString());  
// 결과 (2) : toString = Tue Jan 01 2019 09:00:00 GMT+0900 (GMT+09:00) / Tue Jan 01 2019 00:00:00 GMT+0900 (GMT+09:00)  

 

date1에는 UTC(협정 세계시, Coordinated Universal Time)로, date2에는 현지 시간을 입력했습니다. Date는 입력된 값을 분석하여 UTC로 값을 보관합니다. 

이를 그대로 출력하면 "결과 (1)"과 같이 UTC 기준으로 출력되는 것을 확인할 수 있습니다. Seoul은 시간은 UTC 기준 +9 시간이므로 UTC로 표현하게 되면 9시간 전의 시간으로 표기됩니다. 두 값을 특정한 조건이나 Date의 함수를 사용하지 않고 출력하면 UTC 기본값으로 출력됩니다. 그래서 date1은 입력값과 동일하게, date2는 9시간 전으로 출력되는 것을 확인할 수 있습니다.  

이제 문자열로 시간을 표현하기 위해서 toString 함수를 사용하니 "결과 (2)"과 같이 date1, date2 모두 현지 시간으로 출력되는 것을 확인할 수 있습니다. date1는 UTC+9에 맞춰 입력된 시간에 +9시간이 되어 출력되고, date2는 현지 시간으로 입력한 값이 그대로 보이는 것을 확인할 수 있습니다. 

그럼 시간 데이타에서 getHours()로 시간을 알아보면 어떻게 나오게 될까요?

var date1 = new Date('2019-01-01T00:00:00.000Z'); 
var date2 = new Date('2019-01-01T00:00:00'); 

console.log( "hours = ",date1.getHours() ," / ", date2.getHours() ); 
// 결과 (3) : hours = 9 / 0 
console.log( "hours = ",date1.getUTCHours() ," / ", date2.getUTCHours() ); 
// 결과 (4) : hours = 0 / 15 

getHours 함수는 현지 시간값을 기준으로 값을 반환하며, UTC 시간값을 기준으로 값을 반환받길 원한다면 getUTCHours 함수를 사용할 수 있습니다. setHours와 setUTCHours도 마찬가지입니다.

var date1 = new Date('2019-01-01T00:00:00.000Z'); 
var date2 = new Date('2019-01-01T00:00:00'); 

date1.setHours(9); 
date2.setHours(9); 

console.log( "DATE1 = ",date1 ," / DATE2 = ", date2 ); 
// 결과 (4) : DATE1 =  2019-01-01T00:00:00.000Z  / DATE2 =  2019-01-01T00:00:00.000Z 

setHours 함수는 첫 인자를 UTC가 아닌, 현지 시간의 시간값으로 인지합니다. 그러므로 당연히 내부에서도 시간값을 설정할 때 UTC가 아닌 현재 시간을 기준으로 주어진 시간값을 설정하게 됩니다. 

date1의 경우 현지 시간은 2019-01-01 09:00:00 이었으며, setHours에서 9시로 지정되었기 때문에 수정된 것은 없습니다. 그래서 출력하면 UTC 기준으로 2019-01-01T00:00:00.000Z 입니다.

date2의 경우 현지 시간은 2019-01-01 00:00:00 이었으며, setHours에서 9시로 지정되어 2019-01-01 09:00:00로 수정되었습니다. 그래서 출력하면 UTC 기준으로 2019-01-01T00:00:00.000Z 입니다. (결과 (1)에서는 2018-12-31T15:00:00.000Z 이었습니다.)


지금까지 JavaScript에서 Date 객체에 대해서 간단히 알아보았습니다. 


MaxScale 추가 설정하다가 이전 내용을 한번에 다 정리해봤습니다. CentOS7 최소 버전이 설치된 환경에서 MariaDB 10.1 버전을 기준으로 진행된 내용입니다.

 

[ MariaDB 설치하기 ]

1. mariadb repo 파일을 만듭니다. 

[mariadb]  
name = MariaDB  
baseurl = http://yum.mariadb.org/10.1/centos7-amd64  
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB  
gpgcheck=0 

2. MariaDB를 설치합니다.

yum install -y MariaDB MariaDB-server MariaDB-client 

[ Galera Cluster 설정 ]

 

1. 우선 config 파일을 설정합니다.
vi /etc/my.cnf.d/server.cnf

[mysqld] 
init_connect='SET NAMES utf8' 
character-set-server = utf8 
collation-server=utf8_unicode_ci 

[galera] 
# Mandatory settings 
wsrep_on=ON 
wsrep_provider=/usr/lib64/galera/libgalera_smm.so 
wsrep_cluster_address='gcomm://'  ### 추가 서버에서는 기존 가동중인 서버 ip를 입력하세요.
wsrep_cluster_name='cluster_name' 
wsrep_node_address='172.xx.xx.xx'  ### 자신의 ip를 입력하세요.
wsrep_node_name='server1'
wsrep_sst_method=rsync 
wsrep_auto_increment_control=off 
binlog_format=row 
default_storage_engine=InnoDB 
innodb_autoinc_lock_mode=2 

bind-address=0.0.0.0 

wsrep_slave_threads=1 
innodb_flush_log_at_trx_commit=0 


2. 방화벽 설정
  추가할 포트는 TCP 3306/4568/4444 port와 TCP, UDP 4567 입니다.

firewall-cmd --permanent --zone=public --add-port=해당 포트/tcp 


3. selinux 설정

 최소 버전에는 semanage가 없어 설치해야 합니다.

yum install policycoreutils-python  

아래와 같이 추가 설정을 해주세요.

> semanage port -a -t mysqld_port_t -p tcp 4567 
> semanage port -a -t mysqld_port_t -p tcp 4568 
> semanage port -a -t mysqld_port_t -p tcp 4444 
> semanage port -a -t mysqld_port_t -p udp 4567 
> semanage permissive -a mysqld_t 

 

이제 mariadb를 실행하여 테스트용 DB와 테이블을 만들어 서버별로 모두 존재하는지 테스트 해보시면 됩니다. 

클러스터 첫번째 node를 실행할 때는 gcomm에 node ip를 명시하지 않지만, 모두 가동후에는 다른 node들에 대한 ip를 추가한 후 재시작 하시기 바랍니다.

 


[ MaxScale 설치 ]

 

 HA Proxy(http://www.haproxy.org/.  high availability, load balancing, and proxying for TCP and HTTP-based applications. 주로 Load balancer로 사용됨. H/W 형식을 오픈소스로 구현한 프로젝트)와 유사하며, DB read/write 쿼리를 지정된 DB 서버로 분산하는 기능이 있는 등 DB에 좀 더 특화되어 있습니다.

1. yum 저장소 설치

curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | bash 


2. MaxScale을 설치합니다. 

yum install -y maxscale 


3. MaxScale을 위한 유저 생성합니다. 필요한 권한만 설정합니다.

  create user 'maxscale'@'ip' identified by 'maxscalePW'; 
  grant select on mysql.user to 'maxscale'@'ip'; 
  grant select on mysql.db to 'maxscale'@'ip'; 
  grant select on mysql.tables_priv to 'maxscale'@'ip'; 
  grant show databases on *.* to 'maxscale'@'ip'; 


4. MaxScale을 모니터링 하기 위한 유저 계정을 생성합니다.

  create user 'ms_user'@'%' identified by 'ms_userPW'; 
  grant show databases on *.* to ms_user@'%'; 
  flush privileges; 



6. vi /etc/maxscale.cnf , config 파일 설정, 아래 내용을 통으로 사용하면 됩니다.

#Global MaxScale Settings 
[maxscale] 
threads=auto 

#Define Server Nodes 
[server1] 
type=server 
address=172.xx.xx.01
port=3306 
protocol=MariaDBBackend 

[server2] 
type=server 
address=172.xx.xx.02
port=3306 
protocol=MariaDBBackend 

[server3] 
type=server 
address=172.xx.xx.03
port=3306 
protocol=MariaDBBackend 


#Define Monitoring Service 
[Galera-Monitor] 
type=monitor 
module=galeramon 
servers=server1,server2,server3 
user=maxscale 
password=maxscalePW 
monitor_interval=1000 

#Define Galera Service 
[Galera-Service] 
type=service 
router=readconnroute 
router_options=synced 
servers=server1,server2,server3 
user=maxscale 
passwd=maxscalePW 

#Define Galera Listener 
[Galera-Listener] 
type=listener 
service=Galera-Service 
protocol=MariaDBClient 
port=4306 ### 기존 3306 포트 말고 이 포트로 쿼리를 보내면 됩니다.

#Define Administration Service 
[MaxAdmin-Service] 
type=service 
router=cli 

#Define Administration Listener 
[MaxAdmin-Listener] 
type=listener 
service=MaxAdmin-Service 
protocol=maxscaled 
socket=default 


7. 방화벽 설정. 쿼리를 받기 위한 포트입니다. 수정 가능합니다.

firewall-cmd --permanent --zone=public --add-port=4306/tcp 
firewall-cmd --reload 


8. MaxScale 시작 

systemctl start maxscale.service 
systemctl enable maxscale.service 



9. 테스트

 > maxctrl (maxadmin보다 깔끔하게 출력됩니다.)
          list servers
          show service Galera-Service 

'개발 이야기 > DATABASE' 카테고리의 다른 글

MariaDB, Galera Cluster, MaxScale 전체 정리  (0) 2019.07.04
SELinux for Galera cluster  (0) 2019.07.03
mariadb 시작 오류  (0) 2019.03.18
Galera 포트 리스트 및 용어 정리  (0) 2019.02.19
MariaDB MaxScale (발)번역  (0) 2015.01.23
mysql query browser 세션 문제  (0) 2014.07.02

http://galeracluster.com/library/documentation/selinux.html

 

SELinux Configuration — Galera Cluster Documentation

SELinux Configuration Security-Enhanced Linux, or SELinux, is a kernel module for improving security of Linux operating systems. It integrates support for access control security policies, including mandatory access control (MAC), that limit user applicati

galeracluster.com

 

꼭 읽어봐야 함.

 

tcp 4567, 4444는 설정되어 있다고 나오고, tcp 4568, udp 4567은 설정이 반영됨.

 

semanage 사용하려면 아래와 같이 설치!

 

yum install policycoreutils-python

'개발 이야기 > DATABASE' 카테고리의 다른 글

MariaDB, Galera Cluster, MaxScale 전체 정리  (0) 2019.07.04
SELinux for Galera cluster  (0) 2019.07.03
mariadb 시작 오류  (0) 2019.03.18
Galera 포트 리스트 및 용어 정리  (0) 2019.02.19
MariaDB MaxScale (발)번역  (0) 2015.01.23
mysql query browser 세션 문제  (0) 2014.07.02
[root@lnk635 ~]# ssh 'root'@'172.xx.xx.xx'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @ 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!

Someone could be eavesdropping on you right now (man-in-the-middle attack)! 
It is also possible that a host key has just been changed. 
The fingerprint for the ECDSA key sent by the remote host is 
SHA256:FTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Please contact your system administrator. 
Add correct host key in /root/.ssh/known_hosts to get rid of this message. 
Offending ECDSA key in /root/.ssh/known_hosts:8 
ECDSA host key for [172.xx.xx.xx]:22 has changed and you have requested strict checking. 
Host key verification failed.

 

 

ssh로 원격접속을 시도하면 위와 같은 에러가 출력될 때가 있다. 기존에 접속하던 시스템의 변경 문제(시스템 재설치 혹은 교체)로 저장된 원격 시스템의 고유값이 기존에 저장된 값과 다를 때 발생한다. 

 

스푸핑 같은 해킹으로 의심되기 때문에 위와 같은 경고를 출력하는데, /root/.ssh/known_hosts  파일에 들어가서 해당 ip로 저장된 키 값이 저장된 라인을 삭제한 후 재접속을 시도하면 된다. 

 

 

기존에 사용하던 ELK 6.3을 7.1.1 버전으로 업그레이드하며 그 사이 발생했던 문제들을 정리해 보았습니다. 참고로 모두 수동 설치되어 있는 상태입니다.

1. 설치 및 사용 환경 
2. 신규 장비 세팅하기
3. 신규 장비에 ES 설치하기 (ver 6.3)
4. Rolling 업그레이드 시작 - 6.3에서 6.8로 
5. Rolling 업그레이드 시작 - 6.8에서 7.1.1로
6. Kibana, Logstash 업그레이드


[1. 설치 및 사용 환경 ]
  

 현재 ELK를 사내 시스템에 설치하여 사용중에 있습니다. 돈이 많으면 그냥 편하게 Cloud 서비스를 사용하고 싶은 마음은 간절했으나 사정상 외부에서 서비스하는 시스템들이 보내는 raw data를 모두 가져와 사내의 ES에 밀어 넣고 있습니다. 운영비용도 절감할 수 있지만, 사내에 두고 쓰기 때문에 접근 속도, 운영 편의성 등 여러가지 장점도 있습니다. 어쨌든 좋은 솔루션을 제공해 준 elastic.co 과 오픈소스 개발자 여러분들께 무한 감사 드립니다. 

 

사양은 아래와 같습니다. 

 

OS  CentOS 7.5.x 
H/W

Intel i5, 32GB RAM, 1TB SCSI HDD x2

Intel i7, 32GB RAM, 1TB SSD x2

( 예. 맞아요.   ...    PC에 설치해서 사용중입니다. T-T )

 

총 4대를 모두 master, data mode로 설정하여 사용중에 있습니다. i7 장비 두 대는 이번 업그레이드할 때 신규로 추가했습니다.

 


[2. 신규 장비 세팅하기]

 

 다른 글에서도 정리한 적 있지만, 이번 기회에 다시 한번 깔끔하게 정리를 다시 해봤습니다. 

 1) CentOS 최소 버전 설치(USB로...)
  CentOS 설치용 USB 제작하는 방법은 이 곳을 참고해 주세요. 
 
 2) 설치 시 minimal version으로 설치합니다. 필요한 별도의 패키지는 없으며, 필요하면 추가로 설치하면 되니까요. ES는 root 계정으로 실행하지 않으니 사용할 유저를 미리 추가해 주세요. (이 글에서는 esuser라고 명명합니다.)

 3) Network 설정하기
  /etc/sysconfig/network-scripts/ifcfg-enpxxx 파일을 열어 아래와 같이 내용을 편집/추가 합니다. 

. 
. 
ONBOOT=yes 
IPADDR=172.xx.xx.xx 
GATEWAY=172.xx.xx.x 
DNS1=xx.xx.xx.xx 
DNS2=xxx.xxx.xxx.xxx 
ZONE=public 
. 
. 

   이후 systemctl restart network 한 후 외부와의 통신이 잘 되는지 확인합니다.


 4) hostname을 변경해 두세요. 

 그냥 놔두면 어느 시스템으로 원격 접속을 해도 localhost로 보일 수 있습니다.  /etc/hostname에서 원하는 이름으로 수정할 수 있습니다.

 5) sshd로 원격 접속도 하고, 파일도 이동시켜야 하니 설치를 해둡니다.
  > yum install openssh-server openssh-clients openssh-askpass

 

   22번 포트를 그대로 사용하기 보다는 다른 포트로 바꿔봅니다.
  > vi /etc/ssh/sshd_config

 

  수정된 포트를 방화벽에 추가합니다. 
  > firewall-cmd --permanent --zone=public --add-port=XXX/tcp

  > firewall-cmd --reload

 

  아래와 같이 원격 접속, 파일 전송을 테스트 해보세요.
   원격 접속 시 : > ssh 'root'@'172.31.xx.xx' -p ssh_port_number
   파일 이동 시 : > scp -r -P ssh_port_number /path_you_want_to_copy root@172.31.xx.xx:/path_to_copy

 6) Java 설치 - 7.0부터는 OpenJDK가 내장되어 별도로 설치하실 필요 없습니다.. 7.0 이상 버전을 설치하시려면 이 과정을 건너띄세요.
 > java -version  // 버전을 확인합니다.
 > yum remove java-1.7.0-openjdk.x86_64 -y // 기존 버전이 있을 경우 삭제합니다.
 > yum install java-1.8.0-openjdk-devel.x86_64 -y // 신규 버전을 설치합니다.

 7) ES는 많은 자원을 사용합니다. 아래 내용을 참고하여 시스템 자원 사용량의 제한을 수정하세요.
  > vi /etc/security/limits.conf 에 아래 내용을 추가하세요.  (https://www.elastic.co/guide/en/elasticsearch/reference/current/file-descriptors.html)

esuser hard memlock unlimited >> 하드 세팅으로 메모리 락 제한 없도록 설정 
esuser soft memlock unlimited >> 소프트 세팅으로 메모리 락 제한 없도록 설정 
esuser hard nofile 65536 >> 하드 세팅으로 65536번의 파일을 열어 볼 수 있게 설정 
esuser soft nofile 65536 >> 소프트 세팅으로 65536번의 파일을 열어 볼 수 있게 설정 
esuser hard nproc 65536 >> 하드 세팅으로 65536번의 프로시저를 실행 할 수 있게 설정 
esuser soft nproc 65536 >> 소프트 세팅으로 65536번의 프로시저를 실행 할 수 있게 설정 

* esuser가 아닌 모든 유저의 리소스 자원 한계를 수정하려면 esuser 대신 *을 사용할 수 있습니다.
* ES에서 해당 설정이 잘 되어 있는지는 아래의 방법으로 확인할 수 있습니다. 

GET _nodes/stats/process?filter_path=**.max_file_descriptors 

  > vi /etc/sysctl.conf 에 아래 내용을 추가하세요. 

 vm.max_map_count=262144 


[3. 신규 장비에 ES 설치하기 (ver 6.3)]


 1. 파일을 /app/(혹은 선정된 다른 폴더) 폴더에 복사하고 압축을 풀어둡니다.
 2. /home/esuser/esdata 폴더를 생성합니다. 
 3. 1/2번 과정을 root 계정으로 실행했다면 chown esuser:esuser /path_to_yours 로 권한을 꼭 설정하세요.
 4. /app/elasticsearch-6.xx/config의 jvm.options을 수정합니다.

-Xms15g  // 통상 메인 메모리의 절반 
-Xmx15g 

 5. /app/elasticsearch-6.xx/config의 elasticsearch.yml을 수정합니다.

cluster.name: cluster-name 
node.name: node-mdata-X.XX (ip끝번으로 이름 지정하면 구분하기 쉽습니다.) 
node.master: true 
node.data: true 

path.data: /home/esuser/esdata/data 
path.logs: /home/esuser/esdata/logs 
path.repo: /home/esuser/esdata/repo 

bootstrap.memory_lock: true 

network.bind_host: 0.0.0.0          
network.publish_host: 172.xx.xx.xx      // 설치된 시스템의 IP. 외부 통신용 주소 
network.host: 172.xx.xx.xx              // 내부 통신용 주소  

transport.tcp.compress: true        // node간 통신하는 데이터의 압축 여부를 설정. 
transport.tcp.port: 9300              // node간 통신에 사용하는 포트 

http.port: 9200                         // http를 통한 elasticsearch API 지원 노드의 port를 설정. master에게만 필요함. 

discovery.zen.minimum_master_nodes: 1   // 실제 서비스 환경에서는 최소 3대 이상의 마스터를 운영 필수.해당 옵션은 7.0부터 사용되지 않음 
discovery.zen.ping.unicast.hosts: ["172.xx.xx.xx:9300"] // node 간 연결을 위해 unicast로 master 노드를 지정. 마스터로 등록된 시스템의 모든 ip를 기록. 기본 포트인 9300을 사용한다면 굳이 기록할 필요는 없고, 포트를 변경한 경우만 이와 같이 기록하여 처리. 해당 옵션은 7.0부터 사용되지 않음 

 

 

(* 아래 업그레이드 내용 중 시스템 A/B는 (Intel i5, 32GB RAM, 1TB 자기 기록방식 HDD x2, 기존 사용 중인 시스템)로 구성된 시스템, C/D는 (Intel i7, 32GB RAM, 1TB SSD x2, 신규 시스템)로 구성된 시스템입니다. )
(* 업그레이드 전 두 시스템(A, B)에 400GB의 데이터, 1080개의 인덱스, 8500개의 샤드를 운영중에 있습니다. )


[4. Rolling 업그레이드 시작 - 6.3에서 6.8로]

 

 우선 C, D 시스템에 ES 6.3으로 순차적으로 가동했습니다. 6.8 혹은 7.1로 바로 갈 수 있지만 테스트를 위해 네 대 모두 6.3에서 시작되도록 준비했습니다. ( 호기심에 Kibana 6.8을 연결해 보았지만 실패!! Kibana는 ES와 버전을 맞춰야 하네요. )


 이제 C, D 시스템을 순차적으로 6.8로 업그레이드하여 재시작했습니다. 이까지는 아주 순조로왔습니다. 다만, Kibana 모니터링 화면에서는 시스템을 재가동 할 때 elected master가 바뀌는 것을 확인할 수 있었고, 6.8로 업그레이드 된 C와 D는 Node수에서는 변하지 않았지만, 모니터링 화면에서는 보이지 않는 것을 확인할 수 있었습니다.


 A를 업그레이드 하기 전, A에 연결된 Logstash를 잠시 종료한 후 (ps -ef | grep logstash로 확인 후 kill -SIGTERM ... , rpm으로 설치되어 있지 않은 상태입니다.), C로 연결했습니다. Kibana도 A에서 C로 연결되도록 설정ㅇ르 변경했습니다. 이 때, Kibana 모니터링 화면에서 6.8로 업그레이드 된 모든 서버가 보였습니다. 아마도 kibana 혹은 elected master의 버전과 같은 ES 서버만 보이게 되는 듯 합니다.


 바로 이어 B도 6.8 버전으로 재시작했습니다. 6.8로의 업그레이드는 전반적으로 순조롭게 마무리 되었습니다.
 
[5. Rolling 업그레이드 시작 - 6.8에서 7.1.1로]


 7.1.1에서 ES 설정 중 "discovery.zen.minimum_master_nodes", "discovery.zen.ping.unicast.hosts" 옵션이 "discovery.seed_hosts", "cluster.initial_master_nodes" 옵션으로 대체되었습니다.

    - "discovery.seed_hosts"는 "discovery.zen.ping.unicast.hosts"를 그대로 대체하면 됩니다.
    - "cluster.initial_master_nodes"는 "node.name"에 기록된 이름을 입력해야 합니다. 

 두 옵션에 대해서는 공식 문서에서 보다 상세 내용을 확인할 수 있습니다.

 

 A, B, C 를 7.1.1로 순차적으로 업그레이드 완료하였고, 당시 elected master는 D ES 6.3인 상태였습니다. 이어서 D를 업그레이드 하기 위해 종료했는데, 이때부터 문제가 발생하기 시작했습니다. 이상하게 다른 때와 달리 Kibana에서 elected master가 D인 상태로 유지되었으며, D를 종료한 상태인데도 모니터링 화면에서는 계속 live 되어 있다고 표기가 되었습니다. 시간이 지나도 바뀌는건 없었습니다. 일단 D를 재시작하면 괜찮겠지 하는 안일한 마음에 D를 7.1.1 버전으로 다시 시작했지만, "waiting for elected master node.."라는 메세지가 계속 나오면서 시작되지 않았습니다. 급한 마음에 A를 재시작 해보았지만 역시 "waiting for elected master node.."라는 메세지가 나오면서 시작되지 않았습니다. 이때 서두르지 않고 GET _cluster/health로 상태를 체크하면 시간을 더 두고 어떤 문제가 발생하는지 로그를 정확히 봤어야 하는데, 사정상 그러지 못한 것이 너무 아쉽더군요.


 결국 모든 서버를 내린 후 전체를 재시작하기로 결정을 했습니다. 하지만 계속 같은 경고 메세지를 출력하며, 정상적으로 진행되지 않았습니다. 그래서 공식 포럼에 질문을 올려보았습니다. 이하 내용은 "https://discuss.elastic.co/t/rolling-upgrade-problem-from-6-8-to-7-1-1/186571"에 담당자분과 확인하며 진행한 내용을 정리했습니다.

 

 ES 클러스터일 경우 한 대만 실행했을 때는 elected master를 선출할 수 없는 상태이므로 최소 2대 이상 실행해야 합니다. "cluster.initial_master_nodes"에 설정하면 한 대일 경우도 정상기동이 되는줄 알았는데 제가 잘못 이해한 듯 했습니다. 하지만 2대(B, C)를 실행했을 때도 실행되지 않았습니다. 이때는 아래와 같은 에러가 발생했습니다. 

[REDACTED] failed to join REDACTED... 
org.elasticsearch.transport.RemoteTransportException: 
. 
. 
Caused by: org.elasticsearch.ElasticsearchException: publication cancelled before committing: timed out after 30s 
. 
. 

 담당자는 timeout이 발생한 원인을 좀 더 상세히 알기 위해 elasticsearch.yml에 아래 옵션을 추가 후 로그를 보내달라고 제게 요청했죠.

logger.org.elasticsearch.cluster.service:TRACE
logger.org.elasticsearch.gateway.MetaStateService:TRACE

담당자는 로그를 살핀 후 현재 클러스터에 1000개가 넘는 인덱스가 있으며, elected master는 선출과정에서 각각의 인덱스를 위해 작은 metadata를 써야만 하는데, 이는 인덱스당 평균 60ms가 걸린다고 합니다. 추척된 로그에는 아래와 같은 내용이 기록되어 있었습니다. 

4  [2019-06-20T17:20:50,030][TRACE][o.e.g.MetaStateService   ] [REDACTED-NODE-NAME] [[REDACTED-INDEX-NAME/SHRkSR17SkKb9YAd6q-fEA]] state written ... 
1008  [2019-06-20T17:21:51,765][TRACE][o.e.g.MetaStateService   ] [REDACTED-NODE-NAME] [[REDACTED-INDEX-NAME/jkTAbDtIShmorVWmk-nxUQ]] state written 


   담당자는 현재 시스템 구성에서 1000개 이상의 인덱스는 너무 많으며, 이 때문에 기동 시 제한 시간인 60s를 넘어가면서 timeout이 발생했다고 했습니다. 또한 기동된 B서버는 자기 기록방식의 디스크라 속도가 느려지는 원인 중 하나임을 알려주었습니다. 그래서 인덱스를 줄여야 하지만, 당장 지울 수 없으니 cluster.publich.timeout : 90s 옵션을 elasticsearch.yml에 추가하는게 좋겠다고 이야기 했습니다.

   이 설정을 추가 후 B, C로 다시 시작했지만 "waiting for elected master node..." 경고가 계속 올라왔습니다. 여전히 B 서버의 느린 읽기 속도의 문제 인 것 같아  C, D 서버로 재시작을 시도했더니, 시스템이 정상적으로 가동되기 시작했습니다. 이후 A 서버를 실행하니 정상적으로 가동되었습니다.

 (이 시점에 모니터링을 위해 Kibana를 기동에 문제 발생. 아래 챕터에서 확인하실 수 있습니다.)

 다음으로 남은 B 서버를 가동했는데, 에러가 화면에 나타나지는 않았지만 status 가 계속 red인 상태에서 변하지 않는 문제가 발생했습니다. curl http://172.xx.xx.xx:9200/_cluster/state?pretty=true >> /app/status.txt 로 상태 출력해서 :/UNASSINGED 로 할당 안되는 것 확인하니.. 파일이 너무 많이 열려 있는 문제가 확인되었습니다. 분명 ulimit 설정은 65535까지 설정했는데... ;;  curl http://172.xx.xx.xx:9200/_nodes/stats/process?filter_path=**.max_file_descriptors 로 확인해봐도 65535로 설정된 것을 확인할 수 있었습니다. 다시 > ulimit -a 로 시스템 사용 자원을 확인해 봤더니 open files의 값이 65535였습니다. 할 수 없이 Kibana에서 red로 되어 있는 인덱스와 1000개 넘는 인덱스 중 테스트로 올라간 후 사용하지 않는 인덱스를 삭제했습니다. 이후 인덱스 총 개수는 900여개로 줄었고, B 서버도 정상 가동 되었습니다.

 이로서 이틀간의 롤링 업그레이드를 겨우 마칠 수 있었습니다. 하지만...  ;;;

[6. Kibana, Logstash 업그레이드]
 업그레이드 중간에 키바나도 7.1.1 로 업그레이드 하여 재시작을 해봤습니다. 하지만, A, C, D 서버가 정상 가동 된 후 1000개가 넘는 인덱스 정리를 위해 Kibana를 재시작했지만 정상 가동이 되지 않고 프로세스가 종료되는 것을 확인했습니다. 로그를 확인하니 max shard count의 값이 1000인데 현재 node 당 2000개가 넘어가고 있었습니다. (당시 에러 로그를 찾을 수 없어 정확한 메세지는 알 수 없네요.) ES는 정상 기동했는데 Kibana에서 이 에러가 나는 이유를 에러를 기록해두지 않아 정확히 알 수 없는 상태입니다. 어쨌든 아래와 같이 각 노드 별 최대 shard 개수를 조정했습니다. 

 curl -XPUT -H 'Content-Type: application/json' '172.xx.xx.xx:9200/_cluster/settings' -d '{ "persistent" : {"cluster.max_shards_per_node" : 3000}}'

 이후 Kibana가 정상 가동 되었으며, 마지막 가동되지 않던 B 서버도 정상화 될 수 있었습니다. 하지만 Kibana의 Discover화면으로 들어가서 검색을 시도하면 계속 에러가 발생했습니다. 로그를 보니 painless script 에서 오류가 나는 것을 확인할 수 있었습니다. 검색하는 data에 painless script에서 사용하는 키워드가 없기 때문인데, 이전 버전에서는 문제가 없었던 것 같은데, 7.0이상에서는 에러가 나더군요. 해당 script에 특정 컬럼이 존재하는지를 검사하는 코드를 모두 추가 했습니다. 

if (!doc.containsKey('your_column') || doc['your_column'].empty) return 'NULL'; else 

.

.

 이제 logstash(6.3 버전)를 재가동 했습니다. 아래 에러가 발생했네요. logstash를 재가동할 때는 이미 새로운 에러가 발생할 것이라는 기대를 하고 있었습니다. 부끄럽군요. :(

 Could not index event to Elasticsearch. 
 {
 	:status=>400, 
    :action=>
 	[
    	"index", 
        	{
            	:_id=>nil, 
                :_index=>"logstash-2019.06.21", 
                :_type=>"_doc", 
                :_routing=>nil
            }, 
    #], 
    :response=>{
    	"index"=>{
        	"_index"=>"logstash-2019.06.21", 
            "_type"=>"_doc", 
            "_id"=>nil, 
            "status"=>400, 
            "error"=>{
            	"type"=>"illegal_argument_exception", 
                "reason"=>"The [default] mapping cannot be updated on index [logstash-2019.06.21]: 
                defaults mappings are not useful anymore now that indices can have at most one type."
            }
        }
    }
}

아마도... 7.0에 수정된 type 관련 문제인 듯 했습니다. logstash도 이제 7.1.1로 업그레이드 후 변경된 config를 우선 적용했습니다.
   
<pipelines.yml file>

- pipeline.id : your_pipeline_name 
  path.config : "/app/logstash-7.1.1/config/your_pipeline_file.config" 

<logstash.yml file>

pipeline.batch.delay : 10 
config.reload.automatic: true 
config.reload.interval: 10s 

자! 이제 끝이길 기대하며 logstash를 다시 재시작했습니다. 조용!!! 오.. !!  끝인가..!! 했는데 신규 데이터가 들어오질 않더군요. 원인은 기존의 "your_pipeline_file.config"에서 type값을 _doc가 아닌 값으로 기존에 지정해뒀기 때문이었습니다.

재시작!! 또 에러!!! logstash 7.0 에서(인지 6.3 다음의 다른 버전이었는지 모르지만.. ) 다중 파이프라인 설정은 하나의 config파일안에 설정하지 않고 pipelines.yml에 추가 id와 config를 추가 설정하여 사용하도록 개선되었습니다. (문서 정독이 꼭 필요하네요!)

 드디어!! ELK의 모든 업그레이드가 종료되었습니다. 6.8 업그레이드와 네 대 중 세 대의 7.1.1 업그레이드가 순조로와 금방 끝날 것으로 기대했던 작업이 무려 하루하고 반일이 걸려버렸습니다. 끝까지 도와주신 David Turner씨에게 다시 한번 감사드리며, 다음부터 업그레이드 전 문서 정독 잘 하고 공식 포럼은 담당자들의 작업 시간을 알아둬야 겠다는 교훈을 얻고 마무리를 할 수 있었습니다.

 이제 index Forcemerge( https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html ) 해봐야 겠네요. 무슨 일이 일어날지 두렵긴 하지만... 또 삽집을 하게 되면 공유해 보겠습니다. ^^a

 

글이 다 정리되고 나니 7.2 버전이 발표되었네요. 하하하!!


안녕 ~~!! 

It may not be safe to bootstrap the cluster from this node. It was not the last one to leave th..

mariadb 테스트 중에 위와 같은 오류가 나서 찾아봤다. 


3대에 galera 설정해서 클러스터 구성하여 사용 중이었다. 


centos7 mariadb 10 사용 중.


다른 서버들은 모두 정상 가동 중이었고, 한 대만 문제가 발생한 상태.


netstat -na | grep 3306으로 포트를 확인하니 죽어있고 


systemctl start mariadb로 재가동이 안되어


systemctl status mariadb.service로 확인하니 위와 같은 에러가 발생한 상태.


설치된 폴더 (/var/lib/mysql)로 가서 


galera.cache, grastate.dat 파일을 삭제 후 재시작하니 정상 가동됨. 


두 파일은 시스템이 갑자기 문제가 생기면서 mariadb 프로세스가 죽으면서 미처 삭제 못한 temp 파일 인 듯.



'개발 이야기 > DATABASE' 카테고리의 다른 글

MariaDB, Galera Cluster, MaxScale 전체 정리  (0) 2019.07.04
SELinux for Galera cluster  (0) 2019.07.03
mariadb 시작 오류  (0) 2019.03.18
Galera 포트 리스트 및 용어 정리  (0) 2019.02.19
MariaDB MaxScale (발)번역  (0) 2015.01.23
mysql query browser 세션 문제  (0) 2014.07.02

https://yuddomack.tistory.com/entry/1React-Native-%EC%84%A4%EC%B9%98%EC%99%80-%EC%8B%A4%ED%96%89hello-world?category=754156 (이하 링크 문서) - 이 링크에 너무 잘 정리되어 있어 따라하면서 배우는 중입니다. (글쓴이님. 감사합니다. :)


https://wix.github.io/react-native-navigation/#/docs/Installing (이하 공식 문서)


아래 내용은 다음과 같은 환경에서 진행된 내용입니다. 

OS 

 macOS Mojave 10.14.1

 Android Studio 

 3.3.1

 XCode 

 10.1

 nodejs 

 10.13.0

 react 

 16.6.3

 react-native

 0.58.6

 react-native-navigation

 2.13.1



일단 링크문서의 1~5 chapter까지는 좋은 가이드가 되니 꼭 참고하시기 바랍니다.


chapter 6에서는 react native navigation을 다루는데, 최신 버전에서 변경된 내용들이 있어 별도로 정리를 해둡니다.


react-native-navigation을 설치하고 나면 low severity vulnerabilities에 대한 경고를 출력하고 npm audit fix(npm v6)를 실행하라는 안내가 나올 수 있습니다.


이를 실행하면 react-native-navigation을 사용하기 위해 필요한 몇몇 module의 버전을 조정하는 작업이 진행됩니다.


Android/iOS 세팅은 공식문서의 내용 중 수동 링크를 기준으로 정리하며 부족한 샘플 코드를 추가하였습니다. 왜 수동 링크 작업을 해야 하는지는 링크 문서에 잘 나와 있으니 참고하시기 바랍니다.


[RNN iOS 세팅]


우선 링크 문서 6장 의 내용을 참고하여 xcode에 react native navigation을 추가합니다. 공식문서보다 이 링크가 좀 더 명확히 정리되어 있습니다.


AppDelegate.m을 수정할 때 아래와 같은 에러가 발생할 수 있습니다.


 React/RCTBundleURLProvider.h file not found

 Use of undeclared identifier 'rootView'


이와 관련된 해결책은 공식 문서에 있으며, XCode에서 프로젝트를 선택 후, 메뉴 Product >> Scheme 에서 react native navigation을 선택하면 사라집니다.


링크 문서에서는 공식 문서와는 달리 RCCManager.h를 사용하도록 코드가 되어 있는데, 이전 버전의 내용이니, 아래 내용을 참고하시면 됩니다.


** 중간에 여러 코드 및 세팅을 테스트를 위해 수정하면서 Systrace.setEnable  관련된 에러가 ios 에뮬레이터에서 발생. 검색해보니 방법없으니 다시 설치하라는 내용만 있어 프로젝트 삭제 후 다시 설치. -0-a


관련 코드들은 공식 문서의 내용으로 적용하면 됩니다. 


(( AppDelegate.m ))


#import "AppDelegate.h" #import <React/RCTBundleURLProvider.h> #import <React/RCTRootView.h> #import <ReactNativeNavigation/ReactNativeNavigation.h> @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSURL *jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; [ReactNativeNavigation bootstrap:jsCodeLocation launchOptions:launchOptions]; return YES; } @end


XCode를 위한 세팅은 이것으로 끝입니다.


[RNN Android 세팅]


** 간간히 이런 작업들을 할 때 느끼는 거지만 아래 링크 문서의 샘플 코드에서 rootProject.projectDir 처럼, 저런 정의된 값을 어디서 찾아야 하는지 난감할 때가 많다. 기존에 android studio를 많이 다뤄 보신 분들은 쉽게 알 수도 있을 듯 한데, 처음 볼 때는 뜬금없어서.. 특히 javascript 프로젝트 할 때는 predefined keyword가 아닌 것들이 (intelligence를 지원하지 않는 ide에서) class의 public 맴버처럼 접근하는걸 볼 때마다 이게 어디에 정의되어 있는지, 올바르게 사용된건지 확인하기가 만만치 않은 듯 합니다. 자꾸 하다보니 그러려니 하긴 하지만...


아래 네 개의 gradle 파일을 수정할 때는 공식 문서를 참고하고, 자신의 android studio 버전에 따라 문서의 내용과 다를 수 있으니, 그에 맞추어 수정해야 합니다.

(( android/settings.gradle ))

(( android/gradle/wrapper/gradle-wrapper.properties ))

(( android/build.gradle ))

(( android/app/build.gradle ))


아래 두 코드를 공식 문서를 참고하여 수정 합니다.


(( MainActivity.java ))

(( MainApplication.java ))


그 다음으로 React Navtive 의 버전을 타겟팅하는 설정이 android/app/build.gradle에 추가해야 합니다. 별도 항목으로 제외된 것을 보면 중요한 항목인 듯 하네요. package.json 파일을 확인하니 제가 사용하는 버전은 0.58.6인 상태입니다.


저는 missingDimensionStrategy "RNN.reactNativeVersion", "reactNative57_5"로 설정을 추가 했습니다. 


공식 문서의 내용 1~8가지 따라하면서 주의할 점은 app/build.gradle의 dependencies를 추가할 때 특정 버전 대신 "${rootProject.ext.supportLibVersion}"을 설정하세요. 버전이 맞지 않아 빌드 실패 하는 경우가 종종 있었습니다. 

(https://github.com/wix/react-native-navigation/issues/3419 를 참고하세요.)







+ Recent posts