环境
M版本neutron+neutron_lbaas+haproxy方案,没有使用octavia。
neutron.conf配置如下:
1 2 3 |
[DEFAULT] service_plugins = neutron_lbaas.services.loadbalancer.plugin.LoadBalancerPluginv2 service_provider = LOADBALANCERV2:Haproxy:neutron_lbaas.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default |
service_lbaas.conf无特殊配置,基本都是默认值。
问题描述
创建中文名称的负载均衡器,之后创建监听器,lbaas-agent.log报错:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager [-] Unable to deploy instance for loadbalancer: 34af08dc-5dd6-4bdd-a8bc-3546ebfebe04 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager Traceback (most recent call last): 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager File "/usr/lib/python2.7/site-packages/neutron_lbaas/agent/agent_manager.py", line 185, in _reload_loadbalancer 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager self.device_drivers[driver_name].deploy_instance(loadbalancer) 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager File "/usr/lib/python2.7/site-packages/oslo_concurrency/lockutils.py", line 271, in inner 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager return f(*args, **kwargs) 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager File "/usr/lib/python2.7/site-packages/neutron_lbaas/drivers/haproxy/namespace_driver.py", line 175, in deploy_instance 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager self.create(loadbalancer) 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager File "/usr/lib/python2.7/site-packages/neutron_lbaas/drivers/haproxy/namespace_driver.py", line 203, in create 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager self._spawn(loadbalancer) 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager File "/usr/lib/python2.7/site-packages/neutron_lbaas/drivers/haproxy/namespace_driver.py", line 361, in _spawn 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager haproxy_base_dir) 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager File "/usr/lib/python2.7/site-packages/neutron_lbaas/services/loadbalancer/drivers/haproxy/jinja_cfg.py", line 91, in save_config 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager n_utils.replace_file(conf_path, config_str) 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager File "/usr/lib/python2.7/site-packages/neutron/common/utils.py", line 535, in replace_file 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager tmp_file.write(data) 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager File "/usr/lib64/python2.7/socket.py", line 316, in write 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager data = str(data) # XXX Should really reject non-string non-buffers 2017-12-21 03:35:31.661 3652 ERROR neutron_lbaas.agent.agent_manager UnicodeEncodeError: 'ascii' codec can't encode characters in position 20-21: ordinal not in range(128) |
问题原因
写入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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
{# # Copyright 2014 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # #} {% extends 'haproxy_proxies.j2' %} {% set loadbalancer_name = loadbalancer.name %} ### 定义变量loadbalancer_name对应的数据来源 {% set usergroup = user_group %} {% set sock_path = stats_sock %} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{# # Copyright 2014 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # #} # Configuration for {{ loadbalancer_name }} ### 就是这行注释模板中用到的负载均衡中文名称出错了 global |
有两种方法解决该问题:
- 修改变量定义{% set loadbalancer_name = loadbalancer.name %},改成{% set loadbalancer_name = loadbalancer.vip_address %},用其他非中文变量如vip_address代替可能为中文的name即可
- 直接删除# Configuration for {{ loadbalancer_name }}这行注释,干净省事儿,注释要不要都无所谓,反正目录名称是负载均衡UUID,可以区分出来
最后,如果手工修改了haproxy配置文件模板,可以通过修改模板文件路径的配置项来加载自己的模板,当然也可以不修改配置而是修改源码中的配置模板后打包发布,我个人倾向于增加配置而不是二次打包,否则后续包的维护成本比较高。修改的配置文件是:
1 2 3 |
[haproxy] # 加上这行,并且把自定义的jinjia2模板文件放到对应目录下 jinja_config_template = /etc/neutron/templates/haproxy.loadbalancer.j2 |
注意配置文件是/etc/neutron/lbaas_agent.ini,不是services_lbaas.conf,前者是neutron-lbaas-agent服务用到的,后者是neutron-server用到的,根据模板生成haproxy配置文件是在agent里面做的,所以修改后者是没效果的。