ELK日志分析平台的运维

在上一节中,我们在日志文件中增加了调用链信息,方便我们追踪每一次调用的完整关系链条。

尽管有了追踪信息,可以更好地排查信息。但在微服务架构下,微服务众多,每个微服务又会启动若干个副本,日志文件的数量会随着文件系统迅速增加。

为了排查一个问题,我们可能要分别到十几个服务上打开几十个不同的文件,效率非常低下。

ELK就是在这种场景下营运而生的,ELK是一套数据分析套件,由Elasticsearch, Logstach, Kibana组成。在微服务架构的应用场景下,一般用来分析日志。

在ELK套件中:

  • Logstash负责从不同的微服务、不同的副本上收集日志文件,进行格式化。
  • Elasticsearch负责日志数据的存储、索引
  • Kibana提供了友好的数据可视化、分析界面

ELK套件流程图

在本节中,我们暂不接入微服务的日志,单纯探讨ELK套件的运维工作。

与之前类似,我们的ELK套件将运行在Kubernetes集群上。

Elasticsearch的运维

Elasticsearch是ELK套件的核心与中枢。我们首先来看一下它的运维工作。

Elasticsearch的索引需要持久化存储,我们首先声明Pv:

  1. apiVersion: v1
  2. kind: PersistentVolume
  3. metadata:
  4. name: pv031
  5. spec:
  6. storageClassName: standard
  7. accessModes:
  8. - ReadWriteOnce
  9. capacity:
  10. storage: 20Gi
  11. hostPath:
  12. path: /data/pv031/

然后创建一下这个pv:

  1. kubectl apply -f ./pvs.yaml

下面看一下elasticserch的定义:

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: es
  5. spec:
  6. ports:
  7. - name: p2
  8. port: 9200
  9. - name: p3
  10. port: 9300
  11. selector:
  12. app: elasticsearch
  13. clusterIP: None
  14. ---
  15. apiVersion: apps/v1
  16. kind: StatefulSet
  17. metadata:
  18. name: elasticsearch
  19. spec:
  20. selector:
  21. matchLabels:
  22. app: elasticsearch
  23. serviceName: "es"
  24. replicas: 1
  25. template:
  26. metadata:
  27. labels:
  28. app: elasticsearch
  29. spec:
  30. hostname: elasticsearch
  31. containers:
  32. - name: elasticsearch-ct
  33. image: docker.elastic.co/elasticsearch/elasticsearch:6.3.1
  34. ports:
  35. - containerPort: 9200
  36. - containerPort: 9300
  37. env:
  38. - name: "ES_JAVA_OPTS"
  39. value: "-Xms384m -Xmx384m"
  40. volumeMounts:
  41. - mountPath: /usr/share/elasticsearch/data
  42. name: elasticsearch-pvc
  43. volumeClaimTemplates:
  44. - metadata:
  45. name: elasticsearch-pvc
  46. spec:
  47. storageClassName: standard
  48. accessModes:
  49. - ReadWriteOnce
  50. resources:
  51. requests:
  52. storage: 20Gi

如上所述:

  • 考虑到日志数据量大了之后,可能需要分片,我们这里采用了StatefulSet,但目前只有一台服务器。
  • 暴露两个端口9200和9300,前者是Restful接口,后者是集群同步接口
  • 采用IP直发,service伪组名是”es”。这样配置后,所有Pod都可以通过elasticsearch-0.es来直接访问这台服务器

启动一下:

  1. kubctl apply -f ./elasticsearch.yaml

如果启动失败,可以查看日志,可能是如下原因:

  1. kubectl logs elasticsearch-0
  2. ...
  3. vm.max_map_count < 262144
  4. ...

这种情况,可以使用具有sudo权限的帐号,更改宿主机(物理机)的配置:

  1. sudo sysctl -w vm.max_map_count=262144

再次启动一下,可以发现启动成功:

  1. NAME READY STATUS RESTARTS AGE
  2. elasticsearch-0 1/1 Running 4 6h

Logstash运维

在启动了Elasticsearch后,我们来看一下Logstash的运维。

