现场回顾

故事发生于某个下午,采用 salt 更新某集群的 neutron.conf (log 相关配置项) 并批量重启 neutron-openvswitch-agent(以下简称 neutron-ovs-agent),不久便有人反馈云主机宕机。

立即排查发现云主机并没有宕机,只是网络不通,大部分计算节点的 ovs 流表空空如也。Nova 和 Neutron 打出 ERROR 级别的日志。

$ ovs-ofctl dump-flows br-bond
NXST_FLOW repy (xid=0x4) cookies=0x0, duration=433.691s, table=0, n_packages=568733, n_bytes=113547542, idle_age=0, priority=1 actions=NORMAL cookies=0x0, duration=432.358s, table=0, n_packages=8418, n_bytes=356703, idle_age=0, priority=2, in_port=3 actions=drop

neutron-ovs-agent Log:

DeviceListRetrievalError: Unable to retrieve port details for devices because of error: Remote error: TimeoutError QueuePool limit of size 10 overflow 20 reached, connection timed out, timeout 10

neutron-server Log:

File "/usr/lib64/python2.6/site-packages/sqlalchemy/pool.py", ... 'TimeoutError: QueuePool limit of size 10 overflow 20 reached, connection timed out, timeout 10\n'

nova Log:

NeutronClientException: Request Failed: internal server error while processing your request.

上述信息可得出以下结论:

  • Neutron 日志表明 neutron-ovs-agent 通过 rpc 向 neutron-server 请求虚拟机 port 相关信息失败,失败的原因是 neutron-server 和数据库的连接数超出连接池的上限。
  • Nova 日志表明 neutron-server 无法响应 HTTP 请求。
  • 被清空的 ovs 流表导致虚拟机的网络瘫痪。

导火索

深入剖析之前,先了解该 Icehouse 集群的基本信息:该集群有 102 个计算节点,运行着 nova, neutron, glance,ceilometer 等服务,为了避免单点故障,我们去除了 neutron l3 等相关服务,采用大二层的网络,虚拟机通过物理路由与外界通信。理论上说,无论哪个服务异常,甚至任意节点宕机,最差的结果是 openstack 服务不可用或者少量虚拟机故障,但绝大部分虚拟机依旧能正常运行。

经验告知,采用以上网络模型的多个集群一年多以来从未发生如此规模的故障。由于 log 模块配置项不会影响流表,直觉上推测批量重启可能是触发 ovs 流表被清空的导火索。


Neutron 的一个坑

由于流表被清空前仅仅重启了 neutron-openvs-agent,而计算节点,仅仅只有 neutron-ovs-agent 与 ovs 有交互,故按图索骥的浏览 neutron-ovs-agent 重启流程,梳理其逻辑如下:

  1. 清除所有流表
  2. 通过 rpc 向 neutron-server 获取流表相关信息
  3. 创建新流变

不难发现,如果步骤 2 异常,比如 neutron-server 繁忙,消息中间件异常和数据库异常等种种因素,都会影响流表的重建,重则导致虚拟机网络瘫痪。事实上,社区也意识到了类似的问题:重启 neutron-ovs-agent 会导致网络暂时中断。

Restarting neutron ovs agent causes network hiccup by throwing away all flows

社区的处理方式是增加配置项 drop_flows_on_start,默认其值为 False,从而避免上述问题。该 Patch 已合入 Liberty,梳理其重启的逻辑流程如下:

  1. 用一个 cookie 标志当前流表
  2. 获取新流变并更新至 ovs
  3. 根据 cookie 清除旧流表

neutron-ovs-agent 在重启的过程中就流表的处理留下了一个隐患,直接的后果就是导致计算节点的流表被清理的干干净净,虚拟机成一个个孤立的点,而多种因素可触发该隐患。


最大连接数

现在解释为什么批量重启 neutron-ovs-agent 会触发上述隐患,重启过程中,neutron 日志报出如下错误:

'TimeoutError: QueuePool limit of size 10 overflow 20 reached, connection timed out, timeout。

这条日志意味着 neutron-server 和数据库的连接数超出客户端连接池的上限,当 neutron-ovs-agent 批量重启时,上百并发的通过 rpc 向 neutron-server 请求构建流表的相关信息,neutron-server 和数据库的连接数也就远远超过 30,造成大量的请求失败,计算节点获取不到流表相关信息无法重建流表,故计算节点的流表为空。

要解决因 QueuePool 的限制而引起的 TimeoutError 问题也很简单,sqlalchemy 提供了两个配置项[1],把下面两个参数适当调大即可。

