k8s pod日志写入ELK的具体实现

shigen坚持更新文章的博客写手,擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长,分享认知,留住感动。

在上一部分,shigen讲到了k8spod的日志写入ELK的三种技术方案,并在最后展示了一下我实现的效果,那具体的怎么实现呢?今天这一篇文章我们具体的展示一下,先带大家回顾一下上篇文章的效果:

上一篇的地址shigen会在文章末尾贴出,今天的文章主要是讲解它的集体实现。

ELK的搭建

当我们搭建好了ELK集群之后,需要着重的修改一下logstash的配置文件logstash/pipeline/logstash.conf:

ini 复制代码
   input {
     tcp {
         mode => "server"
         host => "0.0.0.0"    
         port => 50000
         codec => json_lines
     }
   }
   output {
     elasticsearch {
       hosts => "elasticsearch:9200"       #es地址
       index => "springboot-logstash-%{+YYYY.MM.dd}"           #写入的索引名
       user => "elastic"                   #es用户
       password => "123456"                #es密码
     }
     #logstash控制台输入采集到的数据,用于调试
     stdout {
         codec => rubydebug
     }
   }

这是shigen本次用到的配置文件,需要注意的是:

  • 约定TCP服务的端口是50000,需要在docker-compose中挂载到主机上
  • es的地址尽量使用内网或者k8s提供的svc,节省不必要的流量消耗
  • 需要安装插件 log stash-codec-json_lines 需要的时间老长了

配置完了启动即可。

搭建spring boot服务

基本的项目结构就不说了,用到了mybatis-plus作为ORM框架。我们现在需要的就是把项目的日志输出到logstash,让它处理完放到elasticsearch

配置日志文件

本次的日志框架shigen选取的是logback,它需要把日志写入到logstach,它的途径就是logstash提供的TCP端口。

在项目的resource目录下边新建文件logback-spring.xml文件,文件内容是这样的:

xml 复制代码
 <?xml version="1.0" encoding="UTF-8"?>
 ​
 <configuration>
     <!--指定property属性变量-->
     <property name="log.path" value="./logs/logback-demo"/>
     <property name="destination" value="127.0.0.1:50000"/>
     <property name="appname" value="logdemo"/>
 ​
     <!-- 日志输出格式
      %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
      -->
     <!-- 控制台 appender-->
     <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
         <encoder>
             <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
             <charset>UTF-8</charset>
         </encoder>
     </appender>
 ​
 ​
     <!-- 文件 滚动日志 (all)-->
     <appender name="allLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
         <!-- 当前日志输出路径、文件名 -->
         <file>${log.path}/all.log</file>
         <!--日志输出格式-->
         <encoder>
             <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
             <charset>UTF-8</charset>
         </encoder>
         <!--历史日志归档策略-->
         <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
             <!-- 历史日志: 归档文件名 -->
             <fileNamePattern>${log.path}/%d{yyyy-MM, aux}/all.%d{yyyy-MM-dd}.%i.log.gz
             </fileNamePattern>
             <!--单个文件的最大大小-->
             <maxFileSize>64MB</maxFileSize>
             <!--日志文件保留天数-->
             <maxHistory>15</maxHistory>
         </rollingPolicy>
     </appender>
 ​
 ​
     <!-- 文件 滚动日志 (仅error)-->
     <appender name="errorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
         <!-- 当前日志输出路径、文件名 -->
         <file>${log.path}/error.log</file>
         <!--日志输出格式-->
         <encoder>
             <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
             <charset>UTF-8</charset>
         </encoder>
 ​
         <!--历史日志归档策略-->
         <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
             <!-- 历史日志: 归档文件名 -->
             <fileNamePattern>${log.path}/%d{yyyy-MM, aux}/error.%d{yyyy-MM-dd}.%i.log.gz
             </fileNamePattern>
             <!--单个文件的最大大小-->
             <maxFileSize>64MB</maxFileSize>
             <!--日志文件保留天数-->
             <maxHistory>15</maxHistory>
         </rollingPolicy>
 ​
         <!-- 此日志文档只记录error级别的  level过滤器-->
         <filter class="ch.qos.logback.classic.filter.LevelFilter">
             <level>error</level>
             <onMatch>ACCEPT</onMatch>
             <onMismatch>DENY</onMismatch>
         </filter>
     </appender>
 ​
 ​
     <!-- 文件 异步日志(async) -->
     <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender"
         immediateFlush="false" neverBlock="true">
         <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
         <discardingThreshold>0</discardingThreshold>
         <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
         <queueSize>1024</queueSize>
         <neverBlock>true</neverBlock>
         <!-- 添加附加的appender,最多只能添加一个 -->
         <appender-ref ref="allLog"/>
     </appender>
 ​
 ​
     <!--输出到logstash的appender-->
     <appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
         <!--可以访问的logstash日志收集端口-->
         <destination>${destination}</destination>
         <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
             <!--自定义字段,区分应用名称-->
             <customFields>{"appname":"logdemo"}</customFields>
         </encoder>
     </appender>
 ​
 ​
     <!-- root 级别的配置 -->
     <root level="INFO">
         <appender-ref ref="CONSOLE"/>
         <appender-ref ref="ASYNC"/>
         <appender-ref ref="errorLog"/>
         <appender-ref ref="logstash"/>
     </root>
 ​
     <!--可输出mapper层sql语句等-->
     <logger name="com.gitee.shigen.logbackspringboot.mapper" level="debug"/>
 ​
     <!--输出jdbc 事务相关信息-->
     <logger name="org.springframework.jdbc" level="debug"/>
 ​
 </configuration>

