<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>elasticsearch on Digi Hunch</title><link>https://static.digihunch.com/tag/elasticsearch/</link><description>Recent content in elasticsearch on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Tue, 08 Apr 2025 14:57:09 -0400</lastBuildDate><atom:link href="https://static.digihunch.com/tag/elasticsearch/index.xml" rel="self" type="application/rss+xml"/><item><title>Log Shipping in Kubernetes with EFK stack</title><link>https://static.digihunch.com/2021/09/log-shipping-in-kubernetes-with-efk/</link><pubDate>Sat, 04 Sep 2021 21:50:00 -0400</pubDate><guid>https://static.digihunch.com/2021/09/log-shipping-in-kubernetes-with-efk/</guid><description>&lt;img src="https://static.digihunch.com/wp-content/uploads/2025/04/feature-elk-logshipping.webp" alt="Featured image of post Log Shipping in Kubernetes with EFK stack" /&gt;&lt;p class="wp-block-paragraph"&gt;I first worked on &lt;a href="https://static.digihunch.com/2018/09/log-shipping-through-elk/"&gt;log shipping&lt;/a&gt; with ELK stack three years ago. In the context of Kubernetes cluster, log shipping has similar challenges. In this post I will discuss the set up of log shipping with Kubernetes cluster using EFK stack&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-logging-architecture"&gt;Logging Architecture&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;As &lt;a href="https://static.digihunch.com/2021/08/docker-desktop-a-single-node-kubernetes-cluster/"&gt;discussed&lt;/a&gt;, if the Kubernetes cluster has a runtime in compliant with CRI (e.g. &lt;em&gt;containerd&lt;/em&gt;), then the stdout and stderr of the Pod is stored on the node, in the location /var/log/containers/.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When creating log shipping solution, it is important to use a compliant cluster (e.g. minikube) to ensure what you develop will work across environments. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The Kubernetes document has a section on &lt;a href="https://kubernetes.io/docs/concepts/cluster-administration/logging/#cluster-level-logging-architectures"&gt;logging architecture&lt;/a&gt; which is a good start point. It outlines several different patterns. Logging at the node level is turned on by default and does not require special configuration, as explained in the section above. The EFK pattern is close to the diagram under &lt;a href="https://kubernetes.io/docs/concepts/cluster-administration/logging/#cluster-level-logging-architectures"&gt;using a node logging agent&lt;/a&gt; for cluster-level logging.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://d33wubrfki0l68.cloudfront.net/2585cf9757d316b9030cf36d6a4e6b8ea7eedf5a/1509f/images/docs/user-guide/logging/logging-with-node-agent.png" alt="Using a node level logging agent"/&gt;&lt;figcaption class="wp-element-caption"&gt;Node logging agent&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The diagram above is stolen from Kubernetes documentation. In EFK stack, the agent is a daemonset running fluentd Pod. &lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-efk-stack"&gt;EFK stack&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;While we can use ELK (Elasticsearch, Logstash, Kibana) stack for log shipping, EFK (Elasticsearch, Fluentd, Kibana) is generally recommended in Kubernetes cluster. We compare the two in the following table:&lt;/p&gt;&#10;&lt;figure class="wp-block-table is-style-regular"&gt;&lt;table class="has-white-background-color has-background has-fixed-layout"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;ELK&lt;/td&gt;&lt;td&gt;EFK&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Development language&lt;/td&gt;&lt;td&gt;All in Java. Logstash and Filebeat both require JVM. Managed as an open-source project by Elastic company&lt;/td&gt;&lt;td&gt;Fluentd in Ruby and does not require JVM to run. Fluentd is a CNCF project built to integrate with Kubernetes.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Typical pattern&lt;/td&gt;&lt;td&gt;Filebeat acts as a lightweight collector to monitor the source log. Logstash as aggregator to receive from filebeat, and push to Elasticsearch&lt;/td&gt;&lt;td&gt;The fluentd Pod can be configured to serve as forwarder and aggregator based on configuration. fluentd-forwarder is deployed as daemonset on node, and ship the result to fluentd-aggregator, which may run in a separate cluster. The fluentd-aggregator pushes processed results to Elasticsearch.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Metrics&lt;/td&gt;&lt;td&gt;use metric beat for data collection&lt;/td&gt;&lt;td&gt;scrape metrics from prometheus server&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Event Routing&lt;/td&gt;&lt;td&gt;tag-based&lt;/td&gt;&lt;td&gt;if-then statement&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;figcaption class="wp-element-caption"&gt;ELK and EFK stacks comparison&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The main problems in log shipping are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;column mapping : identify column patterns in each log line and map them to appropriate column in Elasticsearch.&lt;/li&gt;&#10;&lt;li&gt;multi-line processing: identify when a logging entry spread across multiple lines and process accordingly.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Suppose we want to congregate the logs from stdout and stderr of PostgreSQL pods. The raw output in /var/log/container on the node, looks like this:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:46.75370563Z stdout F server stopped&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:46.757173069Z stderr F postgresql-repmgr 15:27:46.75 INFO &lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; Starting PostgreSQL in background...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:46.883126928Z stderr F postgresql-repmgr 15:27:46.88 INFO &lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; Registering Primary...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.017164653Z stderr F postgresql-repmgr 15:27:47.01 INFO &lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; Loading custom scripts...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.023334611Z stderr F postgresql-repmgr 15:27:47.02 INFO &lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; Loading user&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;s custom files from /docker-entrypoint-initdb.d ...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.026169813Z stderr F postgresql-repmgr 15:27:47.02 INFO &lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; Starting PostgreSQL in background...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.343607487Z stderr F postgresql-repmgr 15:27:47.34 INFO &lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; Stopping PostgreSQL...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.448111425Z stdout F waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; server to shut down.... &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.448172479Z stdout F server stopped&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.453722807Z stderr F postgresql-repmgr 15:27:47.45 INFO &lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; ** PostgreSQL with Replication Manager setup finished! **&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.453829953Z stdout F&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.503516746Z stderr F postgresql-repmgr 15:27:47.50 INFO &lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; Starting PostgreSQL in background...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.532558987Z stdout F waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; server to start....2021-08-28 15:27:47.532 GMT &lt;span style="color:#f92672"&gt;[&lt;/span&gt;273&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: pgaudit extension initialized&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.533307459Z stdout F 2021-08-28 15:27:47.533 GMT &lt;span style="color:#f92672"&gt;[&lt;/span&gt;273&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: listening on IPv4 address &lt;span style="color:#e6db74"&gt;&amp;#34;0.0.0.0&amp;#34;&lt;/span&gt;, port &lt;span style="color:#ae81ff"&gt;5432&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.533466407Z stdout F 2021-08-28 15:27:47.533 GMT &lt;span style="color:#f92672"&gt;[&lt;/span&gt;273&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: listening on IPv6 address &lt;span style="color:#e6db74"&gt;&amp;#34;::&amp;#34;&lt;/span&gt;, port &lt;span style="color:#ae81ff"&gt;5432&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.537987947Z stdout F 2021-08-28 15:27:47.537 GMT &lt;span style="color:#f92672"&gt;[&lt;/span&gt;273&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: listening on Unix socket &lt;span style="color:#e6db74"&gt;&amp;#34;/tmp/.s.PGSQL.5432&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.547956465Z stdout F 2021-08-28 15:27:47.547 GMT &lt;span style="color:#f92672"&gt;[&lt;/span&gt;273&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: redirecting log output to logging collector process&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.548005463Z stdout F 2021-08-28 15:27:47.547 GMT &lt;span style="color:#f92672"&gt;[&lt;/span&gt;273&lt;span style="color:#f92672"&gt;]&lt;/span&gt; HINT: Future log output will appear in directory &lt;span style="color:#e6db74"&gt;&amp;#34;/opt/bitnami/postgresql/logs&amp;#34;&lt;/span&gt;.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.551741571Z stdout F 2021-08-28 15:27:47.551 GMT &lt;span style="color:#f92672"&gt;[&lt;/span&gt;275&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: database system was shut down at 2021-08-28 15:27:47 GMT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.558012894Z stdout F 2021-08-28 15:27:47.557 GMT &lt;span style="color:#f92672"&gt;[&lt;/span&gt;273&lt;span style="color:#f92672"&gt;]&lt;/span&gt; LOG: database system is ready to accept connections&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.618577092Z stdout F &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.618708978Z stdout F server started&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.630065958Z stderr F postgresql-repmgr 15:27:47.62 INFO &lt;span style="color:#f92672"&gt;==&lt;/span&gt;&amp;gt; ** Starting repmgrd **&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.638116348Z stderr F &lt;span style="color:#f92672"&gt;[&lt;/span&gt;2021-08-28 15:27:47&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;NOTICE&lt;span style="color:#f92672"&gt;]&lt;/span&gt; repmgrd &lt;span style="color:#f92672"&gt;(&lt;/span&gt;repmgrd 5.2.1&lt;span style="color:#f92672"&gt;)&lt;/span&gt; starting up&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.65317627Z stderr F INFO: set_repmgrd_pid&lt;span style="color:#f92672"&gt;()&lt;/span&gt;: provided pidfile is /opt/bitnami/repmgr/tmp/repmgr.pid&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.653232015Z stderr F &lt;span style="color:#f92672"&gt;[&lt;/span&gt;2021-08-28 15:27:47&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;NOTICE&lt;span style="color:#f92672"&gt;]&lt;/span&gt; starting monitoring of node &lt;span style="color:#e6db74"&gt;&amp;#34;orthweb-postgresql-ha-postgresql-0&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;ID: 1000&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:27:47.681683703Z stderr F &lt;span style="color:#f92672"&gt;[&lt;/span&gt;2021-08-28 15:27:47&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;NOTICE&lt;span style="color:#f92672"&gt;]&lt;/span&gt; monitoring cluster primary &lt;span style="color:#e6db74"&gt;&amp;#34;orthweb-postgresql-ha-postgresql-0&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;ID: 1000&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2021-08-28T15:28:11.742865958Z stderr F &lt;span style="color:#f92672"&gt;[&lt;/span&gt;2021-08-28 15:28:11&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;NOTICE&lt;span style="color:#f92672"&gt;]&lt;/span&gt; new standby &lt;span style="color:#e6db74"&gt;&amp;#34;orthweb-postgresql-ha-postgresql-1&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;ID: 1001&lt;span style="color:#f92672"&gt;)&lt;/span&gt; has connected&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;From this snippet of log, we can see each line in stdout or stderr is appended with a timestamp. There are multi-line log entries but each is still appended with a timestamp. This is just how kubernetes keeps the log file for Pod stdout and stderr. To handle that, we need to first take out the real log line, and then process multi-line.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We will go over the installation of EFK stack and the mechanism to address the two challenges above.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-install-elasticsearch-and-kibana"&gt;Install Elasticsearch and Kibana&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To install Elasticsearch, we use the helm chart provided by the official repository:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm repo add elastic https://helm.elastic.co&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;If we run multiple pods on the same hosts, then we need some customized values in order to get the installation to work. The values.yaml file looks like this:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;---&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;antiAffinity&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;soft&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;esJavaOpts&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;-Xmx128m -Xms128m&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;#&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Allocate&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;smaller&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;chunks&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;memory&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;per&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pod&lt;/span&gt;.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;resources&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;requests&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;cpu&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;100m&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;memory&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;512M&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;limits&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;cpu&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;1000m&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;memory&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;512M&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Then we can &amp;#8220;preview&amp;#8221; what values are used for installation, with helm&amp;#8217;s template command:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm template elasticsearch elastic/elasticsearch -f values.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The effect of the antiAffinity property allows multiple Elasticsearch Pod to be scheduled on the same node. This is not required in production with multiple nodes. To install Elasticsearch and Kibana, run:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm install elasticsearch elastic/elasticsearch -f values.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm install kibana elastic/kibana&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The Kibana service is exposed on port 5601 of the cluster. To access the port on cluster, we need to run port-forward command as below:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl port-forward deployment/kibana-kibana &lt;span style="color:#ae81ff"&gt;5601&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 class="wp-block-heading" id="h-install-fluentd"&gt;Install Fluentd&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There are different ways to configure Fluentd. For example, in the forwarder-aggregator pattern, a forwarder Pod is a Daemonset on each Kubernetes node. The forwarder pushes to the aggregator, at port 24224. &lt;a href="https://docs.fluentd.org/deployment/high-availability"&gt;This&lt;/a&gt; page has some configuration details. This pattern is similar to filebeat -&amp;gt; logstash pattern in ELK stack.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In our case, we use a simplified pattern, with a fluentd daemonset acting as collector and then forward to Elasticsearch. Similarly, in ELK stack we can use filebeat to push to Elasticsearch without Logstash. The only reason is the entire architecture isn&amp;#8217;t as complicated as requiring an aggregator. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We need to create configmap as below:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ConfigMap&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;v1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;fluentd-cm&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;default&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;labels&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;app.kubernetes.io/component&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;forwarder&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;app.kubernetes.io/instance&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;fluentd&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;app.kubernetes.io/managed-by&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Helm&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;app.kubernetes.io/name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;fluentd&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;helm.sh/chart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;fluentd-1.3.0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;annotations&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;meta.helm.sh/release-name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;fluentd&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;meta.helm.sh/release-namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;default&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;data&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;fluentd.conf&lt;/span&gt;: |&lt;span style="color:#e6db74"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; # Ignore fluentd own events&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;match fluent.**&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; @type null&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;/match&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; # HTTP input for the liveness and readiness probes&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;source&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; @type http&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; port 9880&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;/source&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; # Throw the healthcheck to the standard output instead of forwarding it&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;match fluentd.healthcheck&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; @type null&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;/match&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; # Get the logs from the containers running in the node&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;source&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; @type tail&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; read_from_head true&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; tag kubernetes.*&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; path /var/log/containers/orthweb-postgresql-ha-postgresql-**.log&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; pos_file /opt/bitnami/fluentd/logs/buffers/fluentd-docker.pos&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;parse&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; @type regexp&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; expression ^(?&amp;lt;time&amp;gt;\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.[^Z]*Z)\s(?&amp;lt;stream&amp;gt;[^\s]+)\s(?&amp;lt;character&amp;gt;[^\s])\s(?&amp;lt;message&amp;gt;.*)$&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;/parse&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;/source&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; # enrich with kubernetes metadata&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;filter kubernetes.**&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; @type kubernetes_metadata&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; @id filter_kube_metadata&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; kubernetes_url &amp;#34;#{ENV[&amp;#39;FLUENT_FILTER_KUBERNETES_URL&amp;#39;] || &amp;#39;https://&amp;#39; + ENV.fetch(&amp;#39;KUBERNETES_SERVICE_HOST&amp;#39;) + &amp;#39;:&amp;#39; + ENV.fetch(&amp;#39;KUBERNETES_SERVICE_PORT&amp;#39;) + &amp;#39;/api&amp;#39;}&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; verify_ssl &amp;#34;#{ENV[&amp;#39;KUBERNETES_VERIFY_SSL&amp;#39;] || true}&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ca_file &amp;#34;#{ENV[&amp;#39;KUBERNETES_CA_FILE&amp;#39;]}&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; skip_labels &amp;#34;#{ENV[&amp;#39;FLUENT_KUBERNETES_METADATA_SKIP_LABELS&amp;#39;] || &amp;#39;false&amp;#39;}&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; skip_container_metadata &amp;#34;#{ENV[&amp;#39;FLUENT_KUBERNETES_METADATA_SKIP_CONTAINER_METADATA&amp;#39;] || &amp;#39;false&amp;#39;}&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; skip_master_url &amp;#34;#{ENV[&amp;#39;FLUENT_KUBERNETES_METADATA_SKIP_MASTER_URL&amp;#39;] || &amp;#39;false&amp;#39;}&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; skip_namespace_metadata &amp;#34;#{ENV[&amp;#39;FLUENT_KUBERNETES_METADATA_SKIP_NAMESPACE_METADATA&amp;#39;] || &amp;#39;false&amp;#39;}&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;/filter&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;match kubernetes.var.log.containers.orthweb-postgresql-ha-postgresql-**.log&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; @type elasticsearch&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; include_tag_key true&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; host &amp;#34;elasticsearch-master.default.svc.cluster.local&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; port &amp;#34;9200&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; index_name &amp;#34;postgresql-logs&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;buffer&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; @type file&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; path /opt/bitnami/fluentd/logs/buffers/orthanc-logs.buffer&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; flush_thread_count 2&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; flush_interval 5s&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;/buffer&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;lt;/match&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Then we can create the resource, with helm chart pointing to the config map:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm install fluentd bitnami/fluentd --set aggregator.enabled&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false --set forwarder.configMap&lt;span style="color:#f92672"&gt;=&lt;/span&gt;fluentd-cm&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;We can validate the index creation on Elasticsearch:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl port-forward service/elasticsearch-master 9200&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -XGET localhost:9200/_cat/indices&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;From Kibana, we can forward the port as instructed above, and browse to the UI. Once logged on to Kibana, we need to add index pattern first before being able to view the content of index.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-how-about-fluent-bit"&gt;How about Fluent Bit&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Fluentd has an even more lightweight brother Fluent Bit, also a CNCF project, designed by the same team, for environments with tighter resource restrictions. The technical differences are outlined on &lt;a href="https://docs.fluentbit.io/manual/about/fluentd-and-fluent-bit"&gt;this&lt;/a&gt; page outlines the technical differences. In terms of use case, Fluentd is a log aggregator and Fluent Bit is simply a forwarder. In terms of ecosystem, Fluentd has a stronger ecosystem whereas Fluent Bit is more seen in IoT devices. Read &lt;a href="https://logz.io/blog/fluentd-vs-fluent-bit/"&gt;this&lt;/a&gt; post for more comparison.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-summary"&gt;Summary&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;EFK stack (Elasticsearch, Fluentd and Kibana) on Kubernetes is a natural choice for ELK users. Fluentd is a CNCF project created for integration with Kubernetes. It is good alternative to enterprise solution such as &lt;a href="https://docs.fluentd.org/v/0.12/articles/free-alternative-to-splunk-by-fluentd"&gt;Splunk&lt;/a&gt;. There are lots of &lt;a href="https://docs.fluentd.org/input"&gt;plugins&lt;/a&gt; supported and &lt;a href="https://docs.fluentd.org/v/0.12/articles"&gt;articles&lt;/a&gt; on configuration. While developing a solution I had to spend time reading the &lt;a href="https://docs.fluentd.org/input"&gt;input plugin&lt;/a&gt; documentations. &lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2021/08/creating-tls-certificate-kubernetes/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Creating X.509 TLS certificate for workload on Kubernetes&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2021/09/single-node-kubernetes-cluster-minikube/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Local multi-node cluster – Minikube, MicroK8s and KinD&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Intro to Big Data Projects</title><link>https://static.digihunch.com/2020/09/intro-to-big-data-projects/</link><pubDate>Thu, 10 Sep 2020 21:33:00 -0400</pubDate><guid>https://static.digihunch.com/2020/09/intro-to-big-data-projects/</guid><description>&lt;p class="wp-block-paragraph"&gt;Modern applications produce super large datasets beyond what traditional data-processing application can handle. Big data is a discipline that specialize in processing such data. For example, analysis, information extraction etc. The scale of large dataset grows well beyond the capacity of a single computer, which calls for computing power delivered by multi-node clustered systems. Intensive computing tasks are completed in a distributed system consisting multiple nodes each performing some tasks, known as High-Performance Computing Cluster (HPCC).&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Cluster computing inherit the challenges of distributed system. Moreover, two main challenges to solve are: distributed storage, and distributed computation. In Apache Hadoop projects, HDFS and MapReduce address these two challenges respectively. Now the Hadoop ecosystem has evolved to include several core projects:&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;HDFS&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A distributed file system for reliably storing huge amount of unstructured, semi-structured or structured data in the form of files. Parts of a single large file can be stored on different nodes across the cluster. HDFS works in master-slave mode:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;NameNode (master): holds file system namespace, controls access, keep track of DataNodes and replication factor &lt;/li&gt;&lt;li&gt;DataNode (slave): stores user data&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;HDFS is Java-based so is portable across all platforms. User interact with HDFS using a command-line interface called &amp;#8220;FS shell&amp;#8221;. There is also an interface called FUSE (filesystem in userspace) to mount HDFS to Linux OS. Since HDFS supports commodity hardware it is great for storing data for further processing. However, HDFS is not suitable for storing data related to applications requiring low latency access, nor is it good for simultaneous writes to the same file. Also HDFS is not suitable for large number of small files because the metadata for each file needs to be stored on the NameNode and is held in memory. &lt;a href="https://hadoop.apache.org/docs/stable1/hdfs_design.html"&gt;Here&lt;/a&gt; is the architecture guide for HDFS, and this &lt;a href="https://data-flair.training/blogs/hadoop-hdfs-data-read-and-write-operations"&gt;page&lt;/a&gt; expands further on the read and write operations in HDFS.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Compared to NAS(e.g. NFS), HDFS is distributed by design. The data blocks are distributed across different nodes. NFS storage may or may not be distributed depending on the implementation. HDFS is designed to work with MapReduce paradigm, where computation is moved to the data. In NAS, data is stored separately from the computations. Lastly, NAS is usually made up of enterprise grade hard drive but HDFS works with commodity hardware.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;MapReduce&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Hadoop MapRecude is a distributed algorithm framework that allows parallel processing of huge amounts of data. It breaks a large chunk into smaller ones to be processed separately on different data nodes and automatically gather the results across the multiple nodes to return a single result. If the duration of linear data processing can be done during night hours, it makes sense to choose Hadoop MapReduce. MapReduce runs on Hadoop cluster but also supports other database formats like Cassandra and HBase. MapReduce includes:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;Job: a unit of work to be performed as requested by the client.&lt;/li&gt;&lt;li&gt;Task: Jobs are divided into sub-jobs known as tasks. The tasks can be run independent of each other on different nodes. There are two types of tasks: &lt;ul&gt;&lt;li&gt;Map task is performed by map() function to process one or more chunks of data and produce the output results&lt;/li&gt;&lt;li&gt;Reduce task is performed by reduce() function to consolidate the results produced by each of the map task&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;JobTracker: like the storage (HDFS), the computation (MapReduce) also works in master-slave fashion. A JobTracker node acts as the master to schedule task on appropriate nodes, coordinate execution of tasks, get the result back after execution of each task, re-execute failed tasks, and monitor overall progress. There is only one JobTracker node per Hadoop Cluster.&lt;/li&gt;&lt;li&gt;TaskTracker: a TaskTracker node acts as teh slave and is responsible for executing a task assigned to it by the JobTracker. There are usually a number of JobTracker nodes in a Hadoop Cluster. They execute the heavy lifting tasks.&lt;/li&gt;&lt;li&gt;Data Locality: if MapReduce cannot place the data and the compute on the same node, data locality put the compute on the node nearest to the respective data node(s) which contains the data to be processed.&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The MapReduce programming model includes these steps: input-&amp;gt;split-&amp;gt;map-&amp;gt;combine-&amp;gt;shuffle&amp;amp;sort-&amp;gt;reduce-&amp;gt;output.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://ars.els-cdn.com/content/image/3-s2.0-B9780128093931000064-f06-04-9780128093931.jpg?_" alt=""/&gt;&lt;figcaption&gt;MapReduce programming model&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;h3 class="wp-block-heading"&gt;YARN&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;YARN (yet another resource negotiator) is a system to schedule applications and services on an HDFS cluster and manage the cluster resources like memory and CPU. The two components are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;ResourceManager: receives the processing requests, and then passes the parts of requests to corresponding NodeManager accordingly based on the needs. ResourceManager is a central authority.&lt;/li&gt;&lt;li&gt;NodeManager: installed on every DataNode, is responsible for execution of the task on every single DataNode, monitoring the resource usage and reporting to the ResourceManager.&lt;/li&gt;&lt;/ul&gt;&#10;&lt;h3 class="wp-block-heading"&gt;HBase&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A key-value pair NoSQL database based on HDFS storage, with column family data representation, and mater-slave replication. HBase is based on Google&amp;#8217;s BigTable concept (similar to Cassandra). It runs on a cluster of commodity hardware and scales linearly. Compared with Cassandra, HBase doesn&amp;#8217;t have a query language of its own. You will have to work with JRuby-based shell, or Apache Hive. HBase is also a master-slave architecture and it uses Zookeeper as a status manager. In that sense, Cassandra is a &amp;#8220;self-sufficient&amp;#8221; database technology whereas HBase relies on other components in Hadoop. This &lt;a href="https://www.scnsoft.com/blog/cassandra-vs-hbase"&gt;article&lt;/a&gt; also compares the data model difference between the two.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Hive&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Hive is a SQL interface over MapReduce for developers and analysts who prefer SQL interface over native Java MapReduce programming to query and manage large datasets residing in HDFS. With Hive you can map a tabular structure on to data stored in distributed storage. The Hive queries are written in SQL-like language known as HiveQL, executed via MapReduce. When a HiveQL query is issued, it triggers a Map and/or Reduce job(s) to perform the operation defined in the query.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Pig&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A scripting interface over MapReduce for developers who prefer scripting interface over the native Java MapReduce programming. It is a runtime environment with a shell (named &lt;strong&gt;Grunt Shell&lt;/strong&gt;) for execution of MapReduce jobs via a high-level scripting language called Pig Latin. Pig is an abstraction (high-level programming language) on top of a Hadoop cluster. The Pig Latin query/command are complied into one or more MapReduce jobs and then executed on Hadoop cluster. The most common commands in Pig are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;DUMP: displays the results to screen&lt;/li&gt;&lt;li&gt;STORE: stores the results to HDFS&lt;/li&gt;&lt;/ul&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://2.bp.blogspot.com/-w7KeAnwWnBQ/WfYBJzgtvQI/AAAAAAAAAMk/D58SpZfK7lkJ8QnKnQZW268mKzRvuOOnACLcBGAs/s640/HadoopStack.png" alt="Apache Hadoop Ecosystem"/&gt;&lt;figcaption&gt;Hadoop Ecosystem&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There are some other Apache projects, which are sometimes considered as in the Hadoop ecosystem as well:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;&lt;strong&gt;Oozie&lt;/strong&gt;: worflow scheduling system to manage Hadoop jobs. In Oozie, a workflow is defined as a collection of control flow nodes and action nodes in a directed acyclic graph. Control flow nodes define the beginning and the end of a workflow, as well as a mechanism to control the workflow execution path. Action nodes are the mechanism by which a workkflow triggers the execution of a computation/processing task, such as MapReduce, Pig, etc.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Sqoop&lt;/strong&gt; (SQL-to-Hadoop): a command-line interpreter tool for importing data from database (e.g. MySQL, data warehouse, etc) into the Hadoop environment (e.g. HDFS, Hive). It can also export the data back.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Flume&lt;/strong&gt;: data ingestion for streaming logs into Hadoop environment. Flume is a distributed and reliable service for collecting and aggregating huge amounts of log data.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ZooKeeper&lt;/strong&gt;: distributed service coordinator, as previously &lt;a href="https://static.digihunch.com/2020/08/zookeeper/"&gt;discussed&lt;/a&gt;. It is based on a Paxos algorithm variant called ZAB protocol.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Ambari&lt;/strong&gt;: a framework for provisioning, managing and monitoring Hadoop clusters.&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Hortonworks &lt;a href="https://www.cloudera.com/downloads/hortonworks-sandbox.html"&gt;sandbox&lt;/a&gt; provide a VM image that have some Hadoop services pre-installed for beginners to get a taste of how it works all together.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Spark&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Hadoop is used in the industry owing to a simple programming model (MapReduce) but the speed and waiting time (between queries and running the program). Spark is introduced to speed up the computing process. Spark uses Hadoop for storage (HDFS) and processing. It extends the MapReduce model to efficiently use more types of computations which includes interactive queries and stream processing. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Spark started as a sub-project of Hadoop in 2009 but since 2014 Apache has run it as a top-level project. It is a lightning-fast in-memory cluster computing technology. The features are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;Speed: in-memory computing makes super fast processing;&lt;/li&gt;&lt;li&gt;Built-in APIs supports multiple languages: Scala, Python and Java;&lt;/li&gt;&lt;li&gt;Advanced analytics &amp;#8211; apart from map and reduce, Spark also has libraries that supports SQL query, near real-time stream processing, Graph algorithms and machine learning.&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Spark can run in &lt;a href="https://spark.apache.org/docs/latest/spark-standalone.html"&gt;standalone mode&lt;/a&gt;, on &lt;a href="https://spark.apache.org/docs/latest/running-on-mesos.html"&gt;Mesos&lt;/a&gt;, or with &lt;a href="https://spark.apache.org/docs/latest/running-on-yarn.html"&gt;YARN cluster manager&lt;/a&gt;. The document also provides guide on deployment on EC2 and &lt;a href="https://spark.apache.org/docs/latest/running-on-kubernetes.html"&gt;Kubernetes&lt;/a&gt;. Spark contains these components:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;Spark Core: the underlying general execution engine for spakr platform that all other functionality is built upon. It provides in-memory computing and referencing datasets in external storage systems.&lt;/li&gt;&lt;li&gt;SparkSQL: a components on top of Spark Core that introduces a new data abstraction called SchemaRDD, which supports both structured and semi-structured data.&lt;/li&gt;&lt;li&gt;Spark Streaming: perform streaming analytics on top of Spark Core. It ingests data in mini-batches and performs RDD (Resilient Distributed Datasets) transformation on the fly.&lt;/li&gt;&lt;li&gt;MLib: a distributed machine learning framework &lt;/li&gt;&lt;li&gt;GraphX: a distributed graph-processing framework&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The speed of Spark is owing to its fundamental data structure &amp;#8211; Resilient Distributed Datasets (RDD), an immutable distributed collection of objects. Each dataset in RDD (object collection) is divided into logical partitions, which can be computed on different nodes of the cluster. The object can be any type of Python, Java or Scala object, including user-defined classes. There are two ways to create RDDS:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;Parallelizing an existing collection in your driver program&lt;/li&gt;&lt;li&gt;Referencing a dataset from external storage system (e.g. HDFS, HBase) or data source offering a Hadoop Input Format&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;You can also create RDD based on other existing RDDs. This &lt;a href="https://www.tutorialspoint.com/apache_spark/apache_spark_rdd.htm"&gt;page&lt;/a&gt; explains further how RDD speeds up computing compared to MapReduce.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/09/host-legacy-application-with-docker-compose/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Host legacy application in Docker 1 of 2&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/09/spark-cassandra-and-python/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Spark, Cassandra and Python&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>AWS Certified DevOps Engineer Exam Tips</title><link>https://static.digihunch.com/2019/08/aws-certified-devops-engineer-exam-tips/</link><pubDate>Sat, 17 Aug 2019 23:07:59 -0400</pubDate><guid>https://static.digihunch.com/2019/08/aws-certified-devops-engineer-exam-tips/</guid><description>&lt;p class="wp-block-paragraph"&gt;The last 30 days have been exhausting for me. I studied hard on the new AWS Certified DevOps Engineer exam and thank goodness I passed (750 out of 1000 is required). This was the hardest professional certification I ever worked on. The exam was re-launched recently in March 2019 so there is still a shortage of information around the community. I was hoping to share my experience to help demystify this new exam. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I had a somewhat solid background to begin with, having taken the AWS Certified Solution Architect Professional exam (before the 2019 update), and worked quite a bit on CloudFormation, automation and Git. However, I still did not anticipate the exam to be this difficult until I was halfway through and already had the exam and materials paid for.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img loading="lazy" decoding="async" width="1469" height="518" src="https://static.digihunch.com/wp-content/uploads/2019/08/image.png" alt="" class="wp-image-127"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Without clear guideline on study material other than the white papers, I first skimmed through the ACloudGuru course, which helped me form a high level sense of exam coverage. Nonetheless it does not cover any topic in-depth and therefore by no means makes an essential part of my study. I checked out &lt;strong&gt;LinuxAcademy course&lt;/strong&gt; and they are much more in-depth for the major topics indeed. I like the course material in Lucid chart. However, the LinuxAcademy course along does not cover everything you need to know.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;What I found extremely helpful is the free training videos from the &lt;a href="https://www.aws.training"&gt;official training website&lt;/a&gt;. I strongly recommend the 7-hour course &lt;strong&gt;Exam Readiness: AWS Certified DevOps Engineer – Professional&lt;/strong&gt;. The instructor did a great job outlining the services and knowledge areas in the assessment . The course also comes with quality sample questions with answers and explanations on what the thinkings are behind the correct answers or why some choices are obviously wrong. I went through these questions twice and feel much better at not only understanding the question, but also understanding the intent of the question.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img loading="lazy" decoding="async" width="833" height="156" src="https://static.digihunch.com/wp-content/uploads/2019/08/image-1.png" alt="" class="wp-image-129"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Apart from the Exam Readiness course, other &lt;strong&gt;free introductory courses&lt;/strong&gt; from the official training website are helpful as well especially for those services that you only need to know the basics. Most of those courses are 5 ~ 10 minutes long, with brief but sufficient introduction and a demo session. The other extremely helpful resource is the &lt;strong&gt;official practice questions&lt;/strong&gt;. The practice exam is harder than the actual exam but they closely resemble the actual question style in the exam. Unfortunately, no answer is provided but they made me spend time finding answers across the documentations and blogs. It is worth-noting that the AWS blogs provides plenty of use cases that are covered in the questions.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When it comes to the real exam, it covers a lot more topics than its predecessor. Many questions are long and confusing. And I wish I could run a diff command to highlight the differences between choices. During exam preparation you really need to train yourself on reading efficiently. I found myself sometimes eyeball through all four choices at the same time, which get my mind scattered.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;During my study, I divide all services into three categories based on the level of familiarity, and here is my list:&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Category 1. Know these services very well, in and out:&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;AWS ElasticBeanstalk, OpsWorks Stacks, OpsWorks Chef Automate, CloudFormation, CloudWatch, CodeBuild, CodeCommit, CodeDeploy, CodePipeline, CodeStar, Lambda, API Gateway, Config, Trusted Advisor, CloudTrail, Systems Manager, Autoscaling Group in EC2, DynamoDB&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Category 2. Know these services well, but not necessarily down to every single detail:&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Amazon Kinesis Firehose, Kinesis Analytics, Kinesis Streams, Step Functions, Elastic Load Balancer, Secrets Manager, Serverless Application Model (SAM), Route53, RDS, Certificate Manager, ElasticSearch, ECS, ECR&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Category 3. Know about these services at a high level, but do not skip any:&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;AWS Organization, X-Ray, GuardDuty, Macie, Inspector, Service Catalog, KMS, Batch, Athena, Single-Sign-On, Data LifeCycle Manager, CloudSearch, Health Dashboard, Glue, QuickSight, LightSail&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Although I did not mention much about the white papers, I want to highlight their importance again. I would not attempt the exam without reading and understanding the required white papers. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;If you aspire to take the AWS certified DevOps Engineer exam I hope this helps you a little bit. Good luck.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2019/07/storage-nitty-gritty-3-of-5-nas-and-object-storage/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Storage Nitty-Gritty 3 of 5 – NAS and Object Storage&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2019/09/cryptographic-concepts-for-busy-it-professionals-2-of-2/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Cryptography basics 2 of 2&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Log shipping through ELK</title><link>https://static.digihunch.com/2018/09/log-shipping-through-elk/</link><pubDate>Wed, 19 Sep 2018 17:26:51 -0400</pubDate><guid>https://static.digihunch.com/2018/09/log-shipping-through-elk/</guid><description>&lt;p class="wp-block-paragraph"&gt;A common devops task is build logging pipeline with ELK stack (Elasticsearch, Logstash, Kibana). Suppose the application is written in Java and currently use log4j&amp;#8217;s RollingFileAppender to generate log files locally. We can use log4j&amp;#8217;s socket appender to write to Logstash, which further pushes the log stream to Elasticsearch cluster. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In this model, failure to push a log line results in the following in log4j output:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2018-09-06 11:05:39,778,ERROR,stderr - [AsyncAppender-Dispatcher-Thread-672] log4j:WARN Detected problem with connection: java.net.SocketException: Broken pipe (Write failed)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The logstash log displays the socket exception as well:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[2018-09-06T10:12:21,935][DEBUG][logstash.inputs.log4j ] Accepted connection {:client=&amp;gt;&amp;#34;192.168.111.56:58118&amp;#34;, :server=&amp;gt;&amp;#34;0.0.0.0:4560&amp;#34;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[2018-09-06T10:12:21,963][DEBUG][logstash.pipeline ] filter received {&amp;#34;event&amp;#34;=&amp;gt;{&amp;#34;method&amp;#34;=&amp;gt;&amp;#34;?&amp;#34;, &amp;#34;thread&amp;#34;=&amp;gt;&amp;#34;676774870@qtp-1804103302-6&amp;#34;, &amp;#34;message&amp;#34;=&amp;gt;&amp;#34;Unable to resolve session ID from SessionKey [org.apache.shiro.web.session.mgt.WebSessionKey@71da9a4]. Returning null to indicate a session could not be found.&amp;#34;, &amp;#34;priority&amp;#34;=&amp;gt;&amp;#34;DEBUG&amp;#34;, &amp;#34;type&amp;#34;=&amp;gt;&amp;#34;log4j&amp;#34;, &amp;#34;path&amp;#34;=&amp;gt;&amp;#34;org.apache.shiro.session.mgt.DefaultSessionManager&amp;#34;, &amp;#34;@timestamp&amp;#34;=&amp;gt;2018-09-06T15:12:21.950Z, &amp;#34;file&amp;#34;=&amp;gt;&amp;#34;?:?&amp;#34;, &amp;#34;@version&amp;#34;=&amp;gt;&amp;#34;1&amp;#34;, &amp;#34;host&amp;#34;=&amp;gt;&amp;#34;192.168.111.56:58118&amp;#34;, &amp;#34;logger_name&amp;#34;=&amp;gt;&amp;#34;org.apache.shiro.session.mgt.DefaultSessionManager&amp;#34;, &amp;#34;class&amp;#34;=&amp;gt;&amp;#34;?&amp;#34;, &amp;#34;timestamp&amp;#34;=&amp;gt;1536246741950}}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[2018-09-06T10:12:21,963][DEBUG][logstash.pipeline ] output received {&amp;#34;event&amp;#34;=&amp;gt;{&amp;#34;method&amp;#34;=&amp;gt;&amp;#34;?&amp;#34;, &amp;#34;thread&amp;#34;=&amp;gt;&amp;#34;676774870@qtp-1804103302-6&amp;#34;, &amp;#34;message&amp;#34;=&amp;gt;&amp;#34;Unable to resolve session ID from SessionKey [org.apache.shiro.web.session.mgt.WebSessionKey@71da9a4]. Returning null to indicate a session could not be found.&amp;#34;, &amp;#34;priority&amp;#34;=&amp;gt;&amp;#34;DEBUG&amp;#34;, &amp;#34;type&amp;#34;=&amp;gt;&amp;#34;log4j&amp;#34;, &amp;#34;path&amp;#34;=&amp;gt;&amp;#34;org.apache.shiro.session.mgt.DefaultSessionManager&amp;#34;, &amp;#34;@timestamp&amp;#34;=&amp;gt;2018-09-06T15:12:21.950Z, &amp;#34;file&amp;#34;=&amp;gt;&amp;#34;?:?&amp;#34;, &amp;#34;@version&amp;#34;=&amp;gt;&amp;#34;1&amp;#34;, &amp;#34;host&amp;#34;=&amp;gt;&amp;#34;192.168.111.56:58118&amp;#34;, &amp;#34;logger_name&amp;#34;=&amp;gt;&amp;#34;org.apache.shiro.session.mgt.DefaultSessionManager&amp;#34;, &amp;#34;class&amp;#34;=&amp;gt;&amp;#34;?&amp;#34;, &amp;#34;timestamp&amp;#34;=&amp;gt;1536246741950}}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[2018-09-06T10:12:22,041][DEBUG][logstash.inputs.log4j ] Closing connection {:client=&amp;gt;&amp;#34;192.168.111.56:58118&amp;#34;, :exception=&amp;gt;java.io.InvalidObjectException: Object type java.util.Hashtable is not allowed.}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The troubleshooting isn&amp;#8217;t very straightforward. So its alternative is preferred. The alternative is to keep the existing RollingFileAppender as well as the local log files, but use a filebeat agent for each application node. Here is the diagram:&lt;/p&gt;&#10;&lt;figure class="wp-block-image is-style-default"&gt;&lt;img decoding="async" src="https://miro.medium.com/max/960/1*AZPJdp8V82H6t7Vbu68_Ig.png" alt="Log Analysis Pipelines in Elastic Stack | by Thejan Rupasinghe | Medium"/&gt;&lt;figcaption&gt;ELK Log Shipping Pipeline&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;ol class="wp-block-list"&gt;&lt;li&gt;Filebeat is a very light agent to be installed with the application on the same server or container. &lt;/li&gt;&lt;li&gt;Streams of text information congregate to logstash nodes. These log stash service pushes the converged stream to ElasticSearch cluster&lt;/li&gt;&lt;li&gt;ElasticSearch cluster ingest the stream for indexing&lt;/li&gt;&lt;li&gt;Kibana is responsible for viewing. &lt;/li&gt;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This is an example architecture with many potential variations. For example, log stash service may be deployed on the same hosts with ElasticSearch cluster. If there aren&amp;#8217;t many application nodes, filebeat may directly push its output to ElasticSearch. This architecture provides a lot of flexibility and scalability.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With log4j format, two challenges to address are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;identifying multi-line entry in the log&lt;/li&gt;&lt;li&gt;mapping sections of a log entry into fields in Elastisearch&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For example, the following log entry reflects both challenges above:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2018-09-06 11:52:18,022,DEBUG,service.dataportal.web.retrieve - [687285925@qtp-564051174-3350] creating streaming output request 9868594 and requid=fb9a2cad-e24b-4eb8-ad62-b027184e7b9b&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2018-09-06 11:52:18,054,ERROR,org.glassfish.jersey.server.ServerRuntime$Responder - [687285925@qtp-564051174-3350] An I/O error has occurred while writing a re&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sponse message entity to the container output stream.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;org.glassfish.jersey.server.internal.process.MappableException: org.mortbay.jetty.EofException&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:91)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:163)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1135)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:662)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:395)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:385)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:280)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.internal.Errors$1.call(Errors.java:272)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.internal.Errors$1.call(Errors.java:268)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.internal.Errors.process(Errors.java:316)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.internal.Errors.process(Errors.java:298)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.internal.Errors.process(Errors.java:268)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:289)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:256)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:703)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:416)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:370)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:389)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:342)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:229)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:390)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.handler.HandlerList.handle(HandlerList.java:49)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.handler.RequestLogHandler.handle(RequestLogHandler.java:49)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.Server.handle(Server.java:326)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:926)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:549)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Caused by: org.mortbay.jetty.EofException&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.HttpGenerator.flush(HttpGenerator.java:789)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.AbstractGenerator$Output.flush(AbstractGenerator.java:568)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.HttpConnection$Output.flush(HttpConnection.java:1010)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.servlet.internal.ResponseWriter$NonCloseableOutputStreamWrapper.flush(ResponseWriter.java:330)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.message.internal.CommittingOutputStream.flush(CommittingOutputStream.java:287)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$UnCloseableOutputStream.flush(WriterInterceptorExecutor.java:305)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.message.internal.StreamingOutputProvider.writeTo(StreamingOutputProvider.java:79)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.message.internal.StreamingOutputProvider.writeTo(StreamingOutputProvider.java:61)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:266)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:251)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:163)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.java:109)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:163)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.spi.ContentEncoder.aroundWriteTo(ContentEncoder.java:137)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:163)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:85)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ... 40 more&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Caused by: java.net.SocketException: Broken pipe (Write failed)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at java.net.SocketOutputStream.socketWrite0(Native Method)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at java.net.SocketOutputStream.write(SocketOutputStream.java:155)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.io.ByteArrayBuffer.writeTo(ByteArrayBuffer.java:368)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.io.bio.StreamEndPoint.flush(StreamEndPoint.java:122)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org.mortbay.jetty.HttpGenerator.flush(HttpGenerator.java:723)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ... 58 more&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;To address multi-line entry we need to tell filebeat how to identify the start of a line through its multiline.pattern configuration option:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- type: log&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; enabled: true&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; paths:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - /var/log/dhunch/app.log&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; multiline.pattern: &amp;#39;^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3}&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; multiline.negate: true&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; multiline.match: after&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fields:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; product:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: dhunchapp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; log:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; type: app_log&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; content: diagnostic&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;When filebeat pushes log entries to logstash, there will be an additional &amp;#8220;time&amp;#8221; column added, which reflects the time the log is ingested. The entire log4j message line is all put in a single field called &amp;#8220;message&amp;#8221;, this message field contains the timestamp from application, the thread, class, logging level and the actual diagnostic message. These are not mapped to separate sections making it difficult to search in Elasticsearch.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To address section mapping, the configuration is made on the logstash side. We will take advantage of a plugin called &lt;a href="https://www.elastic.co/guide/en/logstash/current/plugins-filters-grok.html"&gt;grok filter&lt;/a&gt;. The function of grok filter here, is to parse the original &amp;#8220;message&amp;#8221; field, map different sections into separate columns, respectively called logtime, loglevel, logclass, logthread and logmsg. The grok filter expression is as below:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;filter {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; grok {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; match =&amp;gt; { &amp;#34;message&amp;#34; =&amp;gt; &amp;#34;%{TIMESTAMP_ISO8601:logtime},%{LOGLEVEL:loglevel},%{NOTSPACE:logclass} - \[%{DATA:logthread}\] %{GREEDYDATA:logmsg}&amp;#34; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; date {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; match =&amp;gt; [ &amp;#34;logtime&amp;#34; , &amp;#34;yyyy-MM-dd HH:mm:ss,SSS&amp;#34; ]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; timezone =&amp;gt; &amp;#34;America/Chicago&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; target =&amp;gt; &amp;#34;@timestamp&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mutate {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; replace =&amp;gt; [ &amp;#34;message&amp;#34; , &amp;#34;%{logmsg}&amp;#34; ]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mutate {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; remove_field =&amp;gt; [ &amp;#34;logmsg&amp;#34; ]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The date plugin indicates to Elasticsearch to treat this field as datetime with specified time zone. The mutate plugin below essentially renames the &amp;#8220;logmsg&amp;#8221; column to &amp;#8220;message&amp;#8221;, which allows Elasticsearch to understand this field as log message.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2018/07/overview-of-vsphere/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;A review of vSphere virtualization technologies&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2018/10/redhat-firewall-configuration-firewalld-vs-iptables/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Redhat Firewall configuration: from iptables to firewalld&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>