1. 日志收集方式简介

官方文档:https://kubernetes.io/zh/docs/concepts/cluster-administration/logging/

(1)node节点收集
基于daemonset部署日志收集进程,实现json-file类型(标准输出/dev/stdout、错误输出/dev/stderr)日志收集;
该方式的优点:日志收集架构简单,易部署、易维护。
该方式的缺点:node节点产生的日志、路径、类型、日志内容都不同,很难做到把每个容器的日志都完整的处理好。


(2)边车模式
使用sidcar容器(一个pod多容器)收集当前pod内一个或者多个业务容器的日志(通常基于emptyDir实现业务容器与sidcar之间的日志共享)。
该方式的优点:对当前收集日志的pod能做更详细的处理,按照预定义规则处理好的日志,再输出到kafka或者filebeat。
该方式的缺点:性能可能没那么好,因为一个pod就需要一个sidecar,如果有100个pod,那就需要100个sidecar,那么这个日志收集的agent就必须选用一个轻量级的工具,不然会占用很多额外资源。


(3)在业务容器中内置日志收集服务进程。
就是除了业务容器,再另外起一个日志收集的进程。


一般公有云的话,第一种方式较多,能够更好的节约系统资源。

2. 日志收集示例一:daemonset收集日志(ELK)

2.1 介绍

基于daemonset运行日志收集服务,主要收集以下类型日志:
(1)node节点收集,基于daemonset部署日志收集进程,实现json-file类型(标准输出/dev/stdout、错误输出/dev/stderr)日志收集,即收集应用程序产生的标准输出和错误输出的日志。


(2)宿主机系统日志等以日志文件形式保存的日志。

2.2 不同容器运行时的日志路径

2.2.1 containerd

(1)日志存储路径
真实路径:/var/log/pods/$CONTAINER_NAMEs #真实路径
软连接:同时kubelet也会在/var/log/containers目录下创建软链接指向/var/log/pods/$CONTAINER_NAMEs

(2)日志配置参数
配置文件:
/etc/systemd/system/kubelet.service

配置参数:
- --container-log-max-files=5 \
--container-log-max-size="100Mi" \
--logging-format="json" 

2.2.2 docker

(1)日志存储路径
真实路径:/var/lib/docker/containers/$CONTAINERID
软连接:kubelet会在/var/log/pods和/var/log/containers创建软连接指向/var/lib/docker/containers/$CONTAINERID

(2)日志配置参数
配置文件:
/etc/docker/daemon.json

参数:
"log-driver": "json-file",
"log-opts": {
  "max-file": "5",
  "max-size": "100m"
}

2.3 daemonset日志收集架构

在这里插入图片描述

2.3.1 注意事项

首先要规划好pod日志输出方式,是标准输出,还是自定义路径。
因为如果是标准输出的话,路径相对固定,因为都是/dev/stdout、/dev/stderr。
如果是自定义路径的话,就得提前进行规划,以为不同的进程,默认情况下的日志输出路径是不同的。

2.4 环境准备

2.4.1 基础环境

(1)elasticsearch cluster
本次演示准备3台节点组成es集群。

  • zookeeper && kafka
    3个节点,部署zk和kafka


    (2)logsatsh
    准备2个节点。

  • kibana

2.5 二进制部署ES集群-7.12.1

安装包就是官网直接下载带jdk的就行,过程略

2.5.1 配置es01

[root@es01 ~]# ls
anaconda-ks.cfg  elasticsearch-7.12.1-linux-x86_64.tar.gz  update.sh
[root@es01 ~]# tar xf elasticsearch-7.12.1-linux-x86_64.tar.gz -C /opt

[root@es01 ~]# cd /opt/elasticsearch-7.12.1/
[root@es01 elasticsearch-7.12.1]# ls
bin  config  jdk  lib  LICENSE.txt  logs  modules  NOTICE.txt  plugins  README.asciidoc

