OpenShift에서의 Logstash
업데이트: 이 글은 예전에 Found라는 이름으로 제공되었던 호스트형 Elasticsearch 제품에 대한 것입니다. Found는 이제 Elastic Cloud로 알려져 있습니다.
OpenShift에서 로그 분석을 시작해 보십시오. OpenShift를 통해 앱의 로그를 추적할 수 있지만, Elasticsearch/Logstash/Kibana 삼총사는 이러한 로그를 시각화하고 분석할 수 있는 매우 유연하고 강력한 툴체인을 제공합니다. 이 기사에서는 OpenShift에서 Logstash 카트리지를 만드는 방법을 설명합니다. 이 카트리지는 로그를 Elasticsearch로 전달하며, 여기서 Kibana 시각화 엔진을 사용하여 환경 내의 추세를 파악하고, 이상 징후를 탐지하며, 사고를 조사할 수 있습니다.
서론
OpenShift는 RedHat의 PaaS 이니셔티브로, 퍼블릭 제품과 함께 점점 더 대중화되고 있는 서비스형 플랫폼(PaaS) 접근 방식을 자체 데이터 센터 및 프라이빗 클라우드에 도입할 수 있는 엔터프라이즈 버전을 제공합니다.
Logstash는 이벤트와 로그를 관리하기 위한 도구입니다. Logstash를 Elasticsearch 및 Kibana와 결합하면 로그를 검색, 분석 및 시각화할 수 있는 매우 강력한 툴체인을 얻을 수 있습니다. 이 세 가지 조합을 흔히 ELK-stack이라고 부릅니다.
OpenShift를 사용하면 모든 앱의 로그를 쉽게 추적할 수 있지만, 추적 기능이 ELK-stack만큼 강력하지는 않습니다. 그러나 설계상 로깅과 같은 애플리케이션별 작업은 OpenShift에서 cartridge라고 부르는 기능에 맡겨집니다. cartridge는 매우 구체적인 기능을 제공하며, 이를 배포하는 애플리케이션의 gear에 혼합하여 사용합니다. gear는 특정 목적을 가진 컨테이너이며, 애플리케이션은 여러 개의 gear로 구성될 수 있습니다.
이 문서에서는 애플리케이션에 쉽게 혼합하여 로그에 대한 인사이트를 얻을 수 있는 간단한 Logstash 카트리지를 만들어 보겠습니다.
가정 및 목표
Logstash에는 Elasticsearch, Graphite, S3 등 다양한 출력이 있습니다. Elasticsearch는 가장 널리 사용되는 출력 중 하나입니다. 여기서는 Logstash가 로그를 Elasticsearch로 출력하도록 구성하지만, 이 접근 방식은 다른 출력에도 쉽게 일반화할 수 있습니다. 로그 전송과 로그 처리를 구분하기 위해 상위 Logstash로 출력할 수도 있습니다.
호스팅된 Elasticsearch 클러스터가 필요하시면 Found를 사용해 보십시오.
OpenShift에 대한 어느 정도의 이해가 있다고 가정합니다. OpenShift 경험이 없다면 시작하기가이드를 확인하십시오.
목표는 애플리케이션에 추가할 수 있는 카트리지를 확보하여 Elasticsearch 클러스터에 로그가 나타나는 것을 확인하는 것입니다. 그런 다음 Kibana를 사용하여 로그를 시각화 및 분석 하고, 인시던트를 조사하며, 환경 내의 추세를 파악하고 이상 징후를 탐지할 수 있습니다.
OpenShift 구성 및 로그
카트리지는 일반적으로 환경 변수를 통해 애플리케이션별 구성(예: 데이터베이스 자격 증명)으로 사용자 지정됩니다. 이러한 변수 중 하나인 $OPENSHIFT_LOG_DIR은 카트리지가 로그를 기록할 위치를 나타냅니다.
Cartridge는 무엇이든 실행할 수 있으므로 표준 로깅 형식이 없으며, 표준 타임스탬프 형식조차 없습니다. 이는 로깅의 보편적인 문제이며 Logstash가 매우 잘 처리하는 부분입니다. Logstash에는 다양한 입력과 필터가 있습니다. 이어지는 예제에서는 file 입력, Apache 로그, 타임스탬프 및 IP 처리를 위한 몇 가지 필터로 Logstash를 구성하고, 마지막으로 로그를 Elasticsearch로 출력할 것입니다. Logstash는 훨씬 더 많은 작업을 수행할 수 있으며 관련 문서도 잘 갖춰져 있습니다.
로그 형식은 애플리케이션마다 크게 다르므로 그에 따라 Logstash의 처리를 구성해야 합니다. 실제 예제를 살펴보기 위해 액세스 로그를 생성하는 간단한 Python 애플리케이션을 살펴보겠습니다:
# 애플리케이션을 생성합니다. 로그를 생성하는 것이라면 무엇이든 좋습니다. 이 앱을 사용하면 액세스 로그를 생성하는 웹 서버가 실행되며, 이것으로 충분합니다. $ rhc app create my-app python-2.6 애플리케이션 옵션 ------------------- 도메인:네임스페이스 카트리지: python-2.6 Gear Size: 기본값 확장: 아니요 'my-app' 앱 생성 중 ... 완료 [ ... ] 사용자의 애플리케이션 'my-app'을 이제 사용할 수 있습니다. URL: http://my-app-namespace.rhcloud.com/ [ ... ] # 클러스터 호스트 이름 및 인증 옵션과 같은 환경 변수 구성 $ rhc set-env --app my-app --env "OPENSHIFT_LOGSTASH_ES_HOST=dabadeee123-us-east-1.foundcluster.com" 환경 변수 설정 중... 완료 $ rhc set-env --app my-app --env "OPENSHIFT_LOGSTASH_ES_USER=readwrite" 환경 변수 설정 중... 완료 $ rhc set-env --앱 my-앱 --env "OPENSHIFT_LOGSTASH_ES_PASSWORD=secret" 환경 변수 설정 중... 완료 # 마지막으로 카트리지를 추가합니다. $ rhc cartridge add -a my-app https://cartreflect-claytondev.rhcloud.com/github/foundit/openshift-logstash-cartridge 카트리지 'https://cartreflect-claytondev.rhcloud.com/github/foundit/openshift-logstash-cartridge' 다운로드 및 설치됩니다 https://cartreflect-claytondev.rhcloud.com/github/foundit/openshift-logstash-cartridge 추가 'my-app' 애플리케이션으로 ... 완료 found-logstash-1.4.1 (Logstash 1.4.1) ------------------------------------- 출처: https://cartreflect-claytondev.rhcloud.com/github/foundit/openshift-logstash-cartridge Gears: Python-2.6과 함께 위치함
잠시 후, 구성된 Elasticsearch 클러스터에 로그가 나타나기 시작할 것입니다. 웹 애플리케이션을 방문하면 다음과 유사한 액세스 로그가 python.log에 표시됩니다:
1.2.3.4 - - [10/Jun/2014:10:31:17 -0400] "GET / HTTP/1.1" 200 39617 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36"
그런 다음 Logstash가 이를 가져와 다음과 같이 Elasticsearch로 색인합니다:
{
"_type": "logs",
"_source": {
"tags": ["app-name", "gear-name", "네임스페이스"],
"@timestamp": "2014-06-10T14:31:18.907Z",
"host": "ex-std-node7.prod.rhcloud.com",
"path": "/var/lib/openshift/530001200012cd3502000122/app-root/logs/python.log",
"message": "1.2.3.4 - - [10/Jun/2014:10:31:17 -0400] \"GET / HTTP/1.1\" 200 39617 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36\"",
"@version": "1"
},
"_index": "logstash-2014.06.10",
"_id": "dCfV_YUjSwOlISJWQMafaw"
}
이것은 좋은 시작이지만, 가장 흥미로운 정보는 1.2.3.4 - - [10/Jun/2014:10:31:17 -0400] "GET / HTTP/1.1\" 200 39617 \"-\" \"Mozilla/5.0 [...]" 스트링에 뭉쳐 있습니다.
이 스트링은 Apache Combined 형식을 따르며, Logstash에는 이를 매칭하기 위한 사전 정의된 패턴이 있습니다. 일반적으로 잘 알려진 소프트웨어를 사용 중이라면, 해당 소프트웨어에 대한 Logstash 패턴을 찾을 가능성이 높습니다. Logstash의 patterns디렉토리를 살펴보십시오. Grok Debugger의 Discover기능도 유용할 수 있습니다. 위 로그 메시지를 거기에 붙여넣으면 %{COMBINEDAPACHELOG}이 출력됩니다. 다음 섹션에서는 이를 사용하는 방법을 알아보겠습니다.
카트리지 사용자 정의
GitHub(foundit/openshift-logstash-cartridge)에서 제공되는 기본 카트리지에는 위 로그를 생성하는 매우 간단한 구성이 포함되어 있습니다.
Logstash가 로그를 올바르게 처리하고 데이터를 추출하도록 구성하려면 구성을 약간 변경해야 합니다. 먼저 python.log파일이 apache 유형임을 지정한 다음, 이후에 apache 유형의 모든 로그를 적절하게 필터링하도록 합니다.
Logstash 구성의 입력 및 필터 섹션이 다음과 같이 보이기를 원합니다. GitHub에서 전체 logstash.conf.erb를 확인하세요. logstash.conf.erb는 URL 및 인증 정보와 같은 환경 변수를 보간하여 Logstash 구성 파일을 생성하는 데 사용되는 템플릿입니다.
입력 {
# python.log를 제외하고 로깅된 모든 것
파일 {
path => "<%= ENV['OPENSHIFT_LOG_DIR'] %>*.로그"
# 필터링 목적으로 일부 openshift-metadata를 추가합니다.
tags => ["<%= ENV['OPENSHIFT_APP_NAME'] %>", "<%= ENV['OPENSHIFT_GEAR_NAME'] %>", "<%= ENV['OPENSHIFT_NAMESPACE'] %>"]
exclude => "python.로그"
}
# python.log에 Apache 액세스 로그가 포함되어 있음을 알고 있습니다.
파일 {
path => "<%= ENV['OPENSHIFT_LOG_DIR'] %>python.로그"
tags => ["<%= ENV['OPENSHIFT_APP_NAME'] %>", "<%= ENV['OPENSHIFT_GEAR_NAME'] %>", "<%= ENV['OPENSHIFT_NAMESPACE'] %>"]
type => "apache"
}
}
필터 {
if [type] == "apache" {
# 이는 타임스탬프, IP, 메서드 등 로그 메시지에 포함된 다양한 메타데이터를 추출합니다.
Grok {
match => ["message", "%{COMBINEDAPACHELOG}"]
}
# 시간 형식을 합리적인 방식으로 변환합니다.
날짜 {
match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
}
# 대략적인 지리 정보로 로그에 주석을 답니다.
geoip {
source => "clientip"
}
}
}
해당 구성을 사용하면 Logstash는 다음과 같은 문서를 생성합니다.
{
"_type": "apache",
"_source": {
"ident": "-",
"tags": ["앱-name", "gearname", "네임스페이스"],
"type": "apache",
"@timestamp": "2014-06-10T15:19:31.000Z",
"request": "/",
"auth": "-",
"응답": "200",
"referrer": "\"-\"",
"bytes": "39617",
"host": "ex-std-node7.prod.rhcloud.com",
"verb": "GET",
"agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) [...]",
"timestamp": "10/Jun/2014:11:19:31 -0400",
"path": "/var/lib/openshift/539709b8e0b8cd3502000122/앱-root/logs/Python.로그",
"message": "1.2.3.4 - - [10/Jun/2014:11:19:31 -0400] \"GET / HTTP/1.1\" 200 39617 [...]",
"@version": "1",
"clientip": "1.2.3.4",
"httpversion": "1.1",
"geoip": {
"region_name": "16",
"ip": "1.2.3.4",
"continent_code": "EU",
"country_name": "Norway",
"city_name": "Trondheim",
"timezone": "Europe/Oslo",
"longitude": 10.416699999999992,
"country_code3": "NOR",
"country_code2": "NO",
"location": [
10.416699999999992,
63.41669999999999
],
"위도": 63.41669999999999,
"real_region_name": "Sor-Trondelag"
}
},
"_index": "logstash-2014.06.10",
"_id": "Z1N65K5-QTOwZ9z3jPgEUw"
}
이 문서로 훨씬 더 많은 작업을 수행할 수 있습니다. 사용자의 출처, 방문 페이지를 기반으로 액세스 로그를 세부적으로 분석하고, 문제가 있는 요청을 쉽게 찾는 등의 작업을 할 수 있습니다. 아래 그림은 위 데이터를 사용하는 Kibana 대시보드의 예를 보여줍니다.
카트리지를 사용자 지정하려면 리포지토리를 포크하고 원하는 Logstash 구성으로 conf/logstash.conf.erb를 편집하십시오.
그런 다음 카트리지를 추가할 때 URL을 사용자 지정하십시오. 즉, foundit/openshift-logstash-cartridge를 your-organization/repository-name으로 변경하십시오.
$ rhc cartridge add -a my-app https://cartreflect-claytondev.rhcloud.com/github/your-organization/your-repo
기본적으로 master 브랜치가 사용됩니다. URL에 ?commit=branch-or-commit-id옵션을 전달할 수도 있습니다(예: https://cartreflect-claytondev.rhcloud.com/github/foundit/openshift-logstash-cartridge?commit=python-sample).
카트리지 사용자 지정 및 공개적으로 이용할 수 없는 카트리지 사용에 대한 자세한 내용은 카트리지 다운로드 방법에 대한 OpenShift 가이드를 참조하십시오.
로그 친화적인 매핑
살펴본 바와 같이, Logstash는 로그를 Elasticsearch로 전송하는 역할을 합니다. 여전히 Elasticsearch에 해당 로그를 처리하는 방법을 알려주어야 합니다. 결과 인덱스에 대한 매핑을 구성해야 합니다. (참조: Elasticsearch 매핑 소개 및 매핑을 위한 데이터 탐색 워크플로우)
일반적으로 Logstash는 로그를 logstash-YYYY-MM-DD 인덱스로 전송하며, 여기서 YYYY-MM-DD는 로그 날짜입니다. 이를 통해 검색을 특정 날짜 범위로 제한하고 오래된 로그를 보관하거나 삭제할 수 있습니다.
로그 매핑을 구성하려면 인덱스 템플릿을 정의해야 합니다. 이 템플릿은 이름이 logstash-*와 일치하는 모든 인덱스에 대한 매핑을 정의합니다.
다음은 위에서 생성된 로그에 대한 적절한 매핑입니다. message 필드를 제외하고 스트링 필드는 기본적으로 분석되지 않으며, geoip-location은 geo_point 유형으로, clientip는 ip 유형 등으로 구성됩니다.
{
"template": "logstash-*",
"settings": {
"index.refresh_interval": "5s"
},
"mappings": {
"_default_": {
"_all": {
"enabled": true
},
"dynamic_templates": [
{
"string_fields": {
"match": "*",
"match_mapping_type": "스트링",
"매핑": {
"type": "string",
"index": "not_analyzed"
}
}
}
],
"properties": {
"geoip": {
"properties": {
"location": {
"type": "geo_point"
}
}
},
"clientip": {
"type": "ip"
},
"bytes": {
"type": "long"
},
"message" : {
"type": "string",
"index": "analyzed",
"omit_norms": true
}
}
}
}
}
템플릿을 적용하려면 JSON 본문과 함께 /_template/logstash로 PUT 요청을 보내십시오:
$ curl https://user:pass@cluster-id.foundcluster.com:9243/_template/logstash -XPUT -d @index-template.json
{"acknowledged":true}
그러면 Elasticsearch는 새로운 logstash-index를 생성할 때마다 인덱스 템플릿에 지정된 설정과 매핑을 사용합니다.
요약
이제 더 애플리케이션별 구성이 가능한 사용자 정의 Logstash-cartridge의 기반으로 사용할 수 있는 cartridge가 생겼습니다. 이제 OpenStack cartridge를 추가하기만 하면 Elasticsearch 클러스터로 로그를 가져와 훌륭한 검색 및 분석을 수행할 수 있습니다.