Skip to main content

4 posts tagged with "자동화"

View All Tags

· 8 min read

LB 이중화에 대해서 정리하는 것을 미루고 있다가 아예 이중화 구축을 자동화하는 것까지 해보기로 했다. 지난번에는 HAProxy를 하나만 두었었는데 다른 VM (192.168.100.54)에 동일한 설정으로 HAProxy를 올리고 VRRP를 위해 keepalived를 사용했고 keepalived 설치에 대해서는 '믿고 보는' Digital Ocean의 문서를 참조했음. 아래의 그림처럼 만들어봤다.

(두 개의 VM에 공통으로 설정할 내용이 있고 각각 다르게 해야 하는 부분이 있어서 아래 소제목에 공통으로 적용해야 하는 내용들만 별도 표기함)

 

1. haproxy_check 계정 수정

지난번에는 하나의 HAProxy에서 로드밸런싱을 했기 때문에 MySQL에 연결되는지 확인할 계정 (haproxy_check)을 MySQL에 추가할 때 host로 192.168.100.53을 지정했는데 192.168.100.54에서도 접근해야 하므로 미리 다른 host에 대한 계정을 추가하거나 host를 192.168.100.0/24 255.255.255.0 수정하는 등의 작업을 해두어야 한다.

 

2. keepalived 설치 (공통)

keepalived는 최신 버전(현재 1.3.4)을 다운받아서 빌드해 설치했다. 빌드에 필요한 package 들을 사전에 설치해 두어야 한다.

sudo apt-get install build-essential libssl-dev

아래 경로로 최신 버전을 다운받아 압축을 풀고 아래의 명령으로 빌드해서 설치하면 완료된다.

http://keepalived.org/software/keepalived-1.3.4.tar.gz

./configure
make
sudo make install

 

3. keepalived upstart script (공통)

빌드해서 설치한 경우 ubuntu에 service로 등록되어있지 않기 때문에 upstart script를 만들어줘야만 한다. /etc/init/keepalived.conf 파일을 생성해서 아래의 내용으로 채워준다. 어떤 경우에 시작할지, 서비스 시작은 어떻게 할지 등을 결정하는 내용이다.

description "load-balancing and high-availability service"

start on runlevel [2345]
stop on runlevel [!2345]

respawn

exec /usr/local/sbin/keepalived --dont-fork

 

4. keepalived 설정

이제 중요한 keepalived 설정을 할 순서인데 무엇을 어떻게 감시할 것인지 failover시 backup instance가 인계하거나 master가 가지고 있을 VIP 설정을 해야 한다. Master 역할을 할 첫번째 LB (지난번에 설치한)가 있는 VM에 가서 우선은 /etc/keepalived 디렉토리가 없으므로 생성해둔다. 그리고 /etc/keepalived/keepalived.conf 파일을 아래와 같은 형태로 만든다.

vrrp_script chk_haproxy {
script "pidof haproxy"
interval 2
}

vrrp_instance VI {
state MASTER
interface eth0
virtual_router_id 100
priority 200

virtual_ipaddress {
192.168.100.60
}

track_script {
chk_haproxy
}
}

vrrp_script에는 감시할 내용을 기술하면 되는데 HAProxy가 제대로 떠있는지를 확인하면 되기 때문에 단순하게 pidof를 이용해 pid만 확인하기로 한다. 상황에 따라 다른 방식으로 기술될 수도 있을 것 같고 다양한 방법이 있을 것 같다. vrrp_instance는 VRRP에 대한 설정이라고 보면 되는데 keepalived를 어떻게 동작시킬 것인지에 대한 내용. Master로 사용할 내용이므로 state는 MASTER, eth0로 통신하니 interface는 eth0로 지정하고 virtual_router_id는 임의로 100을 지정했다. virtual_router_id는 다른 keepalived와 중복되지만 않으면 되니 임의의 수를 입력한다. priority는 여러개의 keepalived가 있는 상태에서 failover를 할 때 어떤 instance가 인계할 것인지를 결정하는 수치인데 높은 값일수록 인계할 가능성이 높다. virtual_ipaddress에는 보유하고 있는 VIP를 지정해준다.

Backup instance로 동작할 VM (192.168.100.54)에도 동일한 경로에 아래와 같은 형태로 설정 파일을 만들어준다.

vrrp_script chk_haproxy {
script "pidof haproxy"
interval 2
}

vrrp_instance VI {
state BACKUP
interface eth0
virtual_router_id 200
priority 100

virtual_ipaddress {
192.168.100.60
}

track_script {
chk_haproxy
}
}

