背景
由于以下容器本身特性和现有日志采集工具的缺陷,开发者在收集Kubernetes分布式集群日志时常常遇到困扰:
容器本身特性:
采集目标多:容器本身的特性导致采集目标多,需要采集容器内日志、容器stdout。对于容器内部的文件日志采集,现在并没有一个很好的工具能够动态发现采集。针对每种数据源都有对应的采集软件,但缺乏一站式的工具。
弹性伸缩难:Kubernetes是分布式的集群,服务、环境的弹性伸缩对于日志采集带来了很大的困难,无法像传统虚拟机环境下那样,事先配置好日志的采集路径等信息,采集的动态性以及数据完整性是非常大的挑战。
现有日志工具的一些缺陷:
缺乏动态配置的能力。目前的采集工具都需要事先手动配置好日志采集方式和路径等信息,因为它无法自动感知到容器的生命周期变化或者动态漂移,所以它无法动态地去配置。
日志采集重复或丢失的问题。因为现在的一些采集工具通过tail的方式进行日志采集,这样可能导致日志丢失,比如采集工具在重启的过程中,而应用依然在写日志,那么就有可能导致这个窗口期的日志丢失。对于这种情况一般保守的做法默认往前多采集1 M日志或2 M的日志,那么这就又会可能引起日志采集重复的问题。
未明确标记日志源。因为一个应用可能有很多个容器,输出的应用日志也是一样的,那么当将所有应用日志收集到统一日志存储后端时,在搜索日志的时候,您无法明确这条日志具体是哪一个节点上的哪一个应用容器产生的。
Log-pilot介绍
Log-pilot是一个智能容器日志采集工具,它不仅能够高效便捷地将容器日志采集输出到多种存储日志后端,同时还能够动态地发现和采集容器内部的日志文件。
针对前面提出的日志采集难题,Log-pilot通过声明式配置实现强大的容器事件管理,可同时获取容器标准输出和内部文件日志,解决了动态伸缩问题,此外,Log-pilot具有自动发现机制、CheckPoint及句柄保持的机制、自动日志数据打标、有效应对动态配置、日志重复和丢失以及日志源标记等问题。
基于阿里云的开源日志搜集方案,并且使用daemonset的方式部署到node节点上用来自定义搜集控制台或者固定目录下的日志文件
本次的yaml是自定义输出到后端到kafka然后由logstash过滤以后发送到es中,kibana直接读es的索引
注:在阿里云上开通阿里云sls日志收集与arms应用链路监控,
会导致自定义安装的log-polit日志收集无法收集到日志,
默认的阿里云自定义前缀是aliyun_logs,
会导致冲突,需要自定义 - name: PILOT_LOG_PREFIX 日志收集格式的前缀可以解决。
架构图
log-pilot安装
#在k8s集群內以daemonset的方式来进行部署
#注:在阿里云上开通阿里云sls日志收集与arms应用链路监控,
会导致自定义安装的log-polit日志收集无法收集到日志,
默认的阿里云自定义前缀是aliyun_logs,
会导致冲突,需要自定义 - name: PILOT_LOG_PREFIX 日志收集格式的前缀可以解决。
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: log-pilot
labels:
k8s-app: log-pilot
namespace: kube-system
spec:
updateStrategy:
type: RollingUpdate
template:
metadata:
labels:
k8s-app: log-pilot
spec:
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: log-pilot
image: registry.cn-hangzhou.aliyuncs.com/acs/log-pilot:0.9.7-filebeat
env:
- name: "LOGGING_OUTPUT"
value: "kafka"
- name: PILOT_LOG_PREFIX
value: ailieyun
- name: "KAFKA_BROKERS"
value: "192.168.200.100:9092,192.168.200.101:9092,192.168.200.102:9092"
- name: "NODE_NAME"
valueFrom:
fieldRef:
fieldPath: spec.nodeName
volumeMounts:
- name: sock
mountPath: /var/run/docker.sock
- name: logs
mountPath: /var/log/filebeat
- name: state
mountPath: /var/lib/filebeat
- name: root
mountPath: /host
readOnly: true
- name: localtime
mountPath: /etc/localtime
securityContext:
capabilities:
add:
- SYS_ADMIN
terminationGracePeriodSeconds: 30
volumes:
- name: sock
hostPath:
path: /var/run/docker.sock
- name: logs
hostPath:
path: /var/log/filebeat
- name: state
hostPath:
path: /var/lib/filebeat
- name: root
hostPath:
path: /
- name: localtime
hostPath:
path: /etc/localtime
安装zookeeper和kafka集群
#zookeeper集群
#以其中一台机器为例
tar -zxvf zookeeper-3.4.14.tar.gz -C /data/service/
cd /data/service/zookeeper-3.4.14/ && cp conf/zoo_sample.cfg conf/zoo.cfg
查看配置:
cat /data/service/zookeeper-3.4.14/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data/data/zookeeper
clientPort=2181
server.1=192.168.1.7:2888:3888
server.2=192.168.1.6:2888:3888
server.3=192.168.1.5:2888:3888
添加:
echo 1 > /data/data/zookeeper/myid
其他机器:
echo 2 > /data/data/zookeeper/myid
echo 3 > /data/data/zookeeper/myid
启动: /data/service/zookeeper-3.4.14/bin/zkServer.sh start
查看状态: /data/service/zookeeper-3.4.14/bin/zkServer.sh status
#kafka集群
tar -zxvf kafka_2.12-2.0.1.tgz -C /data/service/
#修改zookeeper链接地址:
/data/service/kafka_2.12-2.0.1/config/server.properties
zookeeper.connect=192.168.1.7:2181,192.168.1.6:2181,192.168.1.5:2181
安装logstash
#logstash集群
tar -zxvf logstash-7.7.1.tar.gz -C /data/service/
cd /data/service/logstash-7.7.1
cat log-polit.conf
input {
kafka {
bootstrap_servers=>"192.168.2.137:9092,192.168.2.138:9092,192.168.2.139:9092"
topics_pattern => "logs.*"
client_id => "kafka_client_one"
group_id => "logstash"
codec => "json"
}
}
filter {
mutate {
remove_field => ["input","beat","prospector","@version","offset"]
}
}
output {
if "nginx-access" in [tags] {
elasticsearch {
hosts => ["192.168.1.5:9200","192.168.1.6:9200","192.168.1.7:9200"]
index => "%{[domain]}-%{+YYYY-MM-dd}"
}
} else {
elasticsearch {
hosts => ["192.168.1.5:9200","192.168.1.6:9200","192.168.1.7:9200"]
index => "%{[topic]}-%{+YYYY-MM-dd}"
}
}
}
#cd /data/app/logstash-7.7.1 && nohup ./bin/logstash -f log-polit.conf &
es集群安装
#es集群
tar -zxvf elasticsearch-7.7.1-linux-x86_64.tar.gz -C /data/service/
cd /data/service/elasticsearch-7.7.1
#cat elasticsearch.yml
cluster.name: kkb-logs
node.name: kkb-sys-esmaster-001
path.data: /data/data/elasticsearch/data
path.logs: /data/data/elasticsearch/logs
bootstrap.memory_lock: true
network.host: 192.168.23.30
action.auto_create_index: true
http.port: 9200
discovery.seed_hosts: ["192.168.1.18", "192.168.1.19"]
cluster.initial_master_nodes: ["192.168.1.18", "192.168.1.19"]
node.master: true
node.data: false
#设置堆内存大小
# cat jvm.options|grep "Xm"
# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space
-Xms6g
-Xmx6g
#cd /data/app/elasticsearch && ./bin/elasticsearch -d
kibana集群
此处应该为3台机器,由于是test,所以只上了一台
rpm -ivh kibana-7.7.1-x86_64.rpm
cat /etc/kibana/kibana.yml |grep -Ev "^#|^$"
server.port: 5601
xpack.reporting.csv.maxSizeBytes: 2097152000
server.host: "192.168.1.21"
server.name: "192.168.1.21"
elasticsearch.hosts: ["http://192.168.1.18:9200","http://192.168.1.19:9200"]
elasticsearch.requestTimeout: 300000
k8s集群日志接入
#nginx deployment
#- name: ailieyun_logs_logs-plat-file-console
# value: "stdout"
#- name: ailieyun_logs_logs-plat-file-console_ttl
# value: "3"
#这两行会自动在kafka集群中创建topic
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: ng-demo-1
name: ng-demo-1
spec:
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
replicas: 5
selector:
matchLabels:
run: java-demo-1
template:
metadata:
labels:
run: ng-demo-1
spec:
containers:
- image: nginx:latest
name: ng-demo-1
ports:
- containerPort: 80
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "500m"
memory: "512Mi"
env:
- name: ailieyun_logs_logs-java-demo
value: "stdout"
- name: ailieyun_logs_logs-java-demo_ttl
value: "3"
#创建好deploy以后进到容器里while true;do curl 127.0.0.1;sleep 1 ;done
#然后手动执行数据消费
./kafka-console-consumer.sh --bootstrap-server 192.168.1.5:9092,192.168.1.6:9092,192.168.1.7:9092 --topic logs-java-demo
#然后看到下面到图即视为任务收集成功