23

“网红架构师”解决你的Ceph 运维难题

 5 years ago
source link: https://studygolang.com/articles/15488?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

欢迎大家前往 腾讯云+社区 ,获取更多腾讯海量技术实践干货哦~

本文由 Tstack 发表于 云+社区专栏

本文为长篇连续剧,将分多个篇幅发表,主要介绍了从动手部署环境到后期运营故障处理过程中常见的问题,内容由浅入深,是居家旅行运维Ceph的必备良药。

Q1. 环境预准备

绝大多数MON创建的失败都是由于防火墙没有关导致的,亦或是SeLinux没关闭导致的。一定一定一定要关闭每个每个每个节点的防火墙(执行一次就好,没安装报错就忽视):

CentOS

sed -i 's/SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
setenforce 0
systemctl stop firewalld 
systemctl disable firewalld
# iptables -F
service iptables stop

Q2. 清理环境

MON部署不上的第二大问题就是在旧的节点部署MON,或者在这个节点部署MON失败了,然后重新 newmon create-initial ,请查看要部署MON的节点上的 /var/lib/ceph/mon/ 目录下是否为空,如果不为空,说明已经在这个目录部署过MON,再次部署会检测子目录下的 done 文件,由于有了这个文件,就不会再建立新的MON数据库,并且不会覆盖之,导致了部署时的各种异常,这里就不赘述了,直接给出万能清理大法:

对于任何需要新部署MON的节点,请到这个节点下执行如下指令,确保环境已经清理干净:

ps aux|grep ceph |awk '{print $2}'|xargs kill -9
ps -ef|grep ceph
#确保此时所有ceph进程都已经关闭!!!如果没有关闭,多执行几次。
rm -rf /var/lib/ceph/mon/*
rm -rf /var/lib/ceph/bootstrap-mds/*
rm -rf /var/lib/ceph/bootstrap-osd/*
rm -rf /var/lib/ceph/bootstrap-rgw/*
rm -rf /etc/ceph/*
rm -rf /var/run/ceph/*

请直接复制粘贴,遇到过好些个自己打错打漏删了目录的。

Q3. 部署前最后的确认

这里介绍的都是个案,不过还是需要提一下:

  • 确保每个节点的 hostname 都设置正确,并且添加至 /etc/hosts 文件中,然后同步到所有节点下。克隆出来的虚拟机或者批量建的虚拟机有可能发生此情形。
  • 确保以下目录在各个节点都存在:
  • /var/lib/ceph/
  • /var/lib/ceph/mon/
  • /var/lib/ceph/osd/
  • /etc/ceph/
  • /var/run/ceph/
  • 上面的目录,如果Ceph版本大于等于 jewel ,请确认权限均为 ceph:ceph ,如果是 root:root ,请自行 chown

Q4. 安装Ceph

官网指导方法是使用 ceph-deploy install nodeX ,但是因为是国外的源,速度慢得令人发指,所以我们换到阿里的源,并且使用 yum install 的方式安装,没差啦其实,这样反而还快点,毕竟多个节点一起装。

很多安装失败的都是因为没有添加epel源请在每个存储节点都执行以下指令,来安装Ceph:

yum clean all
rm -rf /etc/yum.repos.d/*.repo
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
sed -i '/aliyuncs/d' /etc/yum.repos.d/CentOS-Base.repo
sed -i '/aliyuncs/d' /etc/yum.repos.d/epel.repo
sed -i 's/$releasever/7.2.1511/g' /etc/yum.repos.d/CentOS-Base.repo
echo "
[ceph]
name=ceph
baseurl=http://mirrors.aliyun.com/ceph/rpm-hammer/el7/x86_64/
gpgcheck=0
[ceph-noarch]
name=cephnoarch
baseurl=http://mirrors.aliyun.com/ceph/rpm-hammer/el7/noarch/
gpgcheck=0
" > /etc/yum.repos.d/ceph.repo
yum install ceph ceph-radosgw -y

这里是安装的 hammer 版本的Ceph,如果需要安装 jewel 版本的,请执行:

sed -i 's/hammer/jewel/' /etc/yum.repos.d/ceph.repo
yum install ceph ceph-radosgw -y

如果安装了 jewel 版本的Ceph,想要换回 hammer 版本的Ceph,可以执行下面的指令:

卸载Ceph客户端

rpm -qa |grep `ceph -v |awk '{print $3}'` |xargs rpm -e --nodeps

更改ceph.repo里面的Ceph版本

sed -i 's/jewel/hammer/' /etc/yum.repos.d/ceph.repo
yum install ceph ceph-radosgw -y

Q5. ceph-deploy

这里我要开启话唠模式:

① Ceph-deploy 是什么?

Ceph-deploy是Ceph官方给出的用于 部署Ceph 的一个工具,这个工具几乎全部是Python写的脚本,其代码位于 /usr/lib/python2.7/site-packages/ceph_deploy 目录下( 1.5.36 版本)。最主要的功能就是用几个简单的指令部署好一个集群,而不是手动部署操碎了心,敲错一个地方就可能失败。所以对于新人来说,或者说以我的经验,接触Ceph少于一个月的,又或者说,集群规模不上PB的,都没有必要手动部署,Ceph-deploy完全足够了。

② Ceph-deploy怎么装?

这个包在ceph的源里面:

yum install ceph-deploy -y

③Ceph-deploy装在哪?

既然Ceph-deploy只是个部署Ceph的脚本工具而已,那么这个工具随便装在哪个节点都可以, 并不需要单独为了装这个工具再搞个节点 ,我一般习惯放在第一个节点,以后好找部署目录。

④Ceph-deploy怎么用?

详细的指令暂时不介绍,下面会有,在安装好后,需要在这个节点新建一个目录,用作 部署目录 ,这里是强烈建议建一个单独的目录的,比如我习惯在集群的第一个节点下建一个 /root/cluster 目录,为了以后好找。 Ceph-deploy的所有的指令都需要在这个目录下执行 。包括 new,mon,osd 等等一切ceph-deploy的指令都需要在这个部署目录下执行!最后一遍,所有的 ceph-deploy 的指令都要在部署目录下执行!否则就会报下面的错:

[ceph_deploy][ERROR ] ConfigError: Cannot load config: [Errno 2] No such file or directory: 'ceph.conf'; has ceph-deploy new been run in this directory?

⑤ Ceph-deploy怎么部署集群?

我们暂且把 部署目录 所在的节点叫做 部署节点 。Ceph-deploy通过SSH到各个节点,然后再在各个节点执行本机的Ceph指令来创建MON或者OSD等。所以在部署之前,你需要从 部署节点ssh-copy-id 到各个集群节点,使其可以免秘钥登陆。

⑥Ceph-deploy部署的日志在哪里?

就在部署目录下面的 ceph-deploy-ceph.log 文件,部署过程中产生的所有的日志都会保存在里面,比如你大半年前敲的创建OSD的指令。在哪个目录下执行ceph-deploy指令,就会在这个目录下生成log,如果你跑到别的目录下执行,就会在执行目录里生成log再记下第四点的错。当然,这个LOG最有用的地方还是里面记录的部署指令,你可以通过 cat ceph-deploy-ceph.log |grep "Running command" 查看到创建一个集群所需的所有指令,这对你手动建立集群或者创建秘钥等等等等有着很大的帮助!!!

⑦ Ceph-deploy版本

写这段时的最新的版本号为 1.5.36 ,下载链接为ceph-deploy-1.5.36-0.noarch.rpm, 之前的 1.5.35 里面有点bug在这个版本被修复了,如果使用 1.5.25 部署遇到了问题,可以更新至这个版本,会绕过一些坑。更新到 1.5.36 之后,腰也不酸了,退了不疼了,Ceph也能部署上了。

Q6. ceph-deploy new 做了什么

进入部署目录,执行 ceph-deploy new node1 node2 node3 ,会生成两个文件(第三个是 ceph-deploy-ceph.log ,忽视之):

[root@blog cluster]# ls
ceph.conf  ceph-deploy-ceph.log  ceph.mon.keyring

new 后面跟的是你即将部署MON的节点的 hostname ,推荐三个就够了,需要是奇数个MON节点。不要因为只有两个节点就搞两个MON,两个节点请用一个MON,因为两个MON挂掉一个,集群也就挂了,和一个MON挂掉一个效果是一样的。生成的 ceph.conf 默认情况下长成这样:

[root@blog cluster]# cat ceph.conf 
[global]
fsid = 13b5d863-75aa-479d-84ba-9e5edd881ec9
mon_initial_members = blog
mon_host = 1.2.3.4
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx

会调用 uuidgen 生成一个 fsid ,用作集群的唯一ID,再将 new 后面的主机加入到 mon_initial_membersmon_host 里面,剩下的三行大家都是一样的,默认开启CephX认证。下面有一节会专门介绍这个,需要注意的是, 部署的时候,千万不要动这三行 下面会有一节介绍之。还有一个文件 ceph.mon.keyring

[root@blog cluster]# cat ceph.mon.keyring 
[mon.]
key = AQB1yWRYAAAAABAAhMoAcadfCdy9VtAaY79+Sw==
caps mon = allow *

除了 key 的内容不一样,剩下的都会是一样的。因为是开启了CephX认证了,所以MON直接的通讯是需要一个秘钥的, key 的内容就是秘钥。是不是对Ceph里面的明文认证感到吃惊,有总比没有强。如果,你再次执行 new ,会生成新的 ceph.conf 和新的 ceph.mon.keyring ,并将之前的这两个文件给覆盖掉,新旧文件唯一不同的就是 fsidkey 的内容,但是对Ceph来说,这就是两个集群了。这里说一下我个人非常非常非常反感的一个问题,有的朋友喜欢在 /etc/ceph/ 目录下面执行ceph-deploy的命令,这么做和在 部署目录 下面做一般是没有差别的,因为这两个目录下面都有 ceph.confceph.client.admin.keyring ,但是我还是强烈推荐创建独立的 部署目录 ,因为 /etc/ceph 目录是Ceph节点的运行目录,为了体现各自的功能性,也为了安全性, 请不要在 **/etc/ceph** 目录下部署集群!!!