# 修改配置文件
[root@es01 elasticsearch-7.12.1]# cd config  
[root@es01 config]# vim elasticsearch.yml
[root@es01 config]# grep -v "^#" elasticsearch.yml
cluster.name: myserver-cluster # 同一个集群中,不同节点的cluster.name相同
node.name: es01 # 同一个集群中,node.name不能相同
path.data: /data/es-data # 数据目录,可自定义
path.logs: /data/es-log # 日志目录,可自定义
network.host: 10.31.200.130 # 本机IP
http.port: 9200 # es端口
discovery.seed_hosts: ["10.31.200.130", "10.31.200.131","10.31.200.132"] # 服务发现
cluster.initial_master_nodes: ["10.31.200.130", "10.31.200.131","10.31.200.132"] # 可以参与选主的节点
action.destructive_requires_name: true # 通过api删除索引时,是否需要指定详细的索引名称。true为必须指定。

# 创建数据目录并授权
[root@es01 config]# mkdir -p /data/es-data /data/es-log
[root@es01 config]# useradd -s /sbin/nologin -M elasticsearch
[root@es01 config]# chown elasticsearch. -R /data/es-* /opt/elasticsearch-7.12.1
[root@es01 config]# ll /data/
总用量 4
drwxr-xr-x 2 elasticsearch elasticsearch    6 1123 16:31 es-data
drwxr-xr-x 2 elasticsearch elasticsearch 4096 1123 16:32 es-log

# 编辑启动脚本
[root@es01 es-log]# cat /etc/systemd/system/elasticsearch.service
[Unit]
Description=Elasticsearch
Documentation=https://www.elastic.co
Wants=network-online.target
After=network-online.target

[Service]
Environment=ES_HOME=/opt/elasticsearch-7.12.1/
Environment=ES_USER=elasticsearch
Environment=ES_GROUP=elasticsearch
ExecStart=/opt/elasticsearch-7.12.1/bin/elasticsearch
Restart=always
User=elasticsearch
LimitMEMLOCK=infinity
LimitNOFILE=65536
StandardOutput=journal
StandardError=journal
SyslogIdentifier=elasticsearch

[Install]
WantedBy=multi-user.target

# 调整虚拟内存区域数量,es默认需要262144
[root@es01 es-log]# cat /etc/sysctl.conf
vm.max_map_count = 262144

[root@es01 es-log]# sysctl -p
vm.max_map_count = 262144
[root@es01 es-log]# sysctl vm.max_map_count
vm.max_map_count = 262144

# 启动服务
[root@es01 es-log]# systemctl daemon-reload
[root@es01 es-log]# systemctl restart elasticsearch.service
[root@es01 es-log]# systemctl enable elasticsearch.service

[root@es01 es-log]# netstat -lntup|grep 9
tcp6       0      0 10.31.200.130:9200      :::*                    LISTEN      15501/java
tcp6       0      0 10.31.200.130:9300      :::*                    LISTEN      15501/java

2.5.2 配置es02

安装步骤一样,这里只展示配置文件

[root@es02 ~]# grep -v "^#" /opt/elasticsearch-7.12.1/config/elasticsearch.yml
cluster.name: myserver-cluster
node.name: es02
path.data: /data/es-data
path.logs: /data/es-log
network.host: 10.31.200.131
http.port: 9200
discovery.seed_hosts: ["10.31.200.130", "10.31.200.131","10.31.200.132"]
cluster.initial_master_nodes: ["10.31.200.130", "10.31.200.131","10.31.200.132"]
action.destructive_requires_name: true

2.5.3 配置es03

安装步骤一样,这里只展示配置文件

[root@es03 ~]# grep -v "^#" /opt/elasticsearch-7.12.1/config/elasticsearch.yml
cluster.name: myserver-cluster
node.name: es03
path.data: /data/es-data
path.logs: /data/es-log
network.host: 10.31.200.132
http.port: 9200
discovery.seed_hosts: ["10.31.200.130", "10.31.200.131","10.31.200.132"]
cluster.initial_master_nodes: ["10.31.200.130", "10.31.200.131","10.31.200.132"]
action.destructive_requires_name: true

2.5.4 验证集群状态

2.5.4.1 安装插件

我这样操作要翻墙,可以提前下载下来安装
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.5.4.2 连接集群

在这里插入图片描述
在这里插入图片描述

2.6 部署zk和kafka集群

2.6.1 二进制安装zk3.7.2

2.6.1.1 下载软件包