[database]
max_overflow =
max_pool_size =

Note: MySQL server 默认最大连接数为 100,当集群的规模上升时,需适当调整 MySQL server 最大连接数。


进程的性能问题

然而问题并没有完全解决,请注意 nova 的错误日志:

nova.compute.manager NeutronClientException: Request Failed: internal server error while processing your request.

这是nova 发给 neutron-server 的一条 HTTP 请求,neutron 返回了 internal server error。Internal server error 对应的 HTTP status code 为 500,意味着 neutron-server 无法响应 nova 请求。为什么会无法响应呢,批量重启的过程中,发现 neutron-server 进程的 CPU 使用率为 100 %,意味着 neutron-server 正忙于处理 neutron-ovs-agent 大量的请求,因而无暇处理 nova 的 HTTP 请求。

解决该问题的方法同样很简答,增加更多的 neutron-server 进程数即可。事实上,因 nova-conductor 要处理 nova-compute 大量的 rpc 请求(nova-compute 通过 nova-conductor 访问数据库),自 Icehouse 起,nova-conductor 就默认启动了多个进程,进程的数目等同服务器 CPU 的逻辑核数。

$ workers=`cat /proc/cpuinfo |grep processor |wc | awk '{print $1}'`

[DEFAULT]
api_workers = $workers
rpc_workers = $workers


Python 的并发 & IO

值得思考的是,对双路 12 核共 24 线程的服务器来说,数百并发请求真的算高么?neutron-server 进程的 CPU 最大使用率只能到达 100 %,意味着 neutron-server 仅仅利用了服务器的一个线程。这里不得不提协程(crontine)[2],这种伪并发的“用户态线程” 意味着任意时刻只有一个协程在执行,即任意时刻只能利用服务器 CPU 的一个线程,而 openstack 所有组件的进程里满满都是协程(只有一个主线程),因而单个进程下,neutron-server 不能充分利用多核的优势以提高处理并发的能力。

传统的 web 服务器 apache 和 nginx 利用多进程多线程提高并发数(上下文切换的开销:进程 > 线程 > 协程)。那么问题来了,单进程条件下,是不是可以用线程替换协程从而提高 neutron 的并发能力呢?真实的答案是 No, 根本原因在于 python GIL[3],俗称 python 全局锁。对于 python 的程序来说,单进程只能在任何时刻只能占用一个物理线程,所有只有多进程才能充分利用服务器的多核多线程。

让我们深入一点,假设的 CPU 足够强大,是不是可以解决 neutron-server 单进程的并发问题呢?我觉得未必,这又回到了 IO 问题。Monkey patch[4] 虽然把系统的 socket 库替换成自己提供的非阻塞 socket 库,从而避免某些阻塞 IO 阻塞了整个进程(主线程)。但是 OpenStack 访问 MySQL 使用的是 libmysqlclient 库,eventlet 并不能对这个使用了系统 socket 的 C 库使用 monky_patch,所以对 MySQL CRUD 的时候会阻塞主线程,意味着 neutron-server 在访问数据库也容易出现性能瓶颈。

解决上诉并发问题的方法之一就是启动更多的 api worker 和 rpc worker。在较新的版本,OpenStack 默认的 wokers 就是服务器的逻辑核数。另外一种办法是用 apache 替换 python http server,最近各个组件逐步提供了对 apache 的支持。


Reference

    1. http://docs.sqlalchemy.org/en/rel_0_9/core/pooling.html
    2. http://www.dabeaz.com/coroutines/Coroutines.pdf
    3. http://stackoverflow.com/questions/1294382/what-is-a-global-interpreter-lock-gil
    4. http://stackoverflow.com/questions/11977270/monkey-patching-in-python-when-we-need-it

http://wsfdl.com/openstack/2015/10/10/%E4%B8%80%E6%AC%A1%E6%89%B9%E9%87%8F%E9%87%8D%E5%90%AF%E5%BC%95%E5%8F%91%E7%9A%84Neutron%E7%BD%91%E7%BB%9C%E6%95%85%E9%9A%9C.html