Q7. 为ceph-deploy添加参数

Ceph-deploy的log还是很有看头的,查看 ceph-deploy new blog (blog是我的一台主机)的log:

[root@blog cluster]# ceph-deploy new blog
[ceph_deploy.conf][DEBUG ] found configuration file at: /root/.cephdeploy.conf
[ceph_deploy.cli][INFO  ] Invoked (1.5.36): /usr/bin/ceph-deploy new blog
[ceph_deploy.cli][INFO  ] ceph-deploy options:
[ceph_deploy.cli][INFO  ]  username                      : None
[ceph_deploy.cli][INFO  ]  func                          : <function new at 0x288e2a8>
[ceph_deploy.cli][INFO  ]  verbose                       : False
[ceph_deploy.cli][INFO  ]  overwrite_conf                : False
[ceph_deploy.cli][INFO  ]  quiet                         : False
[ceph_deploy.cli][INFO  ]  cd_conf                       : <ceph_deploy.conf.cephdeploy.Conf instance at 0x28eccf8>
[ceph_deploy.cli][INFO  ]  cluster                       : ceph
[ceph_deploy.cli][INFO  ]  ssh_copykey                   : True
[ceph_deploy.cli][INFO  ]  mon                           : ['blog']
[ceph_deploy.cli][INFO  ]  public_network                : None
[ceph_deploy.cli][INFO  ]  ceph_conf                     : None
[ceph_deploy.cli][INFO  ]  cluster_network               : None
[ceph_deploy.cli][INFO  ]  default_release               : False
[ceph_deploy.cli][INFO  ]   fsid                          : None
[ceph_deploy.new][DEBUG ] Creating new cluster named ceph