문제가 발생했는지 여부를 검사할 내용이나 VIP 설정 등은 동일한데 state와 virtual_router_id, priority 가 다르다. state는 BACKUP으로 지정하고 앞서 기술했듯이 virtual_router_id는 master와 다르게 지정하고 priority는 election에 관여하는 내용이니 master보다 낮은 값을 입력해준다.

 

5. 서비스 시작과 확인

Master, backup instance 모두에서 keepalived service를 시작하고 문제없이 시작되었다면 예전과 비슷한 방식으로 이중화가 제대로 되는지 확인해본다.

mysql -h 192.168.100.60 -u tester -p -e "show variables like 'server_id'"

지난번에는 HAProxy 하나에서 round robin으로 로드밸런싱을 했기 때문에 HAProxy가 있는 VM의 ip (192.168.100.53)로 연결해서 server_id가 변경되는지 확인했었는데 이번에는 HAProxy도 이중화를 했기 때문에 위에서 설정한 VIP (192.168.100.60)를 통해 server_id를 확인할 수 있다. Master가 정상동작중인 상태이므로 master instance가 VIP에 연결된 상태일텐데 이 상태에서 이중화가 제대로 되고 있는지 확인하려면 master의 haproxy service를 중단시키고 위와 동일한 command로 server_id를 확인해보면 되겠다. VRRP에 의해 backup instance가 인계하는 내용은 syslog에서도 확인 가능하다.

 

6. 자동화

Ansible을 사용해서 HAProxy로 mysql을 로드밸런싱 하는 내용은 만들어둔 상태였는데 keepalived 설치와 설정하는 내용도 추가해봤다. 또 여러개의 instance를 한 번에 설정할 수 있도록 수정했는데 실제 OS만 올려져 있는 VM 몇 개를 두고 playbook 실행만으로 귀찮은 반복작업이 줄어들어 너무 편해졌음. 상세 내용은 아래 저장소 참조.

https://github.com/blurblah/ansible-role-mysql-lb

· 6 min read

빌드와 배포를 자동화하는 작업을 진행하는 도중에 Database에 data를 쓰고 업데이트 하는 기능이 필요하게 되었다. 이 경우 여러가지 방법이 있을 수 있지만 최대한 간단하게, 추가 개발없이 진행하고 싶었다. (Shell script에서)

1. 과거에 사용했던 방법들

간단히 Java로 DB와 connection을 맺고 CRUD를 하는 모듈을 개발해서 사용했던 적이 있다. Jar로 묶어 놓으면 script에서는 jar에 parameter만 몇 개 넘겨서 실행하면 가능했다. 하지만 난 그 당시의 소스를 가지고 있지 않고 간단하더라도 개발을 추가로 하기가 귀찮았다. 시간도 없었고.

두번째로 groovy script를 사용했었다. Groovy 자체가 java와 유사한 부분이 많기 때문에 작성이 어렵지 않았고 그렇게 만들어진 groovy script를 shell에서 호출하는 것도 어렵지는 않다. 하지만 역시 추가로 script를 구현하는게 번거롭고 어딘가에 script를 보관하고 사용해야 한다는게 마음에 걸렸다. 난 단지 하나의 shell script로만 해당 기능을 구현하고 싶었다.

마지막으로 사용해봤던 방법은 REST API를 구현하고 shell script에서는 curl을 이용해 REST API를 호출하는 방법인데, 꽤 괜찮은 방법이 아닌가 생각했었지만 역시 REST API를 구현해야 하는 부담이 있었다. 하지만 대규모 개발이 아니라면 node.js로 충분히 할만하다. (간단하면 개발하는데 그리 오래 걸리지도 않는다)

2. Command line에서 query 실행하기

그동안 사용할 일이 없었기 때문에 MySQL client 실행옵션 중에 -e가 있다는 걸 이번에 알았다. -e 옵션은 뒤에 오는 query 문을 실행해주는 역할을 하는데 이 옵션만 사용하더라도 단 한 줄의 명령으로 원하는 기능을 수행하게 만들 수 있다.

3. Password prompt

한 줄의 명령으로 원하는 기능에 근접했지만 항상 password prompt가 뜨는 문제에 봉착했다. expect를 사용하거나 하면 되겠지만 그것보다 간단한 방법을 원했다. 그리고 찾은게

mysql -uuser_id -ppassword

-p 옵션에 password를 붙여쓰면 따로 묻지 않는다. 그 사이에 공백이 있다면 password prompt를 띄우라는 걸로 인식하고 뒤에 있는 password를 사용하려는 DB schema로 인식한다.

4. Inserted id를 알고 싶어요

