You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: observe/examples/el-shippy/article.md
+43-11
Original file line number
Diff line number
Diff line change
@@ -5,13 +5,15 @@ status: complete
5
5
6
6
# Advanced Docker Logs with Filebeat and Elasticsearch
7
7
8
-
Elastic stack is one of the most robust observability systems out there. Application logs are most likely to be handled by docker. The most intuitive way to connect them I've found is Filebeat. So in this article, we will try to fire up a complete stack, that allows the export of logs from docker to elasticsearch in a manner that will lay a simple yet powerful foundation of an observability solution. So, start the beat!
8
+
If we want to track what is going on in a system we will probably start by connecting application logs to an observability stack. Our application logs most likely already reside in docker and if we aim for the most robust technology we'll probably go with elastic stack. The challenge then is to connect those two. I suggest we'll use Filebeat for that.
9
+
10
+
So in this article, we will fire up a complete stack, exporting logs from docker to elasticsearch, building a simple yet powerful foundation of an observability solution. So, start the beat!
9
11
10
12

11
13
12
14
## Firing up the foundations
13
15
14
-
Deploying and connecting all the basic components is a twisted task even in the most basic setup. Therefore, in my [previous article]() I've talked in depth about the basic setup. This time we'll start from what we got there. If something in the setup wouldn't make sense, feel free to refer to the [old piece](). Anyway, here's the initial setup we got:
16
+
We'll start with a basic setup, firing up `elasticsearch`, `kibana`, and `filebeat`, configured in a separate file `filebeat.yml`. Check the configuration below and if something doesn't make sense please refer to [the previous article](https://medium.com/p/ebe75fd13041), explaining the basics. I'll meet you here.
15
17
16
18
`compose.yaml`
17
19
@@ -38,7 +40,7 @@ services:
38
40
- /var/run/docker.sock:/var/run/docker.sock
39
41
```
40
42
41
-
`filebeat.yaml`
43
+
`filebeat.yml`
42
44
43
45
```yaml
44
46
filebeat.inputs:
@@ -56,7 +58,7 @@ output.elasticsearch:
56
58
- index: "docker-logs"
57
59
```
58
60
59
-
Which produces logs looking something like this:
61
+
This setup produces logs looking something like this:
60
62
61
63
```json
62
64
{
@@ -151,7 +153,7 @@ Which produces logs looking something like this:
151
153
152
154
## Indexing the logs right
153
155
154
-
There are a few unsatisfying things about the current log. First of all, logs from all containers end up in a single elasticsearch "index" - which is roughly analogous to a table in a relational database. This prevents us from using an index pattern for really anything useful. Let's fix this! Here are some ideas of what we may want to know from the index names:
156
+
There are a few unsatisfying things about the log above. First of all, logs from all containers end up in a single elasticsearch "index" - which is roughly analogous to a table in a relational database. This prevents us from using indexes for really anything useful. Let's fix this! Here are some ideas of what we may want to know from the index names:
155
157
156
158
- **Service that produced the log**. So that we can see logs produced by a particular service. `container.name` seems to suit the purpose the best. It does append an instance index (`-1`), but we just need to keep that in mind when creating an index pattern.
157
159
- **Type/Family of service that produced the log**. Let's say we have a few services that produce similar logs e.g. HTTP API services. If we want to get a holistic view of their performance we would need to be able to filter them by some common index pattern. We can use docker labels to identify such services. Let's call the label `family`
@@ -186,9 +188,9 @@ Let's also give a family to just one of our containers. Let's for example give `
186
188
- 5601:5601
187
189
```
188
190
189
-
With that, we'll be able to see all `ui` family logs using `docker-logs-ui-*` pattern, all `elasticsearch` service logs using `*-elasticsearch-*`, and so on.
191
+
With that, we'll be able to see all `ui` family logs using `docker-logs-ui-*` index pattern, all `elasticsearch` service logs using `*-elasticsearch-*`, and so on.
190
192
191
-
## Getting the important stuff
193
+
## Getting Only the Important Stuff
192
194
193
195
You may notice, that all our deployed services produce not just text logs, but JSON. This is probably the most powerful ability of our stack: structured logging. What that means is that we can extract fields from the message JSON and use them for almost any analytics we can think of. This is enabled by the processor, called `decode_json_fields`. We'll decode JSON from the `message` field into the document root (`""`) for simplicity's sake. Here's the configuration snippet:
194
196
@@ -213,9 +215,7 @@ The regular expression for that will be `container\.labels\..*_.*`. Agent inform
213
215
ignore_missing: true
214
216
```
215
217
216
-
## Let's wrap it up!
217
-
218
-
Here's an example of the log we get now:
218
+
Giving us logs looking like this:
219
219
220
220
```json
221
221
{
@@ -266,7 +266,9 @@ Here's an example of the log we get now:
266
266
}
267
267
```
268
268
269
-
Although the record is huge now it contains supposedly useful data from the actual log message, instead of mostly pointless docker metadata. Here's how `compose.yaml` and `filebeat.yml` look after the changes we made:
269
+
## Wrapping It Up!
270
+
271
+
Although the record is still pretty big now it contains supposedly useful data from the actual log message, instead of mostly pointless docker metadata. Here's how `compose.yaml` and `filebeat.yml` look after the changes we made:
270
272
271
273
```yaml
272
274
services:
@@ -323,4 +325,34 @@ output.elasticsearch:
323
325
324
326
With that setup we export structured logs to Elasticsearch, allowing the creation of any metric we could possibly imagine from the supplied logs. Beyond that, we can now create various index patterns for a bunch of possible use cases. As the cherry on top, we cleaned up our logs from useless metadata.
325
327
328
+
## Or simply...
329
+
330
+
If you don't want to carry the `filebeat.yml` around I have one more thing for you! I've made a docker image, which includes a [similar configuration file]() just with some additional perks. I called the image `el-shof` (`shippy` as it ships logs and connected to docker i.e. ship and `el` from `elastic`). Here's the `compose.yml` file that will solely deploy about the same stack as the two files above:
331
+
332
+
```yaml
333
+
services:
334
+
elasticsearch:
335
+
image: elasticsearch:7.17.3
336
+
environment:
337
+
- discovery.type=single-node
338
+
339
+
kibana:
340
+
image: kibana:7.17.3
341
+
labels:
342
+
- family=ui
343
+
environment:
344
+
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
345
+
ports:
346
+
- 5601:5601
347
+
348
+
shipper:
349
+
image: vosarat/el-shippy
350
+
user: root
351
+
environment:
352
+
- ES_HOSTS=elasticsearch:9200
353
+
volumes:
354
+
- /var/lib/docker:/var/lib/docker:ro
355
+
- /var/run/docker.sock:/var/run/docker.sock
356
+
```
357
+
326
358
Thank you for reading! By the way... claps are appreciated 👉👈
0 commit comments