注意到我们的其实是有四个目的地的,包括:控制台、文件、logstash以及我们的滚动策略和文件大小超过一定的指标之后的策略。

现在我们只需要启动服务,在kibana那边持续的观察:

和我们常见的都一样,输出了mybatis-plus查询的sql语句。我们再来看下kibana的界面,刚才我们的日志也展示出来了。而且字段很全,自动的帮我们处理了。

后记

也许我们还会存在这样的疑问:这是一个实例的,如果是多实例的,或者一个服务有多个副本怎么办呢?这个shigen考虑到了,我么可以自定义字段,在我的配置文件中有这个字段:

xml 复制代码
 <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
     <!--自定义字段,区分应用名称-->
     <customFields>{"appname":"logdemo"}</customFields>
 </encoder>

就可以标识出来,在es中也可以一个查询条件,查找相对应地服务日志。

现在还是本地启动,shigen也会持续输出在k8s上的服务日志,欢迎持续关注。


以上就是今天分享的全部内容了,觉得不错的话,记得点赞 在看 关注支持一下哈,您的鼓励和支持将是shigen坚持日更的动力。同时,shigen在多个平台都有文章的同步,也可以同步的浏览和订阅:

平台 账号 链接
CSDN shigen01 shigen的CSDN主页
知乎 gen-2019 shigen的知乎主页
掘金 shigen01 shigen的掘金主页
腾讯云开发者社区 shigen shigen的腾讯云开发者社区主页
微信公众平台 shigen 公众号名:shigen

shigen一起,每天不一样!

相关推荐
凡人的AI工具箱4 小时前
AI教你学Python 第11天 : 局部变量与全局变量
开发语言·人工智能·后端·python
是店小二呀4 小时前
【C++】C++ STL探索:Priority Queue与仿函数的深入解析
开发语言·c++·后端
canonical_entropy4 小时前
金蝶云苍穹的Extension与Nop平台的Delta的区别
后端·低代码·架构
我叫啥都行5 小时前
计算机基础知识复习9.7
运维·服务器·网络·笔记·后端
无名指的等待7125 小时前
SpringBoot中使用ElasticSearch
java·spring boot·后端
.生产的驴6 小时前
SpringBoot 消息队列RabbitMQ 消费者确认机制 失败重试机制
java·spring boot·分布式·后端·rabbitmq·java-rabbitmq
AskHarries6 小时前
Spring Boot利用dag加速Spring beans初始化
java·spring boot·后端
苹果酱05677 小时前
一文读懂SpringCLoud
java·开发语言·spring boot·后端·中间件
掐指一算乀缺钱7 小时前
SpringBoot 数据库表结构文档生成
java·数据库·spring boot·后端·spring
计算机学姐9 小时前
基于python+django+vue的影视推荐系统
开发语言·vue.js·后端·python·mysql·django·intellij-idea