kubernetes日志备份解决ELK中日志丢失问题
背景
为解决日志在ELK中偶发性丢失问题,需要对应用日志进行备份,当关键日志缺失后可以对原始日志进行查询。应用日志除了传ELK,在本地(docker内部)也保存一份原始文件,路径为/opt/logs
并且通过logback相关配置可以对日志进行自动归档。
方案
总体方案
总体方案是在主机上通过本地文件系统找到应用在容器内的日志文件,借助rsync进行备份,再通过crontab配置定时任务就能实现日志的备份。
实现
docker本质就是一个根文件系统(roots)+Linux内核程序,docker内部所有的文件在宿主机上都有对应的映射,通过docker inspect
命令可以查看容器在宿主机上文件系统路径
# docker inspect 84be0c7fd47b --format '{{.GraphDriver.Data.MergedDir }}' /u01/docker/overlay2/a3226f727cf8217bff0bfc8036201834260a50502c7e6b5eb0672a5305665c0e/merged
我们进入该目录
root@k8s-node-dev-10:/u01/docker/overlay2/a3226f727cf8217bff0bfc8036201834260a50502c7e6b5eb0672a5305665c0e/merged# ll total 156444 drwxr-xr-x 1 root root 3488 Oct 19 01:42 ./ drwx--x--- 5 root root 3488 Oct 19 01:42 ../ -rw-r--r-- 1 root root 159961293 Oct 19 01:41 app.jar drwxr-xr-x 1 root root 3488 May 15 01:13 bin/ drwxr-xr-x 1 root root 3488 Oct 19 01:42 dev/ -rwxr-xr-x 1 root root 0 Oct 19 01:42 .dockerenv* -rwxrwxrwx 1 root root 1756 May 29 00:59 entrypoint.sh* drwxr-xr-x 1 root root 3488 Oct 19 01:42 etc/ drwxr-xr-x 2 root root 3488 May 9 2019 home/ drwxr-xr-x 1 root root 3488 May 15 01:15 lib/ drwxr-xr-x 2 root root 3488 May 15 01:13 lib64/ drwxr-xr-x 5 root root 3488 May 9 2019 media/ drwxr-xr-x 2 root root 3488 May 9 2019 mnt/ drwxr-xr-x 1 root root 3488 Oct 19 01:42 opt/ dr-xr-xr-x 2 root root 3488 May 9 2019 proc/ drwx------ 1 root root 3488 Oct 30 06:49 root/ drwxr-xr-x 1 root root 3488 Oct 19 01:42 run/ drwxr-xr-x 1 root root 3488 May 15 01:13 sbin/ drwxr-xr-x 2 root root 3488 May 9 2019 srv/ drwxr-xr-x 2 root root 3488 May 9 2019 sys/ drwxrwxrwt 2 root root 3488 May 9 2019 tmp/ drwxr-xr-x 1 root root 3488 Oct 19 01:42 usr/ drwxr-xr-x 1 root root 3488 May 9 2019 var/
可以发现就是容器内的Linux文件系统,我们可以通过以下脚本,显示出所有容器在主机上的文件系统路径
for container in $(docker ps --all --quiet --format '{{ .Names }}'); do log_path=$(docker inspect $container --format '{{.GraphDriver.Data.MergedDir }}') echo $log_path done
由于日志保存在容器内部的/opt/logs
目录下,对应主机路径就是log_path/opt/logs
目录,找到文件路径后,我们需要知道该文件对应的服务名称,从路径上我们只能得到一个类似a3226f727cf8217bff0bfc8036201834260a50502c7e6b5eb0672a5305665c0e
的ID,那怎么根据这个ID获取到服务名称呢,kubernetes在启动应用docker容器时,会给容器打上标签,其中就包含了应用名称,我们通过inspect命令就可以查看
# docker inspect 84be0c7fd47b .... "Labels": { "annotation.io.kubernetes.container.hash": "f44b328d", "annotation.io.kubernetes.container.ports": "[{\"name\":\"8080tcp2\",\"containerPort\":8080,\"protocol\":\"TCP\"}]", "annotation.io.kubernetes.container.restartCount": "0", "annotation.io.kubernetes.container.terminationMessagePath": "/dev/termination-log", "annotation.io.kubernetes.container.terminationMessagePolicy": "File", "annotation.io.kubernetes.pod.terminationGracePeriod": "30", "io.kubernetes.container.logpath": "/var/log/pods/xinyou-application_xinyou-service-message-7745fd9699-drkzg_26e825a2-8f5e-4b5b-aed1-758139fc019c/xinyou-service-message/0.log", "io.kubernetes.container.name": "xinyou-message-service", "io.kubernetes.docker.type": "container", "io.kubernetes.pod.name": "xinyou-message-service-7745fd9699-drkzg", "io.kubernetes.pod.namespace": "xinyou-application", "io.kubernetes.pod.uid": "26e825a2-8f5e-4b5b-aed1-758139fc019c", "io.kubernetes.sandbox.id": "7bc9954a02c7e43a1a21b8cc47e09f86ada8f6e8584c49150c67d77dc13b6832" } ....
其中io.kubernetes.container.name
就是服务名称,io.kubernetes.pod.name
是pod名称,io.kubernetes.container.name
就是命名空间,所以拿到ID后我们可以通过inspect获取到服务 名称,有了原始文件路径,服务名称后,就可以写备份脚本
#!/bin/bash for container in $(docker ps --all --quiet --format '{{ .Names }}'); do log_path=$(docker inspect $container --format '{{.GraphDriver.Data.MergedDir }}') log_path=${log_path}/opt/logs/ service_name=$(docker inspect $container --format '{{ index .Config.Labels "io.kubernetes.container.name" }}') pod_name=$(docker inspect $container --format '{{ index .Config.Labels "io.kubernetes.pod.name" }}') target_path=/u01/logbackup/$service_name/$pod_name if [ -d "$log_path" ]; then echo "sync $service_name/$pod_name from $log_path to $target_path" mkdir -p $target_path rsync -av "$log_path" "$target_path" >log_backup.log fi done
解释下脚本内容
通过
docker ps --all
获取到所有容器列表,因为加了--all
命令,所以也包含停止运行的容器,这里为什么要包含停止运行的容器,原因是脚本执行是周期性的,假设在执行周期内容器停止运行了,那么就会失去这段时间的日志,所以就算是停止运行的容器也要同步日志。log_path就是日志在主机上的路径
service_name就是服务名称,读取的是io.kubernetes.container.name这个标签
target_path备份目标路径,这里路径加上了pod_name,原因是一个主机上可能运行服务的多个副本,如果不加上pod_name,有可能两个副本的日志会相互覆盖,因为日志名称是一样的。
通过rsync命令进行同步,rsync命令可以实现增量同步,速度和效率都远远比cp命令高
脚本只对包含
opt/logs
的容器进行日志备份,如果有额外情况需要更改脚本
配置crontab就可以定时执行脚本进行备份任务
* * * * * /u01/scripts/log_backup.sh
这里是一分钟执行一次,这个频率其实可以更低,因为我们有将停止的容器包含进去,所以频率低一些也不会有日志丢失。
以下是日志同步后的日志备份目录文件夹分布情况:
root@k8s-node-dev-10:/u01/logbackup# tree -d . ├── xinyou-mes │ └── xinyou-mes-6c5cd57447-qgk29 ├── xinyou-gateway │ └── xinyou-gateway-67bff75986-qsgsq ├── xinyou-bbc-service │ └── xinyou-bbc-service-7455c4dc86-kj6tp ├── xinyou-ddr-service │ └── xinyou-ddr-service-c774bbbb7-mh7fk ├── xinyou-iam-service │ └── xinyou-iam-service-59b844df47-5h5gs ├── xinyou-review-service │ └── xinyou-review-service-856c5f545c-lxmz6 ├── xinyou-sass-oa │ └── xinyou-sass-oa-77845c55bb-jjmf2 ├── xinyou-service-message │ └── xinyou-service-message-7745fd9699-drkzg └── xinyou-tables-service └── xinyou-tables-service-7fd66d4c95-7pcst
以上就是kubernetes日志备份方案细节探究的详细内容,更多关于kubernetes日志备份的资料请关注脚本之家其它相关文章!
相关文章
教你在k8s上部署HADOOP-3.2.2(HDFS)的方法
这篇文章主要介绍了k8s-部署HADOOP-3.2.2(HDFS)的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2022-04-04K8s中的临时容器Ephemeral Containers使用
这篇文章主要介绍了K8s中的临时容器Ephemeral Containers使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2024-07-07详解Rainbond云原生平台简化Kubernetes业务问题排查
这篇文章主要介绍了详解Rainbond云原生平台简化Kubernetes业务问题排查,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2023-03-03在Kubernetes集群中搭建Istio微服务网格的过程详解
这篇文章主要介绍了在Kubernetes集群中搭建Istio微服务网格,我们采用default配置档部署istio网格,istioctl install命令不指定任何配置档默认就是呀default配置档,需要的朋友可以参考下2022-05-05阿里云kubernetes查找镜像中jar包的方法(docker查看镜像中的jar)
这篇文章主要给大家介绍了关于阿里云kubernetes查找镜像中jar包的方法,也就是在docker查看镜像中的jar,文中通过图文介绍的非常详细,需要的朋友可以参考下2022-09-09
最新评论