Fork me on GitHub

kubernetes系列之《k8s构建ELK日志平台》

一、概述

目前主流日志收集系统为:Filebeat + ELK,本文尝试使用该系统对k8s里部署的Pod进行日志收集并加以图形可视化展示;

确定日志收集系统后,接下来就要搞清楚我们想要收集k8s的哪些日志?

这里思考主要日志收集如下:

  1. K8S系统的组件日志
  2. K8S Cluster里面部署的应用程序日志

日志收集方案:Filebeat + ELK

二、容器中日志收集方案

2.1、方案一:Node上部署一个日志收集程序

  • DaemonSet方式部署日志收集程序
  • 对本节点/var/log/和/var/lib/docker/containers两个目录下的日志进行采集
  • Pod中容器日志挂载到宿主机统一目录上。

优点:

  • 每个Node仅需部署一个日志收集程序,资源消耗少,对应用无入侵

缺点:

  • 应用程序日志需要写到标准输出和标准错误输出,不支持多行日志收集

2.2、方案二:Pod中附加专用日志收集的容器

每个预应用程序的Pod中增加一个日志收集容器,使用emptyDir共享日志目录,让日志收集程序能够读取到。

优点:

  • 低耦合

缺点:

  • 每个Pod启动一个日志收集代理,增加资源消耗,并增加运维维护成本

2.3、方案三:应用程序直接推送日志

这超出了k8s的范围,需要开发配合定制,约定规范后,统一向日志收集入口推送日志;

优点:

  • 无需额外收集工具

缺点:

  • 侵入应用,增加应用复杂度

以上三个方案各有优缺点,这就意味着不同环境的选择也不同,本文采用第二种方案来进行试验。

三、部署ELK日志平台

ELK官网:https://www.elastic.co/cn/
配置yum源参考:https://www.elastic.co/guide/en/logstash/current/installing-logstash.html

3.1、安装JDK

在所有节点上安装:

1
$ yum install -y java-1.8.0-openjdk

3.2、配置YUM源

1
2
3
4
5
6
7
8
9
[root@k8s-master-128 ~]# vim /etc/yum.repos.d/elk.repo
[logstash-7.x]
name=Elastic repository for 7.x packages
baseurl=https://artifacts.elastic.co/packages/7.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md

3.3、安装ELK

在Master节点安装即可,因为这里是试验环境,可以不需要es为集群环境。

1
[root@k8s-master-128 ~]# yum install -y logstash elasticsearch kibana

3.4、EKL相关配置

这里主要对ES和kibana的主配置文件进行配置,指定相关IP和端口等。

配置ES:

1
2
3
4
5
6
7
[root@k8s-master-128 ~]# grep -Ev '^#|^$' /etc/elasticsearch/elasticsearch.yml
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
bootstrap.memory_lock: false
network.host: 0.0.0.0
http.port: 9200
discovery.type: single-node # 如果启动单节点,则需要添加此参数

注意,ES需要优化一些内核参数:

1
2
3
4
5
6
7
8
9
10
[root@k8s-master-128 ~]# vim /etc/security/limits.conf
# End of file
* soft nofile 60000
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535

[root@k8s-master-128 ~]# vim /etc/security/limits.d/20-nproc.conf
* soft nproc 65535
root soft nproc 65535

运行: sysctl -p生效配置。

配置kibana:

1
2
3
4
5
6
7
8
[root@k8s-master-128 ~]# grep -Ev '^#|^$' /etc/kibana/kibana.yml
server.port: 5601
server.host: "172.16.194.128"
server.name: "kibana"
elasticsearch.hosts: ["http://172.16.194.128:9200"]
elasticsearch.preserveHost: true
kibana.index: ".kibana"
i18n.locale: "zh-CN"

kibana汉化参考:https://github.com/anbai-inc/Kibana_Hanization

3.5、启动ES和Kibana

1
2
3
4
5
6
7
8
9
$ systemctl start elasticsearch
$ systemctl enable elasticsearch

$ systemctl start kibana
$ systemctl enable kibana

[root@k8s-master-128 ~]# netstat -lntup|grep java
tcp6 0 0 :::9200 :::* LISTEN 119229/java
tcp6 0 0 :::9300 :::* LISTEN 119229/java

访问kibana:http://172.16.194.128:5601

四、采集日志

4.1、采集K8s组件日志

采集日志客户端采用Filebeat来进行采集日志,使用ConfigMap的形式来存储Filebeat的配置,采用DaemonSet形式部署Filebeat到各个集群节点上,然后将配置文件和日志挂载到Filebeat的Pod中,利用Filebeat采集k8s的集群日志。