官网地址:https://zookeeper.apache.org/index.html

[root@es03 opt]# wget https://dlcdn.apache.org/zookeeper/zookeeper-3.7.2/apache-zookeeper-3.7.2-bin.tar.gz

[root@zk01 ~]# ll -h
-rw-r--r--  1 root root  14M Nov 24 22:46 apache-zookeeper-3.7.2-bin.tar.gz
2.6.1.2 查看3.7.2所需jdk版本

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.6.1.3 安装jdk8

所有节点操作相同

[root@zk01 ~]# yum -y install java
[root@zk01 ~]# java -version
openjdk version "1.8.0_392"
OpenJDK Runtime Environment (build 1.8.0_392-b08)
OpenJDK 64-Bit Server VM (build 25.392-b08, mixed mode)
2.6.1.4 解压并配置

所有节点操作相同

# 解压
[root@zk01 ~]# tar xf apache-zookeeper-3.7.2-bin.tar.gz -C /opt/
[root@zk01 ~]# cd /opt/
[root@zk01 opt]# ls
apache-zookeeper-3.7.2-bin

# 调整配置文件名称
[root@zk01 opt]# cd apache-zookeeper-3.7.2-bin/conf/
[root@zk01 conf]# ls
configuration.xsl  log4j.properties  zoo_sample.cfg
[root@zk01 conf]# cp zoo_sample.cfg zoo.cfg # 这就是zk的配置文件

# 修改配置
[root@zk01 conf]# grep -v "^#" zoo.cfg
# 默认配置
tickTime=2000

# 默认配置,如果10个2000(tickTime)毫秒后,集群还没有初始化成功,就认为失败
initLimit=10

# 集群创建好后,每隔5个2000毫秒进行一次探测,检查集群内的节点是否正常。如果检查失败就下线节点,然后开始重新选举
syncLimit=5

# zk数据目录,可自定义
dataDir=/data/zk-data

# 默认客户端端口
clientPort=2181

# 新增集群配置
server.1=10.31.200.133:2888:3888 # 1为集群id,需要手动生成
server.2=10.31.200.134:2888:3888 # 2为集群id,需要手动生成
server.3=10.31.200.135:2888:3888 # 3为集群id,需要手动生成


# 创建数据目录
[root@zk01 conf]# mkdir -p /data/zk-data

# 生成集群ID
[root@zk01 conf]# echo 1 >  /data/zk-data/myid
2.6.1.5 3个节点同时启动zk

这里3个节点一定要在initLimit内启动并初始化完毕

# 查看帮助
[root@zk01 conf]# ../bin/zkServer.sh
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/apache-zookeeper-3.7.2-bin/bin/../conf/zoo.cfg
Usage: ../bin/zkServer.sh [--config <conf-dir>] {start|start-foreground|stop|version|restart|status|print-cmd}

# 启动zk
[root@zk01 conf]# ../bin/zkServer.sh start
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/apache-zookeeper-3.7.2-bin/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
2.6.1.6 查看集群状态
[root@zk01 conf]# ../bin/zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/apache-zookeeper-3.7.2-bin/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower # 只要是follower 或者leader就说明集群部署完毕

2.6.2 二进制安装kafka2.6.2

2.6.2.1 下载并解压

所有节点操作相同

[root@zk01 ~]# wget https://archive.apache.org/dist/kafka/2.6.2/kafka_2.12-2.6.2.tgz

[root@zk01 ~]# tar xf kafka_2.12-2.6.2.tgz -C /opt/
[root@zk01 ~]# cd /opt/kafka_2.12-2.6.2/
[root@zk01 kafka_2.12-2.6.2]# ll
total 40
drwxr-xr-x 3 root root  4096 Apr  8  2021 bin
drwxr-xr-x 2 root root  4096 Apr  8  2021 config
drwxr-xr-x 2 root root  8192 Nov 26 13:20 libs
-rw-r--r-- 1 root root 14556 Apr  8  2021 LICENSE
drwxr-xr-x 2 root root   236 Apr  8  2021 licenses
-rw-r--r-- 1 root root   952 Apr  8  2021 NOTICE
drwxr-xr-x 2 root root    44 Apr  8  2021 site-docs
2.6.2.2 调整kafka配置文件