또 다른 문제. DB에 insert 하고 특정 작업 이후에 insert된 레코드를 update 해야 했는데 id 이외에 유일한 값을 특정하기가 어려웠다. 강제로라도 유일한 값을 만들수는 있을 것 같았는데 그것을 위해 DB 구조를 변경해야 할 것 같아서 마음에 들지 않았다. 그래서 생각한 방법은 insert 이후에 아래의 query를 바로 실행하는 것이었다.

select last_insert_id();

마지막으로 추가된 id를 알려준다.

5. Shell script에서 text로 된 query 결과를 parsing 해야 하는가?

위의 문제를 해결하니 다른 문제가 등장했다. MySQL client에서 직접 select query를 실행하면 결과를 mysql만의 형태로 돌려준다는 것이었다. Json이나 xml과 같은 정규화된 문자열이 아니라 특수문자로 column의 경계가 그려진 문자열들. 처음엔 이것을 parsing 해야 하나 생각했는데 말도 안되는거라 생각했다. 의미도 없고. 그래서 찾은게 -s와 -N 옵션인데, -s는 silent를 -N은 column name 출력을 하지 않는다. 어차피 마지막에 추가된 id만 알면 되기 때문에 column은 단 하나뿐이고 진정 내가 원하는 것은 그 column의 값일 뿐이다. 두 옵션을 사용해 query를 실행하면 id만 달랑 떨어진다.

6. 결과

mysql -uuser_id -ppassword db_schema -s -N -e "insert_query_with_last_insert_id"

위의 형태로 실행하면 password를 묻지도 않고 insert를 한 후 추가된 id만 받을 수 있다. 단 한줄만으로.

Password가 공개될 여지가 있는데 insert 하려는 값을 parameter로 받는 별도의 script 파일로 만들어서 읽기권한을 제어하는 방법을 사용하는게 어떨까 생각한다. 그게 간단하니까.

· 8 min read

처음 자동화 업무를 시작하면서부터 ssh를 본격적으로 사용하기 시작했다.

그 당시에도 ssh가 제대로 지원되지 않는 환경인 경우 (거의 임베디드 리눅스 환경) 제대로 지원될 수 있도록 기능이나 기타 필요한 내용들을 관련 개발부서에 요청하곤 했었다. ssh를 사용하면 할수록 자동화에 필수적이라는 생각이 드는 이유는

1. 매우 간단하다

어차피 command의 형태로 되어있고 형식이 간단하고 linux와 os x의 경우 기본으로 포함되어 있기 때문에 특별히 뭘 구현하지 않아도 된다.

2. 인증여부를 묻지 않게 할 수 있다

간단하게 장비간 key만 교환하고 등록하면 인증시 계정의 패스워드가 아니라 key의 패스워드를 묻게 되는데 key 생성시 패스워드 없이 생성이 가능하기 때문에 인증여부를 묻지 않는 것처럼 보일 수 있다. 장비에 대한 제어를 자동으로 해야 하는데 인증여부 등을 묻거나 하면 해결하기가 어렵다. 물론 제어 가능하도록 무언가를 구현해서 사용해도 된다. 하지만 구석에 박혀있는 작은 기능이 필요할 때 이전에 구현된 거대한 덩어리들을 수정하지 않아도 되니 꽤 유용하다.

3. 권한만 있다면 해당 OS의 거의 모든 기능을 사용할 수 있다

ssh도 shell 이므로 shell에서 할 수 있는 기능들은 거의 사용 가능하다. 단 한번에 수행되어야 하는 작업이 많은 경우 문제가 생기기도 하고 command가 복잡해져서 나의 경우엔 복잡한 작업을 수행하는 script를 하나 따로 만들어서 ssh로는 그 작업을 하는 script만 호출하는 식으로 처리하곤 한다.

4. 파일 전송이 간단하다

ssh와 시리즈로 사용하는 scp로 파일 전송을 하곤 하는데, ftp를 별도로 서비스하거나 mount 같은 걸 하지 않아도 되니 아쉬울 때 쓰기 좋다.

 

하지만 ssh로 도배를 해보니 몇가지 아쉬운 점이 있었는데

1. 귀찮은 키교환

자동화에 사용하는 장비 수가 늘어날수록 키를 서로 교환하고 등록하는 과정이 무척 귀찮아진다. 이 과정 마저도 어느정도 자동화를 할 수도 있지만 신규 장비에 접속해서 키는 생성해야 하니 짜증스럽다. 예를 들어 한번에 장비가 10대만 늘었다고 하더라도 반복작업이 수십회는 된다. 장비간 키교환이 귀찮아 아예 키를 통째로 전송해서 같은 키를 사용하기도 하는데 이 경우 보안문제도 신경쓰인다.

