[ English | Indonesia | русский ]
HAProxy 和 Keepalived 在 LXC 容器中¶
在某些情况下,您可能希望在 LXC 容器中运行 HAProxy 和 Keepalived。例如,在裸机上运行这些服务假定应为主机设置指向公共网络的默认路由。对于某些部署而言,这种方案可能不太理想,尤其是在您没有独立的负载平衡主机,而是将它们与其它基础设施服务共置的情况下。
库存覆盖¶
为了让 dynamic_inventory 生成用于 HAProxy 的容器集,您需要在 /etc/openstack_deploy/env.d/haproxy.yml 文件中创建以下内容
---
# This file contains an example to show how to set
# the cinder-volume service to run in a container.
#
# Important note:
# In most cases you need to ensure that default route inside of the
# container doesn't go through eth0, which is part of lxcbr0 and
# SRC nat-ed. You need to pass "public" VIP interface inside of the
# container and ensure "default" route presence on it.
container_skel:
haproxy_container:
properties:
is_metal: false
定义主机网络¶
为了使公共网络可用,您需要确保在主机上有一个对应的桥接,HAProxy 容器将通过一个 veth 对的一侧连接到该桥接。该桥接还应包含一个提供“公共”连接性的 VLAN 接口。
您可以手动创建桥接,也可以利用我们的 systemd_networkd 角色,该角色能够配置主机上所需的网络。
对于下面的示例,让我们将我们的桥接命名为 br-public-api,公共 VLAN ID 为 40。在您的 user_variables.yml 文件中定义以下变量
_systemd_networkd_generic_devices:
- NetDev:
Name: bond0
Kind: bond
Bond:
Mode: 802.3ad
TransmitHashPolicy: layer3+4
LACPTransmitRate: fast
MIIMonitorSec: 100
filename: 05-generic-bond0
_systemd_networkd_public_api_devices:
- NetDev:
Name: vlan-public-api
Kind: vlan
VLAN:
Id: 40
filename: 10-openstack-vlan-public-api
- NetDev:
Name: br-public-api
Kind: bridge
Bridge:
ForwardDelaySec: 0
HelloTimeSec: 2
MaxAgeSec: 12
STP: off
filename: 11-openstack-br-public-api
openstack_hosts_systemd_networkd_devices: |-
{% set devices = [] %}
{% if is_metal %}
{% set _ = devices.extend(_systemd_networkd_generic_devices) %}
{% if inventory_hostname in groups['haproxy_hosts'] %}
{% set _ = devices.extend(_systemd_networkd_public_api_devices) %}
{% endif %}
{% endif %}
{{ devices }}
_systemd_networkd_bonded_networks:
- interface: ens3
filename: 05-generic-ens3
bond: bond0
link_config_overrides:
Match:
MACAddress: df:25:83:e1:77:c8
- interface: ens6
filename: 05-generic-ens6
bond: bond0
link_config_overrides:
Match:
MACAddress: df:25:83:e1:77:c9
- interface: bond0
filename: 05-general-bond0
vlan:
- vlan-public-api
_systemd_networkd_public_api_networks:
- interface: "vlan-public-api"
bridge: "br-public-api"
filename: 10-openstack-vlan-public-api
- interface: "br-public-api"
filename: "11-openstack-br-public-api"
openstack_hosts_systemd_networkd_networks: |-
{% set networks = [] %}
{% if is_metal %}
{% set _ = networks.extend(_systemd_networkd_bonded_networks) %}
{% if inventory_hostname in groups['haproxy_hosts'] %}
{% set _ = networks.extend(_systemd_networkd_public_api_networks) %}
{% endif %}
{% endif %}
{{ networks }}
定义容器网络¶
在 LXC 中部署 HAProxy 时,您需要确保与公共网络的连接,并且 haproxy_bind_external_lb_vip_address 存在于容器内部,同时 external_lb_vip_address 可访问。
为此,我们需要在 openstack_user_config.yml 文件中进行以下一系列更改。
在
cidr_networks中,添加一个应作为访问 API 的“公共”网络的网络。例如,我们将使用 203.0.113.128/28cidr_networks: ... public_api: 203.0.113.128/28
在
used_ips中,您需要为您的网关和haproxy_keepalived_external_vip_cidr/external_lb_vip_address预留 IP 地址used_ips: ... - "203.0.113.129" - "203.0.113.140-203.0.113.142"
在
provider_networks中,您需要定义一个新的容器网络,并将其分配给 HAProxy 组。global_overrides: ... provider_networks: ... - network: group_binds: - haproxy type: "raw" container_bridge: "br-public-api" container_interface: "eth20" container_type: "veth" ip_from_q: public_api static_routes: - cidr: 0.0.0.0/0 gateway: 203.0.113.129
虽然这些都是需要在 openstack_user_config.yml 中进行的更改,但还需要应用一个额外的覆盖。
如您可能已经发现,我们正在通过 eth20 为容器定义默认路由。但是,默认情况下,所有容器都通过 eth0 具有其默认路由,eth0 是一个本地 LXC 桥接,地址是通过 DHCP 接收的。为了避免冲突,您需要确保容器内部不会为 eth0 设置默认路由。为此,在 /etc/openstack_deploy/group_vars/haproxy 中创建一个文件,内容如下
---
lxc_container_networks:
lxcbr0_address:
bridge: "{{ lxc_net_bridge | default('lxcbr0') }}"
bridge_type: "{{ lxc_net_bridge_type | default('linuxbridge') }}"
interface: eth0
type: veth
dhcp_use_routes: False
配置容器内的 HAProxy 绑定¶
由于容器内的 IP 分配相当随机,因此将 HAProxy 绑定到特定 IP 地址可能并不总是方便的。如果这样,您可以将 HAProxy 绑定到接口,因为我们始终知道容器内的接口名称。这样,Keepalived 公共/内部 VIP 应该添加到 used_ips 中,因此您仍然可以自由定义它们。
下面的示例显示了 user_variables.yml 中的可能内容
haproxy_bind_external_lb_vip_interface: eth20
haproxy_bind_internal_lb_vip_interface: eth1
haproxy_bind_external_lb_vip_address: "*"
haproxy_bind_internal_lb_vip_address: "*"
haproxy_keepalived_external_vip_cidr: 203.0.113.140/32
haproxy_keepalived_internal_vip_cidr: 172.29.236.9/32
haproxy_keepalived_external_interface: "{{ haproxy_bind_external_lb_vip_interface }}"
haproxy_keepalived_internal_interface: "{{ haproxy_bind_internal_lb_vip_interface }}"
或者,您可以检测容器内使用的 IP 地址来配置 HAProxy 绑定。可以通过引用 container_networks 映射来完成此操作
haproxy_bind_external_lb_vip_address: "{{ container_networks['public_api_address']['address'] }}"
haproxy_bind_internal_lb_vip_address: "{{ container_networks['management_address']['address'] }}"
创建容器¶
完成以上所有步骤后,就可以创建新的 HAProxy 容器了。为此,运行以下命令
# openstack-ansible playbooks/lxc-containers-create.yml --limit haproxy,lxc_hosts