所有节点操作相同

[root@zk01 config]# vim server.properties
……省略部分默认配置,只展示修改的配置
# 每个节点唯一,不能相同
broker.id=133
# 监听地址,ip写宿主机的
listeners=PLAINTEXT://10.31.200.133:9092
# 日志目录,程序启动时会自动创建
log.dirs=/data/kafka-logs
# zk连接地址
zookeeper.connect=10.31.200.133:2181,10.31.200.134:2181,10.31.200.135:2181
# 连接超时时间
zookeeper.connection.timeout.ms=30000
2.6.2.3 启动kafka

所有节点操作相同

[root@zk01 config]# /opt/kafka_2.12-2.6.2/bin/kafka-server-start.sh -daemon /opt/kafka_2.12-2.6.2/config/server.properties

[root@zk01 logs]# netstat -lntup|grep 9092
tcp6       0      0 10.31.200.133:9092      :::*                    LISTEN      3637/java
2.6.3.4 连接kafka

客户端下载地址:https://www.kafkatool.com/

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2.7 k8s部署logstash收集pod日志(消息生产者)

2.7.1 相关配置

2.7.1.1 Dockerfile
[root@master1 1.logstash-image-Dockerfile]# cat Dockerfile
# 使用官方的镜像
FROM logstash:7.12.1

# 设置用户为root
USER root
# 定义工作目录
WORKDIR /usr/share/logstash
#RUN rm -rf config/logstash-sample.conf

# 替换容器中原有的配置文件
ADD logstash.yml /usr/share/logstash/config/logstash.yml
ADD logstash.conf /usr/share/logstash/pipeline/logstash.conf
2.7.1.2 logstash.yml
[root@master1 1.logstash-image-Dockerfile]# cat logstash.yml
http.host: "0.0.0.0" # 调整监听地址
#xpack.monitoring.elasticsearch.hosts: [ "http://elasticsearch:9200" ]

2.7.1.3 logstash.conf
[root@master1 1.logstash-image-Dockerfile]# cat logstash.conf
input { # 日志收集配置
  file {
    #path => "/var/lib/docker/containers/*/*-json.log" #docker
    # 容器日志文件路径,这个是宿主机上的,等下daemonset的yaml中会把这个路径挂在到pod中
    path => "/var/log/pods/*/*/*.log"
    start_position => "beginning" # beginning表示从日志首行开始收集
    type => "jsonfile-daemonset-applog" # 定义该日志类型为app日志
  }

  file {
    path => "/var/log/*.log"
    start_position => "beginning" # beginning表示从日志首行开始收集
    type => "jsonfile-daemonset-syslog" # 这里是定义为系统日志
  }
}

output { # 日志输出配置
  if [type] == "jsonfile-daemonset-applog" {
    kafka { # 日志输出到kafka
      bootstrap_servers => "${KAFKA_SERVER}" # ${KAFKA_SERVER}为kafka地址,具体的地址会在ds的yaml中体现
      topic_id => "${TOPIC_ID}" # 这个变量也会在ds的yaml中体现
      batch_size => 16384  #logstash每次向ES传输的数据量大小(默认配置),单位为字节
      codec => "${CODEC}" # 字符集,这里的变量也会在ds的yaml中体现
   } }

  if [type] == "jsonfile-daemonset-syslog" {
    kafka {
      bootstrap_servers => "${KAFKA_SERVER}"
      topic_id => "${TOPIC_ID}"
      batch_size => 16384
      codec => "${CODEC}" #系统日志不是json格式
  }}
}
2.7.1.4 2.DaemonSet-logstash.yaml
[root@master1 1.logstash-image-Dockerfile]# cd ../
[root@master1 1.daemonset-logstash]# cat 2.DaemonSet-logstash.yaml
ind: DaemonSet
metadata:
  name: logstash-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: logstash-logging
