OpenStack计算节点的奇葩问题

文章目录
  1. 1. 问题描述
  2. 2. 问题分析
  3. 3. 垂死挣扎
    1. 3.1. 查看数据库
    2. 3.2. 重命名计算节点
    3. 3.3. 设置迁移和挂载
    4. 3.4. 再次尝试迁移
    5. 3.5. IP的坑
  4. 4. 破釜沉舟
    1. 4.1. 销毁OpenStack环境
    2. 4.2. 安装OpenStack
    3. 4.3. 设置迁移和挂载
  5. 5. 罪魁祸首
  6. 6. 风波再起
  7. 7. 后记
  8. 8. 书签

问题描述

心态爆炸了!火急火燎!一方面马上要交毕业论文,另一方面马上要提交小论文。就当我打算抽出一天先完成小论文时,实验环境崩了!

之前进行迁移实验都好好的,但是今天进行迁移实验的时候,实例经常死机。本着“重启治百病”的思想,重启了两个计算节点,重新挂载了nfs。然后再次迁移时,实例可以从compute2迁移到compute1。但是,实例从compute1迁移到compute2时,compute2就报错!

1
ERROR oslo_messaging.rpc.server [req-922596a7-f122-45c8-9f91-1446bb855e05 2c04ede78270421da71953f8f07ef115 8de01ef30eed437193725fb759b9992d - default default] Exception during message handling: InvalidCPUInfo: Unacceptable CPU info: CPU doesn't have compatibility.

重新部署了compute2计算节点,依然是这个错误。重装了compute2计算节点的操作系统,然后重新部署,依然是这个错误!很绝望!

问题分析

重装系统无效,那么大概率是控制节点的锅了!那么问题具体出在哪里?凭什么compute1就好好的,compute2就坏了?是因为控制节点的一些残留信息没有清空吗?数据库中记录说compute2已经没有可用CPU了?数据库中记录说不兼容?还是有缓存或者消息?那么该怎么清空关于compute2的信息?。。。
还有一个关键的问题是,为什么突然就无法兼容了?之前不是好好的么?
然而,没有人可以告诉我答案,搜索引擎不行,社区群聊不行,身边也没有OpenStack的大牛。
现在只想赶紧从OpenStack这个大坑中爬出来,遇到问题根本找不到答案,就问你服不服!

垂死挣扎

查看数据库

1、查看数据库密码
less /etc/kolla/passwords.yml | grep password
里面有很多密码,我们需要的是nova_database_password。

2、进入mariadb容器
docker exec -it mariadb /bin/bash

3、登录mariadb数据库
mysql -u nova -p

4、使用nova数据库
use nova;

5、查看计算节点的信息
select * from compute_nodes\G

重命名计算节点

如果,给compute2节点更换hostname和IP呢?比如hostname换成compute3,IP也换成其他的。这样的话,计算节点就不会受控制节点中残留信息的影响了。

1、修改compute2的hostname和IP地址

2、修改multinode文件
控制节点中,把multinode文件中的compute2节点换成compute3,/etc/hosts中添加compute3对应的IP。

3、重新部署
kolla-ansible -i ./multinode deploy

4、查看计算服务

1
2
. admin-openrc.sh
openstack compute service list

设置迁移和挂载

参考《OpenStack中虚拟机的在线迁移》,在compute3节点设置OpenStack允许迁移。参考《OpenStack中共享存储的虚拟机在线迁移》,在compute3节点挂载nfs。

1、修改nova.conf的配置
vim /etc/kolla/nova-compute/nova.conf,在default中添加:

1
live_migration_flag=VIR_MIGRATE_UNDEFINE_SOURCE,VIR_MIGRATE_PEER2PEER,VIR_MIGRATE_LIVE

2、修改libvirtd.conf
vim /etc/kolla/nova-libvirt/libvirtd.conf,修改配置如下:

1
2
3
4
5
6
7
listen_tcp = 1
listen_tls = 0
auth_tcp = "none"
ca_file = ""
log_level = 3
log_outputs = "3:file:/var/log/kolla/libvirt/libvirtd.log"
listen_addr = "0.0.0.0"

