<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Access Log on</title><link>https://taetaetae.github.io/tags/access-log/</link><description>Recent content in Access Log on</description><generator>Hugo</generator><language>en</language><lastBuildDate>Thu, 25 Jan 2018 21:18:35 +0000</lastBuildDate><atom:link href="https://taetaetae.github.io/tags/access-log/index.xml" rel="self" type="application/rss+xml"/><item><title>아파치 엑세스 로그를 엘라스틱서치에 인덱싱 해보자.</title><link>https://taetaetae.github.io/2018/01/25/apache-access-log-to-es/</link><pubDate>Thu, 25 Jan 2018 21:18:35 +0000</pubDate><guid>https://taetaetae.github.io/2018/01/25/apache-access-log-to-es/</guid><description>&lt;p>apache access log 를 분석하고 싶은 상황이 생겼다. 아니 그보다 apache access에 대해서 실시간으로 보고싶었고, log를 검색 &amp;amp; 데이터를 가공하여 유의미한 분석결과를 만들어 보고 싶었다. 그에 생각한것이 (역시) &lt;code>ElasticStack&lt;/code>.&lt;!-- more -->&lt;/p>
&lt;p>처음에 생각한 방안은 아래 그림처럼 단순했다.
&lt;figure>&lt;a class="lightgallery" href="https://taetaetae.github.io/images/apache-access-log-to-es/model_1.png" title="/images/apache-access-log-to-es/model_1.png" data-thumbnail="/images/apache-access-log-to-es/model_1.png" data-sub-html="&lt;h2>처음 생각한 단순한 구조&lt;/h2>">
 &lt;img
 class="lazyload"
 src="https://taetaetae.github.io/svg/loading.min.svg"
 data-src="https://taetaetae.github.io/images/apache-access-log-to-es/model_1.png"
 data-srcset="https://taetaetae.github.io/images/apache-access-log-to-es/model_1.png, https://taetaetae.github.io/images/apache-access-log-to-es/model_1.png 1.5x, https://taetaetae.github.io/images/apache-access-log-to-es/model_1.png 2x"
 data-sizes="auto"
 alt="/images/apache-access-log-to-es/model_1.png" />
 &lt;/a>&lt;figcaption class="image-caption">처음 생각한 단순한 구조&lt;/figcaption>
 &lt;/figure>&lt;/p>
&lt;p>하지만, 내 단순한(?) 예상은 역시 빗나갔고 logstash에서는 다음과 같은 에러를 내뱉었다.&lt;/p>
&lt;blockquote>
&lt;p>retrying individual bulk actions that failed or were rejected by the previous bulk request&lt;/p>&lt;/blockquote>
&lt;p>request가 많아짐에 따라 elasticsearch가 버벅거리더니 logstash에서 대량작업은 거부하겠다며 인덱싱을 멈췄다. 고민고민하다 elasticsearch에 인덱싱할때 부하가 많이 걸리는 상황에서 중간에 버퍼를 둔 경험이 있어서 facebook그룹에 문의를 해봤다.
&lt;a href="https://www.facebook.com/groups/elasticsearch.kr/?multi_permalinks=1566735266745641" target="_blank" rel="noopener noreffer ">https://www.facebook.com/groups/elasticsearch.kr/?multi_permalinks=1566735266745641&lt;/a>
역시 나보다 한참을 앞서가시는 분들은 이미 에러가 뭔지 알고 있으셨고, 중간에 버퍼를 두고 하니 잘된다는 의견이 있어 나도 따라해봤다. 물론 답변중에 나온 redis가 아닌 기존에도 비슷한 구조에서 사용하고 있던 kafka를 적용.
아, 그전에 현재구성은 Elasticsearch 노드가 총 3대로 클러스터 구조로 되어있는데 노드를 추가로 늘리며 스케일 아웃을 해보기전에 할수있는 마지막 방법이다 생각하고 중간에 kafka를 둬서 부하를 줄여보고 싶었다. (언제부턴가 마치 여러개의 톱니바퀴가 맞물려 돌아가는듯한 시스템 설계를 하는게 재밌었다.) 아래 그림처럼 말이다.&lt;/p>
&lt;figure>&lt;a class="lightgallery" href="https://taetaetae.github.io/images/apache-access-log-to-es/model_2.png" title="/images/apache-access-log-to-es/model_2.png" data-thumbnail="/images/apache-access-log-to-es/model_2.png" data-sub-html="&lt;h2>그나마 좀더 생각한 구조&lt;/h2>">
 &lt;img
 class="lazyload"
 src="https://taetaetae.github.io/svg/loading.min.svg"
 data-src="https://taetaetae.github.io/images/apache-access-log-to-es/model_2.png"
 data-srcset="https://taetaetae.github.io/images/apache-access-log-to-es/model_2.png, https://taetaetae.github.io/images/apache-access-log-to-es/model_2.png 1.5x, https://taetaetae.github.io/images/apache-access-log-to-es/model_2.png 2x"
 data-sizes="auto"
 alt="/images/apache-access-log-to-es/model_2.png" />
 &lt;/a>&lt;figcaption class="image-caption">그나마 좀더 생각한 구조&lt;/figcaption>
 &lt;/figure>