spec:
  selector:
    matchLabels:
      name: logstash-elasticsearch
  template:
    metadata:
      labels:
        name: logstash-elasticsearch
    spec:
      tolerations: # 污点容忍配置,这样master上也可以收集日志
      # this toleration is to have the daemonset runnable on master nodes
      # remove it if your masters can't run pods
      - key: node-role.kubernetes.io/control-plane
        operator: Exists
        effect: NoSchedule
      containers:
      - name: logstash-elasticsearch
        image: registry.cn-hangzhou.aliyuncs.com/sanhua-k8s/logstash:v7.12.1-json-file-log-v1
        env:
        - name: "KAFKA_SERVER" # 这就是之前说到的变量
          value: "10.31.200.111:9092,10.31.200.112:9092,10.31.200.113:9092"
        - name: "TOPIC_ID" # 这就是之前说到的变量
          value: "jsonfile-log-topic"
        - name: "CODEC" # 这就是之前说到的变量
          value: "json"
#        resources:
#          limits:
#            cpu: 1000m
#            memory: 1024Mi
#          requests:
#            cpu: 500m
#            memory: 1024Mi
        volumeMounts:
        - name: varlog #定义宿主机系统日志挂载路径
          mountPath: /var/log #宿主机系统日志挂载点
        - name: varlibdockercontainers #定义容器日志挂载路径,和logstash配置文件中的收集路径保持一直
          #mountPath: /var/lib/docker/containers #docker挂载路径
          mountPath: /var/log/pods #containerd挂载路径,此路径与logstash的日志收集路径必须一致
          readOnly: false
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log #宿主机系统日志
      - name: varlibdockercontainers
        hostPath:
          #path: /var/lib/docker/containers #docker的宿主机日志路径
          path: /var/log/pods #containerd的宿主机日志路径

2.7.2 构建logstash镜像

[root@master1 1.logstash-image-Dockerfile]# cat build-commond.sh
#!/bin/bash
nerdctl build -t registry.cn-hangzhou.aliyuncs.com/sanhua-k8s/logstash:v7.12.1-json-file-log-v1 .

nerdctl push registry.cn-hangzhou.aliyuncs.com/sanhua-k8s/logstash:v7.12.1-json-file-log-v1

[root@master1 1.logstash-image-Dockerfile]# sh build-commond.sh

[root@master1 1.logstash-image-Dockerfile]# nerdctl images|grep log
registry.cn-hangzhou.aliyuncs.com/sanhua-k8s/logstash                          v7.12.1-json-file-log-v1    79eb662f2a7b    2 hours ago               linux/amd64    990.5 MiB    470.6 MiB

2.7.3 部署logstash

logstash启动后,会收集挂载点的日志,输出到kafka

[root@master1 1.daemonset-logstash]# kubectl apply -f 2.DaemonSet-logstash.yaml
daemonset.apps/logstash-elasticsearch created

[root@master1 1.daemonset-logstash]# kubectl get po -A |grep log
kube-system   logstash-elasticsearch-2p4mc               1/1     Running   0                   8s
kube-system   logstash-elasticsearch-45j7q               1/1     Running   0                   8s
kube-system   logstash-elasticsearch-n22zf               1/1     Running   0                   8s

2.7.4 查看topic生成结果

在这里插入图片描述

2.8 二进制部署logstash消费者

2.8.1 下载并解压

# 这个包可以直接去官网下载二进制的,里面还包含了java 11
[root@logstash ~]# ll -h logstash-7.12.0-linux-x86_64.tar.gz
-rw-r--r-- 1 root root 352M Dec 12  2023 logstash-7.12.0-linux-x86_64.tar.gz

[root@logstash ~]# tar xf logstash-7.12.0-linux-x86_64.tar.gz -C /opt/
[root@logstash ~]# cd /opt/logstash-7.12.0/
[root@logstash logstash-7.12.0]# ls
bin  config  CONTRIBUTORS  data  Gemfile  Gemfile.lock  jdk  lib  LICENSE.txt  logstash-core  logstash-core-plugin-api  modules  NOTICE.TXT  tools  vendor  x-pack

2.8.2 修改配置文件

[root@logstash logstash-7.12.0]# cat config/logstash-sample.conf
input {
  kafka {
    bootstrap_servers => "10.31.200.133:9092,10.31.200.134:9092,10.31.200.135:9092"
    topics => ["jsonfile-log-topic"]
    codec => "json"
  }
}