4.1.1、部署Filebeat日志收集客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
[root@k8s-master-128 elk]# cat k8s-logs.yaml
apiVersion: v1
kind: ConfigMap # 保存Filebeat的配置信息
metadata:
name: k8s-logs-filebeat-config
namespace: kube-system

data:
filebeat.yml: |-
filebeat.prospectors:
- type: log
paths:
- /opt/kubernetes/logs/* # 指定k8s集群的采集日志目录,星号匹配所有该目录下的文件
fields:
app: k8s
type: module
fields_under_root: true

output.logstash:
hosts: ['172.16.194.128:5044'] # 这里写logstash启动的监听地址和端口

---

apiVersion: apps/v1
kind: DaemonSet # 使用DaemonSet方式将Filebeat部署到集群每个节点上
metadata:
name: k8s-logs # Pod名称
namespace: kube-system # 指定运行命名空间
spec:
selector:
matchLabels:
project: k8s
app: filebeat
template:
metadata:
labels:
project: k8s
app: filebeat
spec:
containers:
- name: filebeat
image: docker.elastic.co/beats/filebeat:6.4.2
args: [
"-c", "/etc/filebeat.yml",
"-e",
]
resources:
requests:
cpu: 100m
memory: 100Mi
limits:
cpu: 500m
memory: 500Mi
securityContext:
runAsUser: 0
volumeMounts:
- name: filebeat-config
mountPath: /etc/filebeat.yml
subPath: filebeat.yml
- name: k8s-logs
mountPath: /opt/kubernetes/logs
volumes:
- name: k8s-logs
hostPath:
path: /opt/kubernetes/logs # 将主机上的目录挂载到Pod容器里
- name: filebeat-config
configMap:
name: k8s-logs-filebeat-config # 指定configmap挂载到Pod容器里

部署Filebeat:

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@k8s-master-128 elk]# kubectl create -f k8s-logs.yaml
configmap/k8s-logs-filebeat-config created
daemonset.apps/k8s-logs created
[root@k8s-master-128 elk]# kubectl get -f k8s-logs.yaml
NAME DATA AGE
configmap/k8s-logs-filebeat-config 1 6s

NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/k8s-logs 2 2 0 2 0 <none> 5s

[root@k8s-master-128 elk]# kubectl get pod -A|grep k8s-log
kube-system k8s-logs-7wwlx 1/1 Running 0 5m
kube-system k8s-logs-pd8m2 1/1 Running 0 5m

检测配置的日志目录是否有挂载到Pod中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@k8s-master-128 elk]# kubectl exec -it -n kube-system k8s-logs-7wwlx bash
[root@k8s-logs-7wwlx filebeat]# ls -lh /opt/kubernetes/logs/ -d
drwxr-xr-x 2 root root 8.0K Jun 3 06:44 /opt/kubernetes/logs/
[root@k8s-logs-7wwlx filebeat]# cat /etc/filebeat.yml
filebeat.prospectors:
- type: log
paths:
- /opt/kubernetes/logs/* # 指定k8s集群的采集日志目录,星号匹配所有该目录下的文件
fields:
app: k8s
type: module
fields_under_root: true

output.logstash:
hosts: ['172.16.194.128:5044'] # 这里写logstash启动的监听地址和端口

能看到配置文件和日志目录都正常挂载到Pod容器里。

4.1.2、配置Logstash接收日志

配置logstash接收日志,stdout {codec => rubydebug } 用于答应日志到控制台方便调试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@k8s-master-128 elk]# cat filebeat-to-logstash.conf
input {
beats {
port => 5044
}
}

filter {
}

output {
if [type] == "module" {
elasticsearch {
hosts => ["http://127.0.0.1:9200"]
index => "k8s-log-%{+YYYY.MM.dd}"
}
}
stdout { codec=> rubydebug }
}

启动logstash:

1
2
3
4
5
6
7
8
9
10
11
12
# 调试启动
[root@k8s-master-128 elk]# /usr/share/logstash/bin/logstash -f filebeat-to-logstash.conf

# 守护程序启动:需要编辑配置文件,去掉stdout配置
[root@k8s-master-128 elk]# cp filebeat-to-logstash.conf /etc/logstash/conf.d/logstash.conf
[root@k8s-master-128 elk]# systemctl start logstash

[root@k8s-master-128 ~]# netstat -lntup|grep java
tcp6 0 0 :::9200 :::* LISTEN 119229/java
tcp6 0 0 :::5044 :::* LISTEN 710/java
tcp6 0 0 :::9300 :::* LISTEN 119229/java
tcp6 0 0 127.0.0.1:9600 :::* LISTEN 710/java

启动后,logstash将会把Filebeat写进来的日志再写入ES数据库,然后由kibana来展示日志数据

4.1.3、配置Kibana展示日志

第一步:点击设置–>创建索引–>匹配索引 (k8s-log-*)

第二步:匹配到索引后,点击创建,然后查看数据

4.2、采集Pod容器日志

采集容器日志,这里选择方案二,在Pod里附加Filebeat容器,专门为这个Pod提供日志采集服务

4.2.1、编写Filebeat配置文件

与上相同,采用ConfigMap来保存Filebeat的配置文件,然后启动Pod时挂载到Pod里的容器里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[root@k8s-master-128 elk]# cat filebeat-nginx-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: filebeat-nginx-config
namespace: kube-system

data:
filebeat.yml: |-
filebeat.prospectors:
- type: log
paths:
- /var/log/nginx/access.log
# tags: ["access"]
fields:
app: www
type: nginx-access
fields_under_root: true

- type: log
paths:
- /var/log/nginx/error.log
# tags: ["error"]
fields:
app: www
type: nginx-error
fields_under_root: true

output.logstash:
hosts: ['172.16.194.128:5044']

创建:

1
2
3
4
5
[root@k8s-master-128 elk]# kubectl create -f filebeat-nginx-configmap.yaml
configmap/filebeat-nginx-config created
[root@k8s-master-128 elk]# kubectl get -f filebeat-nginx-configmap.yaml
NAME DATA AGE
filebeat-nginx-config 1 10s

4.2.2、创建Pod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
[root@k8s-master-128 elk]# cat nginx-deployment.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-demo
namespace: kube-system
spec:
replicas: 3
selector:
matchLabels:
project: www
app: nginx-demo
template:
metadata:
labels:
project: www
app: nginx-demo
spec:
#imagePullSecrets:
#- name: registry-pull-secret
containers:
- name: nginx
image: nicksors/nginx:v1 # 必须要确保此镜像的日志目录与Filebeat配置的收集目录一致
ports:
- containerPort: 80
name: web
protocol: TCP
resources:
requests:
cpu: 0.5
memory: 256Mi
limits:
cpu: 1
memory: 1Gi
livenessProbe:
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 6
timeoutSeconds: 20
volumeMounts:
- name: nginx-logs
mountPath: /var/log/nginx/

- name: filebeat
image: docker.elastic.co/beats/filebeat:6.4.2
args: [
"-c", "/etc/filebeat.yml",
"-e",
]
resources:
limits:
memory: 500Mi
requests:
cpu: 100m
memory: 100Mi
securityContext:
runAsUser: 0
volumeMounts:
- name: filebeat-config
mountPath: /etc/filebeat.yml
subPath: filebeat.yml
- name: nginx-logs
mountPath: /var/log/nginx/

volumes:
- name: nginx-logs
emptyDir: {}
- name: filebeat-config
configMap:
name: filebeat-nginx-config

创建:

1
2
3
4
5
[root@k8s-master-128 elk]# kubectl create -f nginx-deployment.yaml
deployment.apps/nginx-demo created
[root@k8s-master-128 elk]# kubectl get -f nginx-deployment.yaml
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-demo 3/3 3 3 30s

4.2.3、配置Logstash接收日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[root@k8s-master-128 elk]# vim /etc/logstash/conf.d/logstash.conf
input {
beats {
port => 5044
}
}

filter {
}

output {
if [type] == "module" {
elasticsearch {
hosts => ["http://127.0.0.1:9200"]
index => "k8s-log-%{+YYYY.MM.dd}"
}
}
if [type] == "nginx-access" {
elasticsearch {
hosts => ["http://127.0.0.1:9200"]
index => "nginx-access-%{+YYYY.MM.dd}"
}
}
if [type] == "nginx-error" {
elasticsearch {
hosts => ["http://127.0.0.1:9200"]
index => "nginx-error-%{+YYYY.MM.dd}"
}
}
}

重启logstash:

1
systemctl restart logstash

4.2.4、配置Kibana展示日志

配置方法与上同,索引必须得写入es,才可以在kibana上添加索引和显示数据。
匹配索引:nginx-access* ,nginx-

查看Pod访问日志:

至此,使用Filebeat + ELK搭建的日志收集平台,完成了对k8s集群组件日志的监控,以及对集群内部署的Pod容器日志进行监控;本文也是先入门,后面各种监控方法还待自行研究,比如如何批量配置监控等。

参考文章:

-------------本文结束感谢您的阅读-------------