&lt;p>그랬더니 거짓말 처럼 에러하나 없이 잘 인덱싱이 될수 있었다. logstash가 양쪽에 있는게 약간 걸리긴 하지만, 처음에 생각한 구조보다는 에러가 안나니 다행이라 생각한다.&lt;/p>
&lt;p>이 구조를 적용하면서 얻은 Insight가 있기에, 각 항목별로 적어 보고자 한다. ( &lt;del>이것만 적어놓기엔 너무 없어보여서..&lt;/del> )&lt;/p>
&lt;h2 id="access-log-를-어떻게-분석하여-인덱싱-할것인가">access log 를 어떻게 분석하여 인덱싱 할것인가?&lt;/h2>
&lt;p>apache 2.x를 사용하고 별도의 로그 포맷을 정하지 않으면 아래와 같은 access log가 찍힌다.
&lt;code>123.1.1.1 - - [25/Jan/2018:21:55:35 +0900] &amp;quot;GET /api/test?param=12341234 HTTP/1.1&amp;quot; 200 48 1144 &amp;quot;http://www.naver.com/&amp;quot; &amp;quot;Mozilla/5.0 (iPhone; CPU iPhone OS 11_1_2 like Mac OS X) AppleWebKit/604.3.5 (KHTML, like Gecko) Mobile/15B202 NAVER(inapp; blog; 100; 4.0.44)&amp;quot;&lt;/code>
그럼 이 로그를 아무 포맷팅 없이 로깅을 하면 그냥 한줄의 텍스트가 인덱싱이 된다. 하지만 이렇게 되면 elasticsearch 데이터를 다시 재가공하거나 별도의 작업이 필요할수도 있으니 중간에 있는 logstash에게 일을 시켜 좀더 nice 한 방법으로 인덱싱을 해보자. 바로 logstash 의 filter 기능이다. 그중 Grok filter 라는게 있는데 패턴을 적용하여 row data 를 필터링하는 기능이다. 조금 찾아보니 너무 고맙게도 아파치 필터 예제가 있어 수정하여 적용할수 있었다. &lt;a href="http://grokconstructor.appspot.com/do/match?example=2" target="_blank" rel="noopener noreffer ">http://grokconstructor.appspot.com/do/match?example=2&lt;/a>
그래서 적용한 필터설정은 다음과 같다.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">filter &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> grok &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">match&lt;/span> &lt;span class="o">=&lt;/span>&amp;gt; &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">message&lt;/span> &lt;span class="o">=&lt;/span>&amp;gt; &lt;span class="s2">&amp;#34;%{IP:clientIp} (?:-|) (?:-|) \[%{HTTPDATE:timestamp}\] \&amp;#34;(?:%{WORD:httpMethod} %{URIPATH:uri}%{GREEDYDATA}(?: HTTP/%{NUMBER})?|-)\&amp;#34; %{NUMBER:responseCode} (?:-|%{NUMBER})&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>이렇게 하고 elasticsearch 에 인덱싱을 하면 키바나에서 다음과 같이 볼수 있다.
&lt;figure>&lt;a class="lightgallery" href="https://taetaetae.github.io/images/apache-access-log-to-es/access_log_kibana.png" title="/images/apache-access-log-to-es/access_log_kibana.png" data-thumbnail="/images/apache-access-log-to-es/access_log_kibana.png" data-sub-html="&lt;h2>키바나에 내가 원하는 구조대로 이쁘게 들어가 있는 access log&lt;/h2>">
 &lt;img
 class="lazyload"
 src="https://taetaetae.github.io/svg/loading.min.svg"
 data-src="https://taetaetae.github.io/images/apache-access-log-to-es/access_log_kibana.png"
 data-srcset="https://taetaetae.github.io/images/apache-access-log-to-es/access_log_kibana.png, https://taetaetae.github.io/images/apache-access-log-to-es/access_log_kibana.png 1.5x, https://taetaetae.github.io/images/apache-access-log-to-es/access_log_kibana.png 2x"
 data-sizes="auto"
 alt="/images/apache-access-log-to-es/access_log_kibana.png" />
 &lt;/a>&lt;figcaption class="image-caption">키바나에 내가 원하는 구조대로 이쁘게 들어가 있는 access log&lt;/figcaption>
 &lt;/figure>&lt;/p>
&lt;h2 id="각-필드가-아닌-한줄로-인덱싱이-되어버린다">각 필드가 아닌 한줄로 인덱싱이 되어버린다.&lt;/h2>
&lt;p>Elasticsearch 에 인덱싱이 되긴 하는데 로그 한줄이 통째로 들어가 버린다. &lt;code>message&lt;/code>라는 이름으로&amp;hellip; 알고보니 현재 구조는 logstash가 kafka 앞 뒤에 있다보니 producer logstash 와 consumer logstash 의 &lt;code>codec&lt;/code>이 맞아야 제대로 인덱싱이 될수 있었다.
먼저 access log에서 kafka 로 produce 하는 logstash 에서는 output 할때 codec 을 맞춰주고&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">output &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> kafka &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">bootstrap_servers&lt;/span> &lt;span class="o">=&lt;/span>&amp;gt; &lt;span class="s2">&amp;#34;123.1.2.3:9092,123.1.2.4:9092&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">topic_id&lt;/span> &lt;span class="o">=&lt;/span>&amp;gt; &lt;span class="s2">&amp;#34;apache-log&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">codec&lt;/span> &lt;span class="o">=&lt;/span>&amp;gt; json&lt;span class="o">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>kafka 에서 consume 하는 logstash 에서는 input 에서 codec 을 맞춰준다.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">input &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> kafka &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">bootstrap_servers&lt;/span> &lt;span class="o">=&lt;/span>&amp;gt; &lt;span class="s2">&amp;#34;123.1.2.3:9092,123.1.2.4:9092&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">topic_id&lt;/span> &lt;span class="o">=&lt;/span>&amp;gt; &lt;span class="s2">&amp;#34;apache-log&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">codec&lt;/span> &lt;span class="o">=&lt;/span>&amp;gt; json&lt;span class="o">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>그렇게 되면 codec이 맞아 각 필드로 &lt;code>이쁘게&lt;/code> 인덱싱을 할수 있게 되었다.&lt;/p></description></item></channel></rss>