(转) 一次批量重启引发的Neutron网络故障的更多相关文章

  1. CentOS7安装OpenStack(Rocky版)-06.安装Neutron网络服务(控制节点)

    上一章介绍了独立的nova计算节点的安装方法,本章分享openstack的网络服务neutron的安装配制方法 ------------------- 完美的分割线 ----------------- ...

  2. 云计算之路-阿里云上:启用Windows虚拟内存引发的CPU 100%故障

    今天上午11:35~11:40左右,由于负载均衡中的两台云服务器CPU占用突然飚至100%,造成网站5分钟左右不能正常访问,请大家带来了麻烦,请谅解! (上图中红色曲线表示CPU占用) 经过分析,我们 ...

  3. openstack——neutron网络服务

    一.neutron 介绍:   Neutron 概述 传统的网络管理方式很大程度上依赖于管理员手工配置和维护各种网络硬件设备:而云环境下的网络已经变得非常复杂,特别是在多租户场景里,用户随时都可能需要 ...

  4. OpenStack核心组件-neutron网络服务

    1. neutron 介绍 1.1 Neutron 概述 传统的网络管理方式很大程度上依赖于管理员手工配置和维护各种网络硬件设备:而云环境下的网络已经变得非常复杂,特别是在多租户场景里,用户随时都可能 ...

  5. 启用 SR-IOV 解决 Neutron 网络 I/O 性能瓶颈

    目录 文章目录 目录 前言 Neutron 的网络实现模型 基于虚拟网络设备的虚拟机流量走向 Neutron 网络实现模型的性能瓶颈 SR-IOV 技术简介 在 Neutron 中引入 SR-IOV ...

  6. neutron网络服务部署

    控制节点执行 #第一步 登陆数据库 mysql -u root -p #导入neutron这个库 CREATE DATABASE neutron; #创建neutron这个用户和密码,并允许本地登陆和 ...

  7. Neutron网络-OPENSTACK讲得比较透和方便

    http://www.ustack.com/blog/neutron_intro/ Neutron是OpenStack核心项目之一,提供云计算环境下的虚拟网络功能.Neutron的功能日益强大,并在H ...

  8. Neutron网络性能测试与分析(一) CVR

    测试环境:网络节点运行在Intel(R) Xeon(R) CPU E5-2630 v3服务器上,网卡使用intel的万兆卡82599ES 测试仪使用本人基于dpdk编写的程序,基本上可以打满万兆卡,小 ...

  9. openstack第四章:neutron— 网络服务

    第四篇neutron— 网络服务 一.neutron 介绍:   Neutron 概述 传统的网络管理方式很大程度上依赖于管理员手工配置和维护各种网络硬件设备:而云环境下的网络已经变得非常复杂,特别是 ...

随机推荐

  1. UESTC 485 Game(康托,BFS)

    Today I want to introduce an interesting game to you. Like eight puzzle, it is a square board with 9 ...

  2. eclipse content assist 出现错误

    解决方法是,在Window->preference->java->editor>Content Assist->advanced ,将 time out 由50 ms 改 ...

  3. Jquery Ajax Json ashx 实现前后台数据传输

    经过一个多星期的研究,各种查找资料终于自己实现了Jquery  Ajax Json ashx 的前后台数据交流功能 首先一点,Ajax只能对应一个ashx文件,多余两个,如果打开异步传输的async: ...

  4. Just common sense.

    w A's intelligence is just B's common sense.

  5. 任务06——封装与单元测试(Markdown版)

    模块代码地址 Core 模块代码地址 单元测试代码地址 两个地址是一样的,为了方便,所以把测试的代码很模块代码放在一起git了. 封装阶段 public class Core { public sta ...

  6. SAN,NAS区别的联系

    在网络存储中,有着各种网络存储解决方案,例如:SAN,NAS,DAS存储网络,它们各自有着各自的特点,其运用场景也有所不同.下面就说说各自的特点. 一.SAN SAN(Storage Area Net ...

  7. 前端之 Ajax(补)

    概述 对于WEB应用程序:用户浏览器发送请求,服务器接收并处理请求,然后返回结果,往往返回就是字符串(HTML),浏览器将字符串(HTML)渲染并显示浏览器上. 1.传统的Web应用 一个简单操作需要 ...

  8. iOS 优化界面流畅度的探讨

    界面流畅度 大都跟list scrollView有紧密关联 流畅的视觉:就是如丝般顺滑 不流畅视觉:”卡顿”,”抖动”,”迟顿感” 以上两种状态的描述 都是基于主观感觉,对于开发者来说 确实应该有一个 ...

  9. awk中的常用关于处理字符串的函数

    1.替换字符串中的某一部分. 函数:gensub(/rexpr/,"replace","g","string"),gensub返回一个新的字 ...

  10. gem Errno::ECONNRESET: Connection reset by peer - SSL_connect

    问题描述 在使用gem安装软件包时,会时常遇到下面的问题: ERROR: While executing gem ... (Gem::RemoteFetcher::FetchError) Errno: ...