可以看到有很多的参数被列出来了,比如: mon : ['blog'] ,也有很多参数是False或者None, 这些参数能否被设置呢? 因为这里我们可以看到有 fsid : None 这个参数,难道集群的 fsid 可以被指定吗?抱着这些疑惑,我就去看完了ceph-deploy的所有代码,答案是:可以设置。所有上面的参数都可以使用参数的形式进行设置,只需要在前面加上两个 -- ,比如对于 fsid 可以执行:

ceph-deploy  new blog --fsid xx-xx-xx-xxxx

如果想要查看每个执行可指定的参数,可以 -h

[root@blog cluster]# ceph-deploy new -h
usage: ceph-deploy new [-h] [--no-ssh-copykey] [--fsid FSID]
                      [--cluster-network CLUSTER_NETWORK]
                      [--public-network PUBLIC_NETWORK]
                      MON [MON ...]
...
optional arguments:
  -h, --help            show this help message and exit
  --no-ssh-copykey      do not attempt to copy SSH keys
  --fsid FSID           provide an alternate FSID for ceph.conf generation
  --cluster-network CLUSTER_NETWORK
                        specify the (internal) cluster network
  --public-network PUBLIC_NETWORK
                        specify the public network for a cluster

这里就可以看到可以指定 --cluster-network--public-network ,等等,如果 optional arguments 里面没有介绍这个参数,可以直接使用 --xxarg 的方式指定,比如 --overwrite-conf--verbose 等等,能不能设置这些参数,自己动手试一下就知道了。需要注意的是,参数的位置根据指令而异,比如 --overwrite-conf 参数是跟在 ceph-deploy 后面的,而 --public-network 是跟在 new 后面的:

ceph-deploy --overwrite-conf --verbose new blog --fsid a-a-a-a
[root@blog cluster]# cat ceph.conf |grep fsid
fsid = a-a-a-a

Q8. Public VS Cluster

如果非要在刚刚生成的ceph.conf里面添加什么的话,那么可能就要加public_network或者cluster_network了。那么这两个配置项有什么用呢?这里简单得介绍下Ceph的Public(外网或者叫公网或者前端网)和Cluster(内网或者叫集群网或者叫后端网)这两个网络,在Ceph中,存在以下三种主要的网络通讯关系:

  • client-> mon =>public : 也就是客户端获取集群状态,或者叫客户端与MON通讯走的网络,是走的外网。
  • client-> osd => public : 也就是客户端向OSD直接写入数据走的也是外网。
  • osd<-> osd => cluster :也就是OSD之间的数据克隆,恢复走的是内网,客户端写第一份数据时通过外网写,对于三副本剩下的两个副本OSD之间通过内网完成数据复制。当OSD挂掉之后产生的recover,走的也是内网。

通常,我们会将外网配置为千兆网,而内网配置成万兆网,这是有一定原因的:

  • 客户端可能由成百上千的计算节点组成,外网配成万兆成本太高。
  • 存储节点一般只有几个到几十个节点,配置了万兆内网可以大大加快故障恢复速度,而且剩余的两副本写速度会大大加快,万兆网的性价比极高。举个例子,集群坏掉一个OSD千兆需要一小时,那么万兆网只需要五六分钟,一定程度上增加了集群的安全性。

借用官网的这张图来说明集群的网络走势:再假设你的节点有两个网段172.23.0.1和3.3.4.1,还记得我们上一节 ceph-deploy new 的时候是可以指定 public_networkcluster_network 的吗!如果不指定这两个参数,那么ceph-deploy怎么知道用哪个IP作为这个节点的 mon_host 的IP呢,其实他是随便选的,如果它选了172网段但是你想使用3.3网段作为这个节点的 mon_host 的IP,那么只需要指定 --public-network 172.23.0.0/24 就可以了,其中的 /24 就相当于一个掩码,表示前面的IP的前24位,也就是 172.23.0.XXX ,只要你的主机上有一个处于这个范围内的IP,那么就会选择这个IP作为公网IP。类似的, /16 表示范围: 172.23.XXX.XXX 。 如果想指定内网IP,那么只要指定 --cluster-network 3.3.4.1/24 就可以了。