output {
  if [type] == "jsonfile-daemonset-applog" {
    elasticsearch {
      hosts => ["10.31.200.130:9200","10.31.200.131:9200","10.31.200.132:9200"]
      index => "jsonfile-daemonset-applog-%{+YYYY.MM.dd}"
    }}

  if [type] == "jsonfile-daemonset-syslog" {
    elasticsearch {
      hosts => ["10.31.200.130:9200","10.31.200.131:9200","10.31.200.132:9200"]
      index => "jsonfile-daemonset-syslog-%{+YYYY.MM.dd}"
    }}
}

[root@logstash-consumer logstash-7.12.0]# egrep -v "^#|^$" config/logstash.yml
pipeline.ordered: auto
http.host: 10.31.200.140
http.port: 9600-9700
log.level: info
path.logs: /var/log/logstash

2.8.3 启动服务

[root@logstash-consumer logstash-7.12.0]# /opt/logstash-7.12.0/bin/logstash -f /opt/logstash-7.12.0/config/logstash-sample.conf

[root@logstash-consumer ~]# netstat -ltnup|grep 9600
tcp6       0      0 10.31.200.140:9600      :::*                    LISTEN      2287/java

2.8.4 查看es是否有数据

只要消费者能正常消费数据到es,这个时候es应该是有数据的
在这里插入图片描述

2.9 二进制部署Kibana

2.9.1 下载软件包

[root@logstash-consumer ~]# wget https://artifacts.elastic.co/downloads/kibana/kibana-7.12.0-linux-x86_64.tar.gz
[root@logstash-consumer ~]# ll -h kibana-7.12.0-linux-x86_64.tar.gz
-rw-r--r-- 1 root root 269M Mar 23  2021 kibana-7.12.0-linux-x86_64.tar.gz

2.9.2 配置并启动

2.9.2.1 调整配置
root@logstash-consumer ~]# tar xf kibana-7.12.0-linux-x86_64.tar.gz -C /opt/
[root@logstash-consumer ~]# cd /opt/kibana-7.12.0-linux-x86_64/
[root@logstash-consumer kibana-7.12.0-linux-x86_64]# ls
bin  config  data  LICENSE.txt  node  node_modules  NOTICE.txt  package.json  plugins  README.txt  src  x-pack

[root@logstash-consumer kibana-7.12.0-linux-x86_64]# egrep -v "^$|^#" config/kibana.yml
server.port: 5601
server.host: "10.31.200.140"
elasticsearch.hosts: ["http://10.31.200.130:9200"]
i18n.locale: "zh-CN"

2.9.2.2 启动kibana
[root@logstash-consumer bin]# nohup ./kibana --allow-root &

root@logstash-consumer bin]# netstat -lntup |grep 5601
tcp        0      0 10.31.200.140:5601      0.0.0.0:*               LISTEN      12589/./../node/bin

2.9.3 添加所索引并查看日志

2.9.3.1 添加索引

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.9.3.2 查看日志

在这里插入图片描述

2.10 该方式的缺点

使用该方式去收集日志,运行的pod一多,需要通过调整logstash配置文件,去匹配每一个服务,来按服务名生成索引,然后写入es存储,非常繁琐。

2.11 清理环境

[root@master1 ~]# cd /opt/ELK\ cases-N76/1.daemonset-logstash
[root@master1 1.daemonset-logstash]# kubectl delete -f 2.DaemonSet-logstash.yaml
daemonset.apps "logstash-elasticsearch" deleted

3. 日志收集示例二:sidecar模式实现日志收集(ELK)

所谓sidecar模式,就是一个pod中,运行了2个容器,一个业务容器,一个负责收集日志的容器。
但是同一个pod中,不同的容器之间文件系统是隔离的,怎么来收集这个日志呢?这就要用到emptyDir(临时数据目录)。
emptyDir主要是负责临时存储数据的,一旦pod被删除,持久化的数据也会跟着被删除,非常适合存储日志和一些临时数据。
我们在创建pod的时候,可以让两个容器都挂载到同一个emptyDir,这样业务容器负责把日志输出进去,日志收集容器负责收集这些日志数据并写入kafka。