3、挂载nfs

1
2
3
apt-get install nfs-common
mount -t nfs 192.168.56.130:/nfs/share/instances /var/lib/docker/volumes/nova_compute/_data/instances/
chmod -R 777 /var/lib/docker/volumes/nova_compute/_data/instances/

4、重启nova_compute和nova_libvirt

1
2
3
4
docker stop nova_compute
docker start nova_compute
docker stop nova_libvirt
docker start nova_libvirt

再次尝试迁移

1、迁移命令
nova live-migration demo0 compute3

2、查看状态
nova show demo0

3、compute3上查看日志
tail -n 20 /var/lib/docker/volumes/kolla_logs/_data/nova/nova-compute.log

虽然迁移失败,但是好歹是不一样的错误了。。。这个错误以前遇到过,重启计算节点就好了。于是重启compute3节点,但是问题没有解决。

4、测试与控制节点的连接
curl http://192.168.56.120:35357,结果为:

1
curl: (7) Failed to connect to 192.168.56.120 port 35357: Connection refused

5、在compute1节点上测试与控制节点的连接
curl http://192.168.56.120:35357,结果为:

1
{"versions": {"values": [{"status": "stable", "updated": "2018-02-28T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v3+json"}], "id": "v3.10", "links": [{"href": "http://192.168.56.120:35357/v3/", "rel": "self"}]}, {"status": "deprecated", "updated": "2016-08-04T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json"}], "id": "v2.0", "links": [{"href": "http://192.168.56.120:35357/v2.0/", "rel": "self"}, {"href": "https://docs.openstack.org/", "type": "text/html", "rel": "describedby"}]}]}}

这才是正常的啊!

6、重启compute3并且重新挂载nfs

1
2
3
4
5
mount -t nfs 192.168.56.130:/nfs/share/instances /var/lib/docker/volumes/nova_compute/_data/instances/
docker stop nova_compute
docker start nova_compute
docker stop nova_libvirt
docker start nova_libvirt

7、再次执行迁移
nova live-migration demo0 compute3
依然失败,还是同样的错误。

IP的坑

百度谷歌想要找到答案?不存在的。折腾了两天,突然灵光一现!
还记得《Kolla安装OpenStack多节点》一文中,控制节点的IP为192.168.56.110。而配置globals.yml时候,kolla_internal_vip_address的值为192.168.56.120。

因此,compute3节点中,nova.conf中的IP有一部分是192.168.56.110,另外一部分是192.168.56.120。

明明所有控制节点的服务都在一个节点上,却有两个IP,看起来就容易闹幺蛾子。实际上,确实闹过幺蛾子!OpenStack刚刚安装成功时,使用192.168.56.120这个IP可以访问到horizon服务,使用192.168.56.110就不可以。后来突然有一天,192.168.56.120这个IP就不能访问horizon了,使用192.168.56.110却可以访问!再后来突然有一天,两个IP都可以访问horizon服务!真的是醉了。。。

这次,会不会也是IP的问题?于是,在compute3上,换一个IP测试访问控制节点。
curl http://192.168.56.110:35357,果然可以正常访问!于是,思路就清晰了。

1、修改compute3节点中的nova.conf配置文件
vim /etc/kolla/nova-compute/nova.conf,所有的192.168.56.120全部换成192.168.56.110。

2、重启nova_compute

1
2
docker stop nova_compute
dokcer start nova_compute

3、再次迁移,失败,不过报错变了。

依然是IP问题,看来还有其他配置文件中写了192.168.56.120。

4、修改neutron.conf和chrony.conf文件

1
2
vim /etc/kolla/neutron-openvswitch-agent/neutron.conf
vim /etc/kolla/chrony/chrony.conf

所有120替换为110。

5、重启neutron和chrony

1
2
3
4
docker stop neutron_openvswitch_agent
docker start neutron_openvswitch_agent
docker stop chrony
docker start chrony

6、再次迁移,依然失败,报错依然失8780端口。