**一般情况下,会在new生成的ceph.conf文件里加入public_network配置项以指定公网IP。当然你的MON主机上需要有至少一个IP在公网范围内。**除了在生成的 ceph.conf 文件中加入公网IP的方式,我们还可以使用参数的方式来指定公网IP:

[root@ceph-1 cluster]# ceph-deploy new ceph-1 --public-network 172.23.0.0/24
[ceph_deploy.cli][INFO  ] Invoked (1.5.36): /usr/bin/ceph-deploy new ceph-1 --public-network 172.23.0.0/24
[ceph_deploy.cli][INFO  ] ceph-deploy options:
...
[ceph_deploy.cli][INFO  ]  public_network                : 172.23.0.0/24
...
[ceph-1][DEBUG ] IP addresses found: [u'172.23.0.101', u'10.0.2.15']
[ceph_deploy.new][DEBUG ] Resolving host ceph-1
[ceph_deploy.new][DEBUG ] Monitor ceph-1 at 172.23.0.101
[ceph_deploy.new][DEBUG ] Monitor initial members are ['ceph-1']
[ceph_deploy.new][DEBUG ] Monitor addrs are [u'172.23.0.101']
[ceph_deploy.new][DEBUG ] Writing monitor keyring to ceph.mon.keyring...
[ceph_deploy.new][DEBUG ] Writing initial config to ceph.conf...
[root@ceph-1 cluster]# cat ceph.conf 
[global]
fsid = d2a2bccc-b215-4f3e-922b-cf6019068e76
public_network = 172.23.0.0/24
mon_initial_members = ceph-1
mon_host = 172.23.0.101
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx

查看部署log可以发现参数配置已经生效,而这个节点有两个IP, public_nwtwork 这个参数限定了公网IP的搜索范围,生成的ceph.conf文件内也包含了 public_network 这个参数。

Q9. 参数是下划线还是空格分隔

这里只是简单的提一下这个小困惑,对于以下的两个参数书写方式,哪种会有问题呢:

public_network = 172.23.0.1/24
public network = 172.23.0.1/24
osd_journal_size = 128
osd journal size = 128

这两种参数的书写方式其实都是正确的,说到底是因为底层调用的是Python的 argparse 模块。这两种方式都是等效的,所以不需要担心。

Q10. ceph-deploy mon create-initial如何一次性通过

这一步坑哭了多少迫切加入Ceph世界的新人,看到的最多的就是5s,10s,10s, 15s,20s。。。然后报了错。再执行,再报错。所以这里给出以下的预检清单,如果被报错失败所烦恼,请认真执行各个子项,尤其是失败后要执行清理环境:

  1. 请确保所有节点都安装了Ceph。
  2. 请确保所有节点的防火墙等都关闭了。参考 环境预准备 一节
  3. 请前往各个MON节点清理干净,不论你是否相信这个节点是干净的。参考 清理环境 一节。
  4. 请确保各个MON节点下存在以下目录,并且对于Jewel版本及之后的请确保目录权限为 ceph:ceph 。参考 部署前最后的确认 一节。
  5. 请在 ceph-deploy new 生成的 ceph.conf 内添加 public_network 配置项,参考 Public VS Cluster 一节。

这些总结来之不易,我帮过上百个人解决过部署问题和集群故障。我相信在 认真确认 过之后是肯定可以通过的(反正前三点如果有问题一般是不会建好MON的,为什么不认真确认下呢),我遇到过绝大多数都是因为防火墙没关,或者手动删除了一些目录,或者没有修改权限导致的问题。

相对来说,新环境只要关了防火墙就可以一次性通过,旧环境或者失败的环境只要清理环境就可以通过了。