前面已经提到了,我们本节先不会接入Spring Boot的日志,为了方便演示,我们先Mock一个定时任务,每间隔5秒生成日志:

  1. apiVersion: v1
  2. data:
  3. logstash.yml: |
  4. http.host: "0.0.0.0"
  5. xpack.monitoring.elasticsearch.url: http://elasticsearch:9200
  6. input {
  7. heartbeat {
  8. interval => 5
  9. message => 'Hello from Logstash 💓'
  10. }
  11. }
  12. output {
  13. elasticsearch {
  14. hosts => [ 'elasticsearch-0.es' ]
  15. user => 'elastic'
  16. password => ''
  17. }
  18. }
  19. kind: ConfigMap
  20. metadata:
  21. name: logstash-configmap

上述是一个ConfigMap,我们在本书中是第一次使用它。它相当于一个可以加载的Volume,可以方便的直接追加到Pod上。

来创建这个ConfigMap:

  1. kubectl apply -f logstash-configmap.yaml

下面看一下Logstash的部署:

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: ls
  5. spec:
  6. ports:
  7. - name: p
  8. port: 5000
  9. selector:
  10. app: logstash
  11. clusterIP: None
  12. ---
  13. apiVersion: apps/v1
  14. kind: StatefulSet
  15. metadata:
  16. name: logstash
  17. spec:
  18. selector:
  19. matchLabels:
  20. app: logstash
  21. serviceName: "ls"
  22. replicas: 1
  23. template:
  24. metadata:
  25. labels:
  26. app: logstash
  27. spec:
  28. hostname: logstash
  29. containers:
  30. - name: logstash-ct
  31. image: docker.elastic.co/logstash/logstash:6.3.1
  32. ports:
  33. - containerPort: 5000
  34. env:
  35. - name: "ES_JAVA_OPTS"
  36. value: "-Xms384m -Xmx384m"
  37. - name: "XPACK_MONITORING_ENABLED"
  38. value: "false"
  39. - name: "XPACK_MONITORING_ELASTICSEARCH_URL"
  40. value: "http://elasticsearch-0.es:9200"
  41. volumeMounts:
  42. - name: logstash-configmap
  43. mountPath: /usr/share/logstash/pipeline/logstash.conf
  44. subPath: logstash.conf
  45. volumes:
  46. - name: logstash-configmap
  47. configMap:
  48. name: logstash-configmap

如上所述:

  • 我们使用了刚才配置的logstash-configmap,并覆盖到Pod的/usr/share/logstash/pipeline/logstash.conf,这个文件中
  • 监控地址是elasticsearch-0.es:9200,即前面启动的es服务地址

启动一下:

  1. kubectl apply -f ./logstash.yaml

稍等一会,启动成功:

  1. NAME READY STATUS RESTARTS AGE
  2. logstash-0 1/1 Running 0 7h

Kibana的运维

最后,我们来看一下Kibana的运维:

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: kb
  5. spec:
  6. selector:
  7. app: kibana
  8. clusterIP: None
  9. ---
  10. apiVersion: apps/v1
  11. kind: Deployment
  12. metadata:
  13. name: kibana
  14. spec:
  15. selector:
  16. matchLabels:
  17. app: kibana
  18. replicas: 1
  19. template:
  20. metadata:
  21. labels:
  22. app: kibana
  23. spec:
  24. hostname: kibana
  25. containers:
  26. - name: kibana-ct
  27. image: docker.elastic.co/kibana/kibana:6.3.1
  28. ports:
  29. - containerPort: 5601
  30. hostPort: 5601
  31. env:
  32. - name: "ES_JAVA_OPTS"
  33. value: "-Xms384m -Xmx384m"
  34. - name: "ELASTICSEARCH_URL"
  35. value: "http://elasticsearch-0.es:9200"
  36. - name: "XPACK_MONITORING_ENABLED"
  37. value: "false"

一般来说,Kibana作为前端展示组件,只需要一台就够了,我们直接用了Deployment。

尝试打开浏览器访问一下:

Kibana界面图

如果一切顺利,可以发现,访问成功。

对于新一些的ElasticSearch/Kibana版本,可能需要先配置一下索引,比较简单,跟着向导就可以完成。

Kibana的功能非常强大,拿来做日志分析实际有点大材小用。感兴趣的话,可以参考官方使用教程

我们对ELK的运维就介绍到这里。