7、重启所有服务,再次迁移,依然失败。
莫非还有什么文件没有注意到?于是放了一个大招,grep -rn "192.168.56.120:8780" *,然而,没有找到包含该配置的文件。

8、重启了compute3,然后,nova_compute无法启动了!启动报错:

1
2
3
/var/lib/docker/volumes/kolla_logs/_data: no such file or directory
/var/lib/docker/volumes/libvirtd/_data: no such file or directory
/var/lib/docker/volumes/nova_compute/_data: no such file or directory

创建了三个文件夹,依然无法启动nova_compute。

破釜沉舟

实在是没办法了,只能使出最后一招:重装整个OpenStack系统!

销毁OpenStack环境

1、查看镜像
glance image-list

或者进入镜像文件夹查看
cd /var/lib/docker/volumes/glance/_data/images

2、导出镜像

1
2
glance image-download --file ./ubuntu16-env.img 003ae986-4dd9-45a6-9630-1b80fc8dcab3
ll -h

3、在horizon中删除所有镜像

4、在horizon中关闭并删除所有实例

5、编辑multinode文件,取消所有节点的注释

6、销毁整个OpenStack环境
kolla-ansible destroy -i ./multinode --yes-i-really-really-mean-it

安装OpenStack

参考《Kolla安装OpenStack多节点》进行OpenStack的安装。

考虑到两个IP的坑,这次安装我仔细阅读了一下globals.yml文件中关于kolla_internal_vip_address的描述:

This should be a VIP, an unused IP on your network that will float between
the hosts running keepalived for high-availability. If you want to run an
All-In-One without haproxy and keepalived, you can set enable_haproxy to no
in “OpenStack options” section, and set this value to the IP of your
‘network_interface’ as set in the Networking section below.

这应该是VIP,网络上未使用的IP将在运行keepalived以获得高可用性的主机之间浮动。如果要在没有haproxy和keepalived的情况下运行多功能一体机,可以在“OpenStack选项”部分中将enable_haproxy设置为no,并将此值设置为“network_interface”的IP,如下面的“网络”部分所述。

看来,kolla_internal_vip_address不应该设置为192.168.56.120,因为我们的环境中不需要haproxy。所以,在配置配置globals.yml的时候,kolla_internal_vip_address应该设置为和控制节点相同的IP:192.168.56.110,同时enable_haproxy设置为no。

安装完成后,导入之前备份的镜像:

1
2
3
4
5
6
7
8
. admin-openrc.sh
glance image-create \
--name "ubuntu16-env" \
--file ./ubuntu16-env.img \
--disk-format qcow2 \
--container-format bare \
--visibility public \
--progress

设置迁移和挂载

参考本文中垂死挣扎部分设置迁移和挂载。
然后,创建实例,分配浮动IP,测试迁移,成功!nice!

罪魁祸首

再次进行迁移,同时启动间隔1ms的ping命令测试停机时间,然后实例迁移后死机了!Ctrl+C关闭ping命令,实例复活。由此猜想是ping命令的锅。

但是,这是一个单向问题!同样是使用间隔1ms的ping命令测试停机时间,实例从compute1迁移到compute2时正常,实例从compute2迁移到compute1时才会死机。就问你神奇不神奇?!

猜测是因为ping的频率太高,给网络或者实例带来了太大的负荷。ping命令降低到10ms一次,双向迁移都正常。

但是,实例从compute1到compute2时,就不会受到ping命令的影响,这次是为什么?两台机器的配置完全相同的啊!诡异,实在是诡异!

更诡异的是,每次迁移的数据居然都通过不同的网卡,也许这次通过eth0(管理网络),下次就通过eth2(外网网络)!还能不能愉快地玩耍了?!

细细回想整个安装流程,突然想到,在安装前设置了三个节点的hosts文件,三个节点通过eth0通信。但是ansible安装OpenStack后,会根据globals.yml中的network_interface(eth1)修改hosts文件,于是hosts中有了两套规则。默认使用hosts文件中靠前的规则,于是我自己设置的规则就把ansible设置的规则覆盖了。eth0既用于节点间通信,又用于实例迁移。由于eth2和eth0属于同一个网段,所以有时会通过eth2网卡进行迁移!