Q11. mon create-initial 做了什么

简单介绍下流程:

  • ceph-deploy读取配置文件中的

    mon_initial_members

    的各个主机,然后依次SSH前往各个主机:

    1. 部署目录 下的ceph.conf推送到新节点的 /etc/ceph/ 目录下。
    2. 创建 /var/lib/ceph/mon/$cluster-$hostname/ 目录。
    3. 检查MON目录下是否有 done 文件,如果有则直接跳到第6步。
    4. ceph.mon.keyring 拷贝到新节点,并利用该秘钥在MON目录下建立MON数据库。
    5. 在MON目录下建立done文件,防止重新建立MON。
    6. 启动MON进程。
    7. 查看 /var/run/ceph/$cluster-mon.$hostname.asok SOCKET文件,这个是由MON进程启动后生成的,输出MON状态。
  • 在所有的MON都建立好后,再次前往各个主机,查看所有主机是否运行并且到达法定人群(quorum)。如果有没到到的,直接结束报错。如果都到达了,执行下一步。

  • 调用

    auth get-or-create

    方法创建(如果不存在)或者拉取(已经存在)MON节点上的以下几个keyring到

    部署目录

    中:

    ceph.bootstrap-mds.keyring
    ceph.bootstrap-osd.keyring
    ceph.bootstrap-rgw.keyring
    ceph.client.admin.keyring
    
  • 指令结束。

Q12. mon create-initial 为什么会失败

我不喜欢讲怎么做,我愿意花很大的篇幅介绍为什么会造成各种各样的问题,如果知道了原因,你自然知道该怎么做,所以才会理解Ceph,而不是机械的去敲指令。

综合上面的所有小节,我来总结下这一步失败的基本上所有可能的原因:

  • 所谓MON的quorum,相当于多个MON形成的一个群体,它们之间需要通过网络发送数据包来通讯达成某种协议,如果打开了防火墙,会阻断数据交流。所以不能构成群体,一直等待(5s->10s->10s->15s->20s)其他MON的数据包,既然被阻断了这样的等待是没有意义的,等了30s还没有正常,就可以直接 ctrl+z 去检查了。
  • 我在配置文件里面添加了 pubilc_network ,但是有个主机的所有IP都不在公网IP段内,那么这个MON是建不好的,因为没有IP用作MON使用, public_network 相当于一个 过滤器
  • 搭好了一台虚拟机后,直接克隆了两台,没有修改主机名,导致socket文件路径名识别错误,报了异常,不过这很少发生。
  • 如果在旧的MON节点上再次部署新的MON,再又没有清理环境,之前的MON数据库会保留着 done 文件,MON数据库里面还是记录着之前fsid,keyring等等,和新集群是两套完全不同的,所以这个节点的MON自然到达不了MON群体。
  • 即使你单单删除了 /var/lib/ceph/mon 下的东西,而没有清理那些keyring,也有可能会因为收集了旧集群的秘钥而发生稀奇古怪的问题。
  • 对于Jewel,你一不小心删除了 /var/lib/ceph/mon 目录,或者其他的OSD目录或者 /var/run/ceph 目录,然后又重建了目录,依然部署不上,是因为Jewel的所有Ceph指定都是运行在 ceph:ceph 用户下的,自然不能在root权限目录下建立任何文件,修改权限即可。
  • Ceph生成MON数据库是依照主机的 hostname 来命名至目录 /var/lib/ceph/mon/${cluster}-${hostname} 的,而检测SOCKET文件则是用 ceph.conf 里面的 mon_initial_members 里面的名字来检测的 ,如果 mon_initial_members 里面的名字和真是的主机名不一致,就会报错。

​ 一旦你运行了 ceph-deploy mon create-initial 指令,并且失败了,有极大的可能性已经在某些节点建立好了MON的数据库,再次执行可能会因为旧的环境导致再次失败,所以如果失败了,执行一下第二节中的 清理环境 即可。清理完毕后,再执行 ceph-deploy mon create-initial


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK