웹 엔지니어 - 로그
by Yoonkh
로그
로그는 왜 중요한가
로그가 필요한 네가지 경우
-
버그 조사
-
이상 징후 감지
-
가설 검증
-
감사 로그
버그 조사
원인을 조사하는 정보로 가장 효과적인 것이 시스템 로그와 액세스 로그 같은 이른바 각종 ‘로그’입니다. ‘어느 URL에 보내는 요청에서 오류가 발생했는지’, ‘파라미터는 적절하게 전달되었는지’ 알 수 있으면, 문제 해결이 쉬워 집니다.
이상 징후 감지
예를 들어, 매일 CPU와 메모리, 디스크 사용량 등 데이터를 기록해서 그래프로 시각화한다면, 그래프가 갑자기 변동하거나 한계치에 가깝더라도 문제가 되기 전에 파악할 수 있습니다. 이처럼 문제를 감지하는 것이 중요합니다.
가설 검증
무엇보다도 로그를 제대로 가져와야 가설을 검증할 수 있습니다. 예를 들어, 어떤 페이지에 버튼이 있는데 그 버튼을 얼마나 눌렀는지, 로그(정보)가 없다면 그곳에 버튼을 설치한 것이 좋았는지 정량적인 판단을 할 수가 없습니다.
감사 로그
보안이라는 관점에서 로그를 생각해 보겠습니다. ‘언제, 누가, 무엇을 했는지’ 정확히 로그로 남겨 두는 것이 중요합니다. 관계형 데이터베이스에서 조작 로그 등이 이에 해당합니다. 이런 로그가 남아 있지 않다면, 문제가 일어났을 때 단서가 없어 곤란합니다.
Fluentd 등장 배경
여러 대에 걸친 로그를 로그 서버와 같은 어딘가 전용 서버에 실시간으로 모을 수 있다면 편리할 것입니다. 이 장에서 소개할 Fluentd 로그 수집 소프트웨어가 이런 용도에 적합합니다.
Fluentd와 syslogd의 차이
Fluentd와 syslogd의 다른점
- 로그 수집 방법과 저장소 등 유연한 사용자화
- 로그에 태그를 붙여 쉽게 관리
- 다양한 언어를 지원하는 모듈 제공
Fluentd 사용
Fluentd 도입
Fluentd는 다음과 같은 방법으로 설치할 수 있습니다.
- 소스코드로 Fluentd를 설치한다.
- Rubygems로 Fluentd를 설치한다.
- RPM이나 Dev 패키지로 td-agent를 설치한다.
Fluentd의 구조
디렉티브와
- 실제로 몇가지 디렉티브를 이용해서 테스트를 해보겠습니다.
$ sudo / etc/init.d/td-agent start
Starting td-agent (via systemctl): [ OK ]
# 또는
$ sudo systemctl start td-agent.service
Fluentd에 메세지 전송
Fluentd 설정 파일은 /etc/td-agent/td-agent.conf이므로 이 파일을 다음처럼 수정합니다.
<source>
type forward
</source>
<match debug.test>
type stdout
</match>
수정을 마쳤으면 반드시 설정 파일을 다시 로드 합니다.
$ sudo systemctl reload td-agent
로그 감시
Nginx 설치
# Nginx 저장소를 설치합니다
$ sudo rpm -Uvh \
http://nginx.org/packages/centos/7/noarch/RPMS/nginx-releasecentos-7-0.el7.ngx.noarch.rpm
# Nginx를 설치한다
$ sudo yum -y install nginx
Nginx를 시작합니다. 자동 시작 설정도 하겠습니다.
# httpd 데몬이 실행 중일 수도 있으니 일단 중지한다
$systemctl stop httpd.service
# Nginx 시작 및 자동 시작 설정을 한다
$ systemctl start nginx.service
$ systemctl enable nginx.service
로그를 다른 Fluentd 서버로 전송
여러 대의 서버에서 동작하는 좀 더 복잡한 처리를 예로 들어 생각해 봅시다. 어떤 서버에서 Nginx의 액세스 로그를 감시하고 기록된 로그를 Fluentd로 보냅니다. 그리고 out_forward 플러그인을 사용해서 그 로그를 다른 Fluentd에 전송합니다.
호스트 이름 부여
호스트에 이름을 붙이려면 fluent-plugin-record-reformer 플러그인을 사용합니다. 이 플러그인은 외부 플러그인이므로 td-agent-gem install 커맨드로 먼저 설치해야 합니다.
$ /usr/sbin/td-agent-gem install fluent-plugin-record-reformer
MongoDB에 저장
여기서는 스키마가 없는 도큐먼트 지향 데이터베이스인 MongoDB로 출력해봅니다.
etc/yum.repos.d/mongodb-org-3.0.repo 파일을 다음처럼 작성하여 yum 저장소를 추가합니다.
$ sudo yum -y install mongodb-org
설치를 마쳤으면 자동으로 시작되도록 합니다.
$ sudo service mongod start
$ sudo chkconfig mongod on
- 액세스 로그를 MongoDB에 저장했는지 알아보는 커맨드 셸 명령어
$ mongo fluentd
> db.nginx_access.find()
Fluentd의 권장 구성
실제로 Fluentd의 서버 쪽은 active-standby 구성을 권장합니다.
네트워크에 연결하지 않아도 로그 수집을 멈추지 않게 하려는 것입니다. 이때는 다음 처럼 active와 standby를 따로 지정하고 standby 쪽은
로그 시각화
로그의 문제점을 쉽게 파악할 수 있다면 로그를 시각화하는 것도 하나의 방법입니다.
예를 들어, 다음 정보를 시각화할 수 있다면 편리하지 않을까요?
- 오류 로그(404, 500)추이
- 페이지 응답 속도 추이
- 응답에 일정 시간 이상 걸린 액세스 수의 추이
- 로그인에 실패한 수의 추이
엘라스틱 서치
엘라스틱 서치(Elasticsearch)는 엘라스틱이 개발한 오픈 소스 검색엔진으로, 아파치 루씬(Apache Lucene)이라는 전문(Full text) 검색 라이브러리를 기반으로 사용합니다. 스키마를 지정하지 않고 데이터를 등록할 수 있으며, 대량으로 등록된 데이터를 거의 실시간으로 검색할 수 있습니다.
엘라스틱서치 도입
Java 설치
엘라스틱 서치는 Java로 구현하므로, 우선 Java를 설치합니다.
$ sudo yum -y install java-1.7.0-openjdk
엘라스틱서치 설치
엘라스틱 서치는 yum 커맨드로 간단하게 설치할 수 있습니다.
/etc/yum.repos.d/elasticsearch.repo 파일을 다음 내용으로 새로 만들고, yum 리포지터리를 추가합니다.
$ sudo yum -y install elasticsearch
$ sudo systemctl start elaticsearch.service
$ sudo systemctl enable elasticsearch.service
엘라스틱서치 사용
엘라스틱서치는 ‘인덱스’단위로 데이터를 관리합니다. 인덱스는 다음처럼 HTTP 요청으로 쉽게 생성할 수 있습니다.
$ curl -X POST http://localhost:9200/test_index
{"acknowledged":true}
Fluentd에서 엘라스틱서치로 데이터 전송
엘라스틱서치로 데이터를 보낼 때는 Fluent-plugin-elasticsearch 플러그인을 사용하면 간단합니다. 이 플러그인을 사용하려면 libcurl-devel도 필요하므로 함께 설치합니다.
$ sudo yum -y install libcurl-devel
$ sudo /usr/sbin/td-agent-gem install fluent-plugin-elasticsearch
서버쪽 Fluentd 설정을 다음처럼 변경합니다. 여기서는 out_copy 플러그인을 사용하여 앞에서처럼 MongoDB에 로그를 출력하면서 동시에 엘라스틱서치에도 로그를 보냅니다. out_copy는 출력을 복수의 스토리지에 복사해서 전달할 수 있는 편리한 플러그인입니다.
<source>
type forward
</source>
<match hostname.nginx.access_log>
type copy
<store>
type mongo
host localhost
port 27017
database fluentd
collection nginx_access
flush_interval 10s
</store>
<store>
type elasticsearch
host localhost
port 9200
logtash_format true
logstash_prefix test_index
logstash_dataformat %Y%m
type_name nginx_access
buffer_type memory
buffer_chunk_limit 10m
buffer_queue_limit 10
flush_interval 1s
retry_limit 16
retry_wait 1s
</store>
</match>
인덱스 삭제
오래된 인덱스를 삭제할 때는 엘라스틱서치에서 제공하는 Curator 도구를 사용하면 편리합니다. ‘pip’라는 Python의 패키지 관리 도구를 사용해서 설치하겠습니다.
$ sudo pip install elasticsearch-curator
$ sudo pip install argparse
Curator에는 여러 옵션이 있지만, 최근 며칠분의 인덱스만 남기고 오래된 인덱스를 삭제하는 사용법으로도 충분합니다.
$ curator --host localhost delete --older-than 30
키바나
카바나는 엘라스틱서치 안의 데이터를 시각화하고자 엘라스틱서치사에서 제공하는 공식 데이터 시각화 도구입니다. HTML, CSS, JS로만 구성하기 때문에 웹 서버만 준비하면 사용할 수 있습니다.
카바나 도입
적당한 디렉터리에 키바나를 설치하고 Nginx의 도큐먼트 루트에 설정합니다.
$ curl -O https://download.elastic.co/kibana/kibana/kibana-3.1.0.tar.gz
$ tar zxvf kibana-3.1.0.tar.gz
$ mv kibana-3.1.0 /usr/local/
$ vi /etc/nginx/conf.d/default.conf
더미 액세스 로그 생성
우선 apache-loggen을 설치합니다. Ruby 라이브러리 관리; 도구인 Rubygems를 사용할 것이므로 환경을 설정합니다. 이미 앞에서 환경을 설정했다면 건너뜁니다.
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
$ sudo yum -y install gcc make openssl-devel
$ rbenv install 2.2.3
$ rbenv global 2.2.3
이제 Rubygems를 사용할 수 있으니 apache-loggen을 설치합니다.
$ gem install apache-loggen
키바나 사용
로그를 여러 가지 관점에서 분석하고 싶을 때 간편하게 시각화할 수 있는 것이 키바나의 장점입니다.
키바나에서는 다양한 그래프를 자유롭게 생성하고 배치할 수 있지만, 주로 다음 네 가지를 사용합니다.
- 히스토그램
- 테이블
- 텀
- 트렌드
히스토그램
히스토그램에서는 시계열로 데이터를 표시하거나 특정 쿼리로 필터링할 수 있습니다.
테이블
테이블에서는 액세스 로그를 테이블 형식으로 표시합니다. 표시할 요소를 필터링 할 수도 있어 적절히 필터링 하면 보기가 편해집니다.
텀
텀은 이른바 패싯 검색 결과를 표시하는 것입니다. 예를 들어, 아파치의 액세스 로그에서 Field로 Code(스테이터스 코드)를 지정하면, 각 스테이터스 코드가 몇 번씩 발생했는지 표시합니다.
트렌드
트렌드는 10분 전이나 1시간 전과 비교해서 값이 어느 정도 변했는지 알려줍니다.
Subscribe via RSS