2. 늘어나는 script

ssh가 간편하기도 하고 간단한 기능을 쉽게 땜질하는게 가능하지만 땜질이 늘어날수록 script가 늘어나게 된다. 한 번은 script가 수십개가 되었던 적도 있었는데 아무리 작명을 잘해도 어떤게 어떤건지 내용을 열어보거나 실행해봐야 아는 상태에 이르렀다. 게다가 특정 장비간 기능이 달랐기 때문에 script도 퍼져있어서 관리하기가 쉽지 않았다.

3. Known host 문제

장비의 IP가 변경되는 경우 서로 키를 교환하고 있는 상태이기 때문에 인증에는 문제가 없다고 하더라도 변경된 IP로 접속한 기록이 없기 때문에 최초 접속시 known host로 등록할거냐고 묻는다. 이게 자동화에 방해가 되므로 IP 변경시 한번씩은 접속을 해주거나 known host로 등록을 해줘야 하는 번거로움이 발생한다. 물론 sshd 설정에 아예 known host 여부를 따지지 않게 하는 부분이 있긴 하지만 자동화 이외의 다른 용도로 사용되거나 하면 그런 설정을 하기가 꺼려진다.

 

그래서 적합한 방안이라고 생각하는 것들은 이렇다.

1. Script의 공용화

Script는 가능한 적게 만드는게 좋을 것 같다. 그리고 여러 장비에서 사용해야 하는 script 라면 script는 장비 하나에만 두고 공통으로 사용할 수 있는 방안을 마련하는게 좋을 것 같다. 처음엔 한 곳에 script를 두고 필요할 때 마다 다른 장비에 복사해서 호출하게 하곤 했었는데 영 지저분하고 특정 상황에서는 script를 복사하면 안되는 경우도 있어서, 아예 script가 있는 경로를 각 장비에서 mount 해서 사용해보고 있는데 아직은 괜찮은 것 같지만 좀 더 지나봐야 알겠다.

2. 기능의 구조화 및 정리

단편적인 기능들을 간단하게 추가만 하다가 어느 시점이 되면 기능들을 모아서 별도의 모듈로 개발하는게 좋겠다는 생각을 한다. 물론 공수가 들어가는 문제이지만...

3. 별도의 인증과정

무작정 키를 장비 한대에서 등록하고 관리하고 교환하고 할 게 아니라 인증 기능을 담당하는 장비나 서비스를 별도로 분리하는게 좋을 것 같다. 난 이 작업을 진행하는 것 자체가 꽤 재미있을 것 같다. 이미 나와있는 것들도 많겠지만.

· 3 min read

애니팡을 자동화해서 돌려주는 프로그램들이 있다.

유튜브나 기타 인터넷에서 접하는 내용들을 보니 많은 사람들이 "버그를 썼다" 라는 표현을 하는데, 이는 잘못된 표현임. (참조 : 위키피디아-소프트웨어 버그)

버그는 쉽게 설명하면 개발자들의 실수 등으로 인해 예상치 못한 동작이나 결과를 가져오는 문제점이라고 볼 수 있는데 애니팡을 자동으로 게임하는 것은 소프트웨어적인 '버그'를 이용한 것이 아니다.

궁금하기도 해서 실제 해보고 판단한 건데 '버그'가 아니라 그냥 단순히 '자동화'에 의한 처리일 뿐.

그렇다고 애니팡이 전혀 버그를 가지고 있지 않은 완전무결한 소프트웨어라는 얘기는 아니다.

실제로 그런 소프트웨어가 존재하지도 않고.

앞으로는 '버그를 썼다'가 아니라 '자동 프로그램 썼네', '쟤 뭐 돌렸네' 이 정도로만 표현하도록 하자.

애니팡을 몇몇 프로그램을 써서 플레이하면서 얻게 된 인사이트 같은게 있는데 난 그 정도로만 만족하고 내 시간을 더 애니팡에 쓰진 않을 생각이다.

최근 기사들을 보니, 기사내용을 그대로 다 믿을 수는 없지만, 초등학생들 사이에선 애니팡이 어떤 서열화의 수단처럼 되어가는 것 같던데 부모님이 대신해주는 경우도 있다고 하니 이런건 참 문제다.

시간을 조절하면, 사람들이 믿을만한, 원하는 점수를 대충 만들 수 있으니 고심하는 부모님들은 애니팡 자동화하는 방법들을 써보시길 적극 권장하는 바임.

다음엔 재미있는 자동화에 대해서...