Neutron LBaaS负载均衡器名称中文问题解决方案




环境

M版本neutron+neutron_lbaas+haproxy方案,没有使用octavia。

neutron.conf配置如下:

service_lbaas.conf无特殊配置,基本都是默认值。

问题描述

创建中文名称的负载均衡器,之后创建监听器,lbaas-agent.log报错:

问题原因

写入haproxy配置文件的时候,配置里面包含中文的负载均衡名称,导致写入失败。

写入配置文件过程是先使用tempfile库生成临时配置,之后拷贝到负载均衡UUID为名称的haproxy配置目录下,但是写入临时配置文件的时候发现包含无法处理成Unicode的字符,导致写入失败,用的是tempfile.NamedTemporaryFile这个实例写入临时文件,与open打开文件写入不同,这个实例返回的是一个pipe实例,而不是文件句柄实例,所以下面调用到了python自带socket库,socket通过pipe写入字符串时无法处理配置字符串中类似’\u4e2d\u6587’的中文编码,就报了UnicodeEncodeError错误。

解决方案

修改haproxy配置模板。官方默认的模板是包含3个文件,默认路径是/usr/lib/python2.7/site-packages/neutron_lbaas/services/loadbalancer/drivers/haproxy/templates/,文件名分别为haproxy_base.j2、haproxy.loadbalancer.j2、haproxy_proxies.j2,模板内容示例:

有两种方法解决该问题:

  1. 修改变量定义{% set loadbalancer_name = loadbalancer.name %},改成{% set loadbalancer_name = loadbalancer.vip_address %},用其他非中文变量如vip_address代替可能为中文的name即可
  2. 直接删除# Configuration for {{ loadbalancer_name }}这行注释,干净省事儿,注释要不要都无所谓,反正目录名称是负载均衡UUID,可以区分出来

最后,如果手工修改了haproxy配置文件模板,可以通过修改模板文件路径的配置项来加载自己的模板,当然也可以不修改配置而是修改源码中的配置模板后打包发布,我个人倾向于增加配置而不是二次打包,否则后续包的维护成本比较高。修改的配置文件是:

注意配置文件是/etc/neutron/lbaas_agent.ini,不是services_lbaas.conf,前者是neutron-lbaas-agent服务用到的,后者是neutron-server用到的,根据模板生成haproxy配置文件是在agent里面做的,所以修改后者是没效果的。