EFK
插件是k8s
项目的一个日志解决方案,它包括三个组件:Elasticsearch, Fluentd, Kibana;Elasticsearch 是日志存储和日志搜索引擎,Fluentd 负责把k8s
集群的日志发送给 Elasticsearch, Kibana 则是可视化界面查看和检索存储在 ES 中的数据。
参考官方部署文档的基础上使用本项目manifests/efk/
部署,以下为几点主要的修改:
- 修改 fluentd-es-configmap.yaml 中的部分 journald 日志源(增加集群组件服务日志搜集)
- 修改官方docker镜像,方便国内下载加速
- 修改 es-statefulset.yaml 支持日志存储持久化等
- 增加自动清理日志,见后文
第四部分
$ kubectl apply -f /etc/ansible/manifests/efk/
$ kubectl apply -f /etc/ansible/manifests/efk/es-without-pv/
kubectl get pods -n kube-system|grep -E 'elasticsearch|fluentd|kibana'
elasticsearch-logging-0 1/1 Running 0 19h
elasticsearch-logging-1 1/1 Running 0 19h
fluentd-es-v2.0.2-6c95c 1/1 Running 0 17h
fluentd-es-v2.0.2-f2xh8 1/1 Running 0 8h
fluentd-es-v2.0.2-pv5q5 1/1 Running 0 8h
kibana-logging-d5cffd7c6-9lz2p 1/1 Running 0 1m
kibana Pod 第一次启动时会用较长时间(10-20分钟)来优化和 Cache 状态页面,可以查看 Pod 的日志观察进度,如下等待 Ready
状态
$ kubectl logs -n kube-system kibana-logging-d5cffd7c6-9lz2p -f
...
{"type":"log","@timestamp":"2018-03-13T07:33:00Z","tags":["listening","info"],"pid":1,"message":"Server running at http://0:5601"}
{"type":"log","@timestamp":"2018-03-13T07:33:00Z","tags":["status","ui settings","info"],"pid":1,"state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
推荐使用kube-apiserver
方式访问(可以使用basic-auth、证书和rbac等方式进行认证授权),获取访问 URL
- 开启 apiserver basic-auth(用户名/密码认证):
easzctl basic-auth -s -u admin -p test1234
$ kubectl cluster-info | grep Kibana
Kibana is running at https://192.168.1.10:8443/api/v1/namespaces/kube-system/services/kibana-logging/proxy
浏览器访问 URL:https://192.168.1.10:8443/api/v1/namespaces/kube-system/services/kibana-logging/proxy
,然后使用basic-auth
或者证书
的方式认证后即可,关于认证可以参考dashboard文档
首次登陆需要在Management
- Index Patterns
创建 index pattern
,可以使用默认的 logstash-* pattern,点击下一步;在 Time Filter field name 下拉框选择 @timestamp; 点击创建Index Pattern后,稍等几分钟就可以在 Discover 菜单看到 ElasticSearch logging 中汇聚的日志;
日志数据是存放于 Elasticsearch POD
中,但是默认情况下它使用的是emptyDir
存储类型,所以当 POD
被删除或重新调度时,日志数据也就丢失了。以下讲解使用NFS
服务器手动(静态)创建PV
持久化保存日志数据的例子。
- 准备一个nfs服务器,如果没有可以参考nfs-server创建。
- 配置nfs服务器的共享目录,即修改
/etc/exports
(根据实际网段替换192.168.1.*
),修改后重启systemctl restart nfs-server
。
/share 192.168.1.*(rw,sync,insecure,no_subtree_check,no_root_squash)
/share/es0 192.168.1.*(rw,sync,insecure,no_subtree_check,no_root_squash)
/share/es1 192.168.1.*(rw,sync,insecure,no_subtree_check,no_root_squash)
/share/es2 192.168.1.*(rw,sync,insecure,no_subtree_check,no_root_squash)
- 请按实际日志容量需求修改
es-static-pv/es-statefulset.yaml
文件中 volumeClaimTemplates 设置的 storage: 4Gi 大小 - 请根据实际nfs服务器地址、共享目录、容量大小修改
es-static-pv/es-pv*.yaml
文件中对应的设置
# 如果之前已经安装了默认的EFK,请用以下两个命令先删除它
$ kubectl delete -f /etc/ansible/manifests/efk/
$ kubectl delete -f /etc/ansible/manifests/efk/es-without-pv/
# 安装静态PV 的 EFK
$ kubectl apply -f /etc/ansible/manifests/efk/
$ kubectl apply -f /etc/ansible/manifests/efk/es-static-pv/
- 目录
es-static-pv
下首先是利用 NFS服务预定义了三个 PV资源,然后在es-statefulset.yaml
定义中使用volumeClaimTemplates
去匹配使用预定义的 PV资源;注意 PV参数:accessModes
storageClassName
storage
容量大小必须两边匹配。
- 1.集群中查看
pod
pv
pvc
等资源
$ kubectl get pods -n kube-system|grep -E 'elasticsearch|fluentd|kibana'
elasticsearch-logging-0 1/1 Running 0 10m
elasticsearch-logging-1 1/1 Running 0 10m
fluentd-es-v2.0.2-6c95c 1/1 Running 0 10m
fluentd-es-v2.0.2-f2xh8 1/1 Running 0 10m
fluentd-es-v2.0.2-pv5q5 1/1 Running 0 10m
kibana-logging-d5cffd7c6-9lz2p 1/1 Running 0 10m
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-es-0 4Gi RWX Recycle Bound kube-system/elasticsearch-logging-elasticsearch-logging-0 es-storage-class 1m
pv-es-1 4Gi RWX Recycle Bound kube-system/elasticsearch-logging-elasticsearch-logging-1 es-storage-class 1m
pv-es-2 4Gi RWX Recycle Available es-storage-class 1m
$ kubectl get pvc --all-namespaces
NAMESPACE NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
kube-system elasticsearch-logging-elasticsearch-logging-0 Bound pv-es-0 4Gi RWX es-storage-class 2m
kube-system elasticsearch-logging-elasticsearch-logging-1 Bound pv-es-1 4Gi RWX es-storage-class 1m
-
2.网页访问
kibana
查看具体的日志,如上须等待(约15分钟)kibana Pod
优化和 Cache 状态页面,达到Ready
状态。 -
3.登陆 NFS Server 查看对应目录和内部数据
$ ls /share
es0 es1 es2
PV
作为集群的存储资源,StatefulSet
依靠它实现 POD的状态数据持久化,但是当 StatefulSet
动态伸缩时,它的 PVC
请求也会变化,如果每次都需要管理员手动去创建对应的 PV
资源,那就很不方便;因此 K8S还提供了 provisioner
来动态创建 PV
,不仅节省了管理员的时间,还可以根据不同的 StorageClasses
封装不同类型的存储供 PVC 选用。
- 此功能需要
API-SERVER
参数--admission-control
字符串设置中包含DefaultStorageClass
,本项目中已经开启。 provisioner
指定 Volume 插件的类型,包括内置插件(如 kubernetes.io/glusterfs)和外部插件(如 external-storage 提供的 ceph.com/cephfs,nfs-client等),以下讲解使用nfs-client-provisioner
来动态创建PV
来持久化保存EFK
的日志数据。
确保 /etc/exports
配置如下共享目录,并确保 /share
目录可读可写权限,否则可能因为权限问题无法动态生成 PV的对应目录。(根据实际情况替换IP段192.168.1.*
)
/share 192.168.1.*(rw,sync,insecure,no_subtree_check,no_root_squash)
- 首先根据集群存储创建nfs-client-provisioner
- 然后按实际需求修改
es-dynamic-pv/es-statefulset.yaml
文件中 volumeClaimTemplates 设置的 storage: 4Gi 大小
# 如果之前已经安装了默认的EFK或者静态PV EFK,请用以下命令先删除它
$ kubectl delete -f /etc/ansible/manifests/efk/
$ kubectl delete -f /etc/ansible/manifests/efk/es-without-pv/
$ kubectl delete -f /etc/ansible/manifests/efk/es-static-pv/
# 安装动态PV 的 EFK
$ kubectl apply -f /etc/ansible/manifests/efk/
$ kubectl apply -f /etc/ansible/manifests/efk/es-dynamic-pv/
- 首先
nfs-client-provisioner.yaml
创建一个工作 POD,它监听集群的 PVC请求,并当 PVC请求来到时调用nfs-client
去请求nfs-server
的存储资源,成功后即动态生成对应的 PV资源。 nfs-dynamic-storageclass.yaml
定义 NFS存储类型的类型名nfs-dynamic-class
,然后在es-statefulset.yaml
中必须使用这个类型名才能动态请求到资源。
- 1.集群中查看
pod
pv
pvc
等资源
$ kubectl get pods -n kube-system|grep -E 'elasticsearch|fluentd|kibana'
elasticsearch-logging-0 1/1 Running 0 10m
elasticsearch-logging-1 1/1 Running 0 10m
fluentd-es-v2.0.2-6c95c 1/1 Running 0 10m
fluentd-es-v2.0.2-f2xh8 1/1 Running 0 10m
fluentd-es-v2.0.2-pv5q5 1/1 Running 0 10m
kibana-logging-d5cffd7c6-9lz2p 1/1 Running 0 10m
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-50644f36-358b-11e8-9edd-525400cecc16 4Gi RWX Delete Bound kube-system/elasticsearch-logging-elasticsearch-logging-0 nfs-dynamic-class 10m
pvc-5b105ee6-358b-11e8-9edd-525400cecc16 4Gi RWX Delete Bound kube-system/elasticsearch-logging-elasticsearch-logging-1 nfs-dynamic-class 10m
$ kubectl get pvc --all-namespaces
NAMESPACE NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
kube-system elasticsearch-logging-elasticsearch-logging-0 Bound pvc-50644f36-358b-11e8-9edd-525400cecc16 4Gi RWX nfs-dynamic-class 10m
kube-system elasticsearch-logging-elasticsearch-logging-1 Bound pvc-5b105ee6-358b-11e8-9edd-525400cecc16 4Gi RWX nfs-dynamic-class 10m
-
2.网页访问
kibana
查看具体的日志,如上须等待(约15分钟)kibana Pod
优化和 Cache 状态页面,达到Ready
状态。 -
3.登陆 NFS Server 查看对应目录和内部数据
$ ls /share # 可以看到类似如下的目录生成
kube-system-elasticsearch-logging-elasticsearch-logging-0-pvc-50644f36-358b-11e8-9edd-525400cecc16
kube-system-elasticsearch-logging-elasticsearch-logging-1-pvc-5b105ee6-358b-11e8-9edd-525400cecc16
我们知道日志都存储在elastic集群中,且日志每天被分割成一个index,例如:
/ # curl elasticsearch-logging:9200/_cat/indices?v
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open logstash-2019.04.29 ejMBlRcJQvqK76xIerenYg 5 1 69864 0 65.9mb 32.9mb
green open logstash-2019.04.28 hacNCuQVTQCUL62Sl8avOA 5 1 17558 0 21.3mb 10.6mb
green open .kibana_1 MVjF8lQeRDeKfoZcDhA93A 1 1 2 0 30.1kb 15kb
green open logstash-2019.05.05 m2aD8X9RQ3u48DvVq18x_Q 5 1 31218 0 34.4mb 17.2mb
green open logstash-2019.05.01 66OjwM5wT--DZaVfzUdXYQ 5 1 50610 0 54.6mb 27.1mb
green open logstash-2019.04.30 L3AH165jT6izjHHa5L5g0w 5 1 56401 0 55.5mb 27.8mb
...
因此 EFK 中的日志自动清理,只要定时去删除 es 中的 index 即可,如下命令
$ curl -X DELETE elasticsearch-logging:9200/logstash-xxxx.xx.xx
基于 alpine:3.8 创建镜像es-index-rotator
查看Dockerfile,然后创建一个cronjob去完成清理任务
$ kubectl apply -f /etc/ansible/manifests/efk/es-index-rotator/
- 查看 cronjob
$ kubectl get cronjob -n kube-system
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
es-index-rotator 3 1 */1 * * False 0 19h 20h
- 查看日志清理情况
$ kubectl get pod -n kube-system |grep es-index-rotator
es-index-rotator-1557507780-7xb89 0/1 Completed 0 19h
# 查看日志,可以了解日志清理情况
$ kubectl logs -n kube-system es-index-rotator-1557507780-7xb89 es-index-rotator
HAVE FUN!