为了验证自己的猜想,修改了三个节点的hosts文件,保留ansible创建的那一份。这样,就指定了迁移时使用的网卡。修改后在控制节点和计算节点重启nova相关服务。

1
2
3
4
5
6
7
8
9
10
11
12
# 计算节点
docker stop nova_compute
docker start nova_compute
docker stop nova_libvirt
docker start nova_libvirt
# 控制节点
docker stop nova_api
docker start nova_api
docker stop nova_scheduler
docker start nova_scheduler
docker stop placement_api
docker start placement_api

再次迁移实验,迁移数据果然会通过eth1(OpenStack内网网络),而不是eth0或者eth2!而且,双向迁移加1ms的ping命令都可以成功迁移,实例不再死机,问题完美解决!真相大白,罪魁祸首居然是hosts文件!

此外,live_migration_inbound_addr参数也可以指定迁移网络。

风波再起

就当我自以为找到了真相,继续实验时,实例再次出现了实例死机的情况。双向迁移都会偶尔出现死机,而且,使用间隔1ms的ping命令时死机概率会更大。如果使用间隔10ms的ping命令来测试停机时间呢?测出来的停机时间是秒级!Are you kidding me ?
比如同一个迁移,使用两个ping命令进行测试:

1
2
3
4
sudo ping instance_float_ip -i 0.001 >> ping.log
根据丢包数计算出的downtime为434ms
sudo ping instance_float_ip -i 0.01 >> ping.log
根据丢包数计算出的downtime为3340ms

理论上,应该测出同样的结果才对,然而他们差了一个数量级!诡异,实在是诡异!哪个才是真正的downtime?无论哪个是真正的downtime,ping命令本身绝对存在重大缺陷!

如果downtime是毫秒级,那么就符合理论上的值,实验可以正常进行。但是,使用间隔1ms的ping命令测试停机时间容易实例死机啊大哥!

如果downtime是秒级,那么问题要么是出在OpenStack配置上面,要么是出在网络上面。
假设问题出在OpenStack的配置上面,于是参考Configure live migrations,先后设置了最大停机时间,设置了自动收敛,设置了后拷贝。但是,问题依旧,那么应该不是OpenStack的配置问题。
假设问题出在网络上面,那么怎么解决呢?给实例的外网(eth3)设置一个单独的网段,不要和管理网络(eth0)在同一个网段?太麻烦。如果,在另外一个实例中对迁移实例进行ping测试呢?这样至少也可以避免了浮动IP的切换问题,是一个好主意。

于是在实例B中运行间隔1ms的ping命令,通过实例间的内网测试实例A,实例A多次迁移,测出的downtime在几十毫秒到几百毫秒不等,而且不会死机。在实例B中使用间隔10ms的ping命令进行测试,测出的downtime在几百毫秒左右,也很合理。所以,不是ping命令的锅?

不管了不管了,总之找到了解决办法!在另外一个实例中对迁移实例使用ping命令通过实例间的内网测试停机时间,而不是在外部机器中使用ping命令通过浮动IP测试停机时间。命令如下:

1
sudo ping instance_internal_ip -i 0.001 >> ping.log

后记

因为实例迁移会死机,所以开始了折腾。折腾了一大圈,重启所有节点,重装计算节点,重装系统,重装OpenStack,最后发现实例迁移依然会死机!这就排除了硬件问题,也排除了软件问题。好在最后灵光一现猜测是hosts的问题,不然这个坑是怎么都爬不出不来了。。。只是没想到刚爬出一个坑,又跌进了一个坑,修改了hosts不死机,只是刚好那几次实验都没死机!在使用了间隔1ms的ping命令之后,死机依然频繁。再次折腾OpenStack配置,失败。再次从网络方面考虑,终于找到了解决方案,太不容易了!

今天(3月24日)终于修复了实验环境,但是,已经错过了cloud2019的deadline。有些遗憾,不过和毕业论文相比,只能先牺牲小论文了。近期还有会议,加把劲,做实验,写论文,投稿!

书签

openstack中彻底删除计算节点的操作记录