前言

这个问题的来源是ceph社区里面一个群友的环境出现在85%左右的时候,启动osd报错,然后在本地文件系统当中进行touch文件的时候也是报错,df -i查询inode也是没用多少,使用的也是inode64挂载的,开始的时候排除了配置原因引起的,在ceph的邮件列表里面有一个相同问题,也是没有得到解决

看到这个问题比较感兴趣,就花了点时间来解决来定位和解决这个问题,现在分享出来,如果有类似的生产环境,可以提前做好检查预防工作

现象描述

ceph版本

[root@lab8107 mnt]# ceph -v

ceph version 10.2.9 (2ee413f77150c0f375ff6f10edd6c8f9c7d060d0)

我复现的环境为这个版本

查询使用空间



可以看到空间才使用了54%



可以看到,inode剩余比例很多,而文件确实无法创建

这个时候把一个文件mv出来,然后又可以创建了,并且可以写入比mv出来的文件更大的文件,写完一个无法再写入更多文件了

这里有个初步判断,不是容量写完了,而是文件的个数限制住了

那么来查询下文件系统的inode还剩余多少,xfs文件系统的inode是动态分配的,我们先检查无法写入的文件系统的

xfs_db -r -c "sb 0" -c "p" -c "freesp -s" /dev/sdb1|grep ifree



可以看到剩余的inode确实为0,这里确实是没有剩余inode了,所以通过df -i来判断inode是否用完并不准确,那个是已经使用值与理论值的相除的结果

查询xfs碎片,也是比例很低

定位问题

首先查看xfs上面的数据结构

xfs_db -r -c "sb 0" -c "p" -c "freesp -s " /dev/sdb1

上面的输出结果这里简单解释一下,这里我也是反复比对和查看资料才理解这里的意思,这里有篇novell的资料有提到这个,这里我再拿一个刚刚格式化完的分区结果来看下

这里用我自己的理解来描述下,这个extents的剩余数目是动态变化的,刚分完区的那个,有4个1048576-1220608左右的逻辑区间,而上面的无法写入数据的数据结构,剩下的extent的平均大小为22个block,而这样的blocks总数有1138886个,占总体的99.85,也就是剩余的空间的的extents所覆盖的区域全部是16个block到31个block的这种空洞,相当于蛋糕被切成很多小块了,大的都拿走了,剩下的总量还很多,但是都是很小的碎蛋糕,所以也没法取了

默认来说inode chunk 为64 ,也就是需要64*inodesize的存储空间来存储inode,这个剩下的空间已经不够分配了

解决办法

下个段落会讲下为什么会出现上面的情况,现在先说解决办法,把文件mv出来,然后mv进去,这个是在其他场景下的一个解决方法,这个操作要小心,因为有扩展属性,操作不小心会弄掉了,这里建议用另外一个办法xfs_dump的方法

我的环境比较小,20G的盘,如果盘大就准备大盘,这里是验证是否可行

xfsdump -L osd0 -M osd0 -f /mnt/osd0 /var/lib/ceph/osd/ceph-0

还原回去

[root@lab8107 ceph-0]# xfsrestore -f /mnt/osd0 /var/lib/ceph/osd/ceph-0
xfsrestore: using file dump (drive_simple) strategy
xfsrestore: version 3.1.4 (dump format 3.0) - type ^C for status and control
xfsrestore: ERROR: unable to create /var/lib/ceph/osd/ceph-0/xfsrestorehousekeepingdir: No space left on device
xfsrestore: Restore Status: ERROR

直接还原还是会有问题,没有可以写的地方了,这里因为已经dump了一份,这里就mv pg的数据目录出去

mv /var/lib/ceph/osd/ceph-0/current/ /mnt

开始还原

xfsrestore  -o -f /mnt/osd0 /var/lib/ceph/osd/ceph-0

还原以后如果有权限需要处理的就处理下权限,先检查下文件系统的数据结构



可以看到数据结构已经很理想了

然后启动osd

systemctl restart ceph-osd@0

然后检查下数据是不是都可以正常写进去了

  • 如果出现了上面的空间已经满了的情况,处理的时候需要注意
  • 备份好数据
  • 单个盘进行处理
  • 备份的数据先保留好以防万一
  • 启动好了后,验证下集群的状态后再继续,可以尝试get下数据检查数据

为什么会出现这样

我们在本地文件系统里面连续写100个文件

准备一个a文件里面有每行150个a字符,700行,这个文件大小就是100K

[root@lab8107 test]# seq 100|xargs -i dd if=a of=a{} bs=100K count=1

检查文件的分布

[root@lab8107 test]# seq 100|xargs -i xfs_bmap -v a{} |less

大部分情况下这个block的分配是连续的

先检查下当前的数据结构

我们把刚刚的100个对象put到集群里面去,监控下集群的数据目录的写入情况

inotifywait -m --timefmt '%Y %B %d %H:%M:%S' --format '%T %w %e %f' -r -m /var/lib/ceph/osd/ceph-0/

put数据进去

for a in `ls ./`;do rados -p rbd put $a $a;done





查看对象的数据,里面并没有连续起来,并且写入的数据的方式是:

打开文件,设置扩展属性,填充内容,设置属性,关闭,很多并发在一起做

写完的数据结构

结果就是在100K这个数据模型下,会产生很多小的block空隙,最后就是无法写完文件的情况,这里产生空隙并不是很大的问题,问题是这里剩下的空隙无法完成inode的动态分配的工作,这里跟一个格式化选项的变化有关

准备一个集群

然后写入(一直写)

rados -p rbd bench -b 100K 6000 write --no-cleanup

就可以必现这个问题,可以看到上面的从16-31 block的区间从 12 extents涨到了111 extents

解决办法

用deploy在部署的时候默认的格式化参数为

command_check_call: Running command: /usr/sbin/mkfs -t xfs -f -i size=2048 -- /dev/sdb1

这个isize设置的是2048,这个在后面剩余的空洞比较小的时候就无法写入新的数据了,所以在ceph里面存储100K这种小文件的场景的时候,把mkfs.xfs的isize改成默认的256就可以提前避免这个问题

修改 /usr/lib/python2.7/site-packages/ceph_disk/main.py的256行

    xfs=[
# xfs insists on not overwriting previous fs; even if we wipe
# partition table, we often recreate it exactly the same way,
# so we'll see ghosts of filesystems past
'-f',
'-i', 'size=2048',
],

改成

 '-i', 'size=256',



这个地方检查下是不是对的,然后就可以避免这个问题了,可以测试下是不是一直可以写到很多,我的这个测试环境写到91%还没问题

总结

在特定的数据写入模型下,可能出现一些可能无法预料的问题,而参数的改变可能也没法覆盖所有场景,本篇就是其中的一个比较特殊的问题,定位好问题,在遇到的时候能够解决,或者提前避免掉

后续

在升级了内核到

[root@lab8107 ~]# uname  -a
Linux lab8107 4.13.0-1.el7.elrepo.x86_64 #1 SMP Sun Sep 3 19:07:24 EDT 2017 x86_64 x86_64 x86_64 GNU/Linux

升级xfsprogs到

[root@lab8107 ~]# rpm -qa|grep xfsprogs
xfsprogs-4.12.0-4.el7.centos.x86_64

重新部署osd,还是一样的isize=2048,一样的写入模型

[root@lab8107 ~]# df -h /var/lib/ceph/osd/ceph-0
Filesystem Size Used Avail Use% Mounted on
/dev/sdb1 9.4G 9.0G 395M 96% /var/lib/ceph/osd/ceph-0
meta_uuid = 00000000-0000-0000-0000-000000000000
from to extents blocks pct
1 1 545 545 0.50
2 3 665 1666 1.52
4 7 1624 8927 8.12
8 15 1853 19063 17.34
16 31 19 352 0.32
4096 8191 1 7694 7.00
16384 32767 3 71659 65.20
total free extents 4710
total free blocks 109906
average free extent size 23.3346
[root@lab8107 ~]# xfs_db -r -c "sb 0" -c "p" -c "freesp -s " /dev/sdb1

可以看到已经很少的稀疏空间了,留下比较大的空间,这个地方应该是优化了底层数据存储的算法

另外,xfs的inode是动态分配的,xfs官方也考虑到了这个可能空洞太多无法分配inode问题,这个是最新的mkfs.xfs的man page

 sparse[=value]
Enable sparse inode chunk allocation. The value is either 0 or 1, with 1 signifying that sparse allocation is enabled. If the value is omitted, 1 is assumed. Sparse inode allocation is disabled by default. This feature is only available for filesystems formatted with -m crc=1. When enabled, sparse inode allocation allows the filesystem to allocate smaller than the standard 64-inode chunk when free space is severely limited. This feature is useful for filesystems that might fragment free space over time such that no free extents are large enough to accommodate a chunk of 64 inodes. Without this feature enabled, inode allocations can fail with out of space errors under severe fragmented free space conditions.

是以64个inode为chunk来进行动态分配的,应该是有两个chunk,也就是动态查询看到的是128个inode以下,在更新到最新的版本以后,因为已经没有那么多空洞了,所以即使在没开这个稀疏inode的情况下,ceph的小文件也能够把磁盘写满

变更记录

Why Who When
创建 武汉-运维-磨渣 2017-09-04
增加更新内核和xfsprogs的验证 武汉-运维-磨渣 2017-09-05

osd磁盘空间足够无法写入数据的分析与解决的更多相关文章

  1. docker容器存放目录磁盘空间满了,转移数据修改Docker默认存储位置

    原文:docker容器存放目录磁盘空间满了,转移数据修改Docker默认存储位置 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_3767485 ...

  2. tokudb引擎磁盘空间不足导致写入失败的调查

    故障现象 2016.1.1号早上4点左右,zabbi数据库服务器报警,写入数据失败.登陆机器后检查发现磁盘空间使用95%没有用满,进去zabbix数据库,执行insert命令提示错误“errir 10 ...

  3. 系统磁盘空间/dev/xvda1占满原因分析

    由于项目原因需要定期检查磁盘空间占用情况,常用检查命令如下: 1.查看磁盘空间大小 df -lh 2.查看对应文件大小 du --max-depth=1 -h / 于一日发现在使用Flume + Ka ...

  4. Linux 误删catlina.out导致磁盘空间爆满,无法查询到大文件解决办法

    大概是前俩天吧,发现公司的网站不定时的出现接口调不通的情况,便让手下小弟去服务器上查看一下,小弟告我磁盘空间满了,于是我让他处理一下.结果没想到他直接把 catlina.out 给干掉了.后果可想而知 ...

  5. ElasticSearch 因为磁盘空间不够引起的数据插入错误。(message [ClusterBlockException[blocked by: [FORBIDDEN/12/index read-only / allow delete (api)];]])

    ES升级到624测试从Kettle插入数据的时候,经常提示如下错误 message [ClusterBlockException[blocked by: [FORBIDDEN/12/index rea ...

  6. 【ORACLE】删除表空间,没有删除数据文件怎么办?解决办法

    创建表空间 SQL> create tablespace TEST datafile='+DATA/rac/datafile/test01.dbf' size 1g; Tablespace cr ...

  7. 关于数据库报Packet for query is too large (1986748 > 1048576)(mysql写入数据过大)的解决办法

    方法2 (很妥协,很纠结的办法) 进入mysql server 在mysql 命令行中运行 set global max_allowed_packet = 2*1024*1024*10 然后关闭掉这此 ...

  8. mysql写入数据乱码问题的解决

    mysql默认编码为latin. 我的mysql版本为5.6.安装路径下没有my.ini,但是有my-default.ini.其实mysql没有配置文件也是可以启动的,但是为了设置编码,需要将my-d ...

  9. SQL Server 磁盘请求超时的833错误原因分析以及解决

    本文出处:http://www.cnblogs.com/wy123/p/6984885.html 最近遇到一个SQL Server服务器响应极度缓慢,并且出现客户端请求报错的情况,在数据库中的erro ...

随机推荐

  1. 网络最大流Dinic

    1.什么是网络最大流 形象的来说,网络最大流其实就是这样一个生活化的问题:现在有一个由许多水管组成的水流系统,每一根管道都有自己的最大通过水流限制(流量),超过这个限制水管会爆(你麻麻就会来找你喝茶q ...

  2. 【应用程序见解 Application Insights】在Application Insights中通过自定义查询结果定义指标并显示在Dashboard中

    问题情形 通过Application Insights收集到指标数据后,如Request,Trace,Exception.但是默认的Insights图表不能满足业务的需求,需要自定义相应的类SQL语句 ...

  3. Linux终端 terminal

    终端 一个可以进行人机交互的界面 物理终端 设备终端:键盘.鼠标.显示器 终端类型 控制台终端: /dev/console 串行终端:/dev/ttyS# 虚拟终端:tty:teletypewrite ...

  4. CSS动画菜鸡记录板

    Transition 过渡属性: (background 1s linear 0s) 缓动函数 linear,在 easings.net 可找到相应的功能 若想要多次不同执行,用逗号隔开 Animat ...

  5. 在PostgreSQL中CREATE STATISTICS

    如果你用Postgres做了一些性能调优,你可能用过EXPLAIN.EXPLAIN向你展示了PostgreSQL计划器为所提供的语句生成的执行计划,它显示了语句所引用的表如何被扫描(使用顺序扫描.索引 ...

  6. Spring学习-Bean的基本概念知识

    4月份开始复习一遍spring相关知识.让自己巩固一下spring大法的深奥益处,所以就看了大佬的博客,转载留下来日后继续研读.认为重点的标记为红色 转载自:http://www.cnblogs.co ...

  7. spring3.X版本知识点

    一.SpringMVC重点注解 @Controller 1.@Controller 与 @Component 实际应用中作用等价.     2.和Struct一样,也是单例,意味着被多个请求线程共享, ...

  8. Redis---02Redis的Java客户端

    一.注意 连接Linux里面安装的Redis,需要执行以下步骤: ①禁用防火墙(CentOS 7):systemctl stop firewalld.service ②在redis.conf中注释掉 ...

  9. requests请求获取cookies的字典格式

    python中requests请求的cookies值一般是jar包,如何将cookies值改为字典,此处运用了方法.举例如下: import  requests response = requests ...

  10. STM32入门系列-启动文件介绍

    在启动文件内部使用的都是汇编语言,这个文件的作用是负责执行微控制器从"复位"到"开始执行 main 函数"中间这段启动时间所必须进行的工作.它完成的具体工作有: ...