但是这里有个问题,集成到pod中的sidecar容器,必须非常轻量级(如filebeat),不能占用过多的cpu和内存资源,尽量让sidecar只收集日志,写入kafka,处理日志的工作就交给负责消费消息的logstash进行。

3.1 sidecar模式架构

在这里插入图片描述

3.2 构建sidecar镜像

3.2.1 相关配置文件

[root@master1 1.daemonset-logstash]# cd ../2.sidecar-logstash/
[root@master1 2.sidecar-logstash]# ls
1.logstash-image-Dockerfile  2.tomcat-app1.yaml  3.tomcat-service.yaml  4.logsatsh-sidecar-kafka-to-es.conf

[root@master1 2.sidecar-logstash]# cd 1.logstash-image-Dockerfile/
[root@master1 1.logstash-image-Dockerfile]# ls
build-commond.sh  Dockerfile  logstash.conf  logstash.yml

# dockerfile
[root@master1 1.logstash-image-Dockerfile]# cat Dockerfile
FROM logstash:7.12.1

USER root
WORKDIR /usr/share/logstash
#RUN rm -rf config/logstash-sample.conf
ADD logstash.yml /usr/share/logstash/config/logstash.yml
ADD logstash.conf /usr/share/logstash/config/logstash.conf

# 日志收集配置文件
[root@master1 1.logstash-image-Dockerfile]# cat logstash.conf
input {
  file {
    path => "/var/log/applog/catalina.out" # 指定应用程序日志文件路径
    start_position => "beginning"
    type => "app1-sidecar-catalina-log" # 定义日志类型
  }
  file {
    path => "/var/log/applog/localhost_access_log.*.txt" # 指定应用程序日志文件路径
    start_position => "beginning"
    type => "app1-sidecar-access-log" # 定义日志类型
  }
}

output { # 判断不同的日志type,写入不同的topic中
  if [type] == "app1-sidecar-catalina-log" {
    kafka {
      bootstrap_servers => "${KAFKA_SERVER}" # 这些变量也是在pod的yaml中定义的
      topic_id => "${TOPIC_ID}"
      batch_size => 16384  #logstash每次向ES传输的数据量大小,单位为字节
      codec => "${CODEC}"
   } }

  if [type] == "app1-sidecar-access-log" {
    kafka {
      bootstrap_servers => "${KAFKA_SERVER}"
      topic_id => "${TOPIC_ID}"
      batch_size => 16384
      codec => "${CODEC}"
  }}
}

# 2.tomcat-app1.yaml
[root@master1 1.logstash-image-Dockerfile]# cat ../2.tomcat-app1.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  labels:
    app: magedu-tomcat-app1-deployment-label
  name: magedu-tomcat-app1-deployment #当前版本的deployment 名称
spec:
  replicas: 2
  selector:
    matchLabels:
      app: magedu-tomcat-app1-selector
  template:
    metadata:
      labels:
        app: magedu-tomcat-app1-selector
    spec:
      containers:
      - name: magedu-tomcat-app1-container # 业务容器。注意:exec的时候,一般是进入第一个容器,所以多容器环境,建议把主容器放在第一个,不然进去得-c指定容器。
        image: registry.cn-hangzhou.aliyuncs.com/zhangshijie/tomcat-app1:v1
        imagePullPolicy: IfNotPresent
        #imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
        env:
        - name: "password"
          value: "123456"
        - name: "age"
          value: "18"
        resources:
          limits:
            cpu: 1
            memory: "512Mi"
          requests:
            cpu: 500m
            memory: "512Mi"
        volumeMounts:
        - name: applogs
          mountPath: /apps/tomcat/logs
        startupProbe:
          httpGet:
            path: /myapp/index.html
            port: 8080
          initialDelaySeconds: 5 #首次检测延迟5s
          failureThreshold: 3  #从成功转为失败的次数
          periodSeconds: 3 #探测间隔周期
        readinessProbe:
          httpGet:
            #path: /monitor/monitor.html
            path: /myapp/index.html
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 3
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 3
        livenessProbe:
          httpGet:
            #path: /monitor/monitor.html
            path: /myapp/index.html
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 3
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 3
      - name: sidecar-container # sidecar容器
        image: harbor.linuxarchitect.io/baseimages/logstash:v7.12.1-sidecar
        imagePullPolicy: IfNotPresent
        #imagePullPolicy: Always
        env:
        - name: "KAFKA_SERVER" # sidecar收集日志引用的变量
          value: "10.31.200.133:9092,10.31.200.134:9092,10.31.200.135:9092"
        - name: "TOPIC_ID"
          value: "tomcat-app1-topic"
        - name: "CODEC"
          value: "json"
        volumeMounts:
        - name: applogs
          mountPath: /var/log/applog
      volumes:
      - name: applogs
        emptyDir: {} # 定义通过emptyDir实现业务容器与sidecar容器的日志共享,以让sidecar收集业务容器中的日志

