Sentry上线将近两个月以后崩溃,崩溃的原因有两个:
1、运行postgresql容器的机器磁盘空间被耗尽,导致数据库停止服务
2、运行Nginx和sentry web的docker无法重启。
修复sentry的过程因此分为两个步骤:
1、对postgresql中30天以前的数据进行清理,恢复磁盘空间。
2、对运行sentry web和nginx的机器重装docker,由于nginx和sentry web server不保存状态,因此重新搭建web server不会造成数据丢失。
这里对应的操作应该被称为database rotation,sentry本身有名为cleanup的工具,可以利用cleanup删除过期数据。
但是,cleanup要求数据库提供服务。在sentry 搭建时,postgresql为主备搭建,主库所在机器磁盘已被耗尽,数据库服务无法启动。幸好备库还有20G左右的剩余空间,可以考虑清理备库的磁盘空间,然后将备库升为主库,再将原主库磁盘清空,同步新主库的数据。这样做会损失一部分数据,好在sentry记录的数据不是特别重要。
sentry的cleanup工具操作帮助为
root@9acfe6561812:/# sentry cleanup --help
Usage: sentry cleanup [OPTIONS]
Delete a portion of trailing data based on creation date.
All data that is older than `--days` will be deleted. The default for this is 30 days. In
the default setting all projects will be truncated but if you have a specific project you want
to limit this to this can be done with the `--project` flag which accepts a project ID or a
string with the form `org/project` where both are slugs.
Options:
--days INTEGER Numbers of days to truncate on. [default: 30]
--project TEXT Limit truncation to only entries from project.
--concurrency INTEGER The number of concurrent workers to run. [default: 1]
-q, --silent Run quietly. No output on success.
-m, --model TEXT
--help Show this message and exit.
操作在sentry web所在服务器上进行,对postgresql进行远程cleanup。
docker run -d --name sentry_cleanup
...省略若干其他配置
sentry --config /sentry_conf.py cleanup --days 30
这样可以删除当前日期间30日前的数据。
执行了cleanup之后,使用df -h命令,发现数据库所占用的磁盘空间并没有减小,剩余空间依然只有20多G,这是因为cleanup的使用delete命令删除postgresql数据,但postgrdsql对于delete, update等操作,只是将对应行标志为DEAD,并没有真正释放磁盘空间。(参考:http://www.cnblogs.com/littlehb/archive/2013/04/28/3048892.html)
需要执行vacuum操作,将这些标记为DEAD行记录所占用的空间彻底释放。
vacuum操作可以使用postgresql 自带的vacuumdb工具, vacuumdb操作帮助为:
root@s1226:/# vacuumdb --help
vacuumdb cleans and analyzes a PostgreSQL database.
Usage:
vacuumdb [OPTION]... [DBNAME]
Options:
-a, --all vacuum all databases
-d, --dbname=DBNAME database to vacuum
-e, --echo show the commands being sent to the server
-f, --full do full vacuuming
-F, --freeze freeze row transaction information
-q, --quiet don't write any messages
-t, --table='TABLE[(COLUMNS)]' vacuum specific table(s) only
-v, --verbose write a lot of output
-V, --version output version information, then exit
-z, --analyze update optimizer statistics
-Z, --analyze-only only update optimizer statistics
-?, --help show this help, then exit
Connection options:
-h, --host=HOSTNAME database server host or socket directory
-p, --port=PORT database server port
-U, --username=USERNAME user name to connect as
-w, --no-password never prompt for password
-W, --password force password prompt
--maintenance-db=DBNAME alternate maintenance database
Read the description of the SQL command VACUUM for details.
Report bugs to .
注意vacuumdb需要以postgres用户身份运行,可以配合sudo -u操作,比如,对sentry_进行空间整理的命令为:
root@s1226:/# sudo -u postgres vacuumdb -U postgres -d sentry -t nodestore_node -v -f --analyze
sudo: unable to resolve host s1226.bx.sys.d
INFO: vacuuming "public.nodestore_node"
INFO: "nodestore_node": found 75819 removable, 705972 nonremovable row versions in 461966 pages
DETAIL: 0 dead row versions cannot be removed yet.
CPU 12.00s/52.63u sec elapsed 126.17 sec.
INFO: analyzing "public.nodestore_node"
INFO: "nodestore_node": scanned 30000 of 59846 pages, containing 353649 live rows and 0 dead rows; 30000 rows in sample, 705727 estimated total rows
打印出的信息不是太懂,猜测是发现了那些row是dead,并且是removable的,然后释放空间,对存储空洞进行整理。
虽然看不太懂,但是对所有数据表整理后,发现磁盘被释放出了很大一部分空间:
root@s1226:/# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/docker-253:17-1048577-21e6cfea1af36f66bd554fbb5b5eec529d63692288a2d9115a9ee91d3457cb98 10G 501M 9.6G 5% /
tmpfs 3.9G 0 3.9G 0% /dev
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/vdb1 99G 36G 58G 39% /cluster/database
shm 64M 0 64M 0% /dev/shm
/dev/vda1 12G 1.7G 11G 14% /etc/keepalived/keepalive.conf
/cluster/database挂载的剩余空间由原先的20多G增长到了58G。
至此主库的空间已经整理完毕,然后启动一个备库,并运行keepalived,数据库的修复完成(丢失了一部分数据)
sentry系统中,我将nginx, sentry web, celery cron和celery worker部署在同一个host下,由于未查明的原因,运行两个月后docker挂掉了,重启docker后,重启容器会超时, 容器所在目录磁盘占用100%,有可能是被运行日志填满。
sentry web server本身不存储数据,修复比较简单,直接重新搭建就行了。但是搭建完毕之后,通过浏览器登录sentry 的管理界面,会有500 Internal Error的错误,由于线上的请求源源不断地过来,错误日志被淹没,一时找不到解决方法。
这种情况下,突破口是错误重现+错误定位,理清思路后操作如下:
1、对其中的一个server,关停对外的nginx容器,暂时拒绝外部请求,启动一个调试用的nginx容器,配一个域名为s1226的server
2、使用docker logs -f --tail sentry命令,监控sentry web server的日志(sentry 的日志都是直接输出到stdout的,在服务器内部并没有写入文件)
3、浏览器登录管理界面,前端遇到错误,此时后台发现了异常,原因是操作的一个不存在的数据表sentry_organizationavator
然后,根据stacktrace,跟踪源码,发现执行到了一个存在的文件,这时候才意识到,在搭建环境时,docker pull sentry没有指定版本,拉下来的镜像是sentry 8.13,而数据库对应的是sentry 8.11,更换了sentry版本后,问题解决。