이 게시물은 Hart Hoover와 Ryan Walker가 공동으로 작성했습니다.
최근 Rackspace DevOps Automation 팀은 New Relic에서 Rackspace 지원팀으로 경고를 보내는 서비스를 발표했습니다. 이러한 경고는 DevOps 엔지니어가 응답할 티켓을 생성하므로 고객은 새벽 3시에 경고가 생성될 때 숙면을 취할 수 있습니다. 고객 환경에 대해 수집된 다른 데이터 포인트와 결합하면 엔지니어가 문제가 있는 위치를 식별한 다음 적절한 조치를 취합니다.
이 서비스를 위한 인프라를 설계하는 동안 New Relic이 통신할 수 있는 공용 엔드포인트를 유지하면서 보안을 위해 Rackspace 내부 시스템에 대한 액세스를 제한해야 한다는 공통적이지만 흥미로운 문제가 발생했습니다. 우리의 솔루션은 공개 API 엔드포인트와 개인 작업자가 서로 완전히 분리된 서비스를 설계하는 것이었습니다. 공개 API 끝점은 New Relic에서 경고를 수신하고 대기열 역할을 하는 ObjectRocket Redis 인스턴스에 전달합니다. 작업자 서비스는 RackConnect 방화벽 뒤에서 내부적으로 실행되며 대기열에서 메시지를 가져오고 경고를 생성합니다.
이것은 환경을 매우 잘 분할하지만 로그 집계와 관련하여 우리에게 문제를 일으켰습니다. 우리는 프라이빗 환경 내에서 ElasticSearch/Kibana 스택을 실행합니다. 방화벽 뒤에서 fluentd를 사용하여 ElasticSearch에 직접 로그를 푸시합니다. 방화벽 외부에서는 EK 스택에 연결할 수 없습니다. 이 문제를 해결하기 위해 fluentd를 사용하여 공개 API 서비스의 로그를 ObjectRocket MongoDB 인스턴스로 푸시하기 시작했습니다. 내부적으로는 fluentd를 다시 사용하여 ObjectRocket에서 ElasticSearch로 로그를 가져옵니다. 이를 통해 우리는 모든 환경 활동을 위한 단일 목적지를 얻을 수 있습니다.
Fluentd란 무엇입니까?
Fluentd는 데이터를 최대한 JSON으로 구조화하려는 오픈 소스 데이터 수집기입니다. 즉, 유사한 형식의 로깅 데이터를 얻기 위해 많은 스크립트를 작성하고 유지 관리할 필요가 없습니다. 모두 JSON입니다.
fluentd의 장점은 여러 소스와 대상을 지원하는 데 있습니다. 예를 들어 Twitter 스트림에서 데이터를 수집하고 IRC에서 이에 대해 알릴 수 있습니다. 사용할 수 있는 커뮤니티 플러그인이 많이 있습니다.
도커와 함께 Fluentd 사용
MongoDB fluentd 플러그인을 사용하면 로그를 ObjectRocket에 쉽게 푸시할 수 있습니다. 먼저 소스를 정의해야 합니다. 모든 서비스가 Docker를 사용하기 때문에 컨테이너 로그를 fluentd로 가져와야 합니다. 여기에서 docker-gen과 fluentd로 로그 집계를 수행하는 방법에 대한 이 글을 보완하는 훌륭한 게시물이 있습니다. fluentd 컨테이너가 실행 중이고 docker-gen이 fluentd 구성을 생성하면 실행 중인 각 컨테이너에 대해 다음과 같은 섹션이 있어야 합니다.
<source>
type tail
format json
time_key time
path /var/lib/docker/containers/abcdef/abcdef-json.log
pos_file /var/lib/docker/containers/abcdef/abcdef-json.log.pos
tag docker.container.abcdef
rotate_wait 5
</source>
이것은 컨테이너 로그를 추적하고 위치 파일을 사용하여 로그의 위치를 추적합니다. 이 구성 섹션에 있는 태그는 fluentd 태그로, fluentd가 집계하는 데이터로 무엇을 해야 하는지 알려주는 데 사용됩니다.
MongoDB와 Fluentd 사용
공개적인 측면에서 우리는 fluentd에게 "일치"를 통해 데이터를 처리하도록 지시합니다. 이 경우 동일한 구성 파일에 있는 ObjectRocket 데이터베이스의 실제 정보로 변수를 바꾸십시오.
<match docker.**>
type mongo
database $DBNAME
collection prod
host $HOSTNAME
port $PORT
ssl
capped
capped_size 100m
user $MONGOUSER
password $MONGOPASS
include_tag_key true
</match>
include_tag_key 설정은 MongoDB의 로그에 대한 레코드에 태그를 포함하도록 fluentd에 지시합니다. 이렇게 하면 어떤 로그 항목이 어떤 컨테이너에 속하는지 정확히 알 수 있습니다. Fluentd는 MongoDB에 데이터를 채우기 시작하며, 그런 다음 애플리케이션의 비공개 측에서 풀다운할 수 있습니다.
비공개 측면에서는 여전히 fluentd MongoDB 플러그인을 사용하지만 이번에는 소스로 설정합니다.
<source>
type mongo_tail
database $DBNAME
collection prod
host $HOSTNAME
port $PORT
user $MONGOUSER
password $MONGOPASS
ssl
time_key time
wait_time 5
tag prod
id_store_file /app/prod_last_id
</source>
그런 다음 로그에 대해 "일치"를 제공하여 ElasticSearch에 푸시합니다.
<match **>
type forest
subtype elasticsearch
<template>
host elasticsearch.domain.com
port 9200
index_name fluentd
logstash_format true
buffer_type memory
type_name ${tag}
flush_interval 3
retry_limit 17
retry_wait 1.0
num_threads 1
</template>
</match>
또한 여러 환경에서 태그 구성을 단순화하는 Forest fluentd 플러그인을 사용하고 있습니다.
Fluentd는 여러 호스트에 걸쳐 Docker 로그를 집계하고 이를 MongoDB 데이터베이스에 푸시하는 좋은 방법입니다. 우리의 경우 ObjectRocket은 로그 집계를 위한 공용 환경과 개인 환경 사이의 중간 지점입니다. 다른 사용 사례에는 수집 중인 데이터에 대한 실시간 분석이 포함될 수 있습니다. 우리 팀의 가장 좋은 점은 ObjectRocket의 안정성과 지식 덕분에 MongoDB를 관리할 필요가 없다는 것입니다.