[root@master1 2.sidecar-logstash]# cat 3.tomcat-service.yaml
---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: magedu-tomcat-app1-service-label
  name: magedu-tomcat-app1-service
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: magedu-tomcat-app1-selector


# logstash.yml
[root@master1 1.logstash-image-Dockerfile]# cat logstash.yml
http.host: "0.0.0.0"
#xpack.monitoring.elasticsearch.hosts: [ "http://elasticsearch:9200" ]

# build-commond.sh
[root@master1 1.logstash-image-Dockerfile]# cat build-commond.sh
#!/bin/bash

nerdctl  build -t registry.cn-hangzhou.aliyuncs.com/sanhua-k8s/logstash:v7.12.1-sidecar .
nerdctl push registry.cn-hangzhou.aliyuncs.com/sanhua-k8s/logstash:v7.12.1-sidecar

3.2.2 构建日志收集镜像

[root@master1 1.logstash-image-Dockerfile]# sh build-commond.sh

3.2.3 调整镜像

root@master1 2.sidecar-logstash]# grep ".*-sidecar" 2.tomcat-app1.yaml
        image: registry.cn-hangzhou.aliyuncs.com/sanhua-k8s/logstash:v7.12.1-sidecar

3.3 创建sidecar pod

[root@master1 2.sidecar-logstash]# kubectl apply -f 2.tomcat-app1.yaml
deployment.apps/magedu-tomcat-app1-deployment created

[root@master1 2.sidecar-logstash]# kubectl get po -owide
NAME                                           READY   STATUS    RESTARTS   AGE     IP             NODE    NOMINATED NODE   READINESS GATES
magedu-tomcat-app1-deployment-dd85ddc8-2xpc5   2/2     Running   0          2m18s   10.100.154.4   node1   <none>           <none>
magedu-tomcat-app1-deployment-dd85ddc8-4mfjr   2/2     Running   0          2m18s   10.100.44.1    node2   <none>           <none>

3.3.1 临时目录创建情况

[root@node1 ~]# find / -type d   -name applogs
/var/lib/kubelet/pods/b405281e-bca1-4716-893a-9f9b8a35deed/volumes/kubernetes.io~empty-dir/applogs
/var/lib/kubelet/pods/b405281e-bca1-4716-893a-9f9b8a35deed/plugins/kubernetes.io~empty-dir/applogs

3.4 查看kafka topic创建情况

上述配置无误的话,kafka中会自动生成topic
在这里插入图片描述

3.5 调整logstash消费者配置

[root@logstash-consumer config]# cat logstash-sample.conf
input {
  kafka {
    bootstrap_servers => "10.31.200.133:9092,10.31.200.134:9092,10.31.200.135:9092"
    topics => ["tomcat-app1-topic"]
    codec => "json"
  }
}

output {
  if [type] == "app1-sidecar-catalina-log" { # 这里要和dockefile中add的配置type相同
    elasticsearch {
      hosts => ["10.31.200.130:9200","10.31.200.131:9200","10.31.200.132:9200"]
      index => "sidecar-app1-catalina-log--%{+YYYY.MM.dd}"
    }}

  if [type] == "app1-sidecar-access-log" { # 这里要和dockefile中add的配置type相同
    elasticsearch {
      hosts => ["10.31.200.130:9200","10.31.200.131:9200","10.31.200.132:9200"]
      index => "sidecar-app1-access-log-%{+YYYY.MM.dd}"
    }}
}

然后重启logstash消费者。

在这里插入图片描述

3.6 kibana查看日志

在这里插入图片描述

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