Openstack-网络管理学习指南-全-
Openstack 网络管理学习指南(全)
原文:
annas-archive.org/md5/c71566501ff3d589c71e12191b889fb8译者:飞龙
前言
OpenStack 是用于构建公共和私有云以及私有托管软件定义基础设施服务的开源软件。2017 年秋季,OpenStack 基金会发布了第 16 个版本的 OpenStack,称为 Pike。自从 2010 年由 NASA 和 Rackspace 作为开源项目推出以来,OpenStack 在全球开发者和运营商的努力下,功能和特性有了显著提升。正是他们的辛勤工作,造就了适合生产使用的云软件,支撑着全球各地各种规模的工作负载。
2012 年,OpenStack 的 Folsom 版本引入了一个独立的网络组件,当时被称为 Quantum。现在已更名为 Neutron,OpenStack 的网络组件为云运营商和用户提供了一个 API,用于创建和管理云中的网络资源。Neutron 的可扩展框架允许部署和管理第三方插件及附加的网络服务,如负载均衡器、防火墙和虚拟专用网络等。
作为自 2012 年以来管理数百个基于 OpenStack 的私有云的架构师和运营商,我见证了 OpenStack 在网络能力方面的诸多发展。在本书中,我总结了我认为目前最有价值且适用于生产环境的功能。在全书中,我们将探讨几种常见的网络和服务架构,并为部署和管理 OpenStack 网络奠定基础,这将帮助你作为 OpenStack 云运营商,发展和提升自己的技能。
本书适用人群
本书面向的是具有初级到中级经验的 OpenStack 云管理员或运营商,特别是那些希望通过使用 Neutron 网络服务来构建或增强云环境的读者。通过基于 docs.openstack.org 上的上游文档进行 OpenStack 基础安装,读者应能够按照书中的示例获得对 OpenStack 网络各组件的功能性理解,使用开源参考架构进行部署。
本书涵盖的内容
第一章**, OpenStack 网络介绍,介绍了 OpenStack 网络以及支持的网络技术,并举例说明如何设计物理网络以支持 OpenStack 云。
第二章**,安装 OpenStack,提供了在 Ubuntu 16.04 LTS 操作系统上安装 Pike 版本 OpenStack 核心组件的指南,包括 Keystone、Glance、Nova 和 Horizon。
第三章**, 安装 Neutron,解释了如何安装 OpenStack 的 Neutron 网络组件。我们还将介绍 Neutron 的内部架构,包括使用代理和插件来协调网络连接。
第四章**, 使用 Linux 桥接构建虚拟网络基础设施,帮助你安装并配置 ML2 插件,以支持 Linux 桥接机制驱动程序和代理,并展示如何使用 Linux 桥接将实例连接到网络。
第五章, 使用 Open vSwitch 构建虚拟交换基础设施,帮助你安装并配置 ML2 插件,以支持 Open vSwitch 机制驱动程序和代理,并展示如何使用 Open vSwitch 将实例连接到网络。
第六章**, 使用 Neutron 构建网络,带你了解如何创建网络、子网、子网池和端口。
第七章**, 将实例连接到网络,展示了如何将实例连接到网络,并探讨了获取 DHCP 租约和元数据的过程。
第八章**, 管理安全组,讲解了如何使用 iptables 来确保计算节点的实例流量安全,并带你了解如何创建和管理安全组及相关规则。
第九章**, 基于角色的访问控制,解释了访问控制策略如何将某些网络资源的使用限制在特定项目组之间。
第十章**, 使用 Neutron 创建独立路由器,带你学习如何创建独立的虚拟路由器并将其连接到网络,为实例应用浮动 IP,并追踪流量通过路由器到达实例的过程。
第十一章**, 使用 VRRP 实现路由器冗余,探讨了虚拟路由冗余协议及其在提供高可用虚拟路由器中的应用。
第十二章**, 分布式虚拟路由器,带你了解如何创建和管理分布在计算节点上的虚拟路由器,以便实现更好的扩展性。
第十三章**, 向实例分配负载均衡流量,探讨了 Neutron 负载均衡器的基本组成部分,包括监听器、池、池成员和监视器,并带你学习如何创建和集成虚拟负载均衡器到网络中。
第十四章**,高级网络主题,探讨了其他高级网络功能,包括允许虚拟机实例为流量应用 802.1q VLAN 标签的 VLAN 感知虚拟机功能,提供动态路由到项目路由器的 BGP Speaker 功能,以及可以用于将关键网络组件(如 DHCP 和 L3 代理)分隔到不同区域的网络可用性区域功能。
为了最大限度地发挥本书的价值
本书假设读者具有中等水平的网络经验,包括 Linux 网络配置经验以及物理交换机和路由器配置经验。尽管本书会引导读者完成 OpenStack 的基本安装,但除了 Neutron 服务外,其他服务的讨论较少。因此,读者在配置 OpenStack 网络之前,应该对 OpenStack 及其基本配置有一定的了解。
本书需要以下操作系统:
- Ubuntu 16.04 LTS
需要以下软件:
- OpenStack Pike (2017.2)
安装 OpenStack 软件包并使用本书中的示例架构需要互联网连接。虽然可以使用 VirtualBox 或 VMware 等虚拟化软件模拟服务器和网络基础设施,但本书假设 OpenStack 安装在物理硬件上,并且已经搭建了物理网络基础设施。
如果本书中描述的 OpenStack 安装程序不再适用,请参考docs.openstack.org上的安装指南,获取安装最新版本 OpenStack 的说明。
下载示例代码文件
你可以从你在www.packtpub.com的账户下载此书的示例代码文件。如果你在其他地方购买了此书,可以访问www.packtpub.com/support并注册,以便直接将文件通过邮件发送给你。
你可以通过以下步骤下载代码文件:
-
使用你的电子邮件地址和密码登录或注册我们的网站。
-
将鼠标指针悬停在页面顶部的 SUPPORT 标签上。
-
点击“代码下载与勘误”。
-
在搜索框中输入书籍名称。
-
选择你想要下载代码文件的书籍。
-
从下拉菜单中选择你购买此书的来源。
-
点击“代码下载”。
下载文件后,请确保使用以下最新版本的解压工具解压或提取文件夹:
-
WinRAR/7-Zip for Windows
-
Zipeg/iZip/UnRarX for Mac
-
7-Zip/PeaZip for Linux
本书的代码包也托管在 GitHub 上,链接为github.com/PacktPublishing/Learning-OpenStack-Networking-Third-Edition。如果代码有更新,它将在现有的 GitHub 仓库中更新。
我们还有来自我们丰富书籍和视频目录中的其他代码包,可以在github.com/PacktPublishing/查看。快来看看吧!
下载彩色图像
我们还提供了一份 PDF 文件,其中包含本书中使用的截图/图表的彩色图像。你可以在此下载:www.packtpub.com/sites/default/files/downloads/LearningOpenStackNetworkingThirdEdition.pdf.
使用的约定
本书中使用了许多文本约定。
CodeInText:文本中的代码字、数据库表名、文件夹名称、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 用户名像这样显示:“/etc/openstack-dashboard/local_settings.py 文件中的OPENSTACK_KEYSTONE_DEFAULT_ROLE设置也必须修改,才能使用仪表盘。”
代码块的格式如下:
[DEFAULT]
...
my_ip = 10.254.254.101
vncserver_proxyclient_address = 10.254.254.101
vnc_enabled = True
vncserver_listen = 0.0.0.0
novncproxy_base_url = http://controller01:6080/vnc_auto.html
当我们希望引起你对代码块中特定部分的注意时,相关行或项目将用粗体显示:
nova boot --flavor <FLAVOR_ID> --image <IMAGE_ID> \
--nic net-id=<NETWORK_ID>--security-group <SECURITY_GROUP_ID> \ INSTANCE_NAME
任何命令行输入或输出都按如下格式书写:
# systemctl restart nova-api
# systemctl restart neutron-server
粗体:新术语和重要单词用粗体显示。屏幕上看到的词语,例如菜单或对话框中的内容,像这样出现在文本中:“点击‘下一步’按钮会将你带到下一个屏幕。”
警告或重要提示像这样显示。
提示和技巧像这样显示。
联系我们
我们始终欢迎读者的反馈。
一般反馈:我们始终欢迎读者的反馈。让我们知道你对这本书的看法——你喜欢或不喜欢什么。读者反馈对我们非常重要,因为它帮助我们开发出你能真正受益的书籍。
要发送一般反馈,只需通过电子邮件联系我们:feedback@packtpub.com,并在邮件主题中提及书名。
如果你在某个领域有专业知识,并且有兴趣撰写或为书籍做贡献,请参见我们的作者指南:www.packtpub.com/authors。
勘误:尽管我们已尽一切努力确保内容的准确性,但错误还是难以避免。如果您在我们的书籍中发现错误——可能是文本或代码错误——我们将非常感激您能向我们报告。通过这样做,您可以帮助其他读者避免困扰,并帮助我们改进后续版本。如果您发现任何勘误,请访问www.packtpub.com/submit-errata报告,选择您的书籍,点击勘误提交表单链接,并输入勘误的详细信息。一旦您的勘误被验证,您的提交将被接受,勘误内容将上传到我们的网站或加入到该书籍的勘误清单中。
要查看以前提交的勘误,请访问www.packtpub.com/books/content/support并在搜索框中输入书名。相关信息将出现在勘误部分。
盗版:互联网中的版权材料盗版问题在所有媒体中都普遍存在。我们在 Packt 非常重视版权和许可证的保护。如果您在互联网上发现我们作品的非法复制品,无论形式如何,请立即提供相关的地址或网站名称,以便我们采取进一步行动。
请通过版权@packtpub.com 与我们联系,并提供涉嫌盗版材料的链接。
我们感谢您在保护我们的作者以及我们为您提供有价值内容的能力方面的帮助。
如果您有兴趣成为作者:如果您在某个领域具有专业知识,并且有兴趣撰写或参与撰写书籍,请访问authors.packtpub.com。
评论
请留下评论。当您阅读并使用本书后,为什么不在您购买它的网站上留下评论呢?潜在的读者可以看到并使用您的公正意见来做出购买决策,Packt 可以了解您对我们产品的看法,我们的作者也能看到您对他们书籍的反馈。谢谢!
想了解更多关于 Packt 的信息,请访问packtpub.com。
第一章:OpenStack 网络简介
在今天的数据中心,网络由比以往更多的设备组成。服务器、交换机、路由器、存储系统和安全设备,这些曾经占据数据中心大片空间的设备现在作为虚拟机和虚拟网络设备存在。这些设备给传统的网络管理系统带来了巨大压力,因为它们无法提供可扩展和自动化的方法来管理下一代网络。用户现在期望更高的基础设施控制和灵活性,快速的资源配置,而这些正是 OpenStack 所承诺提供的。
本章将介绍 OpenStack 网络提供的许多功能,以及 OpenStack 支持的各种网络架构。涵盖的主题包括以下内容:
-
OpenStack 网络功能
-
物理基础设施要求
-
服务分离
什么是 OpenStack 网络?
OpenStack 网络是一个可插拔、可扩展的、基于 API 的系统,用于管理 OpenStack 基础云中的网络。与其他核心 OpenStack 组件一样,OpenStack 网络可以供管理员和用户使用,以增加现有数据中心资源的价值并最大化利用。
Neutron,作为 OpenStack 网络服务的项目名称,补充了其他核心 OpenStack 服务,如计算(Nova)、镜像(Glance)、身份(Keystone)、块存储(Cinder)、对象存储(Swift)和仪表盘(Horizon),共同提供完整的云解决方案。
OpenStack 网络为用户提供了一个应用程序可编程接口(API),并将请求传递给配置的网络插件进行额外处理。用户能够在云中定义网络连接,而云运营商则可以利用不同的网络技术来增强和驱动云服务。
OpenStack 网络服务可以分布在多个主机之间,以提供弹性和冗余,或者可以配置为在单个节点上运行。像许多其他 OpenStack 服务一样,Neutron 需要访问数据库以持久化存储网络配置。可以在此看到一个简化的架构示例:

图 1.1
在图 1.1 中,Neutron 服务器连接到一个数据库,该数据库存储着逻辑网络配置。Neutron 服务器可以接收用户和服务的 API 请求,并通过消息队列与代理进行通信。在典型环境中,网络代理会分布在控制节点和计算节点上,并在各自的节点上执行任务。
OpenStack 网络功能
OpenStack 网络包括许多数据中心中常见的技术,包括交换、路由、负载均衡、防火墙和虚拟私人网络。
这些功能可以配置为利用开源或商业软件,提供给云操作员构建功能齐全且自包含的云网络栈所需的所有工具。OpenStack Networking 还为第三方厂商提供了一个框架,供其在此基础上构建并增强云的功能。
切换
虚拟交换机被定义为一种软件应用程序或服务,它在 OSI 模型的数据链路层(也称为第二层)连接虚拟机和虚拟网络。Neutron 支持多种虚拟交换平台,包括由 bridge 内核模块提供的 Linux 桥接和 Open vSwitch。Open vSwitch,也称为 OVS,是一个开源虚拟交换机,支持标准管理接口和协议,包括 NetFlow、SPAN、RSPAN、LACP 和 802.1q VLAN 标签。然而,许多这些功能并未通过 OpenStack API 提供给用户。除了 VLAN 标签之外,用户还可以使用 L2-in-L3 隧道协议(如 GRE 或 VXLAN)在软件中构建覆盖网络。虚拟交换机可以用于促进实例与 OpenStack 控制之外的设备之间的通信,这些设备包括硬件交换机、网络防火墙、存储设备、裸金属服务器等。
有关 Linux 桥接和 Open vSwitch 作为 OpenStack 切换平台的更多信息,请参阅 第四章, 使用 Linux 桥接的虚拟网络基础设施 和 第五章, 使用 Open vSwitch 构建虚拟交换基础设施。
路由
OpenStack Networking 通过使用 IP 转发、iptables 和网络命名空间提供路由和 NAT 功能。每个网络命名空间都有自己的路由表、接口和 iptables 进程,提供过滤和网络地址转换。通过利用网络命名空间将网络分开,可以避免用户创建的网络之间的子网重叠问题。在 Neutron 中配置路由器可以使实例与外部网络或云中的其他网络进行交互和通信。
有关在 OpenStack 中路由的更多信息,请参阅 第十章,使用 Neutron 创建独立路由器、* 第十一章,* 使用 VRRP 实现路由冗余,以及 第十二章,分布式虚拟路由器。
负载均衡
负载均衡即服务(LBaaS v2) 最早在 OpenStack 的 Grizzly 版本中引入,提供了将客户端请求分发到多个实例或服务器的功能。用户可以创建监控器,设置连接限制,并为通过虚拟负载均衡器的流量应用持久化配置。OpenStack 网络提供了一个用于 LBaaS v2 的插件,该插件在开源参考实现中使用 HAProxy,但也有插件可管理来自第三方网络供应商的虚拟和物理负载均衡设备。
有关在 Neutron 中使用负载均衡器的更多信息,请参见 第十三章, 负载均衡流量到实例。
防火墙
OpenStack 网络提供了两种 API 驱动的保护网络流量到实例的方法:安全组和 防火墙即服务(FWaaS)。安全组源于 nova-network,这是 OpenStack 的原始网络堆栈,内置于计算服务中,且基于亚马逊的 EC2 安全组。在 OpenStack 中使用安全组时,实例被放置在共享公共功能和规则集的组中。在参考实现中,安全组规则通过利用 iptables 或 OpenFlow 的驱动程序在实例端口级别实现。使用 FWaaS 构建的安全策略也在端口级别实现,但可以应用于路由器的端口以及实例。原始的 FWaaS v1 API 在 Neutron 路由器的命名空间中实现防火墙规则,但在 v2 API 中已移除该行为。
有关保护实例流量的更多信息,请参见 第八章,管理安全组。本书的范围不包括 FWaaS 的使用。
虚拟私人网络
虚拟私人网络(VPN) 扩展了一个私有网络,跨越公共网络如互联网。VPN 使计算机能够在公共网络上发送和接收数据,就像它直接连接到私有网络一样。当使用开源参考实现时,Neutron 提供了一组 API,允许用户从 Neutron 路由器创建基于 IPSec 的 VPN 隧道到远程网关。本书的范围不包括作为服务的 VPN 的使用。
网络功能虚拟化
网络功能虚拟化(NFV) 是一种网络架构概念,旨在将用于各种网络功能的网络设备虚拟化。这些功能包括入侵检测、缓存、网关、WAN 加速器、防火墙等。使用 SR-IOV 后,实例不再需要使用准虚拟化驱动程序或连接到主机中的虚拟桥。相反,实例会附加到与 NIC 中虚拟功能(VF)关联的 Neutron 端口,从而使实例能够直接访问 NIC 硬件。配置和实现 SR-IOV 与 Neutron 的结合超出了本书的范围。
OpenStack 网络资源
OpenStack 使用户能够创建和配置网络与子网,并指示其他服务(如计算服务)将虚拟设备连接到这些网络上的端口。身份服务使云管理员能够将用户划分为不同的项目。OpenStack 网络支持项目拥有的资源,包括每个项目拥有多个私有网络和路由器。项目可以选择自己的 IP 地址方案,即使这些地址与其他项目的网络重叠,或者管理员可以对子网的大小和可分配地址进行限制。
OpenStack 中可以表达两种类型的网络:
-
项目/租户网络:由项目或管理员代表项目创建的虚拟网络。网络的物理细节对项目不公开。
-
提供商网络:一种虚拟网络,用于映射到物理网络。提供商网络通常是为了访问云外的物理网络资源,如网络网关和其他服务,通常映射到 VLAN。可以为项目提供对提供商网络的访问。
在 OpenStack 社区中,项目和租户这两个术语是可以互换使用的,前者是更新且更推荐的术语。
项目网络 提供项目内资源的连接。用户可以创建、修改和删除项目网络。每个项目网络通过 VLAN 或其他分段 ID 等边界与其他项目网络隔离。提供商网络 则提供对云外网络的连接,通常由云管理员创建和管理。
项目网络与提供商网络的主要区别在于网络配置过程中可见。提供商网络由管理员代表项目创建,可以专用于特定项目,或由部分项目共享,甚至所有项目共享。项目网络由项目创建,供其实例使用,不能与所有项目共享,但可以通过基于角色的访问控制(RBAC)策略与特定项目共享。创建提供商网络时,管理员可以提供普通用户无法获取的具体细节,包括网络类型、物理网络接口和网络分段标识符(如 VLAN ID 或 VXLAN VNI)。项目网络具有相同的属性,但用户无法指定它们,这些属性由 Neutron 自动确定。
这本书后面将详细介绍其他基础网络资源,但在此表格中进行了总结以供参考:
| 资源 | 描述 |
|---|---|
| 子网 | 用于分配创建在网络上的端口的 IP 地址块。 |
| 端口 | 将单个设备(例如虚拟实例的虚拟网络接口卡(vNIC))连接到虚拟网络的连接点。端口属性包括子网上的 MAC 地址和固定 IP 地址。 |
| 路由器 | 提供自服务网络和提供商网络之间路由的虚拟设备。 |
| 安全组 | 一组虚拟防火墙规则,控制端口级别的入站和出站流量。 |
| DHCP | 管理提供商和自服务网络上实例 IP 地址的代理。 |
| 元数据 | 在实例引导过程中向实例提供数据的服务。 |
虚拟网络接口
OpenStack 部署通常配置为使用 libvirt KVM/QEMU 驱动程序进行平台虚拟化。当实例首次启动时,OpenStack 为每个附加到实例的网络接口创建一个端口。在托管实例的计算节点上创建称为tap 接口的虚拟网络接口。tap 接口直接对应于客户实例内的网络接口,并具有 Neutron 创建的端口属性,包括 MAC 和 IP 地址。通过使用桥接,主机可以将客户实例暴露给物理网络。Neutron 允许用户通过在端口上定义特殊属性并将其附加到实例来指定标准 tap 接口的替代方案,如 Macvtap 和 SR-IOV。
虚拟网络交换机
OpenStack Networking 支持多种虚拟和物理交换机类型,并内置支持 Linux 桥接和 Open vSwitch 虚拟交换机。本书将涵盖这两种技术及其各自的驱动程序和代理。
在 OpenStack 网络环境中,bridge 和 switch 这两个术语常常可以互换使用,并且在本书中也将以相同的方式使用。
叠加网络
Neutron 支持叠加网络技术,这些技术可以在不对底层物理基础设施做太多修改的情况下,实现大规模的网络隔离。为了实现这一点,Neutron 利用 L2-in-L3 叠加网络技术,如 GRE、VXLAN 和 GENEVE。经过适当配置后,Neutron 会在云中的所有网络和计算节点之间建立点对点隧道,使用预定义的接口。这些点对点隧道构成了所谓的 mesh network(网状网络),其中每个主机都与其他主机相连。由一个结合了控制器和网络节点的节点,以及三个计算节点组成的云,将拥有一个完全网状的叠加网络,类似于图 1.2:

图 1.2
使用图 1.2 中所示的叠加网络,任何给定主机上实例或其他虚拟设备之间的流量将穿越每个底层主机上的第 3 层端点,而不考虑其下方的第 2 层网络。由于封装,可能需要 Neutron 路由器来促进不同项目网络之间的通信,以及与云外网络的通信。
虚拟可扩展局域网(VXLAN)
本书主要关注 VXLAN,这是一种叠加技术,帮助解决 VLAN 的可扩展性问题。VXLAN 将第 2 层以太网帧封装在第 4 层 UDP 数据包中,这些数据包可以在主机之间转发或路由。这意味着虚拟网络可以透明地跨越大规模网络扩展,而无需对终端主机进行任何修改。然而,在 OpenStack 网络环境中,VXLAN 网状网络通常仅在同一云中的节点之间构建。
与使用 VLAN ID 区分网络不同,VXLAN 使用 VXLAN 网络标识符(VNI)作为链路上的唯一标识符,这个链路可能承载成千上万甚至更多网络的流量。802.1q VLAN 头部支持最多 4,096 个唯一 ID,而 VXLAN 头部则支持大约 1600 万个唯一 ID。在 OpenStack 云中,虚拟机实例并不知道 VXLAN 被用来在主机之间转发流量。物理节点上的 VXLAN 隧道端点(VTEP)负责流量的封装和解封装,实例对此并不知情。
由于 VXLAN 网络流量被封装,许多网络设备在没有额外配置的情况下无法参与这些网络。结果,VXLAN 网络实际上与云中的其他网络隔离,并且需要使用 Neutron 路由器来为连接的实例提供访问。有关创建 Neutron 路由器的更多信息,请参见 第十章,使用 Neutron 创建独立路由器。
虽然在某些硬件上,VXLAN 的性能不如 VLAN 或平面网络,但在云网络架构中,VXLAN 的使用越来越普遍,尤其是在可扩展性和自助服务是主要驱动因素的情况下。如果你正在考虑在云中实现基于 VXLAN 的覆盖网络,应利用提供 VXLAN 卸载功能的较新网络硬件。
有关 VXLAN 封装工作原理的更多信息,请参阅 RFC 7348,详情见以下网址:tools.ietf.org/html/rfc7348
通用路由器封装(GRE)
GRE 网络类似于 VXLAN 网络,其中一个实例到另一个实例的流量被封装并通过第 3 层网络发送。使用唯一的分段 ID 来区分来自其他 GRE 网络的流量。与使用 UDP 作为传输机制不同,GRE 使用 IP 协议 47。由于各种原因,随着 VXLAN 被 Open vSwitch 和 Linux Bridge 网络代理支持,使用 GRE 封装租户网络流量的做法已不再流行。
有关 GRE 封装工作原理的更多信息,请参阅 RFC 2784,详情见以下网址:tools.ietf.org/html/rfc2784
从 OpenStack 的 Pike 版本开始,Open vSwitch 机制驱动程序是唯一支持 GRE 的常用驱动程序。
通用网络虚拟化封装(GENEVE)
GENEVE 是一种新兴的覆盖技术,它类似于 VXLAN 和 GRE,旨在通过标准网络设备传输主机之间的分组,而无需修改客户端或主机应用程序。像 VXLAN 一样,GENEVE 使用独特的头部封装分组,并使用 UDP 作为其传输机制。GENEVE 利用了 VXLAN、NVGRE 和 STT 等多种覆盖技术的优势,并可能随着时间的推移取代这些技术。Open Virtual Networking(OVN)机制驱动程序依赖于 GENEVE 作为其覆盖技术,这可能会加速 GENEVE 在 OpenStack 后续版本中的采用。
准备物理基础设施
大多数 OpenStack 云由适合以下四类之一的物理基础设施节点组成:
-
控制节点:控制节点通常运行所有 OpenStack 组件的 API 服务,包括 Glance、Nova、Keystone、Neutron 等。此外,控制节点还运行数据库和消息服务器,通常也是通过 Horizon 仪表板管理云的入口点。大多数 OpenStack API 服务可以安装在多个控制节点上,并且可以负载均衡以扩展 OpenStack 控制平面。
-
网络节点:网络节点通常运行 DHCP 和元数据服务,并且在安装了 Neutron L3 代理时,也可以承载虚拟路由器。在较小的环境中,控制节点和网络节点的服务往往会合并到同一台服务器或一组服务器上。随着云规模的增长,大多数网络服务可以拆分到其他服务器上,或者为了优化性能,安装在独立的服务器上。
-
计算节点:计算节点通常运行如 KVM、Hyper-V 或 Xen 等虚拟化软件,或如 LXC 或 Docker 等容器软件。在某些情况下,计算节点还可能承载虚拟路由器,特别是当配置了分布式虚拟路由(DVR)时。在概念验证或测试环境中,控制、网络和计算节点的服务经常合并在同一台机器上。这在使用 DevStack(一个用于开发和测试 OpenStack 代码的软件包)时尤其常见。对于生产环境,不建议使用一体化安装。
-
存储节点:存储节点通常仅运行与存储相关的软件,如 Cinder、Ceph 或 Swift。存储节点通常不承载任何类型的 Neutron 网络服务或代理,本书将不讨论这一部分内容。
当 Neutron 服务分布在多个主机之间时,服务的布局通常类似于以下结构:

图 1.3
在图 1.3 中,Neutron API 服务 neutron-server 安装在控制节点上,而负责实现某些虚拟网络资源的 Neutron 代理则安装在专用的网络节点上。每个计算节点上都运行一个网络插件代理,负责在该主机上实现网络连接。Neutron 支持高可用的 API 服务,并具有共享的数据库后台,建议云操作员在可能的情况下对 Neutron API 服务进行流量负载均衡。应尽可能将多个 DHCP、元数据、L3 和 LBaaS 代理部署在独立的网络节点上。虚拟网络、路由器和负载均衡器可以被调度到一个或多个代理上,以提供在代理失败时的基本冗余。Neutron 甚至包括一个内置调度器,能够在检测到故障时重新调度某些资源。
配置物理基础设施
在开始安装 OpenStack 之前,必须配置物理网络基础设施,以支持操作云所需的网络。在生产环境中,这通常包括用于服务器管理和 API 流量的专用管理 VLAN,用于叠加网络流量的 VLAN,以及一个或多个将用于提供商和基于 VLAN 的项目网络的 VLAN。可以在单独的接口上配置这些网络,也可以将它们合并到一个接口上,具体取决于需求。
OpenStack 网络的参考架构定义了网络中至少四种不同类型的流量:
-
管理
-
API
-
外部
-
客户机
这些流量类型通常根据目的被分类为控制平面或数据平面,这些术语用于网络中描述流量的目的。在这种情况下,控制平面流量用于描述与管理、API 及其他非虚拟机相关的流量。数据平面流量则代表由虚拟机实例生成的或指向虚拟机实例的流量。
尽管在本书中我已将网络流量分配到专用接口,但并不需要这样做才能创建一个可操作的 OpenStack 云。事实上,许多管理员和发行版选择将多种流量类型合并到单一或绑定的接口上,使用 VLAN 标记。根据所选的部署模型,管理员可能将网络服务分布在多个节点上,或将它们集中到一个节点上。部署云的企业的安全要求通常会决定云的构建方式。接下来的章节将讨论各种网络和服务配置。
管理网络
管理网络,在某些发行版中也称为内部网络,用于主机之间的内部通信,如消息服务和数据库服务,可以视为控制平面的一部分。
所有主机将在此网络上进行相互通信。在许多情况下,可能会使用相同的接口来促进主机之间的镜像传输或其他带宽密集型流量。管理网络可以配置为专用接口上的隔离网络,或如下一节所述,与其他网络合并。
API 网络
API 网络用于将 OpenStack API 暴露给云的用户和云内服务,并可以视为控制平面的一部分。API 服务的端点地址,如 Keystone、Neutron、Glance 和 Horizon,来自于 API 网络。
通常做法是利用单一接口和 IP 地址来访问 API 端点以及通过 SSH 访问主机本身。该配置的示意图将在本章后面提供。
尽管不是强制要求,但建议将管理和 API 流量与其他流量类型(如存储流量)物理分离,以避免可能影响操作稳定性的网络拥塞问题。
外部网络
外部网络是一个提供给 Neutron 路由器外部网络访问的提供商网络。一旦路由器被配置并连接到外部网络,该网络就成为实例和附加到路由器的其他网络资源的浮动 IP 地址的来源。外部网络中的 IP 地址应当是可路由的,并且可以被公司网络或互联网中的客户端访问。多个外部提供商网络可以通过 VLAN 进行分段,并通过同一个物理接口进行中继。Neutron 负责根据管理员提供的网络配置对 VLAN 进行标记。由于外部网络是由虚拟机使用的,它们可以视为数据平面的一部分。
客户网络
客户网络是专门为实例流量提供的网络。客户网络的选项包括仅限特定节点的本地网络、平面网络或 VLAN 标签网络,或通过 GRE、VXLAN 或 GENEVE 封装技术实现的虚拟覆盖网络。有关客户网络的更多信息,请参阅第六章,使用 Neutron 构建网络。由于客户网络为虚拟机提供连接,因此它们可以视为数据平面的一部分。
用于外部和客户网络的物理接口可以是专用接口,也可以是与其他类型流量共享的接口。每种方式都有其优缺点,后文将详细描述。在接下来的几章中,我将定义将在全书中使用的网络和 VLAN,以展示 OpenStack Networking 的各个组件。还将提供关于交换机端口、路由器或防火墙配置的一般信息。
物理服务器连接
每个主机所需的接口数量取决于云的用途、组织的安全性和性能要求以及硬件的成本和可用性。每个服务器只需要一个接口,控制面和数据面合并在同一个接口中,这样就足以支撑一个完全运行的 OpenStack 云。许多组织选择以这种方式部署云,尤其是在端口密度有限、环境仅用于测试或节点级别的网络故障不会产生影响的情况下。然而,如果可能的话,建议将控制流量和数据流量分配到多个接口上,以减少网络故障的可能性。
单一接口
对于使用单一接口的主机,所有进出实例的流量以及内部 OpenStack、SSH 管理和 API 流量都会穿越同一个物理接口。这种配置可能导致严重的性能损失,因为某个服务或虚拟机可能会消耗所有可用带宽。单一接口仅推荐用于非生产环境的云。
下表展示了多个 VLAN 下通过单一接口穿越的网络和服务:
| 服务/功能 | 目的 | 接口 | VLAN |
|---|---|---|---|
| SSH | 主机管理 | eth0 | 10 |
| APIs | 访问 OpenStack APIs | eth0 | 15 |
| 覆盖网络 | 用于在主机之间隧道化覆盖(VXLAN、GRE、GENEVE)流量 | eth0 | 20 |
| 客户机/外部网络 | 用于提供访问外部云资源和基于 VLAN 的项目网络 | eth0 | 多个 |
多个接口
为减少客户机流量对管理流量的影响,建议在多个物理接口之间进行流量隔离。至少应使用两个接口:一个作为专用接口处理管理和 API 流量(控制平面),另一个作为专用接口处理外部和客户机流量(数据平面)。可以使用额外的接口进一步隔离流量,例如存储流量。
下表展示了通过两个接口和多个 VLAN 的网络和服务:
| 服务/功能 | 目的 | 接口 | VLAN |
|---|---|---|---|
| SSH | 主机管理 | eth0 | 10 |
| APIs | 访问 OpenStack APIs | eth0 | 15 |
| 覆盖网络 | 用于在主机之间隧道化覆盖(VXLAN、GRE、GENEVE)流量 | eth1 | 20 |
| 客户机/外部网络 | 用于提供访问外部云资源和基于 VLAN 的项目网络 | eth1 | 多个 |
绑定
使用多个接口可以扩展为使用绑定而非单独的网络接口。以下是支持的常见绑定模式:
-
模式 1(主动-备份):模式 1 绑定将绑定中的所有接口设置为备份状态,同时保持一个接口处于活动状态。当活动接口失败时,备份接口将替代它。故障切换时使用相同的 MAC 地址,以避免物理网络交换机出现问题。大多数交换机厂商支持模式 1 绑定,因为它不需要在交换机上进行特殊配置。
-
模式 4(主动-主动):模式 4 绑定涉及使用 聚合组,该组中的所有接口共享相同的配置并组合成一个逻辑接口。接口通过 IEEE 802.3ad 链路聚合控制协议(LACP)进行聚合。流量根据物理节点和连接交换机或交换机的协商方法在链路上进行负载均衡。物理交换基础设施 必须 支持这种类型的绑定。尽管一些交换平台要求将 LACP 绑定的多个链路连接到同一交换机,但其他平台支持名为 多机箱链路聚合(MLAG) 的技术,该技术允许多个物理交换机被配置为一个逻辑交换机。这使得绑定的链路可以连接到多个交换机,提供硬件冗余,同时在正常操作条件下允许用户充分利用绑定的带宽,且无需对服务器配置进行额外更改。
Bonding 可以在 Linux 操作系统中通过诸如 iproute2、ifupdown 和 Open vSwitch 等工具进行配置。Bonded 接口的配置超出了 OpenStack 和本书的范围。
Bonding 配置在不同的 Linux 发行版之间差异很大。请参考你所使用的 Linux 发行版的相关文档以帮助配置 bonding。
以下表格演示了使用两个 bond 而非两个单独接口的情况:
| 服务/功能 | 目的 | 接口 | VLAN |
|---|---|---|---|
| SSH | 主机管理 | bond0 | 10 |
| APIs | 访问 OpenStack APIs | bond0 | 15 |
| 覆盖网络 | 用于在主机之间隧道覆盖(VXLAN, GRE, GENEVE)流量 | bond1 | 20 |
| 客户机/外部网络 | 用于提供对外部云资源的访问以及基于 VLAN 的项目网络 | bond1 | 多个 |
本书中将构建一个使用三种非 bonded 接口的环境:一个用于管理和 API 流量,一个用于基于 VLAN 的提供者或项目网络,另一个用于覆盖网络流量。以下接口和 VLAN ID 将被使用:
| 服务/功能 | 目的 | 接口 | VLAN |
|---|---|---|---|
| SSH 和 API | 主机管理和访问 OpenStack APIs | eth0 / ens160 | 10 |
| 覆盖网络 | 用于在主机之间隧道覆盖(VXLAN, GRE, GENEVE)流量 | eth1 / ens192 | 20 |
| 客户机/外部网络 | 用于提供对外部云资源的访问以及基于 VLAN 的项目网络 | eth2 / ens224 | 30,40-43 |
当环境在 VMware 中虚拟化时,接口名称可能与标准的 eth0、eth1、ethX 命名约定有所不同。表中提供的接口名称反映的是虚拟机中存在的控制节点和计算节点的接口命名约定,而不是裸机上的命名。
跨节点分离服务
像其他 OpenStack 服务一样,云操作员可以将 OpenStack 网络服务分布到多个节点。小型部署可能会使用单个节点来托管所有服务,包括网络、计算、数据库和消息服务。其他用户可能会发现使用专用的控制节点和专用的网络节点来处理通过软件路由器路由的客户机流量,并卸载 Neutron DHCP 和元数据服务会更有优势。以下部分描述了一些常见的服务部署模型。
使用单个控制节点
在由单个控制节点和一个或多个计算节点组成的环境中,控制节点通常负责处理所有网络服务和其他 OpenStack 服务,而计算节点严格提供计算资源。
以下图示展示了一个控制节点托管所有 OpenStack 管理和网络服务的情况,其中没有使用 Neutron 层 3 代理。使用两个物理接口来分离管理(控制平面)和实例(数据平面)网络流量:

图 1.3
上述图示反映了使用单一的合并控制/网络节点和一个或多个计算节点的配置,其中 Neutron 仅提供实例与外部网关设备之间的第二层连接。需要外部路由器来处理网络段之间的路由。
以下图示展示了一个控制节点承载所有 OpenStack 管理和网络服务,包括 Neutron L3 代理。三个物理接口用于提供独立的控制面和数据面:

图 1.4
上述图示反映了在使用 Neutron L3 代理的网络配置中,使用单一的合并控制/网络节点和一个或多个计算节点。使用 Neutron 创建的软件路由器驻留在控制节点上,处理连接的项目网络和外部提供商网络之间的路由。
使用专用网络节点
一个网络节点专门处理大部分或所有 OpenStack 网络服务,包括 L3 代理、DHCP 代理、元数据代理等。使用专用网络节点能提供额外的安全性和韧性,因为控制节点在网络和资源饱和方面的风险较小。一些 Neutron 服务,如 L3 和 DHCP 代理以及 Neutron API 服务,可以在多个节点之间进行扩展,以实现冗余和提高性能,尤其是在使用分布式虚拟路由器时。
以下图示展示了一个网络节点承载所有 OpenStack 网络服务,包括 Neutron L3、DHCP、元数据和 LBaaS 代理。然而,Neutron API 服务仍然安装在控制节点上。必要时,使用三个物理接口来提供独立的控制面和数据面:

图 1.5
本书中构建的环境将由五个主机构成,包括以下内容:
-
一个控制节点运行所有 OpenStack 网络服务和 Linux 桥接网络代理
-
一个计算节点运行 Nova 计算服务和 Linux 桥接网络代理
-
两个计算节点运行 Nova 计算服务和 Open vSwitch 网络代理
-
一个网络节点运行 Open vSwitch 网络代理和 L3 代理
如果你选择不完成接下来章节中描述的练习,则并非所有主机都是必需的。
总结
OpenStack Networking 提供了以虚拟化和可编程的方式创建和管理数据中心中不同技术的能力。如果内建的功能和参考实现不够,OpenStack Networking 的可插拔架构允许第三方商业和开源供应商提供额外的功能。构建云的组织的安全要求以及云的使用案例,最终将决定基础设施节点间服务的物理布局和分离。
要成功部署 Neutron 并充分利用它的所有功能,理解核心网络概念非常重要。在本书中,我们将介绍一些与 Neutron 相关的基础网络概念,并为部署实例打下基础。
在下一章中,我们将开始在 Ubuntu 16.04 LTS 操作系统上进行基于软件包的 OpenStack 安装。涉及的内容包括多个核心 OpenStack 项目的安装、配置和验证,其中包括身份认证、镜像、仪表盘和计算服务。基础 OpenStack 网络服务的安装与配置,包括 Neutron API,可以在第三章, 安装 Neutron中找到。
第二章:安装 OpenStack
手动安装、配置和维护 OpenStack 云可能是一项艰巨的任务。许多供应商提供基于 OpenStack 的可下载云软件,使用 Chef、Puppet、Ansible 等工具提供部署和管理策略。
本章将逐步指导您在 Ubuntu 16.04 LTS 操作系统上安装以下 OpenStack 组件:
-
OpenStack 身份(Keystone)
-
OpenStack 镜像服务(Glance)
-
OpenStack 计算(Nova)
-
OpenStack 仪表板(Horizon)
本章中记录的安装过程基于OpenStack 安装指南,该指南可以在 docs.openstack.org/ 找到。如果您希望在其他操作系统上安装 OpenStack,可以参考该网站上的指南。
如果您更愿意下载并安装基于 OpenStack 的第三方云发行版,可以尝试以下 URL:
-
OpenStack-Ansible:
docs.openstack.org/openstack-ansible/ -
Red Hat RDO:
openstack.redhat.com/
一旦安装完成,本书中使用的大部分概念和示例仍然适用于上述发行版,但可能需要额外的努力才能实现。
系统要求
OpenStack 组件旨在运行于标准硬件上,从桌面计算机到企业级服务器均可支持。为了获得最佳性能,计算节点的处理器需要支持虚拟化技术,如英特尔的 VT-x 或 AMD 的 AMD-V。
本书假设 OpenStack 将安装在满足以下最低要求的服务器上:
| 服务器 | 硬件要求 |
|---|---|
| 所有 | 处理器:64 位 x86CPU 数量:2-4 内存:4+ GB RAM 磁盘空间:32+ GB 网络:3x 1-Gbps 网络接口卡 |
虽然不符合这些最低要求的机器也能根据本书中提供的文档进行安装,但这些最低要求是为了确保顺利的体验。在创建多个虚拟机实例用于演示时,强烈建议增加额外的内存和存储。像 VMware ESXi、VMware Fusion 或 VirtualBox 等虚拟化产品可以替代物理硬件使用,但需要对环境和 OpenStack 进行额外的配置,这超出了本书的范围。如果选择虚拟化环境,建议启用硬件虚拟化扩展,以提升性能。
操作系统要求
OpenStack 可以安装在以下 Linux 发行版上:CentOS、Red Hat Enterprise Linux、openSUSE、SUSE Linux Enterprise Server 和 Ubuntu。本书假设在安装 OpenStack 之前,所有主机已经安装了 Ubuntu 16.04 LTS 服务器操作系统。你可以在以下网址找到 Ubuntu Server:www.ubuntu.com/download/server。
为了支持本书中讨论的所有网络功能,推荐使用以下最小内核版本:4.13.0-45-generic。
初始网络配置
为了理解每台主机应该如何初步配置网络,请参考以下图示:

图 2.1
在图 2.1中,三个接口分别连接到每台主机。eth0接口将作为 OpenStack 服务和 API 访问的管理接口,而eth1将用于主机之间的覆盖网络流量。在controller节点,eth2将用于通过 Neutron 路由器向实例传递外部网络流量。如果使用 VLAN 租户网络代替覆盖网络,则eth2将配置在compute节点上,以支持这些网络。
至少,管理接口应该配置一个 IP 地址,并具有访问互联网的外部连接。需要互联网访问才能从 Ubuntu 软件包仓库下载 OpenStack 软件包。建议通过 SSH 从受信任的网络访问服务器的管理地址。
示例网络
在本书中,将会有配置和使用各种 OpenStack 服务的示例。下表列出了用于这些服务的 VLAN 和相关网络:
| VLAN 名称 | VLAN ID | 网络 |
|---|---|---|
| MGMT_NET | 10 | 10.10.0.0/24 |
| OVERLAY_NET | 20 | 10.20.0.0/24 |
| GATEWAY_NET | 30 | 10.30.0.0/24 |
| PROJECT_NET40 | 40 | 待定 |
| PROJECT_NET41 | 41 | 待定 |
| PROJECT_NET42 | 42 | 待定 |
| PROJECT_NET43 | 43 | 待定 |
以下表格提供了每个主机接口推荐的 IP 地址和 VLAN ID,供您在跟随示例时参考:
| 主机名 | 接口 | IP 地址 | 交换端口 | VLAN ID |
|---|---|---|---|---|
| controller01 | eth0 | 10.10.0.100 | 访问端口 | VLAN 10(未标记) |
| controller01 | eth1 | 10.20.0.100 | 访问端口 | VLAN 20(未标记) |
| controller01 | eth2 | 无 | Trunk 端口 | VLAN 30, 40-44(标记) |
| 主机名 | 接口 | IP 地址 | 交换端口 | VLAN ID |
| compute01 | eth0 | 10.10.0.101 | 访问端口 | VLAN 10(未标记) |
| compute01 | eth1 | 10.20.0.101 | 访问端口 | VLAN 20(未标记) |
| compute01 | eth2 | 无 | Trunk 端口 | VLAN 30, 40-44(标记) |
| 主机名 | 接口 | IP 地址 | 交换端口 | VLAN ID |
| compute02 | eth0 | 10.10.0.102 | 访问端口 | VLAN 10(未标记) |
| compute02 | eth1 | 10.20.0.102 | 访问端口 | VLAN 20(未标记) |
| compute02 | eth2 | 无 | 中继端口 | VLAN 30, 40-44(已标记) |
| 主机名 | 接口 | IP 地址 | 交换端口 | VLAN ID |
| compute03 | eth0 | 10.10.0.103 | 访问端口 | VLAN 10(未标记) |
| compute03 | eth1 | 10.20.0.103 | 访问端口 | VLAN 20(未标记) |
| compute03 | eth2 | 无 | 中继端口 | VLAN 30, 40-44(已标记) |
| 主机名 | 接口 | IP 地址 | 交换端口 | VLAN ID |
| snat01 | eth0 | 10.10.0.104 | 访问端口 | VLAN 10(未标记) |
| snat01 | eth1 | 10.20.0.104 | 访问端口 | VLAN 20(未标记) |
| snat01 | eth2 | 无 | 中继端口 | VLAN 30, 40-44(已标记) |
为了避免因接口配置错误或其他问题导致连接丢失,强烈建议使用带外管理访问服务器或其他类似机制。
接口配置
Ubuntu 16.04 LTS 使用位于/etc/network/interfaces.d/目录或/etc/network/interfaces文件中的配置文件来描述如何配置网络接口。
使用文本编辑器,在每个主机上更新网络接口文件,方法如下。
对于controller01:
auto eth0
iface eth0 inet static
address 10.10.0.100
netmask 255.255.255.0
gateway 10.10.0.1
dns-nameserver 8.8.8.8
auto eth1
iface eth1 inet static
address 10.20.0.100
netmask 255.255.255.0
auto eth2
iface eth2 inet manual
对于compute01:
auto eth0
iface eth0 inet static
address 10.10.0.101
netmask 255.255.255.0
gateway 10.10.0.1
dns-nameserver 8.8.8.8
auto eth1
iface eth1 inet static
address 10.20.0.101
netmask 255.255.255.0
auto eth2
iface eth2 inet manual
对于compute02:
auto eth0
iface eth0 inet static
address 10.10.0.102
netmask 255.255.255.0
gateway 10.10.0.1
dns-nameserver 8.8.8.8
auto eth1
iface eth1 inet static
address 10.20.0.102
netmask 255.255.255.0
auto eth2
iface eth2 inet manual
对于compute03:
auto eth0
iface eth0 inet static
address 10.10.0.103
netmask 255.255.255.0
gateway 10.10.0.1
dns-nameserver 8.8.8.8
auto eth1
iface eth1 inet static
address 10.20.0.103
netmask 255.255.255.0
auto eth2
iface eth2 inet manual
对于snat01:
auto eth0
iface eth0 inet static
address 10.10.0.104
netmask 255.255.255.0
gateway 10.10.0.1
dns-nameserver 8.8.8.8
auto eth1
iface eth1 inet static
address 10.20.0.104
netmask 255.255.255.0
auto eth2
iface eth2 inet manual
eth2接口将在后续章节中描述的网络桥接中使用。要激活更改,请使用ifdown和ifup命令在每个节点上重启接口:
# ifdown --all; ifup --all
有关配置网络接口的更多信息,请参考 Ubuntu 手册页,网址如下:manpages.ubuntu.com/manpages/xenial/man5/interfaces.5.html
初步步骤
在我们可以安装 OpenStack 之前,必须做一些准备工作,以确保每个系统能够成功安装。
权限
OpenStack 服务可以作为 root 用户或具有sudo权限的用户安装。后者可能需要将用户添加到每个主机的sudoers文件中。有关配置sudoers的提示,请访问以下网址:help.ubuntu.com/community/RootSudo.
对于此安装,除非另有说明,否则所有命令都应以 root 用户身份运行。
配置 OpenStack 仓库
当安装版本比操作系统自带版本更新的 OpenStack 时,Ubuntu 使用 Ubuntu Cloud Archive(UCA)。要启用 Cloud Archive 仓库,请更新apt缓存,并在所有主机上下载并安装software-properties-common包:
# apt update; apt install software-properties-common
安装完成后,应该将 OpenStack Pike 仓库添加为所有主机的 apt 源:
# add-apt-repository cloud-archive:pike
系统升级
在安装 OpenStack 之前,必须将每个节点上的内核和其他系统包升级到 Ubuntu 16.04 LTS 版本中通过 Cloud Archive 提供的最新版本。请在每个节点上执行以下apt命令:
# apt update
# apt dist-upgrade
设置主机名
在安装 OpenStack 之前,确保环境中的每个节点都已配置正确的主机名。使用hostnamectl命令在每个主机上相应设置主机名:
| 主机 | 命令 |
|---|---|
controller01 |
hostnamectl set-hostname controller01 |
compute01 |
hostnamectl set-hostname compute01 |
compute02 |
hostnamectl set-hostname compute02 |
compute03 |
hostnamectl set-hostname compute03 |
snat01 |
hostnamectl set-hostname snat01 |
为简化主机之间的通信,建议使用 DNS 或本地名称解析器来解析主机名。使用文本编辑器,更新每个节点上的/etc/hosts文件,以包含所有节点的管理 IP 地址和主机名:
10.10.0.100 controller01.learningneutron.com controller01
10.10.0.101 compute01.learningneutron.com compute01
10.10.0.102 compute02.learningneutron.com compute02
10.10.0.103 compute03.learningneutron.com compute03
10.10.0.104 snat01.learningneutron.com snat01
在每个节点上,使用hostname -f命令验证完全限定的主机名是否正确反映:
root@controller01:~# hostname -f
controller01.learningneutron.com
安装和配置网络时间协议
如网络时间协议 (NTP) 等时间同步程序是必需的,因为 OpenStack 服务依赖于主机之间的一致且同步的时间。
对于 Nova 计算,时间同步有助于避免在 compute 节点上调度虚拟机启动时出现问题。其他服务在时间未同步时也会遇到类似问题。
要安装 NTP 实现 chrony,请在环境中的所有节点上执行以下命令:
# apt install chrony
在controller节点上,将以下行添加到/etc/chrony/chrony.conf文件中,以允许环境中的其他主机与控制器同步时间:
allow 10.10.0.0/24
在其他节点上,注释掉/etc/chrony/chrony.conf文件中的任何pool行,并添加以下行,将它们的时间同步指向控制器:
# pool 2.debian.pool.ntp.org offline iburst
server controller01 iburst
在每个主机上,重启 chrony 服务:
# systemctl restart chrony
重启系统
在继续安装之前,重启每个主机:
# reboot
安装 OpenStack
本节的步骤记录了在一个控制节点和三个compute节点上安装 OpenStack 服务(包括 Keystone、Glance、Nova 和 Horizon)的过程。Neutron,OpenStack 网络服务,将在下一章进行安装。
使用以下命令在controller节点上安装 OpenStack 命令行客户端 python-openstackclient,为配置各种服务做好准备:
# apt install python-openstackclient
安装和配置 MySQL 数据库服务器
在controller节点上,使用apt安装 MySQL 数据库服务和相关的 Python 包:
# apt install mariadb-server python-pymysql
如果提示,请将密码设置为openstack。
本书中使用了不安全的密码,以简化配置和概念演示,且不推荐用于生产环境。访问www.strongpasswordgenerator.org为您的环境生成强密码。
安装完成后,创建并编辑 /etc/mysql/mariadb.conf.d/99-openstack.cnf 配置文件。添加 [mysqld] 块和 bind-address 定义。这样可以允许其他主机连接 MySQL。bind-address 的值应为 controller 节点的管理 IP 地址:
[mysqld]
bind-address = 10.10.0.100
除了添加 bind-address 定义外,还需要在 [mysqld] 部分添加以下选项:
default-storage-engine = innodb
innodb_file_per_table = on
max_connections = 4096
collation-server = utf8_general_ci
character-set-server = utf8
保存并关闭文件,然后重新启动 mysql 服务:
# systemctl restart mysql
MySQL 安全安装工具用于创建默认的 MySQL 数据库并为 MySQL root 用户设置密码。以下命令将开始 MySQL 的安装和配置过程:
# mysql_secure_installation
在 MySQL 安装过程中,你将被提示输入密码并修改各种设置。默认的 root 密码可能尚未设置。当系统提示时,请设置 root 密码为 openstack。建议使用更安全的密码,以适应你的环境。
对其余问题回答 [Y]es 以退出配置过程。此时,MySQL 服务器已成功安装在 controller 节点上。
安装和配置消息服务器
高级消息队列协议(AMQP)是支撑大多数基于 OpenStack 的云计算平台的消息技术。像 Nova、Cinder 和 Neutron 等组件通过消息总线在内部以及彼此之间进行通信。以下是安装 RabbitMQ(AMQP 中介)的说明。
在 controller 节点上,安装消息服务器:
# apt install rabbitmq-server
向 RabbitMQ 中添加名为 openstack 的用户,并设置密码为 rabbit,如以下命令所示:
# rabbitmqctl add_user openstack rabbit
设置 RabbitMQ 权限,以允许 openstack 用户进行配置、读取和写入操作:
# rabbitmqctl set_permissions openstack ".*" ".*" ".*"
到此为止,RabbitMQ 的安装和配置已经完成。
安装和配置 memcached
memcached 服务用于将常见的数据和对象缓存到 RAM 中,从而减少它们从磁盘读取的次数,多个 OpenStack 服务都会使用它。
在 controller 节点上,安装 memcached:
# apt install memcached python-memcache
编辑 /etc/memcached.conf 文件,并将默认的监听地址替换为 controller 节点的 IP 地址:
-
来源:
127.0.0.1 -
目标:
10.10.0.100
重启 memcached 服务:
# systemctl restart memcached
安装和配置身份服务
Keystone 是 OpenStack 的身份服务,用于在 OpenStack 云中对用户和服务进行认证和授权。Keystone 应该只安装在 controller 节点上,后续部分将进行介绍。
配置数据库
使用 mysql 客户端,创建 Keystone 数据库和相关用户:
# mysql
在 MariaDB [(none)] > 提示符下输入以下 SQL 语句:
CREATE DATABASE keystone;
GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' IDENTIFIED BY 'keystone';
GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' IDENTIFIED BY 'keystone';
quit;
安装 Keystone
从 OpenStack 的 Kilo 版本开始,Keystone 项目使用 Apache HTTP 服务器和 mod_wsgi 来处理对身份 API 的请求,监听端口 5000 和 35357。
在controller节点上运行以下命令来安装 Keystone 软件包:
# apt install keystone apache2 libapache2-mod-wsgi
更新/etc/keystone/keystone.conf文件中的[database]部分,将 Keystone 配置为使用 MySQL 作为数据库。在此安装中,用户名和密码为keystone。你需要用以下单行值覆盖现有的连接字符串:
[database]
...
connection = mysql+pymysql://keystone:keystone@controller01/keystone
配置令牌和驱动程序
Keystone 支持可自定义的令牌提供程序,这些提供程序可以在配置文件的[token]部分中定义。Keystone 提供 UUID、PKI 和 Fernet 令牌提供程序。在此安装中,将使用 Fernet 令牌提供程序。相应地更新/etc/keystone/keystone.conf文件中的[token]部分:
[token]
...
provider = fernet
使用keystone-manage工具填充 Keystone 数据库:
# su -s /bin/sh -c "keystone-manage db_sync" keystone
使用以下命令初始化 Fernet 密钥存储库:
# keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone # keystone-manage credential_setup --keystone-user keystone --keystone-group keystone
引导身份验证服务
使用keystone-manage命令,使用身份验证端点引导服务目录。在此环境中,admin用户的密码为openstack:
# keystone-manage bootstrap --bootstrap-password openstack --bootstrap-admin-url http://controller01:35357/v3/
--bootstrap-internal-url http://controller01:5000/v3/
--bootstrap-public-url http://controller01:5000/v3/ --bootstrap-region-id RegionOne
配置 Apache HTTP 服务器
使用sed命令,将ServerName选项添加到 Apache 配置文件中,引用controller节点的短名称:
# sed -i '1s/^/ServerName controller01\n&/' /etc/apache2/apache2.conf
重启 Apache web 服务以使更改生效:
# systemctl restart apache2
设置环境变量
为了避免每次运行 OpenStack 命令时都提供凭据,可以创建一个包含环境变量的文件,以便随时加载。以下命令将创建一个名为adminrc的文件,其中包含admin用户的环境变量:
# cat >> ~/adminrc <<EOF export OS_PROJECT_DOMAIN_NAME=default export OS_USER_DOMAIN_NAME=default export OS_PROJECT_NAME=admin export OS_USERNAME=admin export OS_PASSWORD=openstack export OS_AUTH_URL=http://controller01:35357/v3 export OS_IDENTITY_API_VERSION=3 EOF
以下命令将创建一个名为demorc的文件,其中包含demo用户的环境变量:
# cat >> ~/demorc <<EOF export OS_PROJECT_DOMAIN_NAME=default export OS_USER_DOMAIN_NAME=default export OS_PROJECT_NAME=demo export OS_USERNAME=demo export OS_PASSWORD=demo export OS_AUTH_URL=http://controller01:35357/v3 export OS_IDENTITY_API_VERSION=3 EOF
使用source命令从文件加载环境变量:
# source ~/adminrc
demo用户尚不存在,但将在接下来的步骤中创建。
在 Keystone 中定义服务和 API 端点
每个安装的 OpenStack 服务都应该注册到身份验证服务,以便跟踪其在网络上的位置。注册服务时涉及两个命令:
-
openstack service create:描述正在创建的服务 -
openstack endpoint create:将 API 端点与服务关联
在本章之前的引导过程中,已经创建了 OpenStack 身份验证服务和端点。你可以使用openstack endpoint list和openstack service list命令来验证对象是否已创建,如下所示:

OpenStack 云中的资源 ID 是唯一的,并且在不同的环境之间会有所不同,因此如果你的 ID 与这里显示的不一致,请不用担心:

在 Keystone 中定义用户、项目和角色
一旦 Keystone 的安装完成,就需要设置将被各种 OpenStack 服务使用的域、用户、项目、角色和端点。
在此安装过程中,将使用default域。
在 Keystone 中,项目(或租户)代表一组逻辑上的用户,资源分配给这些用户。项目和租户在各种 OpenStack 服务中可互换使用,但项目是优选的术语。资源分配给项目,而不是直接分配给用户。在 Keystone 引导过程中创建了admin项目、用户和角色。为常规用户创建一个demo项目,为其他 OpenStack 服务创建一个service项目:
# openstack project create --description "Service Project" service
# openstack project create --description "Demo Project" demo
接下来,创建一个名为demo的常规用户。为demo用户指定一个安全密码:
# openstack user create demo --password=demo
创建user角色:
# openstack role create user
最后,将user角色添加到demo用户的demo项目中:
# openstack role add --project demo --user demo user
安装和配置镜像服务
Glance 是 OpenStack 的镜像服务,负责存储实例的镜像和快照,并在创建实例时向compute节点提供镜像。
配置数据库
使用mysql客户端创建 Glance 数据库和关联的用户:
# mysql
在MariaDB [(none)] >提示符下输入以下 SQL 语句:
CREATE DATABASE glance;
GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'localhost' IDENTIFIED BY 'glance';
GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'%' IDENTIFIED BY 'glance';
quit;
定义 Glance 用户、服务和端点
使用openstack客户端创建 Glance 用户:
# openstack user create glance --domain default --password=glance
将admin角色添加到service项目中的glance用户:
# openstack role add --project service --user glance admin
接下来,创建glance服务实体:
# openstack service create --name glance \ --description "OpenStack Image" image
最后,创建 Glance 端点:
# openstack endpoint create --region RegionOne \ image public http://controller01:9292 # openstack endpoint create --region RegionOne \ image internal http://controller01:9292 # openstack endpoint create --region RegionOne \ image admin http://controller01:9292
安装和配置 Glance 组件
要安装 Glance,请在controller节点上运行以下命令:
# apt install glance
更新位于/etc/glance/glance-api.conf的glance-api配置文件中的数据库连接字符串,以使用 MySQL Glance 数据库:
[database]
...
connection = mysql+pymysql://glance:glance@controller01/glance
对位于/etc/glance/glance-registry.conf的glance-registry配置文件重复该过程:
[database]
...
connection = mysql+pymysql://glance:glance@controller01/glance
配置身份验证设置
在服务运行之前,必须更新glance-api和glance-registry服务配置文件中的适当身份验证设置。
更新位于/etc/glance/glance-api.conf的glance-api配置文件中的[keystone_authtoken]设置:
[keystone_authtoken]
...
auth_uri = http://controller01:5000
auth_url = http://controller01:35357
memcached_servers = controller01:11211
auth_type = password
user_domain_name = default
project_domain_name = default
project_name = service
username = glance
password = glance
对位于/etc/glance/glance-registry.conf的glance-registry配置文件重复该过程:
[keystone_authtoken]
...
auth_uri = http://controller01:5000
auth_url = http://controller01:35357
memcached_servers = controller01:11211
auth_type = password
user_domain_name = default
project_domain_name = default
project_name = service
username = glance
password = glance
配置附加设置
更新位于/etc/glance/glance-api.conf的glance-api配置文件,添加以下设置:
[paste_deploy]
...
flavor = keystone
[glance_store]
...
stores = file,http
default_store = file
filesystem_store_datadir = /var/lib/glance/images
接下来,更新位于/etc/glance/glance-registry.conf的glance-registry配置文件,添加以下设置:
[paste_deploy]
...
flavor = keystone
当两个文件都更新后,使用glance-manage工具填充 Glance 数据库:
# su -s /bin/sh -c "glance-manage db_sync" glance
最后,使用以下命令重启Glance服务:
# systemctl restart glance-registry glance-api
验证 Glance 镜像服务的安装情况
运行adminrc脚本以设置或更新环境变量:
# source ~/adminrc
为了验证 Glance 是否正确安装和配置,从互联网下载一个测试镜像,并验证其是否可以上传到镜像服务器:
# mkdir /tmp/images # wget -P /tmp/images http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-disk.img
使用以下命令将镜像上传到 Glance:
# openstack image create "cirros-0.4.0" --file /tmp/images/cirros-0.4.0-x86_64-disk.img --disk-format qcow2
--container-format bare --public
使用openstack image list命令验证镜像是否存在于 Glance 中,如下所示:

安装额外的镜像
CirrOS 镜像功能有限,仅推荐用于测试网络连接和基础的计算服务。多个供应商提供适用于 OpenStack 的云镜像,包括以下内容:
| Canonical - Ubuntu | cloud-images.ubuntu.com/ |
|---|---|
| Red Hat - CentOS | cloud.centos.org/centos/ |
要安装 Ubuntu 16.04 LTS 镜像,将文件下载到/tmp/images并上传到 Glance:
# wget -P /tmp/images http://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-disk1.img
使用openstack image create命令上传新镜像:
# openstack image create "ubuntu-xenial-16.04" --file /tmp/images/xenial-server-cloudimg-amd64-disk1.img --disk-format qcow2 --container-format bare --public
再次查看镜像列表,显示新的 Ubuntu 镜像已准备好使用:

安装和配置计算服务
OpenStack 计算是一个服务集合,允许云操作员和用户启动虚拟机实例。大多数服务在controller节点上运行,除nova-compute服务外,后者运行在compute节点上,负责在这些节点上启动虚拟机实例。
配置数据库
在controller节点上使用mysql客户端,创建 Nova 数据库及相关用户:
# mysql
在MariaDB [(none)] >提示符下输入以下 SQL 语句:
CREATE DATABASE nova;
CREATE DATABASE nova_api;
CREATE DATABASE nova_cell0;
GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'localhost' IDENTIFIED BY 'nova';
GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'%' IDENTIFIED BY 'nova';
GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'localhost' IDENTIFIED BY 'nova';
GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'%' IDENTIFIED BY 'nova';
GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'localhost' IDENTIFIED BY 'nova';
GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'%' IDENTIFIED BY 'nova';
quit;
定义 Nova 用户、服务和端点
如下所示,源adminrc凭证:
# source ~/adminrc
使用openstack客户端,创建nova和placement用户:
# openstack user create nova --domain default --password=nova # openstack user create placement
--domain default --password=placement
将admin角色添加到nova和placement用户的service项目中:
# openstack role add --project service --user nova admin # openstack role add --project service --user placement admin
接下来,创建compute和placement服务实体:
# openstack service create --name nova --description "OpenStack Compute" compute
# openstack service create --name placement
--description "Placement API" placement
最后,创建compute和placement端点:
# openstack endpoint create --region RegionOne
compute public http://controller01:8774/v2.1
# openstack endpoint create --region RegionOne compute internal http://controller01:8774/v2.1
# openstack endpoint create --region RegionOne compute admin http://controller01:8774/v2.1
# openstack endpoint create --region RegionOne placement public http://controller01:8778
# openstack endpoint create --region RegionOne placement internal http://controller01:8778
# openstack endpoint create --region RegionOne placement admin http://controller01:8778
安装和配置控制节点组件
在controller节点上执行以下命令,以安装控制节点使用的各种Compute服务:
# apt install nova-api nova-conductor nova-consoleauth nova-novncproxy nova-scheduler nova-placement-api
使用以下数据库连接字符串,更新位于/etc/nova/nova.conf的 Nova 配置文件中的[database]和[api_database]部分:
[database]
...
connection = mysql+pymysql://nova:nova@controller01/nova
[api_database]
...
connection = mysql+pymysql://nova:nova@controller01/nova_api
更新 Nova 配置文件中的[DEFAULT]部分,以配置 Nova 使用 RabbitMQ 消息代理:
[DEFAULT]
...
transport_url = rabbit://openstack:rabbit@controller01
VNC 代理是一个 OpenStack 组件,允许用户通过 VNC 客户端访问他们的实例。VNC 代表虚拟网络计算,是一种图形化桌面共享系统,使用远程帧缓冲协议通过网络控制另一台计算机。控制节点必须能够与compute节点通信,以便通过 Horizon 仪表板或其他 VNC 客户端正常工作 VNC 服务。
更新 Nova 配置文件中的[vnc]部分,以为controller节点配置适当的 VNC 设置:
[vnc]
...
enabled = true
vncserver_listen = 10.10.0.100
vncserver_proxyclient_address = 10.10.0.100
配置认证设置
使用以下与 Keystone 相关的属性,更新位于/etc/nova/nova.conf的 Nova 配置文件:
[api]
...
auth_strategy= keystone
[keystone_authtoken]
...
auth_uri = http://controller01:5000
auth_url = http://controller01:35357
memcached_servers = controller01:11211
auth_type = password
project_domain_name = Default
user_domain_name = Default
project_name = service
username = nova
password = nova
其他控制器任务
更新位于/etc/nova/nova.conf的 Nova 配置文件,指定 Glance API 的位置:
[glance]
...
api_servers = http://controller01:9292
更新 Nova 配置文件,设置 Nova 服务的锁文件路径并指定controller节点的 IP 地址:
[oslo_concurrency]
...
lock_path = /var/lib/nova/tmp
[DEFAULT]
...
my_ip = 10.10.0.100
配置/etc/nova/nova.conf中的[placement]部分。确保注释掉任何现有的os_region_name配置:
[placement]
...
os_region_name = RegionOne
auth_url = http://controller01:35357/v3
auth_type = password
project_domain_name = Default
user_domain_name = Default
project_name = service
username = placement
password = placement
使用nova-manage工具填充nova-api数据库:
# su -s /bin/sh -c "nova-manage api_db sync" nova
使用nova-manage工具注册cell0数据库:
# su -s /bin/sh -c "nova-manage cell_v2 map_cell0" nova
创建cell1单元:
# su -s /bin/sh -c "nova-manage cell_v2 create_cell --name=cell1 --verbose" nova
使用nova-manage工具填充nova数据库:
# su -s /bin/sh -c "nova-manage db sync" nova
最后,重启基于控制器的计算服务,使更改生效:
# systemctl restart nova-api nova-consoleauth nova-scheduler nova-conductor nova-novncproxy
安装并配置计算节点组件
一旦在controller节点上配置了Compute服务,至少还需要配置一个其他主机作为compute节点。compute节点接收来自controller节点的请求,托管虚拟机实例。
在compute节点上,安装nova-compute软件包及相关软件包。这些软件包为compute节点提供虚拟化支持服务:
# apt install nova-compute
在compute节点上,使用以下与 Keystone 相关的设置更新位于/etc/nova/nova.conf的 Nova 配置文件:
[api]
...
auth_strategy= keystone
[keystone_authtoken]
...
auth_uri = http://controller01:5000
auth_url = http://controller01:35357
memcached_servers = controller01:11211
auth_type = password
project_domain_name = Default
user_domain_name = Default
project_name = service
username = nova
password = nova
接下来,更新 Nova 配置文件的[DEFAULT]部分,配置 Nova 使用 RabbitMQ 消息代理:
[DEFAULT]
...
transport_url = rabbit://openstack:rabbit@controller01
然后,更新 Nova 配置文件,以通过controller节点的代理提供远程控制台访问实例。远程控制台可以通过 Horizon 仪表盘访问。配置为my_ip的 IP 应该是每个compute节点的管理 IP。
Compute01:
[DEFAULT]
...
my_ip = 10.10.0.101
[vnc]
...
vncserver_proxyclient_address = 10.10.0.101
enabled = True
vncserver_listen = 0.0.0.0
novncproxy_base_url = http://controller01:6080/vnc_auto.html
Compute02:
[DEFAULT]
...
my_ip = 10.10.0.102
[vnc]
...
vncserver_proxyclient_address = 10.10.0.102
enabled = True
vncserver_listen = 0.0.0.0
novncproxy_base_url = http://controller01:6080/vnc_auto.html
Compute03:
[DEFAULT]
...
my_ip = 10.10.0.103
[vnc]
...
vncserver_proxyclient_address = 10.10.0.103
enabled = True
vncserver_listen = 0.0.0.0
novncproxy_base_url = http://controller01:6080/vnc_auto.html
其他计算任务
更新位于/etc/nova/nova.conf的 Nova 配置文件,指定 Glance API 的位置:
[glance]
...
api_servers = http://controller01:9292
更新 Nova 配置文件,设置Nova服务的锁文件路径:
[oslo_concurrency]
...
lock_path = /var/lib/nova/tmp
配置/etc/nova/nova.conf中的[placement]部分。确保注释掉任何现有的os_region_name配置:
[placement]
...
os_region_name = RegionOne
auth_url = http://controller01:35357/v3
auth_type = password
project_domain_name = Default
user_domain_name = Default
project_name = service
username = placement
password = placement
在所有compute节点上重启nova-compute服务:
# systemctl restart nova-compute
将计算节点添加到单元数据库
当计算服务首次在compute节点上启动时,该节点通过 Nova Placement API 进行注册。要验证compute节点是否已注册,可以使用如下的openstack compute service list命令:

安装 OpenStack 仪表盘
OpenStack 仪表盘,也称为 Horizon,提供了一个基于 Web 的用户界面,用于访问 OpenStack 服务,包括计算、网络、存储和身份等。
为了将 Horizon 添加到环境中,在controller节点上安装以下软件包:
# apt install openstack-dashboard
更新主机和 API 版本配置
编辑/etc/openstack-dashboard/local_settings.py文件,并将OPENSTACK_HOST的值从默认值更改为以下内容:
OPENSTACK_HOST = "controller01"
使用以下字典设置 API 版本:
OPENSTACK_API_VERSIONS = {
"identity": 3,
"image": 2,
"volume": 2,
}
配置 Keystone 设置
编辑/etc/openstack-dashboard/local_settings.py文件,并将以下与 Keystone 相关的配置选项替换为这些值:
OPENSTACK_KEYSTONE_URL = "http://%s:5000/v3" % OPENSTACK_HOST
OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True
OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = "Default"
OPENSTACK_KEYSTONE_DEFAULT_ROLE = "user"
修改网络配置
股票 Horizon 配置启用了某些尚未实现的网络功能。因此,您可能会在仪表板中遇到错误,这些错误可能会影响可用性。现在,请通过设置以下配置禁用仪表板中的所有网络功能:
OPENSTACK_NEUTRON_NETWORK = {
'enable_router': False,
'enable_quotas': False,
'enable_ipv6': False,
'enable_distributed_router': False,
'enable_ha_router': False,
'enable_lb': False,
'enable_firewall': False,
'enable_vpn': False,
'enable_fip_topology_check': False,
}
卸载默认的 Ubuntu 主题(可选)
默认情况下,Ubuntu 上的 OpenStack Dashboard 安装包含由 Canonical 定制的主题。要移除该主题,请更新/etc/openstack-dashboard/local_settings.py文件,并将DEFAULT_THEME值从ubuntu替换为default:
DEFAULT_THEME = 'default'
本书中的示例假设已安装默认主题。
重新加载 Apache
完成上述更改后,使用以下命令重新加载 Apache Web 服务器配置:
# systemctl reload apache2
测试与仪表板的连接
在可以访问controller01节点管理网络的机器上,打开以下 URL:controller01/horizon/.
我的工作站能够访问 API 网络,并且客户端工作站上的/etc/hosts文件已更新,以包含本章前面配置的相同主机名到 IP 的映射。
以下截图演示了成功连接到仪表板。用户名和密码是在本章前面的定义用户、项目和 Keystone 中的角色部分中创建的。在此安装中,域名为Default,用户名为admin,密码为openstack。
熟悉仪表板
成功登录后,仪表板默认显示身份面板。项目相关任务可以在项目面板中完成,而具有admin角色的用户将在管理员面板中找到可以完成管理任务的选项:

通过进入管理员 / 系统面板中的系统信息页面,我们可以看到与本章前面安装的服务相对应的服务列表:

OpenStack Dashboard 允许用户在其拥有权限的任何项目中进行更改。位于 OpenStack 标志右侧的菜单是一个下拉菜单,允许用户选择他们想要操作的项目:

只有用户被分配的项目才会列出。如果用户具有admin角色,可以在管理员面板中进行其他云范围的更改。使用 Horizon 仪表板执行网络功能将在后续章节中介绍。
总结
到目前为止,OpenStack 身份、镜像、仪表盘和计算服务已成功部署到云的各个节点。此时,环境尚未准备好托管实例,因为 OpenStack 网络服务尚未安装或配置。如果在本章描述的服务安装过程中出现问题,请务必查看 /var/log/nova/、/var/log/glance/、/var/log/apache2/ 和 /var/log/keystone/ 中的日志消息,以帮助故障排除。有关安装过程的更多信息,请随时查看 OpenStack 网站上提供的文档,网址为:docs.openstack.org。
在下一章,我们将开始安装 Neutron 网络服务,并探索关于 OpenStack 网络内部架构的更多信息。
第三章:安装 Neutron
OpenStack Networking,也称为 Neutron,为云用户提供网络基础设施即服务平台。在上一章中,我们安装了一些 OpenStack 的基础服务,包括身份验证、镜像和计算服务。在本章中,我将指导你在上一章安装的 OpenStack 环境上安装 Neutron 网络服务。
需要安装的组件包括以下内容:
-
Neutron API 服务器
-
模块化第 2 层(ML2)插件
-
DHCP 代理
-
元数据代理
到本章结束时,你将对各种 Neutron 插件和代理的功能及操作有基本的了解,并且能够在此基础上构建虚拟交换基础设施。
Neutron 中的基本网络元素
Neutron 使用对大多数系统和网络管理员来说都很熟悉的元素来构建虚拟网络,包括网络、子网、端口、路由器、负载均衡器等。
使用 Neutron 核心 API 的 2.0 版本,用户可以构建一个由以下实体组成的网络基础:
-
网络:网络是一个隔离的第 2 层广播域。通常,网络保留给创建它们的项目,但如果进行相应配置,也可以在项目之间共享。网络是 Neutron API 的核心实体。子网和端口必须始终与网络关联。
-
子网:子网是一个 IPv4 或 IPv6 地址块,可以为虚拟机实例分配 IP 地址。每个子网必须有一个 CIDR,并且必须与一个网络相关联。多个子网可以与一个网络关联,并且可以是非连续的。可以为子网设置 DHCP 分配范围,以限制提供给实例的地址。
-
端口:Neutron 中的端口是虚拟交换机端口的逻辑表示。虚拟机接口与 Neutron 端口相映射,这些端口定义了分配给接口的 MAC 地址和 IP 地址。Neutron 端口定义存储在 Neutron 数据库中,然后由相应的插件代理使用,以构建和连接虚拟交换基础设施。
云运营商和用户都可以通过创建和配置网络和子网来配置网络拓扑,然后指示 Nova 等服务将虚拟设备连接到这些网络上的端口。用户可以创建多个网络、子网和端口,但受到云管理员设置的每个项目配额定义的限制。
通过插件扩展功能
OpenStack Networking 项目提供了由 OpenStack 社区开发和支持的参考插件和驱动程序,同时也支持第三方插件和驱动程序,这些插件和驱动程序扩展了网络功能,并实现了 Neutron API。可以创建使用各种软件和硬件技术的插件和驱动程序,以实现由操作员和用户构建的网络。
Neutron 架构中有两种主要的插件类型:
-
核心插件
-
服务插件
核心插件实现了核心的 Neutron API,负责将由网络、端口和子网描述的逻辑网络转换为可以由主机上运行的 L2 代理和 IP 地址管理系统实施的内容。
服务插件提供额外的网络服务,如路由、负载均衡、防火墙等。
本书将讨论以下核心插件:
- 模块化第 2 层插件
以下服务插件将在后续章节中介绍:
-
路由器
-
负载均衡器
-
主干
Neutron API 为用户提供一致的体验,尽管选择了不同的网络插件。有关与 Neutron API 交互的更多信息,请访问以下网址:developer.openstack.org/api-ref/network/v2/index.html。
模块化第 2 层插件
在 OpenStack 的 Havana 版本中引入 模块化第 2 层(ML2) 插件之前,Neutron 仅能使用单一的核心插件。这种设计导致了同质化的网络架构,无法扩展。操作员被迫对网络堆栈做出长期决策,这些决策在未来很难改变。另一方面,ML2 插件在设计上是可扩展的,支持异构的网络架构,可以同时利用多种技术。ML2 插件替换了其参考实现中的两个单体插件:Linux 桥接核心插件和 Open vSwitch 核心插件。
驱动程序
ML2 插件引入了 TypeDrivers 和 Mechanism 驱动程序的概念,以将网络类型的实现与这些类型的网络的实现机制分离。
TypeDrivers
一个 ML2 TypeDriver 维护特定类型的网络状态,验证提供者网络属性,并使用提供者属性描述网络段。提供者属性包括网络接口标签、分段 ID 和网络类型。支持的网络类型包括local、flat、vlan、gre、vxlan 和 geneve。下表描述了这些网络类型之间的差异:
| 类型 | 描述 |
|---|---|
| 本地 | 本地网络是指与其他网络和节点隔离的网络。连接到本地网络的实例可以与同一compute节点上的其他实例通信,但无法与其他主机上的实例通信。由于这种设计限制,本地网络仅推荐用于测试目的。 |
| 平面 | 在平面网络中,不进行 802.1q VLAN 标记或其他网络隔离。在许多环境中,平面网络对应于接入VLAN 或本地VLAN 上的干道。 |
| VLAN | VLAN 网络是利用 802.1q 标记来隔离网络流量的网络。处于同一 VLAN 中的实例被认为是同一网络的一部分,并且处于相同的第二层广播域内。VLAN 间路由或 VLAN 之间的路由只能通过物理或虚拟路由器来实现。 |
| GRE | GRE 网络使用通用路由封装隧道协议(IP 协议 47)来封装数据包并通过点对点网络在节点之间传输。在 GRE 头部的KEY字段用于隔离网络。 |
| VXLAN | VXLAN 网络使用一个独特的分段 ID,称为 VXLAN 网络标识符(VNI),来区分来自其他 VXLAN 网络的流量。来自一个实例到另一个实例的流量通过主机使用 VNI 进行封装,并通过现有的第三层网络使用 UDP 传输,在该网络中解封装并转发到目标实例。使用 VXLAN 封装数据包并通过现有网络传输,旨在解决 VLAN 和物理交换基础设施的局限性。 |
| GENEVE | GENEVE 网络类似于 VXLAN 网络,它使用一个独特的分段 ID,称为虚拟网络接口(VNI),来区分来自其他 GENEVE 网络的流量。数据包被封装在一个独特的头部中,并使用 UDP 作为传输机制。GENEVE 利用了多个覆盖技术的优势,如 VXLAN、NVGRE 和 STT,当前主要由 OVN 使用。 |
机制驱动程序
ML2 机制驱动程序负责获取由类型驱动程序建立的信息,并确保其正确实现。可以配置多个机制驱动程序同时运行,并可以通过三种类型的模型进行描述:
-
基于代理的: 包括 Linux bridge、Open vSwitch、SR-IOV 等
-
基于控制器的: 包括 Juniper Contrail、Tungsten Fabric、OVN、Cisco ACI、VMWare NSX 等
-
机架顶端:包括 Cisco Nexus、Arista、Mellanox 等
本书中将讨论的机制驱动程序包括以下内容:
-
Linux 桥接
-
Open vSwitch
-
L2 人口
Linux 桥接和 Open vSwitch ML2 Mechanism 驱动程序用于配置在承载实例和网络服务的节点内的虚拟交换技术。Linux 桥接驱动程序支持 local、flat、vlan 和 vxlan 网络类型,而 Open vSwitch 驱动程序支持这些网络类型以及 gre 网络类型。对于其他类型的驱动程序(如 geneve)的支持将根据实现的 Mechanism 驱动程序而有所不同。
L2 population 驱动程序用于限制在使用 VXLAN 网络时转发到覆盖网络中的广播流量数量。在正常情况下,未知的单播、多播和广播流量可能会从所有隧道泛洪到其他 compute 节点。这种行为可能对覆盖网络结构产生负面影响,特别是当云中主机数量增加时。
作为云中实例和其他网络资源的权威,Neutron 可以在所有主机上预填充转发数据库,以避免代价高昂的学习操作。ARP 代理是 L2 population 驱动程序的一个特性,允许 Neutron 以类似的方式在所有主机上预填充 ARP 表,以避免 ARP 流量在覆盖网络中广播。
ML2 架构
下图展示了 Neutron API 服务如何与负责构建虚拟和物理网络的各种插件和代理进行交互:

图 3.1
上图展示了 Neutron API、Neutron 插件和驱动程序与 L2 和 L3 代理等服务之间的交互。有关 Neutron ML2 插件架构的更多信息,请参考以下网址:docs.openstack.org/neutron/pike/admin/config-ml2.html
网络命名空间
OpenStack 设计时考虑到了多租户的需求,并为用户提供了创建和管理自己的计算和网络资源的能力。Neutron 支持每个租户拥有多个私有网络、路由器、防火墙、负载均衡器和其他网络资源,并能够通过使用网络命名空间将这些对象隔离开来。
网络命名空间 被定义为网络堆栈的逻辑副本,具有自己的路由、Firewall 规则和网络接口。在使用开源参考插件和驱动程序时,由用户创建的每个 DHCP 服务器、路由器和负载均衡器都会在网络命名空间中实现。通过使用网络命名空间,Neutron 能够为每个网络提供隔离的 DHCP 和路由服务,使用户能够在其他项目的用户甚至同一项目的其他网络中创建重叠的网络。
以下命名规则应适用于网络命名空间:
-
DHCP 命名空间:
qdhcp-<网络 UUID> -
路由器命名空间:
qrouter-<路由器 UUID> -
负载均衡器命名空间:
qlbaas-<负载均衡器 UUID>
一个qdhcp命名空间包含一个 DHCP 服务,用于通过 DHCP 协议为实例提供 IP 地址。在参考实现中,dnsmasq是处理 DHCP 请求的进程。qdhcp命名空间有一个接口连接到虚拟交换机,并能够与相同网络中的实例和其他设备进行通信。对于启用了 DHCP 的相关子网,每个网络都会创建一个qdhcp命名空间。
一个qrouter命名空间代表一个虚拟路由器,负责将流量路由到连接的子网中的实例,或从实例路由出去。像qdhcp命名空间一样,qrouter命名空间根据配置连接到一个或多个虚拟交换机。在某些情况下,可能会使用多个命名空间来建立虚拟路由器基础设施。这些额外的命名空间,称为fip和snat,用于分布式虚拟路由器(DVR),将在本书后面讨论。
一个qlbaas命名空间代表一个虚拟负载均衡器,并包含一个服务,如 HAProxy,用于将流量负载均衡到实例。qlbaas命名空间连接到虚拟交换机,并可以与相同网络中的实例和其他设备进行通信。
有趣的事实:网络命名空间名称中的前导q代表 Quantum,这是 OpenStack Networking 服务的原始名称。
仅在运行 Neutron DHCP、L3 或 LBaaS 代理的节点上,才能看到上述类型的网络命名空间。这些服务通常仅在控制器或专用网络节点上配置。当配置分布式虚拟路由器时,您可能还会在compute节点上找到与路由器相关的命名空间。可以使用ip netns list命令列出可用的命名空间,并使用以下语法在命名空间内执行命令:
ip netns exec NAMESPACE_NAME <command>
可以在命名空间中执行的命令包括ip、route、iptables等。这些命令的输出对应于在它们执行的命名空间中专用的数据。像tcpdump这样的工具也可以在网络命名空间中执行,以帮助排查虚拟网络基础设施的问题。
有关网络命名空间的更多信息,请参阅ip netns的手册页,网址为:man7.org/linux/man-pages/man8/ip-netns.8.html。
安装和配置 Neutron 服务
在此安装过程中,构成 OpenStack Networking 的各种服务将安装在controller节点上,而不是专用的网络节点。compute节点将运行 L2 代理,与controller节点进行接口,并为实例提供虚拟交换机连接。
请记住,这里推荐的配置设置以及在docs.openstack.org上的在线设置,可能不适合生产环境。
创建 Neutron 数据库
在 controller 节点上使用 mysql 客户端创建 Neutron 数据库和相关用户:
# mysql
在 MariaDB [(none)] > 提示符下输入以下 SQL 语句:
CREATE DATABASE neutron;
GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'localhost' IDENTIFIED BY 'neutron';
GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'%' IDENTIFIED BY 'neutron';
quit;
在 Keystone 中配置 Neutron 用户、角色和端点
为了正常运行,Neutron 需要在 Keystone 中创建一个用户、角色和端点。当从 controller 节点执行时,以下命令将在 Keystone 中创建一个名为 neutron 的用户,将 admin 角色与 neutron 用户关联,并将 neutron 用户添加到 service 项目中:
# source ~/adminrc # openstack user create --domain Default --password=neutron neutron # openstack role add --project service --user neutron admin
在 controller 节点上执行以下命令,在 Keystone 中创建一个描述 OpenStack 网络服务的服务:
# openstack service create --name neutron --description "OpenStack Networking" network
要创建端点,请使用以下 openstack endpoint create 命令:
# openstack endpoint create --region RegionOne network public http://controller01:9696 # openstack endpoint create --region RegionOne network internal http://controller01:9696 # openstack endpoint create --region RegionOne network admin http://controller01:9696
安装 Neutron 包
要在控制节点上安装 Neutron API 服务器、DHCP 和元数据代理以及 ML2 插件,请执行以下命令:
# apt install neutron-server neutron-dhcp-agent
neutron-metadata-agent neutron-plugin-ml2 python-neutronclient
Neutron 的 DHCP 和元数据代理可能并非所有机制驱动程序都需要,但在实现 openvswitch 和 linuxbridge 驱动程序时会使用它们。
在所有其他主机上,此时仅需要 ML2 插件:
# apt install neutron-plugin-ml2
在所有节点上,更新 /etc/neutron/neutron.conf 中 Neutron 配置文件的 [database] 部分,使用基于前面值的正确 MySQL 数据库连接字符串,而不是默认值:
[database]
...
connection = mysql+pymysql://neutron:neutron@controller01/neutron
配置 Neutron 使用 Keystone
Neutron 配置文件位于 /etc/neutron/neutron.conf,其中有数十个可以修改的设置,以满足 OpenStack 云管理员的需求。部分设置必须在此安装过程中从默认值更改。
要指定 Keystone 作为 Neutron 的身份验证方法,请在所有主机上更新 Neutron 配置文件的 [DEFAULT] 部分,使用以下设置:
[DEFAULT]
...
auth_strategy = keystone
Neutron 还必须配置适当的 Keystone 身份验证设置。neutron 用户在 Keystone 中的用户名和密码在本章前面已经设置。在所有主机上更新 Neutron 配置文件的 [keystone_authtoken] 部分,使用以下设置:
[keystone_authtoken]
...
auth_uri = http://controller01:5000
auth_url = http://controller01:35357
memcached_servers = controller01:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = neutron
password = neutron
配置 Neutron 使用消息服务
Neutron 与各种 OpenStack 服务通过 AMQP 消息总线进行通信。更新所有主机上 Neutron 配置文件的 [DEFAULT] 部分,以指定 RabbitMQ 作为消息代理:
[DEFAULT]
...
transport_url = rabbit://openstack:rabbit@controller01
配置 Nova 使用 Neutron 网络
在 Neutron 作为 OpenStack 计算服务的网络管理器之前,必须在某些主机上设置 Nova 配置文件 /etc/nova/nova.conf 中的适当配置选项。
在控制节点和 compute 节点上,使用以下内容更新 [neutron] 部分:
[neutron]
...
url= http://controller01:9696
auth_url = http://controller01:35357
auth_type = password
project_domain_name = default
user_domain_name = default
region_name = RegionOne
project_name = service
username = neutron
password = neutron
一旦确定了机制驱动程序,Nova 可能需要额外的配置。Linux bridge 和 Open vSwitch 机制驱动程序及其各自的代理和 Nova 配置更改将在后续章节中详细讨论。
配置 Neutron 以通知 Nova
Neutron 必须配置为通知 Nova 网络拓扑的变化。在controller节点上,更新位于/etc/neutron/neutron.conf的 Neutron 配置文件中的[nova]部分,设置如下:
[nova]
...
auth_url = http://controller01:35357
auth_type = password
project_domain_name = default
user_domain_name = default
region_name = RegionOne
project_name = service
username = nova
password = nova
配置 Neutron 服务
neutron-server服务将 Neutron API 暴露给用户,并将所有调用传递给配置的 Neutron 插件进行处理。默认情况下,Neutron 配置为监听所有配置的地址上的 API 调用,如 Neutron 配置文件中的默认bind_hosts选项所示:
bind_host = 0.0.0.0
作为额外的安全措施,可以将 API 暴露在管理或 API 网络上。要更改默认值,请更新位于/etc/neutron/neutron.conf的 Neutron 配置文件中[DEFAULT]部分的bind_host值,并指定controller节点的管理地址。本书中解释的部署将保持默认值。
可能需要调整的其他配置选项包括:
-
core_plugin -
service_plugins -
dhcp_lease_duration -
dns_domain
其中一些设置适用于所有节点,而另一些仅适用于network或controller节点。core_plugin配置选项指示 Neutron 使用指定的网络插件。从 Icehouse 版本开始,ML2 插件取代了 Linux bridge 和 Open vSwitch 单体插件。
在所有节点上,更新位于/etc/neutron/neutron.conf的 Neutron 配置文件中[DEFAULT]部分的core_plugin值,并指定 ML2 插件:
[DEFAULT]
...
core_plugin = ml2
service_plugins配置选项用于定义 Neutron 加载的插件以实现额外功能。插件的示例包括router、firewall、lbaas、vpnaas和metering。此选项应仅在controller节点或运行neutron-server服务的其他节点上配置。服务插件将在后续章节中定义。
dhcp_lease_duration配置选项指定实例的 IP 地址租期持续时间。默认值为 86,400 秒,即 24 小时。如果设置的值过低,网络可能会因为短期租期和频繁的续租尝试而遭到流量淹没。实例本身的 DHCP 客户端负责续租,且这一操作的频率因操作系统而异。实例尝试在租期到期前很久就进行续租并不少见。然而,dhcp_lease_duration的设置并不会决定 IP 地址与实例关联的时间长度。一旦 Neutron 为端口分配了 IP 地址,直到端口或相关实例被删除,该 IP 地址将保持与端口关联。
dns_domain配置选项指定通过 DHCP 向实例提供的 DNS 搜索域,当它们获取租约时。默认值为openstacklocal。可以更改为适合您组织的任何值。对于本次安装,将值从openstacklocal更改为learningneutron.com. 在controller节点上,更新位于/etc/neutron/neutron.conf的 Neutron 配置文件中的dns_domain选项为learningneutron.com:
[DEFAULT]
...
dns_domain = learningneutron.com
当实例从 DHCP 服务器获取地址时,域名会附加到主机名,形成完全合格的域名。Neutron 默认不支持多个域名,而是依赖于名为 Designate 的项目来扩展对该功能的支持。有关 Designate 的更多信息,请访问以下 URL:docs.openstack.org/designate/latest/。
启动 neutron-server
在启动neutron-server服务之前,必须根据本章之前配置的选项更新 Neutron 数据库。在controller节点上使用neutron-db-manage命令相应地更新数据库:
# su -s /bin/sh -c "neutron-db-manage --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head" neutron
重启controller节点上的 Nova 计算服务:
# systemctl restart nova-api nova-scheduler nova-conductor
重启compute节点上的 Nova 计算服务:
# systemctl restart nova-compute
最后,重启controller节点上的neutron-server服务:
# systemctl restart neutron-server
配置 Neutron DHCP 代理
Neutron 利用dnsmasq,一个免费的轻量级 DNS 转发器和 DHCP 服务器,为网络提供 DHCP 服务。neutron-dhcp-agent服务负责为每个使用 DHCP 的网络启动和配置dnsmasq以及元数据进程。
DHCP 驱动程序在/etc/neutron/dhcp_agent.ini配置文件中指定。可以配置 DHCP 代理使用其他驱动程序,但内置了对dnsmasq的支持,并且无需额外设置。默认的dhcp_driver值为neutron.agent.linux.dhcp.Dnsmasq,可以保持不变。
在dhcp_agent.ini配置文件中,还可以找到其他一些显著的配置选项:
-
interface_driver -
enable_isolated_metadata
interface_driver配置选项应根据您环境中选择的二层代理进行适当配置:
-
Linux 桥接:
neutron.agent.linux.interface.BridgeInterfaceDriver -
Open vSwitch:
neutron.agent.linux.interface.OVSInterfaceDriver
Linux 桥接和 Open vSwitch 驱动程序将在接下来的章节中进一步讨论。目前,默认值<none>已足够。
每个代理每次只能配置一个接口驱动程序。
enable_isolated_metadata配置选项在物理网络设备(如防火墙或路由器)作为实例的默认网关,但仍需要 Neutron 为这些实例提供元数据服务的情况下非常有用。当使用 L3 代理时,实例通过作为其默认网关的 Neutron 路由器访问元数据服务。孤立网络假定为 Neutron 路由器不作为网关的网络,但 Neutron 仍处理实例的 DHCP 请求的情况。当实例利用带有物理网关设备的扁平或 VLAN 网络时,通常出现这种情况。enable_isolated_metadata的默认值为False。当设置为True时,Neutron 可以通过 DHCP 在某些情况下为实例提供到元数据服务的静态路由。有关元数据的使用和此配置的更多信息,请参阅第七章,将实例附加到网络。在controller节点上,更新位于/etc/neutron/dhcp_agent.ini的 DHCP 代理配置文件中的enable_isolated_metadata选项为True:
[DEFAULT]
...
enable_isolated_metadata = True
此处未提及的配置选项具有充分的默认值,除非您的环境需要,否则不应更改。
重新启动 Neutron DHCP 代理
使用以下命令在controller节点上重新启动neutron-dhcp-agent服务并检查其状态:
# systemctl restart neutron-dhcp-agent # systemctl status neutron-dhcp-agent
输出应如下所示:

代理应处于active (running)状态。使用openstack network agent list命令验证服务是否已注册:

在Alive列下的笑脸表示代理与neutron-server服务正常通信。
配置 Neutron 元数据代理
OpenStack Compute 提供了一个元数据服务,允许用户检索有关其实例的信息,这些信息可用于配置或管理运行中的实例。元数据包括主机名、固定和浮动 IP、公钥等信息。除元数据外,用户还可以访问用户数据,如脚本和其他引导配置,这些配置可以在引导过程中或实例激活后执行。OpenStack Networking 实现了一个代理,将实例的元数据请求转发到由 OpenStack Compute 提供的元数据服务。
实例通常在引导过程中通过 HTTP 访问元数据服务,地址为http://169.254.169.254。此机制由cloud-init提供,在大多数云准备的映像中可用,网址为:launchpad.net/cloud-init。
下图概述了当controller节点托管网络服务时,从实例检索元数据的高级概述:

在上面的示意图中,当实例向元数据服务发出请求时,会发生以下操作:
-
实例通过 HTTP 向
169.254.269.254发送元数据请求 -
元数据请求根据实例中的路由,访问路由器或 DHCP 命名空间
-
命名空间中的元数据代理服务通过 Unix 套接字将请求发送给 Neutron 元数据代理服务
-
Neutron 元数据代理服务将请求转发给 Nova 元数据 API 服务
-
Nova 元数据 API 服务响应请求并将响应转发给 Neutron 元数据代理服务
-
Neutron 元数据代理服务将响应发送回命名空间中的元数据代理服务
-
元数据代理服务将 HTTP 响应转发给实例
-
实例接收元数据和/或用户数据,并继续启动过程
为确保元数据服务的正常运行,Neutron 和 Nova 必须配置为使用共享密钥进行通信。Neutron 使用此密钥对元数据请求的 Instance-ID 标头进行签名,以防止欺骗。在 controller 节点上,更新位于 /etc/nova/nova.conf 的 Nova 配置文件中的 [neutron] 部分,以添加以下元数据选项:
[neutron]
...
service_metadata_proxy = true
metadata_proxy_shared_secret = MetadataSecret123
接下来,更新位于 /etc/neutron/metadata_agent.ini 的元数据代理配置文件中的 [DEFAULT] 部分,添加 Neutron 身份验证详细信息和元数据代理共享密钥:
[DEFAULT]
...
nova_metadata_host = controller01
metadata_proxy_shared_secret = MetadataSecret123
此处未提及的配置选项具有足够的默认值,除非您的环境需要,否则不应更改。
重启 Neutron 元数据代理
使用以下命令重新启动 controller 节点上的 neutron-metadata-agent 和 nova-api 服务,并检查服务的状态:
# systemctl restart nova-api neutron-metadata-agent # systemctl status neutron-metadata-agent
输出应类似于以下内容:

代理应处于 active (running) 状态。使用 openstack network agent list 命令验证服务是否已检查:

在 Alive 列下的笑脸符号表示代理正在与 neutron-server 服务正常通信。
如果服务未显示或在 Alive 列下显示 XXX,请检查位于 /var/log/neutron 的相关日志文件,以帮助故障排除。有关元数据使用的更多信息,请参阅 第七章、将实例连接到网络 以及后续章节。
与 OpenStack 网络接口
可以通过多种方式访问 OpenStack 网络 API,包括通过 Horizon 控制面板、openstack 和 neutron 客户端、Python SDK、HTTP 以及其他方法。接下来的几个部分将重点介绍与 OpenStack 网络接口的最常见方式。
使用 OpenStack 命令行接口
在 openstack 命令行客户端问世之前,每个项目负责维护自己的客户端。每个客户端通常使用自己独特的语法来管理对象,并且不同客户端之间缺乏一致性,给用户和运维人员带来了很多困难。openstack 客户端为命令和参数提供了一致的命名结构,以及一个一致的输出格式,支持如 csv、json 等可选的可解析格式。然而,并非所有 API 和服务都由 openstack 客户端支持,这可能意味着某些操作需要项目特定的客户端。
要调用 openstack 客户端,请在 Linux 命令行中输入 openstack 命令:

openstack shell 提供了可以用来创建、读取、更新和删除 OpenStack 云中网络配置的命令。通过在 openstack shell 中输入问号或 help,可以找到命令列表。此外,从 Linux 命令行运行 openstack help 也会提供每个命令功能的简要描述。
使用 Neutron 命令行界面
Neutron 提供了一个命令行客户端,用于与其 API 进行交互。Neutron 命令可以直接在 Linux 命令行中运行,或者可以通过输入 neutron 命令来启动 Neutron shell:

在调用 openstack 和 neutron 客户端之前,必须先加载凭证文件,否则会发生错误。
neutron shell 提供了可以用来创建、读取、更新和删除 OpenStack 云中网络配置的命令。通过在 Neutron shell 中输入问号或 help,可以找到命令列表。此外,从 Linux 命令行运行 neutron help 也会提供每个命令功能的简要描述。
neutron 客户端已被弃用,推荐使用 openstack 命令行客户端。然而,某些功能,包括与 LBaaS 相关的命令,在 openstack 客户端中尚不可用,必须使用 neutron 客户端进行管理。在未来版本的 OpenStack 中,neutron 客户端将不再可用。
客户端 help 列表中列出的许多命令将在本书的后续章节中介绍。
使用 OpenStack Python SDK
OpenStack Python SDK 可以在 PyPI 上找到,并可以通过以下命令进行安装:
$ pip install openstacksdk
SDK 的文档可以通过以下网址访问:developer.openstack.org/sdks/python/openstacksdk/users/index.html。
使用 cURL 工具
OpenStack 网络 API 是基于 REST 的,可以通过 HTTP 直接进行操作。要使用 HTTP 调用 API,你需要一个令牌。加载 OpenStack 凭证文件,并使用下面显示的 openstack token issue 命令来获取令牌:

--fit-width 参数在正常操作中不是必需的,但为了演示的方便,它有助于使令牌 ID 更易于管理。
要获取网络列表,命令应类似于以下内容:
$ curl -v -X GET -H 'X-Auth-Token: <token id>' http://controller01:9696/v2.0/networks
输出将类似于以下内容:

在这个例子中,Neutron API 返回了一个 200 OK 的响应,格式为 json。目前没有网络,因此返回了一个空列表。Neutron 返回的 HTTP 状态码可以用来判断命令是否成功。
OpenStack 网络 API 文档可以通过以下网址查看:developer.openstack.org/api-ref/network/v2/。
摘要
OpenStack 网络提供了一个可扩展的插件架构,使得实现新的网络功能成为可能。Neutron 在其数据库中维护逻辑网络架构,而每个节点上的网络插件和代理负责相应地配置虚拟和物理网络设备。通过使用模块化第二层(ML2)插件,开发人员可以减少实现核心 Neutron API 功能的时间,更多地专注于开发增值功能。
现在,OpenStack 网络服务已在环境中的所有节点上安装完毕,配置机制驱动程序是创建实例之前唯一需要完成的工作。在接下来的两章中,您将学习如何配置 ML2 插件以及 Linux bridge 和 Open vSwitch 驱动程序及代理。我们还将探讨 Linux bridge 和 Open vSwitch 代理在功能和为实例提供连接方面的差异。
第四章:使用 Linux 桥接的虚拟网络基础设施
OpenStack 网络的核心功能之一是为运行在云中的实例提供端到端的网络连接。在 第三章 安装 Neutron 中,我们在云中的所有节点上安装了 Neutron API 服务和 ML2 插件。从本章开始,我们将介绍 Neutron 依赖的网络概念和架构,用于为实例和其他虚拟设备提供连接。
Neutron 的 ML2 插件允许 OpenStack 云通过使用机制驱动同时利用多种二层技术。在接下来的章节中,我们将介绍多种机制驱动,这些驱动扩展了 ML2 网络插件的功能,包括 Linux 桥接和 Open vSwitch 驱动。
在本章中,你将执行以下操作:
-
了解如何使用 Linux 桥接构建虚拟网络基础设施
-
通过虚拟桥接可视化流量流动
-
在主机上部署 Linux 桥接机制驱动和代理
使用 Linux 桥接驱动
Linux 桥接机制驱动支持一系列传统和覆盖网络技术,并支持以下类型的驱动:
-
Local
-
Flat
-
VLAN
-
VXLAN
当主机配置为使用 ML2 插件和 Linux 桥接机制驱动时,主机上的 Neutron 代理依赖于 bridge、8021q 和 vxlan 内核模块,以正确地将实例和其他网络资源连接到虚拟交换机。这些连接允许实例与云中其他网络资源进行通信。Linux 桥接机制驱动因其可靠性和易于故障排除而广受欢迎,但不支持一些高级 Neutron 功能,如分布式虚拟路由器。
在基于 Linux 桥接的网络实现中,有五种接口由 OpenStack 网络管理:
-
Tap 接口
-
物理接口
-
VLAN 接口
-
VXLAN 接口
-
Linux 桥接
tap 接口是由超管程序(如 QEMU/KVM)创建并使用,用于将虚拟机实例中的客操作系统与底层主机连接。这些虚拟接口对应主机内的网络接口。发送到主机上 tap 设备的以太网帧会被客操作系统接收,而从客操作系统接收到的帧则会注入到主机的网络栈中。
物理接口代表主机上与物理网络硬件相连的接口。物理接口通常标记为 eth0、eth1、em0、em1 等,具体取决于主机操作系统。
Linux 支持通过使用虚拟 VLAN 接口进行 802.1q VLAN 标记。可以使用 iproute2 命令或传统的 vlan 工具及 8021q 内核模块来创建 VLAN 接口。VLAN 接口通常标记为 ethX.<vlan>,并与其对应的物理接口 ethX 关联。
VXLAN 接口是一个虚拟接口,用于根据接口创建时配置的参数封装和转发流量,包括 VXLAN 网络标识符(VNI)和 VXLAN 隧道端点(VTEP)。VTEP 的功能是在 IP 网络中通过 IP 标头封装虚拟机实例流量。相同 VTEP 上的流量通过 VNI 提供的 ID 与其他 VXLAN 流量隔离。实例本身并不关心提供连接性的外部网络拓扑。
Linux 桥接是一个虚拟接口,用于连接多个网络接口。在 Neutron 中,一个桥接通常包括一个物理接口和一个或多个虚拟接口或 tap 接口。Linux 桥接是一种虚拟交换机形式。
可视化 Linux 桥接中的流量流动
要使以太网帧从虚拟机实例传输到物理网络上的设备,它将经过主机内部的三到四个设备:
| 网络类型 | 接口类型 | 接口名称 |
|---|---|---|
| all | tap | tapN |
| all | bridge | brqXXXX |
| vxlan | vxlan | vxlan-z(其中 Z 是 VNI) |
| vlan | vlan | ethX.Y(其中 X 是物理接口,Y 是 VLAN ID) |
| flat, vlan | physical | ethX(其中 X 是接口) |
为了帮助理解 Neutron 如何使用 Linux 桥接,以下几个 Linux 桥接架构示例将在接下来的章节中提供。
VLAN
假设一个 OpenStack 云由一个 vlan 提供者网络组成,分段 ID 为 100。三个实例已经连接到该网络。因此,compute 节点中的网络架构类似于以下内容:

图 4.1
在图 4.1 中,三个虚拟机实例通过各自的 tap 接口连接到名为 brqXXXX 的 Linux 桥接。当第一个实例启动并连接到网络时,Neutron 创建了桥接并创建了一个名为 eth1.100 的虚拟接口,并自动将该接口连接到桥接。eth1.100 接口绑定到物理接口 eth1。当实例的流量通过 Linux 桥接并向物理接口传输时,接口 eth1.100 会为该流量打上 VLAN 100 标签,并将其发送到 eth1。同样,进入实例的流量通过 eth1 进入时,eth1.100 会反向去除标签,并将流量发送到连接到桥接的相应实例。
使用brctl show命令,前述图示可以在 Linux CLI 中实现如下:

输出中的bridge id是基于虚拟 VLAN 接口的父 NIC 动态生成的。在此桥接中,父接口是eth1。
以brq前缀开头的bridge name是根据它所关联的 Neutron 网络的 ID 生成的。在 Linux 桥接架构中,每个网络使用其自己的桥接器。桥接器名称应在同一网络的节点之间保持一致。
在物理交换机上,执行此处所述网络配置所需的配置如下所示:
vlan 100
name VLAN_100
interface Ethernet1/3
description Provider_Interface_eth1
switchport
switchport mode trunk
switchport trunk allowed vlan add 100
no shutdown
当配置为中继端口时,提供者接口可以支持多个 VLAN 网络。如果需要多个 VLAN 网络,则会自动创建另一个 Linux 桥接器,其中包含一个独立的 VLAN 接口。新的虚拟接口eth1.101连接到新桥接器brqYYYY,如图 4.2 所示:

图 4.2
在compute节点上,前面的图示可以通过以下brctl show输出实现:

在物理交换机上,执行此处所述网络配置所需的配置如下所示:
vlan 100
name VLAN_100
vlan 101
name VLAN_101
interface Ethernet1/3
description Provider_Interface_eth1
switchport
switchport mode trunk
switchport trunk allowed vlan add 100-101
no shutdown
扁平网络
Neutron 中的扁平网络描述的是一个没有VLAN 标记的网络。与 VLAN 网络不同,扁平网络要求与该网络关联的主机的物理接口直接连接到桥接器。这意味着每个物理接口只能存在一个单一的扁平网络。
图 4.3 演示了物理接口直接连接到 Neutron 管理的桥接器中的扁平网络场景:

图 4.3
在图 4.3 中,eth1 连接到名为brqZZZZ的桥接器,并且与三条对应于来宾实例的 tap 接口相连接。在这种情况下,实例流量不会进行 VLAN 标记。
在compute节点上,前面的图示可以通过以下brctl show输出实现:

在物理交换机上,执行此处所述网络配置所需的配置如下所示:
vlan 200
name VLAN_200
interface Ethernet1/3
description Provider_Interface_eth1
switchport
switchport mode trunk
switchport trunk native vlan 200
switchport trunk allowed vlan add 200
no shutdown
或者,接口也可以配置为接入端口:
interface Ethernet1/3
description Provider_Interface_eth1
switchport
switchport mode access
switchport access vlan 200
no shutdown
每个提供者接口仅支持一个扁平网络。当配置为带有本地 VLAN 的中继端口时,提供者接口可以支持一个扁平网络和多个 VLAN 网络。当配置为接入端口时,该接口只能支持一个扁平网络,任何试图为流量打标签的操作都将失败。
当创建多个扁平网络时,必须为每个扁平网络关联一个独立的物理接口。图 4.4 演示了为第二个扁平网络所需的第二个物理接口:

图 4.4
在 compute 节点上,使用两个物理接口来实现独立的平面网络,其 brctl show 输出如下所示:

在物理交换机上,支持此处所描述的网络配置的设置将类似于以下内容:
vlan 200
name VLAN_200
vlan 201
name VLAN_201
interface Ethernet1/3
description Flat_Provider_Interface_eth1
switchport
switchport mode trunk
switchport trunk native vlan 200
switchport trunk allowed vlan add 200
no shutdown
interface Ethernet1/4
description Flat_Provider_Interface_eth2
switchport
switchport mode trunk
switchport trunk native vlan 201
switchport trunk allowed vlan add 201
no shutdown
在这两个平面网络上,主机不会对穿越这些桥接的流量执行任何 VLAN 标记。连接到这两个桥接的实例需要路由器才能相互通信。由于每个平面网络需要唯一的接口,因此平面网络的可扩展性较差,在生产环境中并不常见。
VXLAN
当创建 VXLAN 网络时,Neutron Linux 桥接代理使用 iproute2 用户空间工具创建相应的 VXLAN 接口,并将其连接到 Linux 桥接。VXLAN 接口会被编程,包含如 VNI 和本地 VTEP 地址等信息。
当配置了 L2 人口驱动程序时,Neutron 会用由实例的 MAC 地址及其相应的主机 VTEP 地址组成的静态条目预填充转发数据库。当实例中的数据包通过桥接时,主机会通过查阅转发表来决定如何转发数据包。如果找到相应的条目,Neutron 将通过相应的本地接口转发数据包,并相应地封装流量。要查看每个主机上的转发数据库表,请使用 bridge fdb show 命令。
使用覆盖网络时的潜在问题
使用覆盖网络技术时需要注意的一点是,封装数据包时添加的额外头部可能会导致数据包超过交换端口或接口的最大传输单元(MTU)。MTU 是网络中可以发送的最大数据包或帧的大小。使用 VXLAN 头部封装数据包可能会导致数据包大小超过默认的 1500 字节 MTU。超出 MTU 导致的连接问题会以奇怪的方式表现出来,包括通过 SSH 连接到实例时出现部分失败,或在实例之间传输大数据包失败等。为避免此问题,可以考虑将虚拟机实例中接口的 MTU 从 1500 字节降低到 1450 字节,以考虑 VXLAN 封装的开销,避免连接问题。
降低 MTU 的替代方法是增加用于 VTEP 的接口的 MTU。通常会在 VTEP 接口和相应的交换端口上设置 9000 字节的巨型 MTU,以避免需要在实例内部降低 MTU。增加 VTEP 接口的 MTU 还被证明能够在使用覆盖网络时提高网络吞吐量。
可以通过修改 DHCP 选项 26,将非标准 MTU 推送到 DHCP 租约中的实例。要配置较低的 MTU,请完成以下步骤:
- 在
controller节点上,修改/etc/neutron/dhcp_agent.ini中的 DHCP 配置文件,并指定自定义的dnsmasq配置文件:
[DEFAULT]
dnsmasq_config_file = /etc/neutron/dnsmasq-neutron.conf
- 接下来,在
/etc/neutron/dnsmasq-neutron.conf路径下创建自定义的dnsmasq配置文件,并添加以下内容:
dhcp-option-force=26,1450
- 保存并关闭文件。使用以下命令重启 Neutron DHCP 代理:
# systemctl restart neutron-dhcp-agent
在运行 Linux 的实例内部,可以使用ip link show <interface>命令观察 MTU 值。
对dnsmasq配置的更改会影响所有网络,即使是 VLAN 网络上的实例也会受到影响。可以单独修改 Neutron 端口以避免这种影响。
本地
在 Neutron 中创建本地网络时,无法指定 VLAN ID,甚至无法指定物理接口。Neutron Linux 桥接代理将创建一个桥接器并仅将实例的 tap 接口连接到该桥接器。位于同一节点的同一本地网络中的实例将连接到同一桥接器,并可以自由相互通信。由于主机没有物理或虚拟 VLAN 接口连接到桥接器,因此实例之间的流量仅限于实例所在的主机。在不同主机上位于同一本地网络的实例之间无法相互通信。
图 4.5 展示了没有物理或虚拟 VLAN 接口连接到桥接器的情况:

图 4.5
在图 4.5 中,创建了两个本地网络及其各自的桥接器,brqZZZZ和brqNNNN。连接到同一桥接器的实例可以相互通信,但无法与桥接器外的其他实例通信。在使用本地网络时,没有机制允许不同桥接器或主机之间的实例通信。
某些应用架构可能要求在同一主机上部署多个实例,而无需跨主机通信。在这种情况下,使用本地网络可能会更合适,并且可以避免浪费宝贵的 VLAN ID 或 VXLAN 开销。
配置 ML2 网络插件
在您可以构建 OpenStack 云中的网络资源之前,必须定义并配置网络插件。ML2 插件提供了一个通用框架,允许多个驱动程序之间互操作。在本节中,我们将了解如何在controller01和compute01主机上配置 Linux 桥接 ML2 驱动程序和代理。
本书将讨论如何配置 Linux 桥接和 Open vSwitch 驱动程序以实现同时操作,但这可能不适合生产环境。为了简化操作,如果不需要分布式虚拟路由器,建议部署 Linux 桥接驱动程序。分布式虚拟路由器的配置和架构在第十二章,分布式虚拟路由器中有详细介绍。
配置桥接接口
在此安装中,物理网络接口eth2将作为提供接口用于 VLAN 和扁平网络。Neutron 将在初始网络配置完成后负责配置 VLAN 接口。
在controller01和compute01节点上,按照以下方式在/etc/network/interfaces文件中配置eth2接口:
auto eth2
iface eth2 inet manual
关闭并保存文件,然后使用以下命令启用接口:
# ip link set dev eth2 up
使用ip link show dev eth2命令确认接口处于UP状态。如果接口已经启动,它就可以在 Neutron 将创建和管理的桥接中使用。
因为该接口将用于桥接,所以不能直接将 IP 地址应用于该接口。如果eth2上应用了 IP 地址,一旦该接口被放入桥接中,它将变得不可访问。如果需要 IP 地址,请考虑将其移动到 Neutron 网络不需要的接口上。
配置覆盖接口
在此安装中,物理网络接口eth1将作为覆盖接口用于使用 VXLAN 的覆盖网络。Neutron 将在初始网络配置完成后负责配置 VXLAN 接口。
在controller01和compute01节点上,按照以下方式在/etc/network/interfaces文件中配置eth1接口:
auto eth1
iface eth1 inet static
address 10.20.0.X/24
使用下表来获取适当的地址,并根据需要替换X:
| 主机 | 地址 |
|---|---|
controller01 |
10.20.0.100 |
compute01 |
10.20.0.101 |
关闭并保存文件,然后使用以下命令启用接口:
# ip link set dev eth1 up
使用ip addr show dev eth1命令确认接口处于UP状态并且地址已经设置。确保两个主机能够通过新配置的接口进行通信,通过从controller01节点 pingcompute01来验证:

如果你在通过该接口进行通信时遇到任何问题,你将会在使用 OpenStack Networking 创建的 VXLAN 网络中遇到问题。所有问题应在继续之前解决。
ML2 插件配置选项
上一章节已安装 ML2 插件,其配置文件位于/etc/neutron/plugins/ml2/ml2_conf.ini,必须配置该文件才能使用 OpenStack Networking 服务。neutron-server服务引用的 ML2 插件配置文件可能被多个代理引用,包括 Linux 桥接和 Open vSwitch 代理。特定代理的更改将在每个主机上的相应配置文件中进行。
ml2_conf.ini文件被分为多个配置区块,并包含以下常用选项:
[ml2]
...
type drivers = ...
mechanism drivers = ...
tenant_network_types = ...
extension_drivers = ...
[ml2_type_flat]
...
flat_networks = ...
[ml2_type_vlan]
...
network_vlan_ranges = ...
[ml2_type_vxlan]
...
vni_ranges = ...
vxlan_group = ...
[securitygroup]
...
enable_security_group = ...
enable_ipset = ...
配置选项必须保留在适当的区块内,否则 Neutron 服务可能无法启动或正常运行。
类型驱动
类型驱动程序描述了可以由机制驱动程序创建和实现的网络类型。与 ML2 插件一起包含的类型驱动程序包括 local、flat、vlan、gre、vxlan 和 geneve。然而,并非所有机制驱动程序都能实现所有类型的网络。Linux 桥接驱动程序不支持 GENEVE 和 GRE 网络。
更新 controller01 节点上的 ML2 配置文件,并添加以下 type_drivers:
[ml2]
...
type_drivers = local,flat,vlan,vxlan
机制驱动程序
机制驱动程序负责实现由类型驱动程序描述的网络。与 ML2 插件一起包含的机制驱动程序包括 linuxbridge、openvswitch 和 l2population。
更新 controller01 节点上的 ML2 配置文件,并添加以下 mechanism_drivers:
[ml2]
...
mechanism_drivers = linuxbridge,l2population
Neutron Linux 桥接代理需要特定的配置选项,这将在本章后续部分讨论。
使用 L2 population 驱动程序
L2 population 驱动程序在 OpenStack 的 Havana 版本中引入,并与 ML2 插件一起发布。它使得在 OpenStack 构建的大型覆盖网络上,广播、组播和单播流量能够扩展。
L2 population 驱动程序的目标是通过在所有主机上预先填充桥接转发和 IP 邻居(ARP)表,从而抑制昂贵的交换学习行为。由于 Neutron 被视为用户创建的网络和实例的逻辑布局的可信来源,它可以轻松地用这些信息预填充包含 MAC 地址和目标 VTEP 的转发表。L2 population 驱动程序还在每个主机上实现了一个 ARP 代理,消除了在覆盖网络上广播 ARP 请求的需要。每个 compute 或 network 节点都能够拦截来自实例或路由器的 ARP 请求,并将响应代理给请求者。然而,L2 population 驱动程序确实有一些限制,稍后将在本章中讨论。
使用 L2 population 驱动程序的替代方案是依赖组播来在主机之间传播转发数据库信息。每个主机应配置为订阅一个在 OpenStack 之外配置的组播组。如果没有正确配置,可能会使用广播消息代替组播,这可能会导致网络上的不必要的干扰。组播的配置超出了本书的范围。
租户网络类型
tenant_network_types 配置选项描述了租户或项目可以创建的网络类型。当使用 Linux 桥接机制驱动程序时,支持的租户网络类型包括 flat、vlan、local、vxlan 和 none。
配置选项的值是按顺序排列的列表,如vlan,vxlan。在此示例中,当用户创建网络时,Neutron 会自动配置一个 VLAN 网络和 ID,无需用户交互。当所有可用的 VLAN ID 被分配完毕后,Neutron 将分配列表中的下一个类型的网络。在这种情况下,将分配一个 VXLAN 网络和 VNI。当任何列出网络类型的所有分段 ID 被分配完时,用户将无法再创建网络,并且系统会向用户呈现一个错误。
拥有admin角色的用户可以通过在网络创建过程中指定提供者属性来覆盖tenant_network_types的行为。
更新controller节点上的 ML2 配置文件,并将以下tenant_network_types配置添加到[ml2]部分:
[ml2]
...
tenant_network_types= vlan,vxlan
如果您希望更改tenant_network_types的值,请相应地编辑所有节点上的插件配置文件,并重启neutron-server服务。
扁平网络
flat_networks配置选项定义了支持使用未标记网络的接口,这些网络通常被称为本地 VLAN 或接入 VLAN。此选项要求指定提供者标签。提供者标签是一个任意标签或名称,映射到主机上的物理接口或桥接。稍后将在本章中详细讨论这些映射。
在以下示例中,physnet1接口已配置为支持一个扁平网络:
flat_networks = physnet1
可以使用逗号分隔的列表定义多个接口:
flat_networks = physnet1,physnet2
由于缺乏用于隔离同一接口上未标记流量的标识符,因此一个接口只能支持单一的扁平网络。
在此环境中,flat_networks选项可以保持未配置状态。
网络 VLAN 范围
network_vlan_ranges配置选项定义了当tenant_network_types为vlan时,项目网络在创建时将与哪些 VLAN 范围相关联。当可用 VLAN 数量达到零时,租户将无法再创建 VLAN 网络。
在以下示例中,VLAN ID 40到43可用于租户网络分配:
network_vlan_ranges = physnet1:40:43
可以通过使用逗号分隔的列表来分配不连续的 VLAN:
network_vlan_ranges = physnet1:40:43,physnet1:51:55
在此特定部署中,提供者标签physnet1将与 VLAN 40到43一起使用。除非由拥有admin角色的用户覆盖,否则这些 VLAN 将在创建时自动分配到vlan网络。
更新controller01节点上的 ML2 配置文件,并将以下network_vlan_ranges添加到[ml2_type_vlan]部分:
[ml2_type_vlan]
...
network_vlan_ranges = physnet1:40:43
VNI 范围
当创建 VXLAN 网络时,每个网络都会分配一个唯一的分段 ID,用于封装流量。当使用 Linux 桥接机制驱动程序时,创建各主机的相应 VXLAN 接口时会使用该分段 ID。
vni_ranges 配置选项是一个用逗号分隔的 ID 范围列表,用于在 tunnel_type 设置为 vxlan 时为项目网络分配可用范围。
在以下示例中,段划分 ID 1 到 1000 被预留用于租户网络分配时使用:
vni_ranges = 1:1000
vni_ranges 选项通过逗号分隔的列表支持非连续的 ID,如下所示:
vni_ranges = 1:1000,2000:2500
更新 controller01 节点上的 ML2 配置文件,并将以下 vni_ranges 添加到 [ml2_type_vxlan] 部分:
[ml2_type_vxlan]
...
vni_ranges = 1:1000
VXLAN 头部中的 24 位 VNI 字段支持大约 1600 万个独特标识符。
安全组
enable_security_group 配置选项指示 Neutron 启用或禁用与安全组相关的 API 功能。该选项默认为 true。
enable_ipset 配置选项指示 Neutron 在使用 iptables 防火墙驱动程序时启用或禁用 ipset 扩展。使用 ipset 允许创建一次匹配整组地址的防火墙规则,而不是为每个地址单独创建规则,这使得查找比传统的线性查找更高效。该选项默认为 true。
如果在任何时候更新了 ML2 配置文件,则必须重新启动 neutron-server 服务及相应的 Neutron 代理,以使更改生效。
配置 Linux 桥接驱动程序和代理
Linux 桥接机制驱动程序包含在 ML2 插件中,并在 第三章,安装 Neutron 中进行安装。以下部分将引导您配置 OpenStack 网络以利用 Linux 桥接驱动程序和代理。
虽然 Linux 桥接和 Open vSwitch 代理及驱动程序可以在同一环境中共存,但不应在同一主机上同时安装和配置它们。
安装 Linux 桥接代理
要安装 Neutron Linux 桥接代理,请在 controller01 和 compute01 上执行以下命令:
# apt install neutron-plugin-linuxbridge-agent
如果系统提示覆盖现有配置文件,请在 [default=N] 提示符下输入 N。
更新 Linux 桥接代理配置文件
Linux 桥接代理使用位于 /etc/neutron/plugins/ml2/linuxbridge_agent.ini 的配置文件。最常见的选项如下:
[linux_bridge]
...
physical_interface_mappings = ...
[vxlan]
...
enable_vxlan = ...
vxlan_group = ...
l2_population = ...
local_ip = ...
arp_responder = ...
[securitygroup]
...
firewall_driver = ...
物理接口映射
physical_interface_mappings 配置选项描述了一个人工标签到服务器物理接口的映射。当创建网络时,它们会关联一个接口标签,例如 physnet1。然后,physnet1 标签会通过 physical_interface_mappings 选项映射到一个物理接口,例如 eth2。以下示例中可以观察到此映射:
physical_interface_mappings = physnet1:eth2
所选标签必须在预期处理由 Neutron 创建的特定网络流量的所有节点之间保持一致。然而,映射到标签的物理接口可能不同。当一个节点将physnet1映射到千兆接口,而另一个节点将physnet1映射到 10 千兆接口时,通常会观察到映射的差异。
允许多个接口映射,可以通过逗号分隔的列表将其添加到列表中:
physical_interface_mappings = physnet1:eth2,physnet2:bond2
在此安装中,eth2接口将作为物理网络接口使用,这意味着与physnet1关联的任何网络的流量将通过eth2。如果租户要创建 VLAN 网络,连接到eth2的物理交换机端口必须支持 802.1q VLAN 标记。
配置 Linux 桥接代理使用physnet1作为物理接口标签,并通过相应更新controller01和compute01上的 ML2 配置文件,将eth2作为物理网络接口:
[linux_bridge]
...
physical_interface_mappings = physnet1:eth2
启用 VXLAN
要启用对 VXLAN 网络的支持,enable_vxlan配置选项必须设置为true。在Controller01和compute01上相应地更新 ML2 配置文件中的enable_vxlan配置选项:
[vxlan]
...
enable_vxlan = true
L2 人口
要启用对 L2 人口驱动程序的支持,l2_population配置选项必须设置为true。在controller01和compute01上相应地更新 ML2 配置文件中的l2_population配置选项:
[vxlan]
...
l2_population = true
L2 人口驱动程序的一个有用功能是其 ARP 响应器功能,有助于避免在覆盖网络中广播 ARP 请求。每个compute节点可以代理来自虚拟机的 ARP 请求并提供回复,所有这些都不会让流量离开主机。
要启用 ARP 响应器,请更新以下配置选项:
[vxlan]
...
arp_responder = true
然而,ARP 响应器与使用 Linux 桥接代理的系统上的allowed-address-pairs扩展存在已知的不兼容问题。Linux 桥接代理使用的vxlan内核模块在启用 ARP 响应器功能时不支持动态学习。因此,当 IP 地址在虚拟机之间迁移时,转发数据库可能不会更新目标主机的 MAC 地址和相应的 VTEP,因为 Neutron 未收到此更改的通知。如果需要allowed-address-pairs功能,我的建议是禁用 ARP 响应器,直到该行为发生变化。
本地 IP
local_ip配置选项指定了用于在主机之间建立覆盖网络的本地 IP 地址。有关覆盖网络架构的设计,请参考第一章,OpenStack 网络介绍。在本安装中,所有通过覆盖网络的来宾流量将通过本章前面配置的eth1接口跨越专用网络。
在controller01和compute01主机上的 ML2 配置文件的[vxlan]部分中相应更新local_ip配置选项:
[vxlan]
...
local_ip = 10.20.0.X
以下表格提供了需要在每个主机上配置的接口和地址。请根据需要替换X:
| 主机名 | 接口 | IP 地址 |
|---|---|---|
controller01 |
eth1 | 10.20.0.100 |
compute01 |
eth1 | 10.20.0.101 |
防火墙驱动程序
firewall_driver配置选项指示 Neutron 使用特定的防火墙驱动程序来实现安全组功能。根据使用的机制驱动程序,可能会配置不同的防火墙驱动程序。
更新controller01和compute01上的 ML2 配置文件,并在[securitygroup]部分的单行中定义适当的firewall_driver配置:
[securitygroup]
...
firewall_driver = iptables
如果你不想使用防火墙,并希望禁用安全组规则的应用,将firewall_driver设置为noop。
配置 DHCP 代理使用 Linux 桥接驱动程序
为了使 Neutron 能够正确地将 DHCP 命名空间接口连接到相应的网络桥接,controller节点上的 DHCP 代理必须配置为使用 Linux 桥接接口驱动程序。
在controller节点上,更新 Neutron DHCP 代理配置文件/etc/neutron/dhcp_agent.ini中的interface_driver配置选项,以使用 Linux 桥接接口驱动程序:
[DEFAULT]
...
interface_driver = linuxbridge
接口驱动程序将根据托管 DHCP 代理的节点上使用的插件代理而有所不同。
重启服务
某些服务必须重新启动才能使更改生效。以下服务应在controller01和compute01上重启:
# systemctl restart neutron-linuxbridge-agent
以下服务应在controller01节点上重启:
# systemctl restart neutron-server neutron-dhcp-agent
验证 Linux 桥接代理
为了验证 Linux 桥接网络代理是否已正确登记,在controller节点上执行openstack network agent list命令:

controller01和compute01节点上的 Neutron Linux 桥接代理应在输出中显示,状态为UP。如果代理不在输出中,或状态为DOWN,你需要通过观察相应主机上的/var/log/neutron/neutron-linuxbridge-agent.log日志消息来排查代理连接问题。
概述
在本章中,我们发现了 Neutron 如何利用 Linux 桥接和虚拟接口为实例提供网络连接。Linux 桥接驱动程序支持多种不同的网络类型,包括带标签、无标签和覆盖网络,稍后的章节中,我将展示在这些网络上启动实例时,它们的不同之处。
在下一章中,你将学习 Linux 桥接与 Open vSwitch 实现之间的区别,并将逐步了解如何在两个额外的 compute 节点和一个专用于分布式虚拟路由功能的网络节点上安装 Open vSwitch 驱动程序和代理。
第五章:使用 Open vSwitch 构建虚拟交换基础设施
在 第四章,使用 Linux 桥接的虚拟网络基础设施 中,我们研究了 Linux 桥接机制驱动程序和代理如何使用不同类型的接口和 Linux 桥接构建虚拟网络基础设施。在本章中,你将了解 Open vSwitch 机制驱动程序及其相应的代理,该代理利用 Open vSwitch 作为虚拟交换技术,将实例和主机连接到物理网络。
在本章中,你将执行以下操作:
-
发现 Open vSwitch 如何用于构建虚拟网络基础设施
-
可视化虚拟交换机中的流量流动
-
在主机上部署 Open vSwitch 机制驱动程序和代理
使用 Open vSwitch 驱动程序
Open vSwitch 机制驱动程序支持多种传统和覆盖网络技术,并支持以下类型的驱动程序:
-
本地
-
扁平化
-
VLAN
-
VXLAN
-
GRE
在 OpenStack 网络中,Open vSwitch 作为一个软件交换机,使用虚拟网络桥接和流规则在主机之间转发数据包。尽管它能够支持许多技术和协议,但 OpenStack 网络仅利用 Open vSwitch 的一部分功能。
以下是 Open vSwitch 的三个主要组件:
-
内核模块:
openvswitch内核模块相当于硬件交换机中的 ASIC。它是交换机的数据平面,所有的数据包处理都发生在此处。 -
vSwitch 守护进程:
ovs-vswitchd守护进程是一个 Linux 进程,在每个物理主机的用户空间中运行,决定内核模块如何编程。 -
数据库服务器:OpenStack/Open vSwitch 实现使用每个物理主机上的本地数据库,称为Open vSwitch 数据库服务器(OVSDB),它维护虚拟交换机的配置。
上述组件的高级架构图可以在这里看到:

Neutron Open vSwitch 代理,neutron-openvswitch-agent,是一个服务,它通过 Open vSwitch 机制驱动程序在主机上配置,负责管理网络及相关接口的实施。该代理根据防火墙配置,将 tap 接口连接到 Open vSwitch 或 Linux 桥接,并使用 ovs-vsctl 和 ovs-ofctl 等工具,根据 neutron-server 服务提供的数据来编程流。
在基于 Open vSwitch 的网络实现中,有五种不同类型的虚拟网络设备,如下所示:
-
Tap 设备
-
Linux 桥接
-
虚拟以太网电缆
-
OVS 桥接
-
OVS 补丁端口
Tap 设备和 Linux 桥接在前一节中已有简要描述,并且它们在 Open vSwitch 网络中的使用保持不变。虚拟以太网 (veth) 电缆是模拟网络补丁电缆的虚拟接口。发送到 veth 电缆一端的以太网帧将被另一端接收,就像真实的网络补丁电缆一样。当 Neutron 在网络命名空间与 Linux 桥接之间建立连接时,或者将 Linux 桥接连接到 Open vSwitch 交换机时,它会利用 veth 电缆。
Neutron 将 DHCP 或路由器命名空间和实例使用的接口连接到 OVS 桥接端口。这些端口本身可以像物理交换机端口一样进行配置。Open vSwitch 维护关于连接设备的信息,包括 MAC 地址和接口统计数据。
Open vSwitch 内置了一种端口类型,模拟 Linux veth 电缆的行为,但经过优化以用于 OVS 桥接。当连接两个 Open vSwitch 桥接时,每个交换机上的一个端口会被保留作为 patch 端口。Patch 端口配置了与另一个交换机的 patch 端口相对应的对等名称。从图形上看,它像这样:

图 5.1
在前面的示意图中,两个 OVS 桥接通过每个交换机上的一个 patch 端口进行交叉连接。Open vSwitch 的 patch 端口用于将 Open vSwitch 桥接互联,而 Linux veth 接口用于将 Open vSwitch 桥接与 Linux 桥接连接,或将 Linux 桥接与其他 Linux 桥接连接。
基本的 OpenvSwitch 命令
Open vSwitch 包括可用于管理用户创建的虚拟交换机的实用工具,包括 OpenStack 网络代理创建的虚拟交换机。这些命令在故障排除时非常有用,尤其是在网络上不可避免地出现问题时。
基本命令
大多数 Open vSwitch 配置和故障排除可以通过以下命令完成:
-
ovs-vsctl:用于配置ovs-vswitchd数据库的工具 -
ovs-ofctl:用于监控和管理 OpenFlow 交换机的工具 -
ovs-dpctl:用于管理 Open vSwitch 数据路径的工具 -
ovs-appctl:用于查询和管理 Open vSwitch 守护进程的工具
ovs-vsctl
ovs-vsctl 工具用于配置和查看 OVS 桥接/交换机操作。通过该工具,用户可以配置交换机上的端口,创建和删除虚拟交换机,创建绑定,并管理端口上的 VLAN 标记。
有用的命令包括以下内容:
-
ovs-vsctl show:打印交换机数据库配置的简要概览,包括端口、VLAN 等 -
ovs-vsctl list-br:打印已配置桥接的列表 -
ovs-vsctl list-ports <bridge>:打印指定桥接上的端口列表 -
ovs-vsctl list interface:打印接口列表及其统计数据和其他信息
ovs-ofctl
ovs-ofctl 工具用于监控和管理 OpenFlow 交换机。Neutron Open vSwitch 代理使用 ovs-ofctl 来编程虚拟交换机上的流量,用以控制流量、执行 VLAN 标记、执行 NAT 等。
有用的命令包括以下内容:
-
ovs-ofctl show <bridge>:显示指定桥接器的 OpenFlow 特性、动作和端口描述。 -
ovs-ofctl dump-flows <bridge> <flow>:打印指定桥接器的流条目。如果指定了流,只会显示该流。 -
ovs-ofctl dump-ports-desc <bridge>:打印指定桥接器的端口统计信息,包括接口的状态、对等端和速度。
ovs-dpctl
ovs-dpctl 工具用于管理和查询 Open vSwitch 数据路径。与 ovs-ofctl 不同,ovs-dpctl 显示的是由实际流量匹配的流。
有用的命令包括以下内容:
ovs-dpctl dump-flows:显示系统中所有流量的流表数据
ovs-appctl
ovs-appctl 工具用于查询和管理 Open vSwitch 守护进程,包括 ovs-vswitchd、ovs-controller 等。
有用的命令包括以下内容:
-
ovs-appctl bridge/dump-flows <bridge>:转储指定桥接器上的 OpenFlow 流量 -
ovs-appctl dpif/dump-flows <bridge>:转储指定桥接器的数据路径流 -
ovs-appctl ofproto/trace <bridge> <flow>:显示给定流的完整流字段,包括匹配的规则和执行的动作
这些命令多数由 Neutron Open vSwitch 代理用于编程虚拟交换机,操作员也经常用它们来排查网络连接问题。强烈建议熟悉这些命令及其输出。
可视化 Open vSwitch 的流量
在使用 Open vSwitch 驱动时,为了让以太网帧从虚拟机实例传输到物理网络,它将经过多个不同的接口,包括以下内容:
| 网络类型 | 接口类型 | 接口名称 |
|---|---|---|
| all | tap | tapN |
| all | bridge | qbrXXXX(仅与 iptables 防火墙驱动一起使用) |
| all | veth | qvbXXXX, qvoXXXX(仅与 iptables 防火墙驱动一起使用) |
| all | vSwitch | br-int |
| flat, vlan | vSwitch | br-ex(用户可配置) |
| vxlan, gre | vSwitch | br-tun |
| flat, vlan | patch | int-br-ethX, phy-br-ethX |
| vxlan, gre | patch | patch-tun, patch-int |
| flat, vlan | physical | ethX(X 为接口编号) |
Open vSwitch 桥接器 br-int 被称为 集成桥。集成桥是大多数虚拟设备连接的中心虚拟交换机,包括实例、DHCP 服务器、路由器等。当启用 Neutron 安全组并使用 iptables 防火墙驱动程序时,实例不会直接连接到集成桥。相反,实例连接到各个 Linux 桥接器,这些 Linux 桥接器通过 veth 电缆与集成桥交叉连接。
openvswitch 防火墙驱动程序是一个替代驱动程序,它通过 OpenFlow 规则实现安全组规则,但这超出了本书的范围。
Open vSwitch 桥接器 br-ethX 被称为 提供者桥。提供者桥通过连接的物理接口提供与物理网络的连接。提供者桥也通过虚拟补丁电缆与集成桥连接,该补丁电缆由补丁端口 int-br-ethX 和 phy-br-ethX 提供。
这里描述的架构的可视化表示可以在以下图表中看到:

图 5.2
在前面的图示中,实例通过各自的 tap 接口连接到单独的 Linux 桥接器。Linux 桥接器通过 veth 接口与 OVS 集成桥连接。集成桥上的 OpenFlow 规则决定了如何通过虚拟交换机转发流量。集成桥通过 OVS 补丁电缆连接到提供者桥。最后,提供者桥连接到物理网络接口,允许流量进出主机并进入物理网络基础设施。
在使用 Open vSwitch 驱动程序时,环境中的每个控制器、网络或计算节点都有自己的集成桥和提供者桥。跨节点的虚拟交换机通过物理网络有效地相互交叉连接。一个主机上可以配置多个提供者桥,但通常需要为每个提供者桥使用一个专用的物理接口。
标识虚拟交换机上的端口
使用 ovs-ofctl show br-int 命令,我们可以看到集成桥的逻辑表示。以下截图展示了使用此命令查看 compute02 上集成桥的交换机端口:

以下是前面截图中展示的组件:
-
端口号 1 被命名为
int-br-eth2,是 OVS 补丁电缆的一端。另一端连接到提供者桥接器br-eth2(未显示)。 -
端口号 2 被命名为
patch-tun,是 OVS 补丁电缆的一端。另一端连接到隧道桥br-tun(未显示)。 -
端口号 3 被命名为
qvo3de035cc-79,对应 Neutron 端口3de035cc-79a9-4172-bb25-d4a7ea96325e。 -
端口号 4 被命名为
qvoce30da31-3a,对应的 Neutron 端口是ce30da31-3a71-4c60-a350-ac0453b24d7d。 -
端口号 5 被命名为
qvoa943af89-8e,对应的 Neutron 端口是`a943af89-8e21-4b1d-877f-abe946f6e565.` -
名为
br-int的本地端口是 Open vSwitch 内部使用的,可以忽略。
以下截图以图形方式展示了交换机的配置:

图 5.3
确定与端口相关的本地 VLAN
每个连接到实例或其他网络资源的集成桥接器端口,都被分配到一个本地 VLAN,该 VLAN 属于该虚拟交换机。
每个主机上的 Open vSwitch 数据库都是独立的,与其他主机无关,且本地 VLAN 数据库与物理网络基础设施没有直接关系。在特定主机上的同一 Neutron 网络中的实例被放置在本地集成桥接器的同一 VLAN 中,但不同主机之间的 VLAN ID 不一定保持一致。也就是说,流规则将在每个主机上实现,将本地 VLAN ID 映射到与相应 Neutron 网络关联的 ID,从而允许跨共享 VLAN 进行主机之间的流量传输。本行为将在本章后续部分进行详细讨论。
使用 ovs-vsctl show 命令,你可以识别主机上所有虚拟交换机上所有端口的本地 VLAN 标签。以下截图展示了在 compute02 上运行该命令的效果:

集成桥接器上连接着三个接口,分别命名为 qvoce30da31-3a、qvoa943af89-8e 和 qvo3de035cc-79。其中两个接口位于同一网络,并处于同一个本地 VLAN 中。另一个接口 qvoa943af89-8e 则位于不同的网络中,因此属于不同的 VLAN。
本地 VLAN ID 是由本地 Open vSwitch 进程随机分配的,可能会在重启 openvswitch-switch 服务或重新启动后发生变化。
编程流规则
与 Linux 桥接架构不同,Open vSwitch 驱动程序不会使用主机上的 VLAN 接口来标记流量。相反,Open vSwitch 代理在虚拟交换机上编程流规则,指示如何在转发前处理通过交换机的流量。当流量经过虚拟交换机时,交换机上的流规则可以在转发流量前转换、添加或去除 VLAN 标签。此外,还可以添加流规则,丢弃匹配特定特征的流量。Open vSwitch 能执行对流量的其他类型操作,但这些操作超出了本书的范围。
使用ovs-ofctl dump-flows <bridge>命令,我们可以观察到当前在指定桥上编程的流。Open vSwitch 插件代理负责将 Neutron 数据库中关于网络的信息转换为 Open vSwitch 流,并在网络发生变化时持续维护这些流。
VLAN 网络的流规则
在以下示例中,VLAN 40和42代表数据中心中的两个网络。这两个 VLAN 已被中继到controller和compute节点,并且已经配置了使用这些 VLAN ID 的 Neutron 网络。
在物理交换机上,为了实现这里描述的网络配置,所需的配置大致如下:
vlan 40
name VLAN_40
vlan 42
name VLAN_42
interface Ethernet1/4
description Provider_Interface_eth2
switchport
switchport mode trunk
switchport trunk allowed vlan add 40,42
no shutdown
当配置为中继端口时,提供商接口可以支持多个 VLAN 网络。进入物理接口eth2的流量会由连接到的br-eth2桥上的流规则进行处理。流规则按照从高到低的优先级顺序进行处理。默认情况下,ovs-ofctl以虚拟交换机发送流条目的相同顺序返回流条目。使用--rsort,可以按照优先级顺序返回结果,从高到低,以匹配数据包处理的顺序:

为了提高可读性,duration和cookie字段已被移除。
前三条规则指定了一个特定的入站端口:
in_port="phy-br-eth2"
根据图 5.3 中的示意图,流量通过物理接口eth2进入桥br-eth2时,使用的是端口 1,而不是名为phy-br-eth2的端口,因此前三条规则不适用。因此,流量将通过第四条规则转发到集成桥接器,其中没有指定特定的端口:

动作为NORMAL的流指示 Open vSwitch 充当学习交换机,这意味着流量将从除接收流量的端口以外的所有端口转发,直到交换机学习并更新其转发数据库。流量将从连接到集成桥接器的端口转发出去。
转发数据库,或 FDB 表,相当于物理交换机上的 CAM 或 MAC 地址表。这种学习行为类似于硬件交换机,它会将流量洪泛到所有端口,直到学习到正确的路径。
当流量从提供商桥接器br-eth2退出并进入集成桥接器br-int的端口 1 时,它会根据br-int上的流规则进行评估,如下所示:

立即需要关注的是检查来自int-br-eth2接口的流规则,因为流量正是从提供者桥接进入集成桥接。这里展示的第一条规则执行的操作是,当原始 VLAN ID(由dl_vlan值标识)为 42 时,将数据包的 VLAN ID 从其原始 VLAN 修改为在compute节点上的集成桥接本地 VLAN:

当带有 VLAN 42 标记的流量从物理网络发送到实例并通过提供者桥接转发到集成桥接时,VLAN 标签会从 42 修改为本地 VLAN 1。然后,该帧被转发到表 60 进行进一步处理,默认动作为 NORMAL。因此,该帧被转发到br-int上的一个端口,该端口连接到与目标 MAC 地址匹配的实例。
下一条规则在数据链路 VLAN 为40时执行类似操作,将其替换为本地 VLAN 2。如果流量匹配drop规则,意味着没有其他更高优先级的规则进入int-br-eth2,流量将被丢弃:

返回流量
从实例返回的流量通过集成桥接br-int时,可能会被各种流规则处理,这些规则用于抑制 ARP 和 MAC 欺骗。如果流量被允许,它将被转发到表 60 进行进一步处理,并最终转发到提供者桥接:

一旦流量到达提供者桥接br-eth2,它将按照以下方式由流规则处理:

如果这些规则看起来很熟悉,那是因为它们与我们之前展示的提供者桥接上的流规则相同。不过这一次,来自集成桥接连接到端口phy-br-eth2的流量将由这些规则处理。
提供者桥接上的第一条流规则检查以太网头部中的 VLAN ID,如果是1,则在将流量转发到物理接口之前将其修改为42。第二条规则在流量离开桥接之前将帧的 VLAN 标签从2修改为40。所有来自集成桥接的流量,若未标记为 VLAN 1或2,则会被丢弃。
如果某个网络中没有实例或资源调度到该节点,则该网络的流规则不会存在于桥接上。每个节点上的 Neutron Open vSwitch 代理负责为相应节点上的虚拟交换机创建适当的流规则。
平面网络的流规则
Neutron 中的平面网络是未标记网络,这意味着在创建网络时,该网络没有与 802.1q VLAN 标签关联。然而,在内部,Open vSwitch 在编程虚拟交换机时,将平面网络与 VLAN 网络相似地处理。平面网络在 Open vSwitch 数据库中被分配一个本地 VLAN ID,就像 VLAN 网络一样,连接到同一集成桥接的同一平面网络中的实例将被置于相同的本地 VLAN 中。然而,VLAN 和平面网络之间存在一个差异,这可以通过在集成桥接和提供桥接上创建的流规则来观察。流量通过桥接时,局部 VLAN ID 被添加到以太网头部或从中去除,而不是将本地 VLAN ID 映射到物理 VLAN ID,反之亦然。
在物理交换机上,为了实现这里描述的网络配置,所需的配置将如下所示:
vlan 200
name VLAN_200
interface Ethernet1/4
description Provider_Interface_eth2
switchport
switchport mode trunk
switchport trunk native vlan 200
switchport trunk allowed vlan add 200
no shutdown
或者,接口也可以配置为接入端口:
interface Ethernet1/4
description Provider_Interface_eth2
switchport
switchport mode access
switchport access vlan 200
no shutdown
每个提供接口只支持一个平面网络。当配置为 trunk 端口并具有原生 VLAN 时,提供接口可以支持一个平面网络和多个 VLAN 网络。当配置为接入端口时,接口只能支持一个平面网络,任何尝试标记流量的行为将失败。
在这个例子中,Neutron 中已添加了一个没有 VLAN 标签的平面网络:

在物理交换机上,这个网络将对应于连接到 compute02 上的 eth2 端口的原生(未标记)VLAN。在这种情况下,原生 VLAN 为 200。已在网络 MyFlatNetwork 上启动了一个实例,导致以下虚拟交换机配置:

注意,关联到实例的端口已被分配了本地 VLAN ID 为 3,如 tag 值所示,即使它是平面网络。在集成桥接上,现在存在一条流规则,当传入的以太网帧没有设置 VLAN ID 时,会修改其 VLAN 头:

TCI 代表 标签控制信息,是 802.1q 头部的一个 2 字节字段。对于带有 802.1q 头部的数据包,此字段包含 VLAN 信息,包括 VLAN ID。对于没有 802.1q 头部的数据包,也称为未标记数据包,vlan_tci 值被设置为零(0x0000)。
结果是,平面网络上的传入流量被标记为 VLAN 3,并转发到连接到集成桥接并位于 VLAN 3 中的实例。
当实例的返回流量由提供桥接上的流规则处理时,本地 VLAN ID 会被去除,流量变为未标记:

未标记的流量随后被转发到物理接口 eth2,并由物理交换机处理。
覆盖网络的流规则
在 Neutron 的参考实现中,覆盖网络是使用 VXLAN 或 GRE 来封装主机之间的虚拟实例流量的网络。连接到覆盖网络的实例附加到集成桥,并使用映射到该网络的本地 VLAN,就像我们到目前为止讨论的其他网络类型一样。同一主机上的所有实例都连接到相同的本地 VLAN。
在此示例中,已创建一个覆盖网络,Neutron 自动分配了分段 ID 39。

无需对物理交换基础设施进行更改以支持此网络,因为流量将通过覆盖网络接口eth1进行封装并转发。
在MyOverlayNetwork网络上启动了一个实例,这导致了以下虚拟交换机配置:

请注意,虽然这是一个覆盖网络,与实例关联的端口已经分配了本地 VLAN ID 4。当一个实例向同一网络中的另一个实例或设备发送流量时,集成桥会将流量转发到隧道桥br-tun,在此会参考以下流量规则:

隧道桥上实现的流量规则是独特的,因为它们为每个目标 MAC 地址指定了一个虚拟隧道端点(VTEP),包括连接到网络的其他实例和路由器。此行为确保流量直接转发到目标所在的compute或network节点,而不是通过桥的所有端口转发。与之不匹配的流量会被丢弃。
在此示例中,目标 MAC 地址fa:16:3e:f1:b0:49的流量被转发到端口vxlan0a140064,正如我们在这里看到的,它被映射到一个隧道端点:

地址10.20.0.100是controller01的 VXLAN 隧道端点,MAC 地址fa:16:3e:f1:b0:49属于MyOverlayNetwork网络中的 DHCP 服务器。
返回流量首先会通过隧道桥上的流量规则处理,然后转发到集成桥,最后再转发到实例。
本地网络的流量规则
在 Open vSwitch 实现中,本地网络的行为类似于 Linux 桥接实现。局域网中的实例连接到集成桥,并能够与同一网络和本地 VLAN 中的其他实例进行通信。然而,对于本地网络,没有创建流量规则。
同一网络中实例之间的流量保持本地在虚拟交换机内,并且根据定义,它局限于实例所在的compute节点。这意味着,如果服务托管在其他节点上(例如 DHCP 和元数据服务),任何不在这些服务所在主机上的实例将无法访问这些服务。
配置 ML2 网络插件
本章的其余部分将专门提供有关安装和配置 Neutron Open vSwitch 代理以及 ML2 插件以便与 Open vSwitch 机制驱动程序一起使用的说明。在本书中,compute02、compute03和snat01将是唯一配置为与 Open vSwitch 一起使用的节点。
配置桥接接口
在本次安装中,物理网络接口eth2将作为提供者接口用于桥接目的。
在compute02、compute03和snat01上,在/etc/network/interfaces文件中配置eth2接口,如下所示:
auto eth2
iface eth2 inet manual
关闭并保存文件,并使用以下命令启用接口:
# ip link set dev eth2 up
由于该接口将用于桥接,无法直接将 IP 地址应用于该接口。如果eth2上应用了 IP 地址,一旦该接口被置于桥接中,它将变得无法访问。桥接将在本章稍后创建。
配置覆盖接口
在本次安装中,物理网络接口eth1将作为覆盖接口用于使用 VXLAN 的覆盖网络。对于 VXLAN 网络,这是 VXLAN 隧道终端(VTEP)的等效物。Neutron 将在初始网络配置完成后,负责配置 Open vSwitch 的某些方面。
在所有主机上,如果尚未完成,在/etc/network/interfaces文件中配置eth1接口:
auto eth1
iface eth1 inet static
address 10.20.0.X/24
使用以下表格来确定适当的地址。在适当的地方,将地址替换为X:
| 主机 | 地址 |
|---|---|
compute02 |
10.20.0.102 |
compute03 |
10.20.0.103 |
snat01 |
10.20.0.104 |
关闭并保存文件,并使用以下命令启用接口:
# ip link set dev eth1 up
使用ip addr show dev eth1命令确认接口处于UP状态,并且地址已被设置。通过 ping controller01确保compute02可以通过新配置的接口进行通信:

对所有节点重复此过程。
如果您在通过此接口通信时遇到任何问题,您将遇到使用 OpenStack Networking 创建的 VXLAN 网络的问题。任何问题应在继续之前进行修复。
ML2 插件配置选项
ML2 插件最初安装在第三章,安装 Neutron,中,并在上一章配置为支持 Linux 桥接机制驱动程序。它必须修改以支持 Open vSwitch 机制驱动程序。
机制驱动程序
机制驱动程序负责实现由类型驱动程序描述的网络。随 ML2 插件一起发布的机制驱动程序包括linuxbridge、openvswitch和l2population。
更新controller01上的 ML2 配置文件,并将openvswitch添加到机制驱动程序列表中:
[ml2]
...
mechanism_drivers = linuxbridge,l2population,openvswitch
Neutron Open vSwitch 代理需要特定的配置选项,稍后将在本章中讨论。
平面网络
flat_networks 配置选项定义了支持使用无标签网络的接口,通常称为原生或接入 VLAN。此选项要求指定提供商标签。提供商标签是映射到主机上物理接口或桥接的任意标签或名称。关于这些映射的详细讨论将在本章稍后部分进行。
在以下示例中,physnet1 接口已配置为支持平面网络:
flat_networks = physnet1
可以使用逗号分隔的列表定义多个接口:
flat_networks = physnet1,physnet2
由于缺乏用于隔离同一接口上无标签流量的标识符,因此一个接口只能支持单个平面网络。
在这种环境中,flat_networks 选项可以保持 未配置。
网络 VLAN 范围
network_vlan_ranges 配置选项定义了一个 VLAN 范围,当 tenant_network_types 为 vlan 时,项目网络将在创建时与这些 VLAN 相关联。当可用的 VLAN 数量为零时,租户将无法再创建 VLAN 网络。
在以下示例中,VLAN ID 40 到 43 可用于租户网络分配:
network_vlan_ranges = physnet1:40:43
可以使用逗号分隔的列表分配非连续的 VLAN:
network_vlan_ranges = physnet1:40:43,physnet1:51:55
在此安装中,提供商标签 physnet1 将与 VLAN 40 到 43 一起使用。这些 VLAN 会在创建时自动分配给 vlan 网络,除非被具有 admin 角色的用户覆盖。
如果 [ml2_type_vlan] 部分中尚未存在,更新 controller 节点上的 ML2 配置文件,并添加以下 network_vlan_ranges:
[ml2_type_vlan]
...
network_vlan_ranges = physnet1:40:43
隧道 ID 范围
当创建 GRE 网络时,每个网络会分配一个唯一的分段 ID,用于封装流量。当流量穿越 Open vSwitch 隧道桥时,分段 ID 用于填充数据包封装头中的字段。对于 GRE 数据包,使用 KEY 头字段。
在 [ml2_type_gre] 下找到的 tunnel_id_ranges 配置选项是一个以逗号分隔的 ID 范围列表,表示当 tunnel_type 设置为 gre 时,可用于租户网络分配的 ID 范围。
在以下示例中,分段 ID 1 到 1,000 保留用于租户网络创建时的分配:
tunnel_id_ranges = 1:1000
tunnel_id_ranges 选项支持使用逗号分隔的列表指定非连续的 ID 范围,如下所示:
tunnel_id_ranges = 1:1000,2000:2500
本书中的练习不会配置 GRE 网络,因此 tunnel_id_ranges 可以保持 未配置。
VNI 范围
当创建 VXLAN 网络时,每个网络会分配一个唯一的分段 ID,用于封装流量。
vni_ranges 配置选项是一个以逗号分隔的 ID 范围列表,表示当 tunnel_type 设置为 vxlan 时,可用于项目网络分配的 ID 范围。
在以下示例中,段号 1 到 1,000 被保留,用于在创建时分配给租户网络:
vni_ranges = 1:1000
vni_ranges选项支持使用逗号分隔的列表表示非连续的 ID,如下所示:
vni_ranges = 1:1000,2000:2500
如果ml2_type_vxlan部分中还没有,更新controller节点上的 ML2 配置文件,并添加以下vni_ranges:
[ml2_type_vxlan]
...
vni_ranges = 1:1000
VXLAN 头中的 24 位 VNI 字段支持最多约 1600 万个唯一标识符。
安全组
enable_security_group配置选项指示 Neutron 启用或禁用与安全组相关的 API 功能。此选项默认为true。
enable_ipset配置选项指示 Neutron 在使用iptables_hybrid防火墙驱动程序时启用或禁用ipset扩展。使用 ipset 允许创建防火墙规则,匹配一组地址,而不是为每个地址创建单独的规则,从而使查找比传统线性查找更高效。此选项默认为true。
如果 ML2 配置文件在任何时候被更新,必须重启neutron-server服务和相应的 Neutron 代理,才能使更改生效。
配置 Open vSwitch 驱动程序和代理
Open vSwitch 机制驱动程序包含在 ML2 插件中,已安装于第三章,安装 Neutron。以下各节将引导您配置 OpenStack Networking,以便您使用 Open vSwitch 驱动程序和代理。
虽然 Linux 桥接和 Open vSwitch 代理与驱动程序可以在同一环境中共存,但不应在同一主机上同时安装和配置它们。
安装 Open vSwitch 代理
要安装 Open vSwitch 代理,请在compute02、compute03和snat01上运行以下命令:
# apt install neutron-plugin-openvswitch-agent
依赖项,如 Open vSwitch 组件openvswitch-common和openvswitch-switch,将被安装。如果提示覆盖现有配置文件,在[default=N]提示符下输入N。
更新 Open vSwitch 代理配置文件
Open vSwitch 代理使用位于/etc/neutron/plugins/ml2/openvswitch_agent.ini的配置文件。常见的选项如下所示:
[agent]
...
tunnel_types = ...
l2_population = ...
arp_responder = ...
enable_distributed_routing = ...
[ovs]
...
integration_bridge = ...
tunnel_bridge = ...
local_ip = ...
bridge_mappings = ...
[securitygroup]
...
firewall_driver = ...
隧道类型
tunnel_types配置选项指定代理支持的隧道类型。两个可用选项为gre和/或vxlan。默认值为None,即禁用隧道。
更新[agent]部分的 tunnel_types配置选项,适用于compute02、compute03和snat01上的 Open vSwitch 代理配置文件:
[agent]
...
tunnel_types = vxlan
L2 人口
要启用对 L2 population 驱动程序的支持,必须将 l2_population 配置选项设置为 true。在 compute02、compute03 和 snat01 上相应更新 Open vSwitch 代理配置文件中的 l2_population 配置选项:
[agent]
...
l2_population = true
L2 population 驱动程序的一个重要功能是其 ARP 响应器功能,它可以避免在覆盖网络中广播 ARP 请求。每个 compute 节点可以代理虚拟机的 ARP 请求并为其提供回复,所有这些操作都在主机内部完成,数据不会离开主机。
要启用 ARP 响应器,请更新以下配置选项:
[agent]
...
arp_responder = true
默认的 arp_responder 配置是 false,在此环境中可以保持 不变。
VXLAN UDP 端口
VXLAN 隧道端点之间的 UDP 流量默认端口因系统而异。互联网号码分配局(IANA)为 VXLAN 指定了 UDP 端口 4789,Open vSwitch 使用的是此默认端口。而 Linux 内核则使用 UDP 端口 8472 来处理 VXLAN。为了与使用 Linux 桥接机制驱动程序和 vxlan 内核模块的主机兼容,端口必须从其默认端口进行更改。
要更改端口号,请将以下配置选项从 4789 更新为 8472:
[agent]
...
vxlan_udp_port = 8472
在纯 Open vSwitch 环境中通常不需要此更改,但对于本书中描述的环境,则需要此更改。
集成桥
integration_bridge 配置选项指定了每个节点上使用的集成桥的名称。每个节点有一个集成桥,充当虚拟交换机,所有虚拟机 VIF(也称为 虚拟网络接口)都连接到该桥。集成桥的默认名称是 br-int,不应修改。
从 OpenStack Icehouse 版本开始,Open vSwitch 代理在第一次启动代理服务时会自动创建集成桥。您无需向集成桥添加接口,因为 Neutron 负责将网络设备连接到此虚拟交换机。
隧道桥
隧道桥是一个虚拟交换机,类似于集成桥和提供者桥,用于连接 GRE 和 VXLAN 隧道端点。此桥上存在流规则,负责在流量穿过桥时正确地封装和解封装租户流量。
tunnel_bridge 配置选项指定了隧道桥的名称。默认值为 br-tun,不应修改。由于 Neutron 会自动创建此桥,因此不需要手动创建。
本地 IP
local_ip 配置选项指定节点上用于构建主机之间覆盖网络的本地 IP 地址。参考 第一章,OpenStack 网络入门,以获取关于如何设计覆盖网络的想法。在这个安装过程中,通过我们之前在本章中配置的 eth1 接口,所有客户端流量将通过专用网络传输。
在 compute02、compute03 和 snat01 上相应地更新 Open vSwitch 代理配置文件中 [vxlan] 部分的 local_ip 配置选项:
[vxlan]
...
local_ip = 10.20.0.X
下表提供了应在每个主机上配置的接口和地址。根据需要替换其中的 X:
| 主机名 | 接口 | IP 地址 |
|---|---|---|
| compute02 | eth1 | 10.20.0.102 |
| compute03 | eth1 | 10.20.0.103 |
| snat01 | eth1 | 10.20.0.104 |
桥接映射
bridge_mappings 配置选项描述了将人工标签映射到使用 Open vSwitch 创建的虚拟交换机的映射。与 Linux 桥接驱动程序不同,后者为每个网络配置单独的桥接,并且每个桥接具有自己的接口,Open vSwitch 驱动程序使用单个虚拟交换机,包含单个物理接口,并使用流规则必要时对流量进行标记。
创建网络时,它们与接口标签关联,例如 physnet1。然后,标签 physnet1 被映射到桥接 br-eth1,其中包含物理接口 eth1。标签到桥接接口的映射由 bridge_mappings 选项处理。此映射可以如下所示观察到:
bridge_mappings = physnet1:br-eth1
所选标签必须在所有预期处理 Neutron 创建的给定网络流量的环境中的所有节点之间保持一致。但是,映射到标签的物理接口可能不同。通常情况下会观察到映射不同的情况,例如一个节点将 physnet1 映射到支持一千兆位的桥接口,而另一个节点将 physnet1 映射到支持十千兆位的桥接口。
可以允许多个桥接口映射,并可以使用逗号分隔的列表添加:
bridge_mappings = physnet1:br-eth1,physnet2:br-eth2
在此安装过程中,physnet1 将用作接口标签,并将映射到桥接 br-eth2。相应地更新 compute02、compute03 和 snat01 上的 Open vSwitch 代理配置文件:
[ovs]
...
bridge_mappings = physnet1:br-eth2
配置桥接口
要使用 Open vSwitch 配置桥接,使用 Open vSwitch 实用工具 ovs-vsctl。在 compute02、compute03 和 snat01 上创建桥接 br-eth2,如下所示:
# ovs-vsctl add-br br-eth2
使用 ovs-vsctl add-port 命令将物理接口 eth2 添加到桥接口,例如:
# ovs-vsctl add-port br-eth2 eth2
桥接配置应该在重新启动后保持持久化。然而,如果需要,桥接接口也可以在 /etc/network/interfaces 中配置,使用以下语法:
auto br-eth2
allow-ovs br-eth2
iface br-eth2 inet manual
ovs_type OVSBridge
ovs_port seth2
allow-br-eth2 eth2
iface eth2 inet manual
ovs_bridge br-eth2
ovs_type OVSPort
请注意,连接到 eth2 的物理交换机端口必须支持 802.1q VLAN 标签,如果要创建任何类型的 VLAN 网络。在许多交换机上,交换机端口可以配置为中继端口。
防火墙驱动
firewall_driver 配置选项指示 Neutron 使用特定的防火墙驱动程序来提供安全组功能。可以根据正在使用的机制驱动程序配置不同的防火墙驱动程序。
更新 compute02 和 compute03 上的 ML2 配置文件,并在 [securitygroup] 部分的单行中定义合适的 firewall_driver:
[securitygroup]
...
firewall_driver = iptables_hybrid
iptables_hybrid 防火墙驱动程序使用 iptables 实现防火墙规则,并依赖于实例的 tap 接口与集成桥接之间使用 Linux 桥接。而 openvswitch 防火墙驱动程序则使用 OpenFlow 实现防火墙规则,不依赖于 Linux 桥接或 iptables。从 OpenStack Pike 版本开始,openvswitch 防火墙驱动程序尚未为生产环境准备好,因此不推荐使用。
如果不想使用防火墙,并希望禁用安全组规则的应用,可以将 firewall_driver 设置为 noop。
配置 DHCP 代理使用 Open vSwitch 驱动程序
为了让 Neutron 正确地将 DHCP 命名空间接口连接到适当的网络桥接,托管代理的节点上的 DHCP 代理必须配置为使用 Open vSwitch 接口驱动程序,如下所示:
[DEFAULT]
...
interface_driver = openvswitch
在此环境中,DHCP 代理运行在 controller01 节点上,使用 Linux 桥接驱动程序和代理,且接口驱动程序已配置为与 Linux 桥接工作。此时无需更改。对于仅运行 Open vSwitch 的环境,确保根据需要配置接口驱动程序。
重启服务
现在,已经修改了相应的 OpenStack 配置文件以使用 Open vSwitch 作为网络驱动程序,必须启动或重启某些服务才能使更改生效。
应该在 compute02、compute03 和 snat01 上重新启动 Open vSwitch 网络代理:
# systemctl restart neutron-openvswitch-agent
以下服务应该在 controller 节点上重新启动:
# systemctl restart neutron-server
验证 Open vSwitch 代理
要验证 Open vSwitch 网络代理是否已正确注册,可以在 controller 节点上执行 openstack network agent list 命令:

compute02、compute03 和 snat01 上的 Open vSwitch 代理现在应该在输出中显示,并且状态为 UP。如果没有代理出现,或者状态为 DOWN,则需要通过查看各主机上 /var/log/neutron/neutron-openvswitch-agent.log 中的日志消息来排除代理连接问题。
总结
本章节我们在两个compute节点和一个专用的network节点上安装并配置了 Neutron Open vSwitch 机制驱动和代理,这将在以后用于分布式虚拟路由功能。计划安排在compute02和compute03上的实例将利用 Open vSwitch 虚拟网络组件,而在compute01和controller01上的网络服务则将利用 Linux 桥接。
Neutron 的 Linux 桥接和 Open vSwitch 驱动程序和代理都为将虚拟机实例连接到网络的同一问题提供了独特的解决方案。使用 Open vSwitch 依赖于流规则来确定如何处理环境内外的流量,并需要用户空间工具和内核模块来执行这些操作。另一方面,Linux 桥接则需要8021q和bridge内核模块,并依赖于主机上的 VLAN 和 VXLAN 接口来将实例桥接到物理网络。对于简单的环境,我建议使用 ML2 插件和 Linux 桥接机制驱动和代理,除非需要与 OpenFlow 控制器集成或使用第三方解决方案或插件。其他 Neutron 技术,如分布式虚拟路由器,仅在使用 Open vSwitch 驱动程序和代理时才可用。
在下一章节中,您将被引导完成创建不同类型网络的过程,以便为实例提供连接。无论是 Linux 桥接环境还是基于 Open vSwitch 的环境,创建网络的过程都是相同的,但基础网络实现会根据使用的驱动程序和代理而有所不同。
第六章:使用 Neutron 构建网络
在第四章,使用 Linux 桥接创建虚拟网络基础设施和 第五章,使用 Open vSwitch 构建虚拟交换基础设施 中,我们构建了一个虚拟交换基础设施,支持本书中讨论的 OpenStack Neutron 网络功能。在本章中,我们将在这个基础上构建网络资源,使其能够被实例使用。
在本章中,我将引导您完成以下任务:
-
使用 CLI 和仪表盘管理网络
-
使用 CLI 和仪表盘管理 IPv4 子网
-
管理子网池
-
创建端口
网络、子网和端口是 Neutron API 的核心资源,在第三章,安装 Neutron 中已介绍。这些核心资源与实例及其他虚拟网络设备之间的关系可以在以下章节中观察到。
OpenStack 中的网络管理
OpenStack 可以通过多种方式进行管理,包括通过 Horizon 仪表盘、Neutron API 和 OpenStack CLI。由 python-openstackclient 包提供的命令行客户端,允许用户从与 Neutron API 接口的 shell 中执行命令。要进入 shell,请在连接到 controller 节点的终端中输入 openstack,如下所示:
root@controller01:~# openstack
(openstack)
openstack shell 提供了自动完成和 help 命令,列出所有可用的命令。也可以直接通过 Linux 命令行使用 openstack 客户端来执行 OpenStack 相关的命令,如下所示:
# openstack network list
# openstack server create
客户端提供了一些命令,帮助创建、修改和删除网络、子网以及端口。
随着时间的推移,openstack 客户端优于 neutron 客户端,但可能没有完全的命令一致性。应尽量减少使用 neutron 客户端。
所有 openstack 客户端命令可以通过使用 --help 标志来查看。本文中将讨论的与网络管理相关的主要命令列在下面的表格中:
| 网络命令 | 描述 |
|---|---|
network create |
创建新的网络 |
network delete |
删除网络 |
network show |
显示网络详细信息 |
network list |
列出网络 |
network set |
设置网络属性 |
network unset |
取消设置网络属性 |
无论您选择基于 Linux 桥接还是 Open vSwitch 的虚拟网络基础设施,创建、修改和删除网络和子网的过程都是相同的。然而,在幕后,将实例和其他资源连接到网络的过程有很大不同。
提供者网络和租户网络
有两类网络可以为实例和其他网络资源提供连接,包括虚拟路由器:
-
提供者网络
-
项目或租户网络,也称为自服务网络
在 Neutron 中创建的每个网络,无论是普通用户还是具有管理员角色的用户创建的,都具有描述该网络的提供者属性。描述网络的属性包括网络类型(如 flat、VLAN、GRE、VXLAN 或 local)、流量经过的物理网络接口以及网络的分段 ID。提供者网络与项目或租户网络之间的区别在于由谁或什么设置这些属性,以及它们在 OpenStack 中是如何管理的。
提供者网络只能由 OpenStack 管理员创建和管理,因为它们需要对物理网络基础设施的了解和配置。
OpenStack 管理员是指与 Keystone 中的 admin 角色相关联的用户。
当创建提供者网络时,管理员必须手动指定该网络的提供者属性。管理员需要对物理网络基础设施有一定的了解,可能还需要配置交换机端口以确保网络的正常运行。提供者网络允许由用户创建的虚拟机实例或虚拟路由器连接到它们。当提供者网络被配置为 Neutron 路由器的外部网络时,该网络被称为 外部提供者网络。提供者网络通常配置为 flat 或 VLAN 网络,并使用外部路由设备来正确地路由云中的流量。
自服务网络与提供者网络不同,由用户创建,通常与云中的其他网络隔离。由于无法配置物理基础设施,租户通常会在需要外部连接时将其网络连接到 Neutron 路由器。租户无法手动指定提供者属性,并且仅能创建管理员在 Neutron 配置文件中预定义的属性的网络。有关 Neutron 路由器配置和使用的更多信息,请参见 第十章,使用 Neutron 创建独立路由器。
在 CLI 中管理网络
要使用 OpenStack 客户端创建网络,请使用下面显示的 network create 命令:

--share 和 --no-share 参数用于分别将网络与所有其他项目共享,或限制网络仅限于拥有项目。默认情况下,网络不会被共享,仅能由拥有项目使用。Neutron 的 RBAC 功能可以用于在部分项目之间共享网络,相关内容将在 第九章 中讨论,基于角色的访问控制。
--enable 和 --disable 参数用于启用或禁用网络的管理状态。
--availability-zone-hint 参数用于定义应该创建网络的可用区。默认情况下,所有网络都放置在一个单一的可用区内,环境中的所有主机预计都具有为网络提供服务的能力。网络可用区是一个高级网络主题,将在第十四章,高级网络主题中涉及。
--enable-port-security 和 --disable-port-security 参数用于启用或禁用在给定网络中创建的任何端口的端口安全性。端口安全性指的是在 Neutron 端口上使用和支持安全组以及 MAC/ARP 过滤,将在第八章,管理安全组中进一步讨论。
--qos-policy 参数用于为网络中创建的任何端口设置 QoS 策略。质量服务扩展的配置和使用是一个高级主题,超出了本书的范围。
--external 和 --internal 参数用于指定网络是作为外部提供商网络(可以作为网关网络或浮动 IP 池使用),还是仅在云内部使用。网络的 router:external 属性的默认值为 false 或 internal。有关 Neutron 路由器的更多信息,请参阅第十章,使用 Neutron 创建独立路由器。
--default 和 --no-default 参数用于指定网络是否应作为云的默认外部网络,并且通常用于 Mitaka 中引入的网络自动分配功能。
Neutron 的网络自动分配功能需要 auto-allocated-topology、router、subnet_allocation 和 external-net 扩展。其中一些默认情况下没有启用。有关这些功能的更多信息,请参阅上游文档,docs.openstack.org/neutron/pike/admin/config-auto-allocation.html。
--provider-network-type 参数定义了正在创建的网络类型。可用的选项包括 flat、VLAN、local、GRE、geneve 和 VXLAN。要使网络类型生效,必须在 ML2 配置文件中启用相应的类型驱动程序,并且由启用的机制驱动程序支持。
--provider-physical-network 参数用于指定将用于通过主机转发流量的网络接口。此处指定的值对应于在 Neutron 代理配置文件中通过 bridge_mappings 或 physical_interface_mappings 选项定义的提供商标签。
--provider-segment参数用于指定与相应网络类型对应的唯一网络 ID。如果你创建的是 VLAN 类型的网络,则使用的值将对应于映射到该网络的 802.1q VLAN ID,并且应通过中继连接到主机。如果你创建的是 GRE 或 VXLAN 网络,则该值应为任意且唯一的整数;这个整数不会被任何其他相同类型的网络使用。该 ID 用于通过 GRE 键或 VXLAN 提供网络隔离。
GRE 和 VXLAN 网络的 VNI 头字段。当未指定provider-segment参数时,插件配置文件中指定的租户范围内会自动分配一个段。用户在创建网络时无法查看或指定段 ID。当项目可用范围内的所有可用 ID 耗尽时,用户将无法再创建此类型的网络。
--tag 和 --no-tag 参数用于为网络添加或移除标签。标签是应用于网络资源的标签,客户端可以使用这些标签进行过滤。
默认情况下,提供者属性只能由 Keystone 中具有管理员角色的用户设置。没有管理员角色的用户只能使用 Neutron 基于 ML2 和代理配置文件中设置的配置提供的值。
在 CLI 中创建平面网络
如果你回顾前面的章节,你会记得平面网络是一个没有进行 802.1q 标签化的网络。
创建平面网络的语法如下:
openstack network create
--provider-network-type flat
--provider-physical-network <provider-physical-network>
<name>
以下是使用 OpenStack 客户端创建名为MyFlatNetwork的平面网络的示例。该网络将使用标记为physnet1的接口或桥接,并将在所有项目之间共享:

在前面的输出中,项目 ID 对应于执行了network create命令的用户所作用的管理员项目。由于网络是共享的,所有项目都可以创建使用MyFlatNetwork网络的实例和网络资源。
尝试使用相同的provider-physical-network名称physnet1创建额外的平面网络将导致错误,如下截图所示:

因为接口上只有一个未标记或本地 VLAN 可用,Neutron 无法创建第二个平面网络,并返回Conflict错误。鉴于这个限制,平面网络很少被使用,VLAN 网络更为常见。
在 CLI 中创建 VLAN 网络
VLAN 网络是 Neutron 将根据 802.1q 分段 ID 对流量进行标记的网络。用于创建 VLAN 网络的语法如下:
openstack network create
--provider-network-type vlan
--provider-physical-network <provider-physical-network>
--provider-segment <provider-segment>
<name>
默认情况下,只有拥有管理员角色的用户才允许指定提供者属性。
在单个提供者接口上最多可以定义 4,096 个 VLAN,尽管其中一些可能会被物理交换平台保留用于内部使用。以下是使用 OpenStack 客户端创建名为 MyVLANNetwork 的 VLAN 网络的示例。
该网络将使用由 physnet1 表示的桥接器或接口,流量将被标记为 VLAN 标识符 300。结果输出如下:

要创建一个使用提供者接口的额外 VLAN 网络,只需指定一个不同的分段 ID。以下示例中,VLAN 301 用于新网络 MyVLANNetwork2。结果输出如下:

使用 VLAN 网络时,不要忘记将物理交换机端口接口配置为 trunk。此配置会因平台不同而有所不同,超出了本书的讨论范围。
在 CLI 中创建本地网络
当一个实例在本地网络上发送流量时,流量将保持在该实例及连接到相同桥接器和/或段的其他接口之间隔离。诸如 DHCP 和元数据之类的服务可能对本地网络中的实例不可用,尤其是当它们位于不同节点上时。
要创建一个本地网络,请使用以下语法:
openstack network create
--provider-network-type local
<name>
使用 Linux 桥接驱动时,会为本地网络创建一个桥接器,但不会添加任何物理或标签接口。流量仅限于连接到桥接器的端口,并不会离开主机。使用 Open vSwitch 驱动时,实例会附加到集成桥接器,并且只能与同一本地 VLAN 中的其他实例进行通信。
在 CLI 中列出网络
要列出 Neutron 所知的网络,请使用 openstack network list 命令,如下图所示:

列表输出提供网络 ID、网络名称以及任何相关的子网。具有管理员角色的 OpenStack 用户可以看到所有网络,而普通用户只能看到共享网络和自己项目中的网络。
如果使用了标签,可以使用以下参数过滤结果:
-
--tags <tag>:列出所有具有指定标签的网络 -
--any-tags <tag>:列出所有具有任意指定标签的网络 -
--not-tags <tag>:排除所有具有指定标签的网络 -
--not-any-tags <tag>:排除所有具有指定标签的网络
在 CLI 中显示网络属性
要显示网络的属性,请使用 openstack network show 命令,如下所示:
openstack network show <network>
前述命令的输出可以在以下截图中看到:

网络的各种属性可以在输出中看到,包括管理状态、默认 MTU、共享状态等。网络提供者属性对普通用户隐藏,只有具有管理员角色的用户才能查看。
在 CLI 中更新网络属性
有时,在网络创建后可能需要更新网络的属性。要更新网络,请使用以下 openstack network set 和 openstack network unset 命令:
openstack network set
[--name <name>]
[--enable | --disable]
[--share | --no-share]
[--description <description]
[--enable-port-security | --disable-port-security]
[--external | --internal]
[--default | --no-default]
[--qos-policy <qos-policy> | --no-qos-policy]
[--tag <tag>] [--no-tag]
<network>
openstack network unset
[--tag <tag> | --all-tag]
<network>
--name 参数可用于更改网络的名称,ID 保持不变。
--enable 和 --disable 参数用于启用或禁用网络的管理状态。
--share 和 --no-share 参数分别用于将网络与所有其他项目共享,或将网络限制为仅限拥有项目使用。其他项目在共享网络中创建端口后,无法撤销该网络的共享状态,直到这些端口被删除。
--enable-port-security 和 --disable-port-security 参数用于启用或禁用从给定网络创建的任何端口上的端口安全性。端口安全性是指在 Neutron 端口上使用和支持安全组及 MAC/ARP 过滤功能,详情请参见 第八章,管理安全组。
--external 和 --internal 参数用于指定网络是否被视为外部提供者网络,该网络可以作为网关网络和浮动 IP 池使用,或者仅在云内部使用。网络的 router:external 属性的默认值为 false,即内部网络。
--default 和 --no-default 参数用于指定网络是否应作为云的默认外部网络。
--qos-policy 参数用于为网络中创建的任何端口设置 QoS 策略。
--tag 参数在与 set 命令一起使用时,会将指定的标签添加到网络上;与 unset 命令一起使用时,则会从网络中移除指定的标签。使用--all-tag与 unset 命令一起使用时,会从网络中移除所有标签。
提供者属性是网络创建后不能更改的属性之一。如果必须在网络创建后更改 segmentation_id 等提供者属性,则必须删除并重新创建网络。
在 CLI 中删除网络
要删除网络,请使用 openstack network delete 命令并指定网络的 ID 或名称:
openstack network delete <network> [<network> ...]
要删除名为MySampleNetwork的网络,可以输入以下命令:
openstack network delete MySampleNetwork
或者,您可以使用网络的 ID:
openstack network delete 3a342db3-f918-4760-972a-cb700d5b6d2c
也可以同时删除多个网络,如下所示:
openstack network delete MySampleNetwork MyOtherSampleNetwork
只要实例、路由器、浮动 IP、负载均衡器虚拟 IP 和其他用户创建的端口所使用的端口被删除,Neutron 将成功删除网络。任何 Neutron 创建的端口(如用于 DHCP 名称空间的端口)将在网络被删除时自动删除。
在仪表盘中创建网络
网络可以在 Horizon 仪表板中创建,但创建方法可能会根据用户角色的不同而有所变化。具有管理员角色的用户可以代表其他项目创建网络并指定提供程序属性,而没有管理员角色的用户只能在各自项目内创建网络,并且具有通过 OpenStack 客户端可用的相同功能。两种方法将在以下章节中描述。
通过项目面板
用户可以通过仪表板中的项目标签页使用向导创建网络。要创建网络,请以演示项目中的用户身份登录并执行以下步骤:
- 导航到 项目 | 网络 | 网络:

在前面的截图中,注意到当前定义的网络旁边没有可用的操作。即使这些网络是共享的,用户也不能修改它们,只有管理员才能进行修改。
- 点击屏幕右上角的“创建网络”按钮。一个窗口将出现,允许你指定网络属性:

- 在网络标签页中,你可以定义网络名称和管理状态(开启或关闭)。在仪表板中创建网络时,用户不需要在创建网络时创建子网。通过取消选中子网标签页中的“创建子网”复选框,可以完成网络创建过程:

本章后面将解释如何在仪表板中创建子网。
通过管理员面板
具有管理员角色的用户将在仪表板中看到额外的功能。仪表板左侧将显示管理员面板,允许管理员角色的用户操作其项目外的网络。作为云管理员在仪表板中创建网络时,请以管理员用户身份登录并执行以下步骤:
- 导航到 管理 | 网络 | 网络:

- 点击屏幕右上角的“创建网络”。一个向导将出现,允许你指定网络属性:

可以通过向导设置各种网络属性,包括网络类型、接口和分段 ID(如果适用)。其他选项包括将网络与项目关联、设置管理状态、启用共享、创建子网以及启用将网络用作 Neutron 路由器的外部网络。完成后,点击“创建网络”按钮以创建网络。
OpenStack 中的子网管理
在 Neutron 中,子网是一个第 3 层对象,可以是使用无类域间路由(CIDR)表示法定义的 IPv4 或 IPv6 地址块。CIDR 是一种使用可变长度子网掩码(VLSM)分配 IP 地址的方法。子网与网络有直接关系,不能独立存在。
更多关于 CIDR 和 VLSM 的信息可以在 Wikipedia 上找到:en.wikipedia.org/wiki/Classless_Inter-Domain_Routing。
本章将讨论与子网管理相关的主要命令,列在以下表格中:
| 子网命令 | 描述 |
|---|---|
subnet create |
创建子网 |
subnet delete |
删除子网 |
subnet show |
显示子网详细信息 |
subnet list |
列出子网 |
subnet set |
设置子网属性 |
subnet unset |
取消设置子网属性 |
subnet pool create |
创建子网池 |
subnet pool delete |
删除子网池 |
subnet pool list |
列出子网池 |
subnet pool set |
设置子网池属性 |
subnet pool show |
显示子网池详细信息 |
subnet pool unset |
取消设置子网池属性 |
使用 IPv4 地址
以下是几个使用 CIDR 表示法描述的 IPv4 地址和子网的示例:
-
192.168.100.50/24表示 IP 地址192.168.100.50,其关联的路由前缀为192.168.100.0,子网掩码为255.255.255.0(即,24 个“1”位)。/24 的总地址数为 256 个,其中 254 个地址可用于使用。 -
172.16.1.200/23表示 IP 地址172.16.0.200,其关联的路由前缀为172.16.0.0,子网掩码为255.255.254.0(即,23 个“1”位)。/23 的总地址数为 512 个,其中 510 个地址可用于使用。 -
10.0.10.4/22表示 IP 地址10.0.10.4,其关联的路由前缀为10.0.8.0,子网掩码为255.255.252.0(即,22 个“1”位)。/22 的总地址数为 1,024 个,其中 1,022 个地址可用于使用。
并非每个子网中的地址都可用,因为第一个和最后一个地址通常分别被保留为网络地址和广播地址。因此,Neutron 不会将子网的第一个或最后一个地址分配给网络资源,包括实例。使用以下公式来确定在设计网络时子网中可用的总地址数。x 变量代表子网掩码中可用的主机位数:
2ˆx-2 = number of useable addresses in a subnet
请记住,在创建子网时,提前规划非常重要,因为子网掩码或 CIDR 当前不是可更新的属性。当实例和其他资源消耗了子网中所有可用的 IP 地址时,设备将无法再添加到网络中。为了解决这个问题,需要创建一个新的子网并将其添加到现有网络中,或者需要创建一个全新的网络和子网。根据您的网络基础设施,这可能不是一个容易实现的变更。
VLSM 和 CIDR 在为 OpenStack 云设计网络时非常重要,并将在本章稍后讨论子网池的使用时发挥更重要的作用。
使用 IPv6 地址
IPv6 是 OpenStack 网络中的一等公民,但它是一个高级主题,本章将不讨论该内容。此处描述的所有与子网相关的命令在定义 IPv6 子网时行为类似,但可能需要额外的参数。
有关 Pike 中 IPv6 的更多信息,请参阅上游文档:docs.openstack.org/neutron/pike/admin/config-ipv6.html。
在 CLI 中创建子网
使用 OpenStack 客户端创建子网时,使用subnet create命令,如下所示:

--project 参数指定子网应与之关联的项目 ID,仅限具有管理员角色的用户使用。此项目应与父网络关联的项目相同。
--project-domain 参数指定子网应与之关联的项目域 ID,仅限具有管理员角色的用户使用(此功能不常用)。
--subnet-pool 参数指定子网将从中获取 CIDR 的池。
--use-default-subnet-pool 参数指示 Neutron 选择默认子网池以获取 CIDR。使用此参数需要首先创建至少一个子网池。
--prefix-length 参数指定从子网池分配子网时的前缀长度。
--subnet-range 参数指定要创建的子网的 CIDR 表示法。除非子网与子网池关联,否则此选项是必需的。
--dhcp 和 --no-dhcp 参数分别启用或禁用子网的 DHCP 服务。默认情况下,启用 DHCP。
网络操作不要求使用 DHCP。禁用 DHCP 仅意味着附加到子网的实例将不使用 DHCP 进行动态接口配置。相反,接口将需要手动配置或通过实例本身中的脚本或其他方法进行配置。无论 DHCP 是否启用,实例仍会在分配池范围内分配 IP 地址。
--gateway 参数定义了子网的网关地址。三个可选项包括 auto、none 或用户选择的 IP 地址。当子网连接到 Neutron 路由器的实例端时,路由器的接口将使用此处指定的地址进行配置。然后,该地址将作为子网中实例的默认网关。如果子网连接到 Neutron 路由器的外部端,则该地址用作路由器本身的默认网关。要查看此行为的实际效果,请参考 第十章**,使用 Neutron 创建独立路由器*。如果未指定网关,Neutron 将默认为 auto 并使用子网中的第一个可用地址。
--ip-version 参数指定了子网所表示的 IP 协议版本。可选项是 4(IPv4)和 6(IPv6)。默认值为 4。
--ipv6-ra-mode 参数定义了当使用 IPv6 时子网的路由器广告模式。可选项包括 dhcpv6-stateful、dhcpv6-stateless 和 slaac。
--ipv6-address-mode 参数定义了当使用 IPv6 时子网的地址模式。可选项包括 dhcpv6-stateful、dhcpv6-stateless 和 slaac。
不是所有的 ipv6-ra-mode 和 ipv6-address-mode 参数组合都是有效的。要查看有效和无效的用例,请参考 API 指南 docs.openstack.org/neutron/pike/admin/config-ipv6.html。有关 IPv6 的更多信息,请参阅附录。
--network-segment 参数指定了要与子网关联的网络段。
--network 参数指定了子网应关联的网络。多个子网可以与同一网络关联,只要子网范围不与同一网络中的其他子网重叠。
--allocation-pool 参数指定了子网中可以分配给端口的 IP 地址范围。IP 地址不能从单一范围中排除。然而,可以定义多个分配池来排除某些地址。例如,要从 192.168.1.0/24 中排除 192.168.1.50-55,需要使用以下语法:
openstack subnet create MyFlatNetwork
--subnet-range 192.168.1.0/24
--allocation-pool start=192.168.1.2,end=192.168.1.49
--allocation-pool start=192.168.1.56,end=192.168.1.254
根据使用的网络类型,OpenStack 外部的设备可以与同一网络和子网中的实例共存。应定义分配池,以确保分配给实例的地址与 OpenStack 云外的设备不重叠。
--dns-nameserver 参数指定了子网的 DNS 名称服务器。此选项可以重复,以设置多个名称服务器。然而,默认情况下,每个子网的最大名称服务器数为五个,可以通过更新 /etc/neutron/neutron.conf 文件中的 max_dns_nameservers 配置选项来修改此值。
--host-route参数指定一个或多个静态路由,这些路由定义为目的地和下一跳对,并通过 DHCP 注入到实例的路由表中。此选项可以多次使用以指定多个路由。每个子网的默认最大路由数为 20,可以通过更新/etc/neutron/neutron.conf文件中的max_subnet_host_routes配置选项来修改此限制。
--tag和--no-tag参数用于将标签应用于子网或移除标签。标签是应用于网络资源的标记,客户端可以利用这些标签进行过滤。
名称参数指定子网的名称。虽然可以创建多个同名的子网,但建议子网名称保持唯一,以便于识别。
在 CLI 中创建子网
要展示此命令的操作效果,可以在MyFlatNetwork网络中创建一个具有以下特征的子网:
-
名称:
MyFlatSubnet -
网络协议:
IPv4 -
子网:
192.168.100.0/24 -
子网掩码:
255.255.255.0 -
外部网关:
192.168.100.1 -
DNS 服务器:
8.8.8.8, 8.8.4.4
要创建子网并将其与MyFlatNetwork关联,请参考以下截图:

在 CLI 中列出子网
要列出现有子网,请使用openstack subnet list命令,如下所示:

默认情况下,命令输出提供每个可用子网的 ID、名称、CIDR 表示法以及关联的网络。具有管理员角色的用户可以看到所有子网,而普通用户则仅能看到他们所在项目的子网或与共享网络关联的子网。openstack subnet list命令也支持过滤器,用于缩小返回结果的范围。
如果使用了标签,可以使用以下参数对结果进行过滤:
-
--tags <tag>:列出所有具有指定标签的子网 -
--any-tags <tag>:列出所有具有任何指定标签的子网 -
--not-tags <tag>:排除所有具有指定标签的子网 -
--not-any-tags <tag>:排除所有具有任何指定标签的子网
通过使用-h或--help选项,可以查看更多详细信息。
在 CLI 中显示子网属性
要显示子网的属性,请使用openstack subnet show命令,如下所示:
openstack subnet show <subnet>
前述命令的输出可以在以下截图中查看:

在 CLI 中更新子网
要在 CLI 中更新子网,请使用openstack subnet set和openstack subnet unset命令,具体如下:
openstack subnet set
[--name <name>] [--dhcp | --no-dhcp]
[--gateway <gateway>]
[--description <description>] [--tag <tag>]
[--no-tag]
[--allocation-pool start=<ip-address>,end=<ip-address>]
[--no-allocation-pool]
[--dns-nameserver <dns-nameserver>]
[--no-dns-nameservers]
[--host-route destination=<subnet>,gateway=<ip-address>]
[--no-host-route] [--service-type <service-type>]
<subnet>
openstack subnet unset
[--allocation-pool start=<ip-address>,end=<ip-address>]
[--dns-nameserver <dns-nameserver>]
[--host-route destination=<subnet>,gateway=<ip-address>]
[--service-type <service-type>]
[--tag <tag> | --all-tag]
<subnet>
--name参数指定子网更新后的名称。
--dhcp和--no-dhcp参数分别用于启用或禁用子网的 DHCP 服务。
依赖 DHCP 来获取或续订 IP 地址租约的实例,如果 DHCP 被禁用,可能会随着时间的推移失去网络连接。
--gateway 参数定义了子网的网关地址。更新子网时的两个可能选项包括无网关或用户选择的 IP 地址。
--tag 参数与 set 命令一起使用时,将指定的标签添加到子网中。与 unset 命令一起使用时,指定的标签将从子网中移除。使用 --all-tag 和 unset 命令一起使用时,将移除子网中的所有标签。
--allocation-pool 参数与 set 命令一起使用时,将指定的池添加到子网中。与 unset 命令一起使用时,指定的池将从子网中移除。
--dns-nameserver 参数与 set 命令一起使用时,将指定的 DNS 名称服务器添加到子网中。与 unset 命令一起使用时,指定的 DNS 名称服务器将从子网中移除。使用 --no-name-servers 将移除子网中的所有 DNS 名称服务器。
--host-route 参数与 set 命令一起使用时,将添加使用目标和下一跳对定义的指定静态路由。与 unset 命令一起使用时,将移除指定的路由。使用 --no-host-route 和 set 命令一起使用时,将从子网中移除所有主机路由。
subnet 参数指定正在修改的子网的名称。
在仪表盘中创建子网
子网可以在 Horizon 仪表盘中创建,但具体的方法可能根据用户的角色而有所不同。具有管理员角色的用户能够代表其他项目创建子网并指定一些普通用户无法使用的其他属性。没有管理员角色的用户只能在各自的项目中创建子网,并且具有通过 OpenStack 客户端可以使用的相同功能。以下章节将介绍这两种方法。
通过“项目”标签
用户可以通过仪表盘中的“项目”标签中的向导在创建网络时创建子网。他们还可以向现有网络添加新的子网。要创建网络和子网,登录为演示项目中的用户并执行以下步骤:
- 导航到“项目”|“网络”|“网络”并点击“创建网络”按钮:

- 点击“创建网络”将打开一个窗口,在该窗口中你可以指定网络和子网的详细信息:

- 点击“子网”标签或“下一步”按钮将引导你到一个面板,在该面板中可以定义子网的详细信息,包括名称、网络地址和网关信息:

- 最后,点击“子网详情”或“下一步”将引导你到一个面板,在该面板中可以定义其他子网详细信息,包括分配池、DNS 名称服务器和主机路由。输入这里显示的详细信息,并点击蓝色的“创建”按钮来完成网络和子网的创建:

在“操作”列下的菜单中提供了添加额外子网或完全删除网络的功能,如下图所示:

通过 Admin 标签
拥有管理员角色的用户会注意到仪表盘中提供了额外的功能。仪表盘左侧可以看到一个管理员面板,允许管理员角色的用户在其各自项目外部操作子网。
作为云管理员,在仪表盘中创建子网时,请以管理员用户身份登录并执行以下步骤:
- 导航至 Admin | Network | Networks,然后点击您希望添加子网的网络名称:

- 点击 MyVLANNetwork 会列出该网络的详细信息,包括关联的子网和端口,它们分别显示在不同的面板中:

- 要向网络添加子网,请点击子网选项卡,并在右侧点击创建子网按钮:

- 会弹出一个向导,允许您定义新子网的属性:

- 点击“下一步”可以显示更多配置选项:

- 点击蓝色的创建按钮,完成子网的创建。子网面板将相应更新:

管理子网池
子网池在 OpenStack 的 Kilo 版本中引入,它允许 Neutron 在创建子网时控制 IP 地址空间的分配。用户可以创建仅供其各自项目使用的子网池,或者管理员可以创建一个在多个项目之间共享的子网池。使用子网池有助于确保子网之间没有 IP 地址重叠,并使用户创建子网更加便捷。子网池非常适合与 Neutron 路由器连接的自服务网络,并且在已实现地址范围和 Neutron 的 BGP Speaker 功能的情况下非常理想。
BGP 代表边界网关协议(Border Gateway Protocol),是一种动态路由协议,用于在互联网上或自治系统内部路由流量。如需了解 Neutron 中 BGP Speaker 功能的更多信息,请参考上游文档,网址为 docs.openstack.org/neutron/pike/admin/config-bgp-dynamic-routing.html。
创建子网池
创建子网池时,至少需要以下信息:
-
子网池前缀采用 CIDR 表示法
-
子网池名称
可以根据您的环境提供其他信息,并可使用 openstack subnet pool create -h 命令来确定。
为了演示此命令的实际操作,请创建一个具有以下特征的子网池:
-
名称:
MySubnetPool -
子网池 CIDR:
172.31.0.0/16
要创建子网池,请参考以下截图:

子网池MySubnetPool现在可供使用,但只能由创建它的项目使用,因为shared为False。
默认前缀长度为 8,这不是理想设置,如果用户在创建子网时没有指定前缀长度,将会导致问题。强烈建议在创建子网池时设置默认前缀长度。
从池中创建子网
要从子网池MySubnetPool创建子网,请使用带有--subnet-pool参数的openstack subnet create命令。为了演示此命令的实际操作,请创建一个具有以下特征的子网:
-
名称:
MySubnetFromPool -
网络:
MyVLANNetwork2 -
前缀长度:
28
要创建子网,请参考以下截图:

如上图所示,子网的 CIDR 是从提供的子网池中划分出来的,所有其他属性都由 Neutron 自动确定。
在撰写本书时,以下错误可能会限制在创建子网时提供前缀长度时使用 OpenStack 客户端:bugs.launchpad.net/python-openstacksdk/+bug/1754062。如果发生错误,请尝试改用 Neutron 客户端。
删除子网池
要删除子网池,请使用openstack subnet pool delete命令,如下所示:
openstack subnet pool delete <subnet-pool> [<subnet-pool> ...]
可以同时删除多个子网池。必须先删除引用子网池的现有子网,才能删除该子网池。
分配默认子网池
可以定义一个默认的子网池,允许用户在不指定前缀或子网池的情况下创建子网。在创建子网时,使用--default-prefix-length和--default参数,将子网池设置为特定网络的默认池。子网池也可以通过使用相同的参数进行更新,成为默认子网池。
以下命令演示了将MySubnetPool设置为默认子网池:
# openstack subnet pool set --default MySubnetPool
成功执行前述命令后没有返回任何输出。
以下截图演示了使用默认子网池创建新子网:

如您所见,Neutron 自动从默认子网池中划分了一个/28 子网,并且在没有用户干预的情况下设置了基本属性。该子网现在可以附加到 Neutron 路由器上供实例使用。
在 OpenStack 中管理网络端口
在 Neutron 中,端口是虚拟网络接口与子网和网络之间的逻辑连接。端口可以与虚拟机实例、DHCP 服务器、路由器、防火墙、负载均衡器等关联。端口甚至可以仅为从子网中保留 IP 地址而创建。Neutron 将端口关系存储在 Neutron 数据库中,并通过网络插件和代理使用这些信息在物理或虚拟交换机层构建交换连接。
与端口管理相关的主要命令列在下表中:
| 端口命令 | 描述 |
|---|---|
port create |
创建新端口 |
port delete |
删除端口 |
port list |
列出端口 |
port set |
设置端口属性 |
port show |
显示端口详细信息 |
port unset |
取消端口属性 |
当在 OpenStack 中创建端口并与实例或其他虚拟网络设备关联时,它会绑定到托管实例或设备的相应节点上的 Neutron 代理。利用端口提供的详细信息,OpenStack 服务可以在主机上构建虚拟机接口(vif)或虚拟以太网接口(veth),以供虚拟机、网络命名空间或其他应用使用。
要检索所有 Neutron 端口的列表,请使用 openstack port list 命令,如下图所示:

具有管理员角色的用户将看到 Neutron 知道的所有端口,而普通用户仅能看到与其相应项目相关联的端口。
如果使用了标签,可以使用以下参数过滤结果:
-
--tags <tag>:列出所有具有给定标签的端口 -
--any-tags <tag>:列出具有任何给定标签的端口 -
--not-tags <tag>:排除具有所有给定标签的端口 -
--not-any-tags <tag>:排除具有任何给定标签的端口
使用 openstack port show 命令查看特定端口的详细信息:

上述截图中的端口属于一个接口,该接口在 DHCP 命名空间中使用,device_owner 为 network:dhcp。network_id 字段显示该网络为 d51943ef-8061-4bdb-b684-8a7d2b7ce73b,即我们在本章前面创建的 MyFlatNetwork 网络。
我们可以使用 ip netns exec 命令在 DHCP 命名空间内执行命令。如果你还记得,DHCP 命名空间可以通过前缀 qdhcp- 和相应的网络 ID 后缀来标识。在 controller01 节点上,运行 ip addr 命令以列出其接口及其详细信息:

在 DHCP 命名空间中,接口的 MAC 地址与端口的 mac_address 字段相对应,而接口的名称与 Neutron 端口的 UUID 的前 10 个字符相对应:

创建端口
通过手动创建 Neutron 端口,用户可以指定特定的固定 IP 地址、MAC 地址、安全组等。
要创建端口,请使用 openstack port create 命令,如下所示:
openstack port create
--network <network> [--description <description>]
[--device <device-id>]
[--mac-address <mac-address>]
[--device-owner <device-owner>]
[--vnic-type <vnic-type>] [--host <host-id>]
[--dns-name dns-name]
[--fixed-ip subnet=<subnet>,ip-address=<ip-address>]
[--binding-profile <binding-profile>]
[--enable | --disable] [--project <project>]
[--project-domain <project-domain>]
[--security-group <security-group> | --no-security-group]
[--qos-policy <qos-policy>]
[--enable-port-security | --disable-port-security]
[--allowed-address ip-address=<ip>[,mac-address=<mac>]]
[--tag <tag> | --no-tag]
<name>
创建后,端口可以与虚拟机实例或其他虚拟网络设备关联。它还可以用于在子网中保留一个 IP 地址。在下一章中,我们将探索多种方法来创建端口并将其与实例关联。
总结
本章为创建可供实例和其他虚拟及物理设备使用的网络和子网奠定了基础。可以使用 Horizon 仪表板和 OpenStack 命令行客户端来管理网络、子网和端口,但建议使用后者进行大多数管理任务。
有关网络、子网和端口属性的更多信息,以及如何使用 Neutron API 的指南,请参阅 OpenStack 维基:developer.openstack.org/api-ref/network/v2/index.html。
在下一章,我们将学习创建实例并将其附加到网络的基础知识。本章中构建的一些网络将用于演示创建端口的过程,这些端口可以与实例连接,最终目标是实现端到端的连接。
第七章:将实例附加到网络
在 第六章,使用 Neutron 构建网络 中,我们创建了多个可供云中项目使用的网络。在本章中,我们将创建居住在这些网络中的实例。
我将引导你完成以下任务:
-
创建并将实例附加到网络
-
向实例添加额外接口
-
演示 DHCP 和元数据服务
将实例附加到网络
使用 OpenStack 命令行客户端,实例可以通过几种方式附加到网络。实例首次创建时,可以通过 openstack server create 命令将其附加到一个或多个网络。正在运行的实例可以通过 openstack server add port 命令附加到更多的网络。以下章节将解释这两种方法。
如果你在跟着教程做,前几章中创建的网络都已被销毁并重新创建,名称和分段 ID 类似,但具有新的 ID 号。
在创建时将实例附加到网络
实例是通过 openstack server create 命令创建的,如下所示:
openstack server create
(--image <image> | --volume <volume>) --flavor <flavor>
[--security-group <security-group>]
[--key-name <key-name>]
[--property <key=value>]
[--file <dest-filename=source-filename>]
[--user-data <user-data>]
[--availability-zone <zone-name>]
[--block-device-mapping <dev-name=mapping>]
[--nic <net-id=net-uuid,v4-fixed-ip=ip-addr,v6-fixed-ip=ip-addr,port-id=port-uuid,auto,none>]
[--network <network>] [--port <port>]
[--hint <key=value>]
[--config-drive <config-drive-volume> | True]
[--min <count>] [--max <count>] [--wait]
<server-name>
Nova 通过实例的虚拟接口(VIF)将实例连接到 compute 节点上的虚拟桥接器和交换机。每个 VIF 在数据库中都有一个对应的 Neutron 端口。
当使用 Open vSwitch 机制驱动程序和 Open vSwitch 防火墙驱动程序时,每个 VIF 插入到各自 compute 节点上的集成桥接器中。虚拟交换机端口会配置一个本地 VLAN ID,与 Neutron 端口和 VIF 关联的网络相对应。当使用 iptables_hybrid 防火墙驱动程序时,VIF 会连接到一个 Linux 桥接器,iptables 规则会应用于该桥接器。
当使用 Linux 桥接机制驱动程序时,每个 VIF 会连接到一个与关联网络相对应的 Linux 桥接器。每个网络都有一个相应的桥接器,用于在第二层隔离流量。
如果你需要复习这些概念,请参考 第四章,使用 Linux 桥接构建虚拟交换基础设施,以及 第五章,使用 Open vSwitch 构建虚拟交换基础设施。
指定网络
openstack server create 命令提供了 --nic 参数,用于指定要附加到实例的网络或端口。
用户可以通过使用 net-id 键,指定由网络 ID 标识的网络:
--nic net-id=<Network ID>
在前面的例子中,Nova 与 Neutron API 交互,通过用户提供的网络 ID 创建端口。然后,Neutron 将端口的详细信息返回给 Nova,供实例使用。用户可以分别使用v4-fixed-ip和v6-fixed-ip键请求特定的未使用 IPv4 或 IPv6 地址,如下所示:
--nic net-id=<Network ID>,v4-fixed-ip=<ipv4 address>
--nic net-id=<Network ID>,v6-fixed-ip=<ipv6 address>
指定端口
用户还可以使用 port-id 键,通过端口 ID 指定一个已经识别的端口,如下所示:
--nic port-id=<Port ID>
在此示例中,Neutron 将现有端口与实例关联,并相应地设置该端口的device_id属性。以后可以使用这种方法将端口从实例中分离,并将其与新实例关联。可选项包括 auto、none 或现有端口的 ID。默认值为 auto。
附加多个接口
通过多次传递--nic参数,可以将多个网络接口附加到实例。实例中的接口随后可以按eth0、eth1、eth2等方式进行枚举,这取决于操作系统。
向实例附加多个网络接口被称为多宿主。当一个实例是多宿主时,Neutron 或实例本身无法知道哪个网络优先于另一个。当附加的网络和子网有各自的网关地址时,实例的路由表可能会填充多个默认路由。这种情况可能会对实例的连接性和路由行为造成严重影响。此配置在直接将实例连接到多个网络时非常有用,但在这种设计中应注意避免网络问题。
使用 virtio 驱动的网络和存储设备等准虚拟化设备是 PCI 设备。KVM 下的虚拟机实例当前限制为最多 32 个 PCI 设备。一些 PCI 设备对操作至关重要,包括主机桥、ISA/USB 桥、显卡和内存气球设备,因此最多可以使用 28 个 PCI 插槽。每个准虚拟化的网络或块设备使用一个插槽。这意味着用户在尝试将多达 20-25 个网络连接到实例时,可能会遇到问题,这取决于该实例的特性。
以下openstack server create命令演示了在创建实例时将实例连接到多个网络的基本过程:
openstack server create --flavor FLAVOR --image IMAGE \
--nic net-id=NETWORK1 \
--nic net-id=NETWORK2 \
--nic net-id=NETWORK3 \
<SERVER-NAME>
在实例内部,第一张附加的网络接口卡(NIC)对应NETWORK1,第二张网络接口卡对应NETWORK2,依此类推。对于许多支持云的镜像,实例中的单一网络接口会通过 DHCP 自动上线。一旦实例启动,可能需要修改网络接口文件或在实例内使用dhclient命令来激活并配置其他网络接口。
向运行中的实例附加网络接口
使用openstack server add port或openstack server add fixed ip命令,可以将现有端口或新端口附加到运行中的实例。
openstack server add port命令可以如下使用:
openstack server add port <server> <port>
port 参数指定要附加到给定服务器的端口。该端口必须是当前未与任何其他实例或资源关联的端口,否则操作将失败。
openstack server add fixed ip命令可以如下使用:
openstack server add fixed ip
[--fixed-ip-address <ip-address>]
<server> <network>
网络参数指定要附加到给定服务器的网络。将自动创建一个具有唯一 MAC 地址和来自指定网络的 IP 地址的新端口。
--fixed-ip-address 参数可用于指定给定网络中的特定 IP 地址,而不是依赖 Neutron 的自动分配。
虽然可以使用热插拔技术将额外的网络接口添加到运行中的实例,但这些接口可能需要在操作系统中进行配置才能使用。您可以使用 dhclient 命令通过 DHCP 配置新连接的接口,或手动配置接口文件。
分离网络接口
要从实例中分离接口,使用 openstack server remove port 或 openstack server remove fixed ip 命令,如下所示:
openstack server remove port <server> <port>
openstack server remove fixed ip <server> <ip-address>
从实例中分离的接口将完全从 Neutron 端口数据库中移除。
从正在运行的实例中移除接口时需要小心,因为这可能导致实例内出现意外行为。
探索实例如何获取其地址
当创建网络并在子网中启用 DHCP 时,该网络将调度到环境中的一个或多个 DHCP 代理。在大多数环境中,DHCP 代理配置在 controllers 或专用的 network 节点上。在更高级的环境中,如使用网络段和叶/脊拓扑的环境中,DHCP 代理可能需要配置在 compute 节点上。
DHCP 代理负责为每个已调度到该代理的网络创建一个本地网络命名空间。然后,在命名空间内的虚拟接口上配置一个 IP 地址,并运行一个 dnsmasq 进程,监听网络上的 DHCP 请求。如果网络上已有一个 dnsmasq 进程并且添加了新子网,则会更新现有进程以支持该子网。
当子网未启用 DHCP 时,dnsmasq 进程不会启动。尽管如此,IP 地址仍然与实例内接口对应的 Neutron 端口关联。然而,在没有 DHCP 服务的情况下,用户必须通过控制台连接手动配置客户操作系统中接口的 IP 地址。
大多数实例依赖 DHCP 获取关联的 IP 地址。DHCP 遵循以下阶段:
-
DHCP 客户端发送一个
DHCPDISCOVER广播包,请求 DHCP 服务器提供 IP 信息。 -
DHCP 服务器响应请求,发送一个
DHCPOFFER包。该包包含发出请求的实例的 MAC 地址、IP 地址、子网掩码、租期和 DHCP 服务器的 IP 地址。一个 Neutron 网络可以同时调度到多个 DHCP 代理,每个 DHCP 服务器都可能响应一个DHCPOFFER包。然而,客户端只会接受第一个响应。 -
响应提供时,DHCP 客户端会向 DHCP 服务器发送一个
DHCPREQUEST数据包,申请所提供的地址。 -
响应请求时,DHCP 服务器会向实例发出一个
DHCPACK数据包或确认数据包。此时,IP 配置已完成。DHCP 服务器还会向实例发送其他 DHCP 选项,例如名称服务器、路由等。
与 DHCP 服务器相关联的网络命名空间以qdhcp为前缀,后跟完整的网络 ID。DHCP 命名空间仅存在于运行neutron-dhcp-agent服务的主机上。即便如此,网络必须被调度到 DHCP 代理上,才能在该主机上创建命名空间。在此示例中,DHCP 代理运行在controller01节点上。
要查看controller01节点上的命名空间列表,请使用如下命令:ip netns list

输出中列出的两个命名空间直接对应于存在子网并启用 DHCP 的两个网络:

在qdhcp命名空间内存在一个接口,用于连接命名空间和虚拟网络基础设施,适用于网络MyVLANNetwork:

在命名空间内的接口ns-6c15d7b8-87是veth接口的一个端点。分配给ns-6c15d7b8-87接口的 IP 地址192.168.206.2/24已由 Neutron 自动分配,并从子网的分配池中获取。
使用 Linux 桥接驱动时,接口的另一端,即对端,连接到与网络对应的桥接,并由tap6c15d7b8-87接口表示,如下截图所示:

在前面的截图中,标签为brq7745a4a9-68的桥接网络对应于网络MyFlatNetwork,通过连接到桥接的untagged接口eth2可以看出。接口tapd1848f67-2e是veth接口的另一端,连接到网络MyFlatNetwork的 DHCP 命名空间。
观察 DHCP 租约周期
在此示例中,将创建一个具有以下特征的实例:
-
名称:
TestInstance1 -
Flavor:
tiny -
镜像:
cirros-0.4.0 -
网络:
MyVLANNetwork -
计算节点:
compute01
创建实例的命令如下:
openstack server create \
--image cirros-0.4.0 \
--flavor tiny \
--nic net-id=MyVLANNetwork \
--availability-zone nova:compute01 \
TestInstance1
可能在你的环境中没有tiny flavor,但可以创建并定义其配置为 1 vCPU、1 MB 内存和 1 GB 硬盘。
要观察实例请求 DHCP 租约,可以使用以下命令在与实例网络对应的 DHCP 网络命名空间内启动数据包捕获:
ip netns exec <namespace> tcpdump -i any -ne port 67 or port 68
当实例启动时,它会发送广播数据包,DHCP 服务器将在命名空间内对其进行响应:

在前面的截图中,可以观察到 DHCP 租约周期的所有四个阶段。通过在compute节点的实例 tap 接口上执行捕获,也可以观察到类似的输出:

使用dhcpdump工具,我们可以观察到更详细的 DHCP 租约周期输出。要安装dhcpdump,在所有节点上执行以下命令:
# apt install dhcpdump
在托管MyVLANNetwork网络的 DHCP 服务器的网络命名空间内,运行dhcpdump,如下所示:
root@controller01:~# ip netns exec qdhcp-03327707-c369-4bd7-bd71-a42d9bcf49b8 dhcpdump -i ns-6c15d7b8-87
当客户端发出初始 DHCP 请求时,你将看到一个DHCPDISCOVER广播包:

然后,DHCP服务器将直接向实例发送一个DHCPOFFER单播包:

接下来,客户端将发送一个DHCPREQUEST广播包:

最后,DHCP 服务器将通过一个DHCPACK单播包确认请求:

排查 DHCP 问题
如果实例无法从 DHCP 获取其地址,可能有助于从网络中的不同位置进行数据包捕获,以查看请求或回复失败的原因。
使用tcpdump或dhcpdump,可以从以下位置捕获在 UDP 端口67和68上的 DHCP 请求和响应数据包:
-
在 DHCP 命名空间内
-
在
network和/或compute节点的物理接口上 -
在实例的 tap 接口上
-
通过控制台在客户操作系统中
一旦识别出负责丢包的节点或接口,可能需要进一步调查。
探索实例如何检索其元数据
在第三章,《安装 Neutron》中,我们简要介绍了实例通过网络访问元数据的过程:通过路由器命名空间或 DHCP 命名空间的代理。后者将在以下部分中描述。
DHCP 命名空间
实例通过169.254.169.254访问元数据,后跟与元数据版本对应的 URI,通常是/latest。当实例连接到不使用 Neutron 路由器作为网关的网络时,实例必须学会如何访问元数据服务。可以通过以下几种方式来实现:
-
在实例上手动设置路由
-
允许 DHCP 提供路由
当在 DHCP 配置文件/etc/neutron/dhcp_agent.ini中将enable_isolated_metadata设置为True时,每个 DHCP 命名空间会为运行在controller节点上的元数据服务提供代理。代理服务直接在端口80上监听,如下图所示:

在命名空间中使用ps命令,您可以看到与此监听器相关的进程是 Neutron 元数据代理:

添加到 169.254.169.254 的手动路由
在实例能够到达位于169.254.169.254的 DHCP 命名空间中的元数据服务之前,必须配置一条路由,使用 DHCP 命名空间接口作为下一跳,而不是实例的默认网关。
观察以下 DHCP 命名空间中的 IP 地址:

169.254.169.254/16已自动配置为命名空间内部接口的二级地址。要从192.168.206.0/24网络中的实例访问169.254.169.254,可以在来宾实例中使用以下ip route命令,设置192.168.206.2为下一跳:
# ip route add 169.254.169.254/32 via 192.168.206.2
虽然这种方法可行,但将路由添加到每个实例的过程并不具有良好的扩展性,特别是当环境中存在多个 DHCP 代理时。一个网络可以调度到多个代理,而这些代理又有各自的命名空间和 IP 地址,且都在同一子网中。用户需要提前了解在其路由语句中使用的 IP 地址,而且该地址可能会发生变化。允许 DHCP 自动注入路由是推荐的方法,下一节将讨论这种方法。
使用 DHCP 注入路由
当enable_isolated_metadata设置为True并且子网的网关未设置或不是 Neutron 路由器时,DHCP 服务能够通过无类静态路由 DHCP 选项(也称为选项 121)注入到元数据服务的路由。
包括 Neutron 在内的多种任务所使用的可能 DHCP 选项,可以在 IANA 网站的以下 URL 找到:www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml。
一旦创建了连接到具有上述特征的子网的实例,观察通过 DHCP 传递给实例的以下路由:

元数据路由的下一跳地址是响应客户端初始 DHCP 请求的 DHCP 服务器的 IP 地址。如果环境中有多个 DHCP 代理并且相同的网络被调度到它们所有人,那么每个实例的下一跳地址可能会有所不同,因为任何一个 DHCP 服务器都可能响应该请求。
概述
在本章中,我演示了如何将实例连接到网络,并阐述了实例从 OpenStack 管理的 DHCP 服务器获取其 IP 地址的过程。我还向您展示了当实例连接到 VLAN 提供商网络时,如何访问元数据服务。本章中的相同示例可以应用于任何最近的 OpenStack 云以及许多不同的网络拓扑。
有关基于提供者网络的部署场景的更多详细信息,请参阅以下 OpenStack Pike 版本的上游文档,位置如下:
Open vSwitch:docs.openstack.org/neutron/pike/admin/deploy-ovs-provider.html
Linux 桥接:
docs.openstack.org/neutron/pike/admin/deploy-lb-provider.html
在下一章中,我们将学习如何利用 Neutron 安全组功能为实例提供网络级安全。
第八章:管理安全组
OpenStack 网络提供了两种不同的 API,用于实现网络流量过滤器。第一种 API,称为安全组 API,在实例端口级别提供基本的流量过滤。安全组规则在 iptables 中或作为 Open vSwitch 流规则在计算节点上实现,并过滤进入或离开 Neutron 端口的流量。第二种 API,称为防火墙即服务 API(FWaaS),也在端口级别实现过滤规则,但它将过滤能力扩展到路由器端口和其他除传统实例端口外的端口。
在本章中,我们将重点介绍安全组,并涵盖 Neutron 的一些基本安全功能,包括以下内容:
-
iptables 简介
-
创建和管理安全组
-
演示通过 iptables 的流量流动
-
配置端口安全
-
管理允许的地址对
由于在 Pike 和 Queens 版本的 OpenStack 中仍处于实验阶段,本书将不讨论 openvswitch 防火墙驱动。
OpenStack 中的安全组
安全组 是一组网络访问规则,称为 安全组规则,它限制了实例可以发送或接收的流量类型。当使用基于 iptables 的驱动时,安全组规则会转换为 iptables 规则,并应用于托管实例的 compute 节点。每个 OpenStack 项目都提供了一个默认的安全组,用户可以在该项目中对其进行修改。OpenStack 网络提供了一个 API,用于创建、修改、应用和删除安全组及规则。
有多种方法可以将安全组应用于实例。例如,可以将一个或多个实例(通常具有相似的功能或角色)放入一个安全组中。安全组规则可以引用 IPv4 和 IPv6 主机以及网络,还可以引用其他安全组。通过在规则中引用特定的安全组,而不是特定的主机或网络,可以使用户免于指定单独的网络地址。Neutron 会根据数据库中的信息自动构建应用于主机的过滤规则。
安全组中的规则在计算节点的端口级别应用,如下图所示:

在前面的图示中,虚拟交换机中的端口属于三个安全组之一:WEB、DB 或 APP。当安全组发生变化时,例如添加或删除组内规则,compute 节点上的相应 iptables 规则会自动更新。
一些用户可能会使用安全组来描述应该应用于特定实例端口的某些类型的规则。例如,可以使用安全组来分类允许访问某个端口的多个主机或子网。可以将多个安全组应用于一个端口,并且所有在这些组中定义的规则都会应用到该端口。因为所有流量默认被拒绝,而安全组规则仅定义了通过端口的允许流量,所以不存在一个安全组中的规则与另一个安全组中规则相互冲突的情况。
以下示例演示了使用安全组对允许通过端口访问的流量进行分类:

当在 Neutron 中创建一个端口时,除非指定了特定的安全组,否则它会关联到默认的安全组。默认的安全组会丢弃所有入站流量,并允许所有出站流量通过该端口。可以向默认安全组添加或删除规则,以改变其行为。此外,基础的端口安全规则会应用到每个端口,禁止 IP、DHCP 和 MAC 地址欺骗。此行为可以更改,稍后在本章中会讨论。
Iptables 介绍
Iptables 是 Linux 内置的防火墙,它允许系统管理员定义包含规则链的表,这些规则链决定了如何处理网络数据包。数据包通过在以下表中依次遍历链中的规则来进行处理:
-
Raw:这是一个默认的表,用于在其他任何表之前过滤数据包。它主要用于与连接跟踪相关的规则。
-
Filter:这是一个默认的表,用于过滤数据包。
-
NAT:这是一个默认的表,用于网络地址转换。
-
Mangle:这是一个默认的表,用于专门的数据包修改,不会被安全组 API 使用。
链中的规则可以导致跳转到另一个链,而后者又可以跳转到另一个链,如此循环。这种行为可以根据需要重复任意多级的嵌套。如果流量没有匹配子链中的规则,系统会记住跳转发生的地方,并返回该点继续处理。当启用 iptables 时,每个到达或离开接口的网络数据包至少会经过一个链。
有五个默认链,数据包的来源决定了最初会经过哪个链。这五个默认链包括:
-
PREROUTING:数据包将在做出路由决策之前进入此链。PREROUTING 链由 raw、mangle 和 NAT 表使用。
-
输入:当数据包要被本地传递到主机时使用。INPUT 链由 mangle 和 filter 表使用。
-
FORWARD: 所有路由过的并且不用于本地传递的数据包将通过此链路。FORWARD 链路被 mangle 和 filter 表使用。
-
OUTPUT: 主机本身发送的数据包将通过此链路。OUTPUT 链路被 raw、mangle、NAT 和 filter 表使用。
-
POSTROUTING: 路由决策已经做出后,数据包将进入此链路。POSTROUTING 链路被 mangle 和 NAT 表使用。
链路中的每条规则包含数据包可以匹配的标准。规则也可以包含目标,如另一个链路,或者结果,如 DROP 或 ACCEPT。当数据包通过链路时,会检查每条规则。如果规则不匹配数据包,则数据包传递到下一条规则。如果规则匹配数据包,则根据目标或结果执行规则指示的操作。
可能的结果包括以下内容:
-
ACCEPT: 数据包被接受并发送到应用程序进行处理
-
DROP: 数据包被静默丢弃
-
REJECT: 数据包被丢弃并向发送方发送错误消息
-
LOG: 数据包详细信息被记录
-
DNAT: 这会重写数据包的目标 IP
-
SNAT: 这会重写数据包的源 IP
-
RETURN: 处理返回到调用链路
ACCEPT、DROP 和 REJECT 结果常被 filter 表使用。常见的规则标准包括以下内容:
-
-p <protocol>: 匹配诸如 TCP、UDP、ICMP 等协议 -
-s <ip_addr>: 匹配源 IP 地址 -
-d <ip_addr>: 匹配目标 IP 地址 -
--sport: 匹配源端口 -
--dport: 匹配目标端口 -
-I <interface>: 匹配数据包进入的接口 -
-o <interface>: 匹配数据包退出的接口
Neutron 从用户那里抽象出安全组规则的实现,但了解其工作原理对于负责故障排除的操作员很重要。有关 iptables 的更多信息,请访问以下资源:
使用 ipset
在 Juno 之前的 OpenStack 版本中,为每个规则中引用的安全组创建了指数数量的 iptables 规则,这些规则对应于每个源和目标地址和端口对。这种行为导致 L2 代理性能差,并且存在虚拟机实例连接到虚拟桥但无法成功连接到网络的竞争条件。
从 Juno 版本开始,iptables 的 ipset 扩展被用于尝试通过创建地址和端口的组进行高效存储以减少所需的 iptables 规则数量。
如果没有 ipset,允许连接到端口 80 的 iptables 规则可能如下所示:
iptables -A INPUT -p tcp -d 1.1.1.1 --dport 80 -j RETURN
iptables -A INPUT -p tcp -d 2.2.2.2 --dport 80 -j RETURN
iptables -A INPUT -p tcp -d 3.3.3.3 --dport 80 -j RETURN
iptables -A INPUT -p tcp -d 4.4.4.4 --dport 80 -j RETURN
上述代码中的匹配语法 -d x.x.x.x 表示“匹配目标地址为 x.x.x.x 的数据包”。为了允许所有四个地址,必须定义四条独立的 iptables 规则,每条规则包含一个独立的匹配规范。
或者,可以使用 ipset 和 iptables 命令的组合来实现相同的结果:
ipset -N webset iphash
ipset -A webset 1.1.1.1
ipset -A webset 2.2.2.2
ipset -A webset 3.3.3.3
ipset -A webset 4.4.4.4
iptables -A INPUT -p tcp -m set --match-set webset dst --dport 80 -j RETURN
ipset 命令创建一个新的集合,名为 webset,其中包含四个地址。iptables 命令通过 --m set --match-set webset dst 引用该集合,表示“匹配目标地址与名为 webset 的集合中的某个条目相匹配的包”。
通过使用 ipset,只需一条规则即可完成之前需要四条规则才能完成的任务。虽然在这个例子中节省的规则很少,但随着实例被添加到安全组并且安全组规则配置的增多,规则的减少对性能和可靠性的影响会变得非常明显。
管理安全组
安全组可以通过 Neutron ReST API、OpenStack CLI 或 Horizon 仪表板进行管理。两种方法都提供了相当完整的体验,以下部分将详细讨论。
在 CLI 中管理安全组
在 OpenStack 命令行客户端中,可以使用多个命令来管理安全组。本章将讨论与安全组管理相关的主要命令,以下表格列出了这些命令:
| 安全组命令 | 描述 |
|---|---|
security group create |
创建一个新的安全组 |
security group delete |
删除安全组 |
security group list |
列出安全组 |
security group rule create |
创建一个新的安全组规则 |
security group rule delete |
删除安全组规则 |
security group rule list |
列出安全组规则 |
security group rule show |
显示安全组规则详情 |
security group set |
设置安全组属性 |
security group show |
显示安全组详情 |
server add security group |
向服务器添加安全组 |
server remove security group |
从服务器中移除安全组 |
在 CLI 中创建安全组
要创建一个安全组,请使用 openstack security group create 命令,格式如下:
openstack security group create
[--description <description>]
[--project <project>]
[--project-domain <project-domain>]
<name>
默认情况下,Neutron 中的安全组已预填充了两条出站规则,允许所有 IPv4 和 IPv6 的出站流量。默认情况下不允许入站流量。
在 CLI 中删除安全组
要删除一个安全组,请使用 openstack security group delete 命令,并指定安全组的 ID 或名称:
openstack security group delete <group> [<group> ...]
要删除名为 MySampleSecGrp 的安全组,可以输入以下命令:
openstack security group delete MySampleSecGrp
另外,你可以使用该安全组的 ID:
openstack security group delete f8ch3db3-e25b-4760-972a-cb700d9a73dc
也可以同时删除多个安全组,如下所示:
openstack security group delete MySampleSecGrp MyOtherSampleSecGrp
只要使用该安全组的端口在请求之前已经被删除,Neutron 将成功删除安全组。
在 CLI 中列出安全组
要获取安全组列表,请使用以下openstack security group list命令:
openstack security group list
[--project <project>]
[--project-domain <project-domain>]
返回的输出包括与指定项目相关联的所有安全组的 ID、名称和描述。如果以具有管理员角色的用户身份运行,将列出所有项目的所有安全组。
在 CLI 中显示安全组的详细信息
要显示安全组的详细信息,请使用openstack security group show命令,如下所示:
openstack security group show <group>
可以指定安全组的名称或 ID。返回的输出包括描述、ID、名称、关联的项目 ID 以及安全组内的各个规则。
在 CLI 中更新安全组
要更新安全组的属性,请使用以下openstack security group set命令:
openstack security group set
[--name <new-name>]
[--description <description>]
<group>
尝试修改默认安全组的名称会导致错误。
在 CLI 中创建安全组规则
要创建安全组规则,请使用以下openstack security group rule create命令:
openstack security group rule create
[--remote-ip<ip-address> | --remote-group <group>]
[--description <description>]
[--dst-port <port-range>]
[--icmp-type <icmp-type>]
[--icmp-code <icmp-code>]
[--protocol <protocol>]
[--ingress | --egress]
[--ethertype<ethertype>]
[--project <project>]
[--project-domain <project-domain>]
<group>
--remote-ip参数是可选的,允许您指定规则适用的源地址或网络。地址或网络应使用 CIDR 格式定义。
--remote-group参数是可选的,允许您指定规则应适用于的安全组的名称或 ID,而不是单个 IP 地址或网络。例如,在创建允许 SQL 流量进入数据库服务器的规则时,您可以指定应用服务器所在安全组的 ID,而无需指定它们的单个 IP 地址。
--description参数用于为安全组规则添加描述。
--dst-port参数是可选的,允许您指定目标端口或端口范围,端口范围之间用冒号分隔,如 137:139\。此选项对于 TCP 和 UDP 协议是必需的。
--icmp-type和--icmp-code参数分别指定 ICMP 类型和代码,用于 ICMP IP 协议。在没有特定类型和代码的情况下允许整个 ICMP 协议可以满足大多数使用场景。
--protocol参数是可选的,允许您根据 IP 协议匹配流量。可能的选项包括 ah、dccp、egp、esp、gre、icmp、igmp、ipv6-encap、ipv6-frag、ipv6-icmp、ipv6-nonxt、ipv6-opts、ipv6-route、ospf、pgm、rsvp、sctp、tcp、udp、udplite、vrrp 或一个 IP 协议号[0-255]。默认值是 tcp。
--ingress参数表示该规则适用于传入流量,而--egress参数表示该规则适用于实例的传出流量。这两个参数是互斥的,意味着只能使用其中一个来描述规则的方向。如果未指定,默认方向为传入(ingress)。
--ethertype参数是可选的,允许你指定规则是适用于 IPv4 还是 IPv6 流量。
--project和--project-domain参数是可选的,可用于指定与创建规则的用户关联的其他项目和域。
group参数用于指定规则应该关联的安全组的名称或 ID。
在 CLI 中删除安全组规则
要删除安全组规则,请使用openstack security group rule delete命令,并指定安全组规则的 ID 或名称:
openstack security group rule delete <group> [<group> ...]
要删除名为MySampleSecGrpRule80的安全组,可以输入以下命令:
openstack security group rule delete MySampleSecGrpRule80
也可以同时删除多个安全组,如下所示:
openstack security group delete MySampleSecGrpRuleTcp80 MySampleSecGrpRuleUDP123
虽然可以删除默认安全组中的规则,但无法删除该安全组本身。
在 CLI 中列出安全组规则
要获取安全组规则及其关联的安全组的列表,请使用openstack security group rule list命令,如下所示:
openstack security group rule list
[--protocol <protocol>]
[--ingress | --egress] [--long]
[<group>]
所有参数都是可选的,但可以用来过滤结果。返回的输出包括与作用域项目相关的所有安全组规则的 ID、协议、IP 范围、远程安全组和关联的安全组。如果指定--long,将提供标准输出中没有的附加详细信息,包括方向和以太类型。如果以管理员角色运行,所有项目中的所有安全组规则都将列出。
在 CLI 中显示安全组规则的详细信息
要显示安全组规则的详细信息,请使用openstack security group rule show命令,如下所示:
openstack security group rule show <group>
将安全组应用于实例和端口
在 CLI 中将安全组应用于实例通常是在实例创建时完成,使用openstack server create命令,如下所示:
openstack server create
--flavor <FLAVOR_ID>
--image <IMAGE_ID>
--nic net-id=<NETWORK_ID>
--security-group <SECURITY_GROUP_ID>
INSTANCE_NAME
通过使用openstack port set或openstack server add security group命令,也可以将安全组应用于正在运行的实例。以下示例演示了使用openstack port set命令将安全组应用于端口。
在此示例中,安全组将应用于端口,相关规则将立即生效:
openstack port set <PORT> --security-group <SECURITY_GROUP>
一个端口可以同时关联多个安全组。要将多个安全组应用于端口,请在每个安全组之前使用--security-group参数,如下所示:
openstack port set <PORT>
--security-group <SECURITY_GROUP_1>
--security-group <SECURITY_GROUP_2>
--security-group <SECURITY_GROUP_3>
以下示例演示了使用openstack server add group命令将安全组应用于实例:
openstack server add security group <INSTANCE> <SECURITY_GROUP>
由于命令中不能指定端口,因此安全组将应用于与实例关联的所有端口。
在 CLI 中从实例和端口中移除安全组
要移除单个安全组,请使用openstack server remove security group命令,如以下示例所示:
openstack server remove security group <INSTANCE> <SECURITY_GROUP>
另外,您可以使用openstack port unset命令将安全组从端口中移除:
openstack port unset --security-group <SECURITY GROUP> <PORT>
要从端口中移除所有安全组,包括默认组,请使用带有--no-security-group参数的openstack port set命令,如下所示:
openstack port set --no-security-group <PORT>
实施安全组规则
在以下示例中,创建了一个名为 WEB1 的实例,该实例作为 Web 服务器运行 Apache,监听端口 80 和 443。向 192.168.206.6:80 发起请求最终超时:

为了演示如何在计算节点上实现安全组规则,请注意以下 WEB_SERVERS 安全组:

以下截图展示了使用openstack security group rule create命令将两条安全组规则添加到 WEB_SERVERS 安全组。这些规则允许来自任何远程主机通过端口 80 和 443 的入站连接,CIDR 为 0.0.0.0/0:

使用openstack server add security group命令,可以将 WEB_SERVERS 安全组应用到 WEB1 实例,如下所示:

一旦安全组被应用到实例的相应端口,计算节点上会实施一系列的 iptables 规则和链。快速的连接性检查表明这些规则按预期工作:

逐步执行链
在 Linux 桥接和 Open vSwitch 环境中,使用 iptables 实施安全组规则的方式是类似的。在compute01上,作为本示例中的计算节点,运行 Linux 桥接代理并托管实例,显示通过 Neutron 代理应用的 iptables 规则,可以使用iptables-save或iptables -L命令观察到。
为了提高可读性,以下截图仅显示与实例相关的原始表和过滤器表中的规则。一些注释已被删除或缩短以适应页面:

首先,查询原始表(raw table)的 PREROUTING 链。在 PREROUTING 链中,我们可以找到将流量与实例接口和/或相关网络关联到特定 conntrack 区域的规则:

每个 Neutron 网络对应一个 conntrack 区域,这有助于在项目之间的地址空间重叠时区分流量。Conntrack 是连接跟踪系统的一部分,iptables 在执行有状态数据包检查时使用它。
接下来,网络流量可能会穿越过滤器表中的 INPUT 链,如下所示:
-A INPUT -j neutron-linuxbri-INPUT
该规则跳转到一个名为 neutron-linuxbri-INPUT 的链,如下所示:
-A neutron-linuxbri-INPUT -m physdev
--physdev-in tapadcc4b66-c1
--physdev-is-bridged -j neutron-linuxbri-oadcc4b66-c
该规则表示,流量通过 tapadcc4b66-c1 接口离开实例时,应转发到 neutron-linuxbri-oadcc4b66-c 链,如下所示:

neutron-linuxbri-oadcc4b66-c 链的规则规定,只有在客户端试图从 DHCP 服务器获取地址时,才允许外发的 DHCP 流量。默认情况下,实例不允许作为 DHCP 服务器,流量会被相应丢弃。规则还规定,标记为 RETURN 或 ESTABLISHED 的流量将被允许,但 INVALID 数据包将被丢弃。最后,任何不匹配的流量将被 neutron-linuxbri-sg-fallback 链中的规则丢弃。
Iptables 可能会根据目的地址以及是否本地化于节点来使用 INPUT 或 FORWARD 链处理流量。在大多数情况下,将使用 FORWARD 链。
如果流量已经通过了 INPUT 链,则会继续进入下图所示的 FORWARD 链:

第一条规则使 iptables 跳转到 neutron-filter-top 链。之后,iptables 跳转到 neutron-linuxbri-local 链进行进一步处理。因为该链中没有定义规则,所以 iptables 会返回到调用链 neutron-filter-top。一旦所有规则被处理完毕,iptables 会返回到之前的调用链,FORWARD。
FORWARD 链中接下来处理的规则如下:
-A FORWARD -j neutron-linuxbri-FORWARD
上述规则使 iptables 跳转到下图所示的 neutron-linuxbri-FORWARD 链:

-m 标志后跟 physdev 是指示 iptables 使用一个扩展的 packet matching 模块,该模块支持绑定到桥接设备的设备。
请记住:当使用 Linux 桥接代理时,实例的 tap 接口会连接到以 brq-* 为前缀的网络桥接器。当使用 OVS 代理时,tap 接口连接到其自己的 Linux 桥接器,前缀为 qbr-*。
数据包将根据其通过接口的方向匹配两个规则之一。在任何情况下,iptables 都会跳转到 neutron-linuxbri-sg-chain 链,如下所示:

数据包的方向将再次决定匹配的规则。通过 tapadcc4b66-c1 接口流向实例的流量将由 neutron-linuxbri-iadcc4b66-c 链处理,如下所示:

安全组链的名称与其关联的 Neutron 端口的 UUID 的前 9 个字符对应。
在上述规则中,iptables 使用state模块来确定数据包的状态。结合连接追踪,iptables 能够跟踪连接并确定数据包的以下状态:INVALID、NEW、RELATED 或 ESTABLISHED。数据包的状态将决定采取相应的措施。未匹配任何规则的流量将被neutron-linuxbri-sg-fallback链丢弃:
-A neutron-linuxbri-sg-fallback -j DROP
通过tapadcc4b66-c1接口退出实例的流量将由neutron-linuxbri-oadcc4b66-c链按照以下方式处理:

第一个 UDP 规则允许实例在 UDP 端口 67 上发送DHCPDISCOVER和DHCPREQUEST广播包。所有其他流量将由neutron-linuxbri-sadcc4b66-c链按照以下方式处理:

上述规则防止实例进行 IP 和 MAC 地址欺骗。所有通过tapadcc4b66-c1接口的流量必须来自 IP 地址192.168.206.6/32和 MAC 地址FA:16:3E:DC:D2:AB。要允许来自其他 IP 或 MAC 地址的出站流量,请使用 Neutron 的allowed-address-pairs扩展,稍后本章将讨论该扩展。
后续处理包括防止 DHCP 欺骗并验证数据包状态,执行相应的操作。流量最终返回到neutron-linuxbri-sg-chain链,在此链中流量被允许通过:
-A neutron-linuxbri-sg-chain -j ACCEPT
在仪表板中使用安全组
在 Horizon 仪表板中,安全组在“网络”标签下的“安全组”部分进行管理:

创建安全组
要创建安全组,请执行以下步骤。
点击屏幕右上角的“创建安全组”按钮。将弹出一个窗口,允许您创建安全组:

“名称”字段是必填项。当您准备好继续时,请点击蓝色的“创建安全组”按钮以创建安全组。
管理安全组规则
创建完成后,您将返回到“安全组”部分,您可以通过点击相应组的“管理规则”按钮来添加规则:

要删除规则,请点击相应安全组规则旁边的红色“删除规则”按钮。要添加规则,请点击右上角的“添加规则”按钮:

将弹出一个窗口,允许您创建规则。在规则列表中,您可以从预定义的协议列表中选择,或按照以下方式创建自定义规则:

向导允许您指定方向、端口或端口范围,以及远程网络或组。要完成规则创建过程,请点击蓝色的“添加”按钮。
将安全组应用于实例
要向实例应用安全组,请返回计算面板的实例部分。单击实例旁边操作菜单下的箭头,并选择编辑安全组:

将出现一个窗口,允许您向实例应用或移除安全组。点击组旁边的蓝色加号将其应用到实例。

单击后,组将移动到实例安全组列,如下截图所示:

单击蓝色保存按钮以应用更改到实例。
禁用端口安全
默认情况下,Neutron 对所有端口应用反欺骗规则,以确保不期望或不希望的流量不能从端口发出或通过。这包括禁止实例运行 DHCP 服务器或充当路由器的规则。要解决后者,可以使用allowed-address-pairs扩展来允许额外的 IP、子网和 MAC 地址通过端口。但是,可能需要额外的功能,这些功能无法通过allowed-address-pairs扩展解决。
在 OpenStack Kilo 版本中,为 ML2 插件引入了端口安全扩展,允许在端口上禁用所有数据包过滤。这包括防止 IP 和 MAC 欺骗以及安全组功能的默认规则。当部署用作路由器或负载均衡器的实例时,此扩展特别有用。端口安全扩展需要额外的配置,将在接下来的部分讨论。
配置 Neutron
要启用端口安全扩展,在controller01节点的/etc/neutron/plugins/ml2/ml2_conf.ini编辑 ML2 配置文件,并在[ml2]部分添加以下内容:
[ml2]
...
extension_drivers = port_security
重启neutron-server服务以使更改生效:
# systemctl restart neutron-server
您可以通过查看openstack extension list命令提供的扩展列表中的名称来验证是否已启用端口安全扩展,如下所示:

禁用网络上所有端口的端口安全
即使没有端口安全扩展,Neutron 也通过在每个端口上实施 DHCP、MAC 地址和 IP 地址欺骗规则来实现扩展的默认行为。端口安全扩展允许具有管理员角色的用户在单个端口或整个网络上禁用端口安全。在网络创建过程中,可以通过设置--disable-port-security参数来禁用连接到特定网络的所有端口上的端口安全:

创建端口并将其附加到网络时,其port_security_enabled属性将自动设置为False:

需要注意的是,当端口禁用端口安全性时,API 将不允许该端口与任何安全组关联。没有安全组规则意味着所有流量都可以进出端口。禁用端口安全性意味着任何过滤必须在虚拟机操作系统内实现。
修改单个端口的端口安全性
当端口安全性扩展启用时,可以通过在创建或更新端口时相应设置port_security_enabled属性来启用或禁用单个端口的端口安全性。
以下截图演示了如何更新端口以启用端口安全性:

启用端口安全性时,默认的防伪规则将应用到端口,安全组可以根据需要应用。禁用端口安全性将移除默认的防伪规则,并且该端口将不允许使用安全组。
允许的地址对
allowed-address-pairs扩展可以用来允许除端口关联的固定 IP 和 MAC 地址之外的额外 IP、子网和 MAC 地址作为源地址,用于流出端口或虚拟接口的流量。这在将实例视为路由设备或 VPN 集中器,或者在使用需要“漂浮”在多个实例之间的地址(例如haproxy和/或keepalived实现)时,尤其有用。
可以通过使用openstack port show命令,在每个端口的详细信息中找到现有的允许地址对。对于每个应该被允许的网络和/或 MAC 地址,应使用带有--allowed-address参数的openstack port set命令,如下所示:
openstack port set <port>
--allowed-address ip_address=<IP_ADDR>,mac-address=<MAC_ADDR>
MAC 地址值是可选的。如果未指定 MAC 地址,则使用端口的 MAC 地址。
可以同时为一个 Neutron 端口关联多个允许的地址对。要将多个允许的地址对应用到端口,只需指定多个ip_address和mac_address键值对,如下所示:
openstack port set <PORT>
--allowed-address ip-address=<IP_ADDR>,mac-address=<MAC_ADDR>
--allowed-address ip-address=<IP_ADDR>,mac-address=<MAC_ADDR>
...
--allowed-address ip-address=<IP_ADDR>,mac-address=<MAC_ADDR>
要从端口中移除所有允许的地址对,请使用带有--no-allowed-address参数的openstack port set命令。
总结
安全组对于控制实例访问至关重要,允许用户创建入站和出站规则,基于特定的地址、端口、协议,甚至其他安全组,限制到达和离开实例的流量。默认安全组由 Neutron 为每个项目创建,允许所有出站通信并将入站通信限制在同一默认安全组中的实例之间。后续的安全组会进一步限制,只允许出站通信,并且不允许任何入站流量,除非用户进行修改。
安全组规则在计算节点上实现,并在流量进入或离开实例所属的虚拟网络接口时触发。用户可以在客户操作系统内实现额外的防火墙,但可能会发现同时管理两个地方的规则有些繁琐。许多组织仍然使用并依赖物理防火墙设备,在网络边缘提供额外的过滤,这可能意味着云用户和传统安全团队之间需要进行协调,以确保在所有位置都有适当的规则和措施到位。
在下一章中,我们将探讨在 Neutron 中实施基于角色的访问控制(RBAC),作为一种从 API 角度控制项目之间网络访问的方法。
第九章:基于角色的访问控制
基于角色的访问控制(RBAC)策略框架使得操作员和用户能够为特定的项目或租户授予资源访问权限。在 RBAC 之前,Neutron 对项目之间网络共享采用了全有或全无的方式。如果一个网络被标记为共享,它将与所有项目共享。使用 Neutron RBAC API 构建的访问控制策略允许操作员和用户通过更细粒度的方式与一个或多个项目共享特定的网络资源。
从 OpenStack 的 Pike 版本开始,访问控制策略可以授予以下访问权限:
-
在网络上创建常规端口的权限
-
将路由器网关连接到网络
-
将 服务质量(QoS)策略权限绑定到网络或端口
本章将重点介绍 Neutron 中基于角色的访问控制的概念和实现,包括以下内容:
-
网络资源的基于角色的访问控制简要介绍
-
创建和管理访问控制策略
-
演示访问控制策略的使用
QoS 是一个高级网络话题,本书未涉及。
使用访问控制策略
管理 RBAC 策略的工作流程遵循标准的创建、读取、更新和删除(CRUD)模型,该模型在整个 Neutron API 中都在使用。可以使用 OpenStack 命令行接口来管理访问控制策略。从 OpenStack 的 Pike 版本开始,Horizon 对 RBAC 的支持尚未实现。然而,通过策略共享的资源可以在仪表板中使用。
在 CLI 中管理访问控制策略
在 openstack 命令行客户端中,可以使用多个命令来管理访问控制策略。本章将讨论与访问控制策略管理相关的主要命令,具体命令如下表所示:
| 基于角色的访问控制命令 | 描述 |
|---|---|
network rbac create |
创建网络 RBAC 策略 |
network rbac delete |
删除网络 RBAC 策略 |
network rbac list |
列出网络 RBAC 策略 |
network rbac set |
设置网络 RBAC 策略属性 |
network rbac show |
显示网络 RBAC 策略详情 |
在 CLI 中创建访问控制策略
要创建访问控制策略,请使用以下 openstack network rbac create 命令:
openstack network rbac create
--type <type> --action <action>
--target-project <target-project>
[--target-project-domain <target-project-domain>]
[--project <project>]
[--project-domain <project-domain>]
<rbac-object>
--type 参数允许您指定策略影响的对象类型。可能的选项包括 network 或 qos_policy。本章仅描述网络策略。
--action 参数允许您指定访问策略的操作。可能的选项包括 access_as_external 或 access_as_shared。前者允许将网络用作某些项目的外部网络,而后者允许将网络用作某些项目的共享网络。
--target-project参数指定将强制实施访问策略的目标项目。
--target-project-domain参数是可选的,允许你指定目标项目所属的域。
--project参数是可选的,允许你指定访问策略的所有者。
--project-domain参数是可选的,允许你指定所有者项目所属的域。
rbac-object参数指定策略应用的对象名称。如果类型是网络,则可能是网络名称或 ID;如果类型是 qos_policy,则是 QOS 策略 ID。
在 CLI 中删除访问控制策略
要删除访问控制策略,请使用openstack network rbac delete命令并指定 RBAC 对象的 ID,方法如下:
openstack network rbac delete <RBAC Policy> [<RBAC Policy> ...]
也可以同时删除多个访问策略,方法如下:
openstack network rbac delete <RBAC Policy ID1> <RBAC Policy ID2>
只要没有其他项目正在使用共享资源,Neutron 就会成功删除访问策略。
在 CLI 中列出访问控制策略
要获取访问控制策略的列表,请使用以下openstack network rbac list命令:
openstack network rbac list
[--type <type>] [--action <action>]
结果可以按类型和操作进行过滤。返回的输出包括操作、ID、共享对象 ID 和共享对象类型。
在 CLI 中显示访问控制策略的详细信息
要显示访问策略的详细信息,请使用以下显示的openstack network rbac show命令:
openstack network rbac show <RBAC Policy>
在 CLI 中更新访问控制策略
要更新访问策略的属性,请使用以下openstack network rbac set命令:
openstack network rbac set
[--target-project <target-project>]
[--target-project-domain <target-project-domain>]
<RBAC Policy>
此命令允许你更改现有访问控制策略的目标项目和域。
将 RBAC 策略应用于项目
在创建 RBAC 策略之前,你需要有一个网络或 QoS 策略,想要在部分项目之间共享。在接下来的章节中,我们将创建项目、角色、用户和网络,我将演示访问控制策略如何限制项目之间共享资源的可见性和使用方式,相对于共享属性的默认行为。
创建项目和用户
使用 openstack 客户端,创建三个名为 ProjectA、ProjectB 和 ProjectC 的项目,如下所示:

使用 openstack 客户端,创建一个名为rbacdemo的角色。然后,在每个项目中创建一个用户,并将rbacdemo角色应用到每个用户:

创建一个共享网络
使用 openstack 客户端,作为管理员用户创建一个名为MySemiSharedNetwork的网络和一个名为MySemiSharedSubnet的子网。这个网络将会在一些新创建的项目之间共享:

在网络详细信息中,可以看到网络的共享属性设置为False。在这种状态下,该网络只能由与拥有项目关联的用户使用。在这种情况下,拥有项目是管理员项目。如果将其设置为True,则该网络可以被所有项目使用,这是我们希望避免的情况。
创建策略
创建 RBAC 策略需要以下四个详细信息:
-
策略类型
-
目标项目
-
执行的操作
-
资源
默认情况下,在上一节中创建的MySemiSharedNetwork网络仅限于创建它的管理员项目使用。使用 openstack 客户端,创建一个新的 RBAC 策略,通过使用access_as_shared操作与ProjectA项目共享该网络,如下所示:

可以使用openstack network rbac list和/或show命令查看访问控制策略,如下所示:

查看策略执行情况
作为 ProjectA 项目中的 UserA,openstack network list命令可以用来确认网络是否可用,如下所示:

然而,ProjectB和ProjectC项目中的用户无法看到该网络:

以ProjectB和ProjectC项目中的用户身份运行查询将返回无结果,且这些项目无法使用该网络。对于每个必须与之共享网络对象的项目,必须创建一个单独的策略。可以通过指定不同的项目来使用openstack network rbac create命令创建其他策略,但共享相同的网络资源。
为外部网络创建策略
外部网络用于将 Neutron 路由器连接到物理网络,并通过路由和浮动 IP 帮助提供进出项目的路由。当一个网络的外部属性被设置为True时,该网络将在所有项目中共享。访问策略可以用来将外部网络限制为某些项目的子集。创建外部网络策略的语法与上一节中展示的策略非常相似。不过,操作会从access_as_shared更改为access_as_external。
在此示例中,创建了一个名为MySemiSharedExternalNetwork的外部网络,使用 VLAN 31,目的是将其与部分项目共享。注意共享属性为False,且外部属性为内部,意味着它只能用于内部网络:

因此,当运行openstack network list --external时,该网络不会被列出,并且无法作为外部网络使用:

在此示例中,管理员用户创建了一个访问策略,将网络作为外部网络与 ProjectB 项目共享:

作为UserB在ProjectB项目中,我们可以使用openstack network list --external命令查看外部网络。该网络将反映其外部状态:

如果没有配置shared_as_external访问策略,其他项目将无法将该网络视为外部网络或使用它。
总结
由基于角色的访问控制框架创建和管理的访问控制策略允许操作员和用户为单个项目提供对某些网络资源的访问,而不是对所有项目。这种能力开启了过去不可用的网络设计选项,并提供了一种更安全的网络资源共享方法。
在下一章中,我们将探讨独立的 Neutron 路由器及其在为项目提供自服务网络中的作用。此外,我们还将查看浮动 IP 的配置和使用,以便为实例提供外部连接。高度可用和分布式虚拟路由器的配置将在后续章节中介绍。
第十章:使用 Neutron 创建独立路由器
Neutron 使用户能够构建在用户创建的网络和外部网络之间提供连接的路由器。在参考实现中,Neutron L3 代理通过利用网络命名空间为云中的虚拟机实例提供 IP 路由和网络地址转换,从而提供隔离的路由实例。通过创建网络并将其附加到路由器,用户可以将连接的虚拟机实例及其应用程序暴露到互联网。
在 OpenStack 的 Juno 版本之前,用户只能构建作为网络堆栈中的单点故障的独立路由器。自从 Juno 及其之后版本引入了分布式虚拟路由器后,独立路由器现在被称为遗留路由器。尽管偏好可能是提供高可用性或分布式虚拟路由器来实现可靠性,但独立路由器提供了三种选项中最简单的实现。
在之前的章节中,我们探讨了提供者网络和自服务项目网络之间的区别,并演示了启动实例并将其连接到网络的过程。在本章中,我们将完成以下内容:
-
安装和配置 L3 代理
-
创建外部提供者网络
-
在 CLI 和 Horizon 仪表板中创建独立路由器
-
将路由器连接到外部网络和租户网络
-
启动实例
-
使用 Linux 桥接演示实例和命名空间的连接性
-
演示浮动 IP 提供的 SNAT 和 DNAT 功能
在云中路由流量
在参考实现中,Neutron 中创建的虚拟路由器作为网络命名空间存在,并驻留在运行 Neutron L3 代理服务的节点上。虚拟路由器通常连接到一个外部提供者网络和一个或多个项目网络。连接到这些网络的路由器接口可以如下识别:
-
qg:网关接口
-
qr:路由器接口
Neutron 路由器通过使用网络地址转换(NAT)为项目网络提供进出连接。以下图示展示了路由器命名空间如何连接到基于 Linux 桥接实现的多个桥接:

上述图示展示了 Neutron 路由器在基于 Linux 桥接的实现中如何连接到多个桥接。在基于 Open vSwitch 的实现中,路由器的接口直接连接到集成桥接。来自项目网络的流量通过 qr 接口路由到外部网络的 qg 接口。命名空间中的路由表决定流量的路由方式,iptables 规则决定流量是否需要转换。
更多关于创建和配置独立 Neutron 路由器的内容,以及它们如何连接到网络并为实例提供连接的示例,请参见本章后面的内容。
安装和配置 Neutron L3 代理
要安装 Neutron L3 代理,请在 controller01 节点上运行以下命令:
# apt install neutron-l3-agent
Neutron 将 L3 代理配置存储在 /etc/neutron/l3_agent.ini 文件中。最常见的配置选项将在以下子节中介绍。
定义接口驱动程序
必须配置 Neutron L3 代理,使用与所选机制驱动程序相对应的接口驱动程序。在参考实现中,这可以是 Linux 桥接驱动程序或 Open vSwitch 驱动程序。在此环境中,linux 桥接驱动程序将安装在 controller01 上。
在 controller01 节点上,更新 Neutron L3 代理配置文件 /etc/neutron/l3_agent.ini,并为此特定环境指定以下 Linux 桥接接口驱动程序:
[DEFAULT]
...
interface_driver = linuxbridge
作为参考,以下配置可用于当 network 节点承载路由器并配置为 Open vSwitch 时:
[DEFAULT]
...
interface_driver = openvswitch
启用元数据代理
当 Neutron 路由器作为实例的网关时,元数据请求将通过路由器代理,而不是 DHCP 服务器,并被转发到 Nova 元数据服务。此功能默认启用,可以通过将 l3_agent.ini 配置文件中的 enable_metadata_proxy 值设置为 False 并取消注释来禁用。在此环境中,保持默认的 True 值即可。
如果禁用了元数据代理,用户可能只能通过 config-drive 获取元数据。
设置代理模式
默认情况下,Neutron L3 代理以传统模式工作,这意味着 L3 代理部署在负责网络服务的集中节点上。agent_mode 的默认值为 legacy,并将在本章其余部分保持不变。
启用路由器服务插件
在 Neutron 接受与 Neutron 路由器相关的 API 命令之前,必须启用路由器服务插件。在 controller01 节点上,更新 Neutron API 服务器配置文件 /etc/neutron/neutron.conf,并将 router 添加到服务插件列表中,如下所示:
service_plugins = router
service_plugins 配置选项可能已被禁用。删除前导的井号 (#) 来启用该选项。
在仪表板中启用路由器管理
可以使用 Horizon 仪表板来管理路由器,但必须首先启用此选项。
在 controller01 节点上,编辑 OpenStack 仪表板配置文件 /etc/openstack-dashboard/local_settings.py,然后找到 OPENSTACK_NEUTRON_NETWORK 配置选项。将 enable_router 字典的值从 False 更改为 True,如下所示:

关闭文件并继续进行下一节,重启服务。
重启服务
在对 Neutron L3 代理和 API 服务配置进行更改后,在controller01节点上执行以下命令以重启相应的服务:
# systemctl restart neutron-l3-agent neutron-server apache2
验证代理是否正在运行:
# systemctl status neutron-l3-agent
服务应返回类似于以下的输出,并处于活动(运行)状态:

如果服务保持停止状态,请排查/var/log/neutron/l3-agent.log日志文件中可能指示的错误。
在 CLI 中管理路由器
Neutron 提供了一些命令,可用于创建和管理路由器。与路由器管理相关的主要命令包括以下内容:
| 路由器管理命令 | 描述 |
|---|---|
router create |
创建一个路由器 |
router delete |
删除一个或多个路由器 |
router set |
设置路由器网关及其他属性 |
router unset |
取消设置路由器网关及其他属性 |
router show |
显示路由器详情 |
router list |
列出路由器 |
router add port |
使用现有端口向路由器添加接口 |
router add subnet |
使用现有子网向路由器添加接口 |
router remove port |
使用相应的端口 ID 从路由器中移除一个接口 |
router remove subnet |
使用相应的子网 ID 从路由器中移除一个接口 |
network agent list |
列出所有网络代理 |
在 CLI 中创建路由器
Neutron 中的路由器与项目相关联,且只能由与该项目相关的用户管理。与网络不同,路由器不能在项目之间共享。然而,共享网络可以附加到路由器,并可能在不同项目之间路由流量。具有管理员角色的用户可以在创建路由器过程中将路由器与其他项目关联。
要创建一个独立的路由器,请使用以下显示的openstack router create命令:
openstack router create
[--enable | --disable]
[--project <project>]
[--project-domain <project-domain>]
<name>
路由器将被创建,但不会附加任何接口,并会立即被调度到 L3 代理。相应的网络命名空间应在托管该 L3 代理的节点上可见,可以使用ip netnslist命令找到它。
在 CLI 中列出路由器
要显示现有路由器的列表,请使用以下显示的openstack router list命令:
openstack router list
[--name <name>] [--enable | --disable] [--long]
[--project <project>]
[--project-domain <project-domain>]
[--agent <agent-id>] [--tags <tag>[,<tag>,...]]
[--any-tags <tag>[,<tag>,...]]
[--not-tags <tag>[,<tag>,...]]
[--not-any-tags <tag>[,<tag>,...]]
可以根据名称、项目、管理员状态、计划代理和标签等过滤条件来缩小返回结果。
用户将仅能看到与其项目相关的路由器。以管理员角色执行时,Neutron 将返回所有项目中的所有路由器列表,除非指定了项目 ID。
在 CLI 中显示路由器属性
要显示路由器的属性,请使用以下显示的openstack router show命令:
openstack router show <router>
返回的输出中包含管理员状态、外部网络、SNAT 状态和与路由器关联的项目 ID。两个附加属性,分布式(distributed)和高可用性(HA),用于标识路由器是否为分布式或高度可用。对于独立路由器,这两个属性将被设置为 False。
在 CLI 中更新路由器属性
要更新路由器的属性,请使用如下所示的 openstack router set 或 openstack router unset 命令:
openstack router set
[--name <name>] [--description <description>]
[--enable | --disable]
[--distributed | --centralized]
[--route destination=<subnet>,gateway=<ip-address>]
[--no-route] [--ha | --no-ha]
[--external-gateway <network>]
[--fixed-ip subnet=<subnet>,ip-address=<ip-address>]
[--enable-snat | --disable-snat] [--tag <tag>]
[--no-tag]
<router>
openstack router unset
[--route destination=<subnet>,gateway=<ip-address>]
[--external-gateway] [--tag <tag> | --all-tag]
<router>
在 CLI 中处理路由器接口
独立的 Neutron 路由器有两种类型的接口:网关和内部。Neutron 路由器的网关接口类似于物理路由器的 WAN 接口。它是连接到上游设备的接口,提供与外部资源的连接。Neutron 路由器的内部接口类似于物理路由器的 LAN 接口。内部接口连接到项目网络,并通常作为这些网络中实例的网关或下一跳。
将内部接口附加到路由器
要创建一个内部路由器接口并将其附加到子网,请使用如下所示的 openstack router add subnet 命令:
openstack router add subnet <router> <subnet>
subnet 参数表示要附加到路由器的子网名称或 ID。Neutron 在创建 qr 接口和相应端口时,将为路由器分配该子网的网关 IP。
要将现有端口直接附加到路由器,请使用如下所示的 openstack router add port 命令:
openstack router subnet add <router> <port>
port 关键字表示要附加到路由器的端口名称或 ID。
Neutron 路由器在给定子网中只能有一个接口,但可以同时连接到多个子网。L3 代理负责将路由器命名空间中的接口连接到主机上的适当桥接器。
在 Neutron 中,一个网络可以包含多个子网。路由器必须连接到网络中的所有子网,以便正确地路由该网络的流量。确保不要使用此过程附加外部网络,因为这可能会对流量产生负面影响!
将网关接口附加到路由器
Neutron 路由器的外部接口被称为网关接口。一个路由器只能有一个网关接口。要作为可用于路由器网关接口的外部网络,提供者网络必须将路由器的外部属性设置为 True 或 External。
要将网关接口附加到路由器,请使用如下所示的 openstack router set 命令:
openstack router set --external-gateway <network> <router>
<network> 参数表示要附加到路由器的作为网关网络的网络名称或 ID。Neutron 会从外部网络为路由器分配一个 IP 地址。默认情况下,Neutron 路由器会对所有没有浮动 IP 的实例流量执行源网络地址转换(SNAT)。NAT 和 SNAT 会在本章后面详细讲解。要禁用此功能,请在使用 openstack router set 命令时使用 --disable-snat 参数。
列出附加到路由器的接口
要列出附加到路由器的接口,请使用如下所示的 openstack port list 命令:
openstack port list --router <router>
路由器 参数表示路由器的名称或 ID。
删除内部接口
要从路由器中删除内部接口,请使用如下所示的 openstack router remove port 或 openstack router remove subnet 命令:
openstack router remove port <router> <port>
openstack router remove subnet <router> <subnet>
<port> 参数表示要从路由器中删除的特定端口的名称或 ID,而 <subnet> 参数表示要从路由器中删除的子网的名称或 ID。在这两种情况下,基于端口或子网删除接口将导致相应的 Neutron 端口从数据库中移除。
清除网关接口
不能通过 openstack router remove 命令删除路由器的网关接口。必须使用 openstack router unset 命令。
要清除路由器的网关,请使用如下所示的 openstack router unset 命令:
openstack router unset --external-gateway <router>
Neutron 会进行检查,如果路由器与浮动 IP 相关联,则无法清除网关接口。
在 CLI 中删除路由器
要删除路由器,请使用 openstack router delete 命令并指定路由器的名称或 ID:
openstack router delete <router> [<router> ...]
也可以同时删除多个路由器,方法如下:
openstack router delete <router1> <router2>
只要删除了所有连接的端口或子网,并且所有浮动 IP 已被解除关联或删除,Neutron 就会成功删除路由器。
网络地址转换
网络地址转换,或称 NAT,是一种网络概念,最早于 1990 年代初期提出,旨在应对全球 IP 地址迅速枯竭的问题。在 NAT 出现之前,每个连接到互联网的主机都有一个唯一的 IP 地址。
独立路由器支持两种类型的 NAT:
-
一对一
-
多对一
一对一 NAT 是一种将一个 IP 地址直接映射到另一个 IP 地址的方法。常被称为静态 NAT,一对一 NAT 常用于将唯一的公共地址映射到私有地址主机。浮动 IP 利用了这种一对一 NAT 的概念。
多对一 NAT 是一种将多个地址映射到一个地址的方法。多对一 NAT 使用端口地址转换(PAT)。当浮动 IP 未分配时,Neutron 使用 PAT 提供对路由器后端实例的外部访问。
如需了解更多有关网络地址转换的信息,请访问以下维基百科页面:en.wikipedia.org/wiki/Network_address_translation。
浮动 IP 地址
自助服务项目网络,在附加到 Neutron 路由器时,通常使用该路由器作为其默认网关。默认情况下,当路由器接收到来自实例的流量并将其路由到上游时,路由器会执行端口地址转换,并将数据包的源地址修改为其自身的外部接口地址。当发生转换时,临时源端口会映射到原始客户端地址,并记录在一个表中,在响应数据包到达时会查阅该表。这确保了数据包能够被路由到上游并返回给路由器,在那里数据包会被修改并返回到发起连接的实例。Neutron 将这种行为称为源 NAT。
当用户需要直接访问实例时,可以使用浮动 IP 地址。OpenStack 中的浮动 IP 地址是一个一对一的静态 NAT,将外部网络的外部地址映射到项目网络中的内部地址。这种 NAT 方法允许实例能够从远程网络(如互联网)进行访问。浮动 IP 地址配置在路由器的外部接口上,该路由器作为实例的网关,负责根据数据包的方向修改数据包的源地址和目标地址。
浮动 IP 管理
OpenStack 命令行客户端提供了多个命令,用于创建和管理浮动 IP。与浮动 IP 相关的主要命令包括以下内容:
| 浮动 IP 命令 | 描述 |
|---|---|
floating ip create |
创建一个浮动 IP |
floating ip delete |
删除一个浮动 IP |
floating ip list |
列出浮动 IP |
floating ip show |
显示浮动 IP 详情 |
floating ip set |
设置浮动 IP 属性 |
floating ipunset |
取消设置浮动 IP 属性 |
floating ip pool list |
列出浮动 IP 地址池 |
server add floating ip |
将浮动 IP 地址添加到服务器 |
server remove floating ip |
从服务器中移除浮动 IP 地址 |
在 CLI 中创建浮动 IP
如果你还记得前几章的内容,IP 地址并不会直接分配给实例。相反,IP 地址与 Neutron 端口相关联,并且该端口被逻辑地映射到一个实例或其他网络资源。
当浮动 IP 被创建时,除非与 Neutron 端口关联,否则它无法正常工作。要在 CLI 中创建浮动 IP,请使用以下 openstack floating ip create 命令:
openstack floating ip create
[--subnet <subnet>]
[--port <port>]
[--floating-ip-address <ip-address>]
[--fixed-ip-address <ip-address>]
[--description <description>]
[--project <project>]
[--project-domain <project-domain>]
<network>
浮动 IP 地址只能在创建它们的项目中使用。管理员可以使用 --project 参数,以便指定与浮动 IP 关联的项目。
--port 参数是可选的,用于在创建时指定要与浮动 IP 关联的端口。
因为一个端口可能与多个 IP 地址关联,所以可能需要定义一个特定的固定 IP 来与浮动 IP 关联。使用 --fixed-ip-address 参数来指定应与浮动 IP 关联的固定 IP 地址。
在 OpenStack 的早期版本中,浮动 IP 是从外部网络的分配池中自动分配的。这种行为对于需要特定地址的用户来说很困难,特别是在上游的 NAT 或防火墙规则已经指定了特定的浮动 IP 地址的情况下。从 Kilo 版本开始,只要地址可用并且没有与其他项目关联,就可以使用指定的地址创建浮动 IP。通过此功能,用户可以指定特定的浮动 IP 地址,避免修改外部系统。
使用 --floating-ip-address 参数来指定从外部网络中选定的地址作为浮动 IP 使用。
在 CLI 中将浮动 IP 与端口关联
一旦浮动 IP 被创建,它可以由创建它的项目中的任何用户使用。要将浮动 IP 与实例关联,首先需要确定与实例固定 IP 关联的 Neutron 端口。
可以通过几种不同的方式来确定与实例的固定 IP 地址关联的端口 ID。最快的方法可能是使用 openstack port list 命令,并使用过滤器来缩小每个实例的端口范围。
例如,可以通过以下方式确定实例 ID 为 3d577137-9658-4226-906e-88d3117e497e 的端口:

一旦确定了端口 ID,就可以使用 openstack floating ip set 命令将浮动 IP 与端口关联:
openstack floating ip set --port <port>
[--fixed-ip-address <ip-address>]
<floating-ip>
Neutron 使用指定端口的子网 ID 来确定要配置浮动 IP 地址和相应 NAT 规则的路由器。涉及的逻辑意味着,在使用浮动 IP 时,任何给定时间只能将一个独立的路由器附加到项目网络上,否则可能会发生意外结果。
在 CLI 中列出浮动 IP
要确定浮动 IP 与 Neutron 端口和地址的关联,可以使用如下所示的 openstack floating ip list 命令:
openstack floating ip list
[--network <network>] [--port <port>]
[--fixed-ip-address <ip-address>] [--long]
[--status <status>] [--project <project>]
[--project-domain <project-domain>]
[--router <router>]
返回的输出包括浮动 IP ID、固定 IP 地址、浮动 IP 地址和与浮动 IP 关联的端口 ID。所有参数都是可选的,并有助于过滤结果。
在 CLI 中显示浮动 IP 属性
要在 CLI 中显示浮动 IP 的属性,请使用以下显示的openstack floating ip show命令:
openstack floating ip show <floating-ip>
返回的输出包括浮动 IP 地址以及关联的外部网络、固定 IP 地址、端口、项目和路由器 ID。
在 CLI 中解除浮动 IP 关联
要将浮动 IP 与端口解除关联,请使用以下显示的openstack floating ip unset命令:
openstack floating ip unset [--port] <floating-ip>
将浮动 IP 与端口解除关联,使该浮动 IP 可供项目中的其他用户使用。
在 CLI 中删除浮动 IP
要删除浮动 IP,请使用以下显示的openstack floating ip delete命令:
openstack floating ip delete <floating-ip> [<floating-ip> ...]
删除浮动 IP 会将该 IP 地址返回到外部网络分配池,之后它可以分配给其他项目并供其他网络资源使用,包括路由器和浮动 IP。
演示从实例到互联网的流量
本节专门介绍一个操作示例,利用本书至今讨论的基本 Neutron 概念。我将演示创建和连接独立的 Neutron 路由器到项目和外部提供者网络,以为实例提供网络连接。
将创建一个基于 VLAN 的提供者网络,并将其用作 Neutron 路由器的外部网关网络,而基于 VLAN 的项目网络将被创建并供实例使用。一个 Neutron 路由器将被创建,并用于将项目网络中的实例流量路由到互联网,同时浮动 IP 将被创建并用于为实例提供直接连接。
设置基础
在本演示中,Cisco 自适应安全设备(ASA)充当物理网络网关设备,并连接到互联网。以下网络将被使用:
| VLAN 名称 | VLAN ID | 网络 |
|---|---|---|
| GATEWAY_NET | 30 | 10.30.0.0/24 |
| PROJECT_NET | auto | 192.168.200.0/24 |
Cisco ASA 的内部接口已配置了 IP 地址 10.30.0.1/24,并位于 VLAN 30,将作为下一节中创建的外部提供者网络的网关。
以下图示是此演示中将构建的网络的逻辑图:

在上述图示中,Cisco ASA 充当了 OpenStack 云前端的外部网络设备。
创建外部提供者网络
为了为实例提供外部连接,必须将 Neutron 路由器连接到可以用作外部网络的提供者网络。
使用openstack network create命令,在管理员项目中创建一个提供者网络,具有以下属性:
-
名称:GATEWAY_NET
-
类型:VLAN
-
分段 ID:30
-
物理网络:physnet1
-
外部:True
以下截图显示了openstack network create命令的输出结果:

使用openstack subnet create命令,创建一个具有以下属性的子网:
-
名称:GATEWAY_SUBNET
-
网络:10.30.0.0
-
子网掩码:255.255.255.0
-
网关:10.30.0.1
-
DHCP:禁用
-
分配池:10.30.0.100 - 10.30.0.254
以下截图展示了openstack subnet create命令的输出结果:

创建 Neutron 路由器
使用openstack router create命令创建一个路由器,并指定以下属性:
- 名称:MyLegacyRouter
以下截图展示了openstack router create命令的输出结果:

将路由器连接到外部网络
将 Neutron 路由器连接到外部网络时,相应的网络必须将其router:external属性设置为True,以便作为外部网络使用。否则,命令将失败。之前创建的GATEWAY_NET网络满足此要求。
使用openstack router set命令,将路由器MyLegacyRouter连接到GATEWAY_NET网络:
openstack router set --external-gateway GATEWAY_NET MyLegacyRouter
命令成功执行后不会返回输出。使用openstack port list命令,确定路由器的外部 IP 地址:

在本例中,分配给路由器外部接口的 IP 地址是10.30.0.106。
确定 L3 代理和命名空间
一旦网关接口添加完成,路由器将被调度到一个合适的 L3 代理。使用openstack network agent list命令,你可以确定路由器被调度到哪个 L3 代理:

在本例中,路由器被调度到controller01节点。在运行多个L3代理的环境中,一个独立的路由器可以调度到任何一个代理,但在任何给定时间只能调度到一个代理。
L3 代理负责创建一个网络命名空间,作为虚拟路由器。为了便于识别,命名空间的名称会包含路由器的 ID。可以使用ip netns list命令列出节点上的所有网络命名空间:

在各自的 qrouter 命名空间内,你会找到一个前缀为qg的接口。qg接口是路由器的网关或外部接口。Neutron 会自动从外部网络子网的分配池中为qg接口分配一个 IP 地址:

在上述截图中,IP 地址 10.30.0.106 已经在命名空间内部的外部接口上自动配置。
当使用 Open vSwitch 接口驱动程序时,qg接口直接连接到集成桥接。当使用 Linux 桥接接口驱动程序时,如本示例所示,qg接口是一个 veth 对的一端,另一端连接到主机上的 Linux 桥接。
使用 ethtool,我们可以确定主机上相应接口的对端索引。这对于排除网络命名空间内外的连接问题非常有用:

使用主机上的ip link show,可以通过在控制器上查找索引来找到相应的接口(对端索引 16):

输出方便地显示了使用link-netnsid标识符的相应网络命名空间。在此示例中,对端接口位于 ID 为 3 的网络命名空间中,通常称为qrouter-9ef2eeed-4a55-4f64-b8be-4b07a43ec373。
ip link show中的 link-netnsid ID 应与ip netns list命令输出中提供的命名空间对应。
当使用 Linux 桥接接口驱动程序时,veth 接口连接到与此处显示的外部网络对应的桥接。

为了便于识别,桥接名称包括 Neutron 网络 ID 的前十个字符。此外,每个 veth 对的两端也包括与接口相关联的端口 ID 的前十个字符。
命名空间能够通过桥接与同一子网中的其他设备进行通信。桥中的另一个接口eth2.30在流量离开桥接并通过物理接口eth2时,会将流量标记为VLAN 30。
查看命名空间中的路由表。默认网关地址与外部提供者子网中gateway_ip属性定义的地址对应。在此例中,地址为10.30.0.1:

在此示例环境中,10.30.0.1已在 Cisco ASA 上配置,并将作为 Neutron 路由器出站流量的下一跳网关。
测试网关连接性
要测试从 Neutron 路由器的外部连接性,可以从路由器命名空间中 ping 边缘网关设备:

从路由器命名空间到物理网关设备的 ping 测试成功,表明物理和虚拟网络组件上的外部 VLAN 配置正确。
创建内部网络
在 admin 项目中,为实例创建一个内部网络。在此示范中,将创建一个具有以下属性的网络:
- 名称:PROJECT_NET
以下截图展示了openstack network create命令的结果输出:

请注意,Neutron 如何自动确定网络的类型、物理网络和分段 ID。由于执行openstack network create命令时未指定特定的提供者属性,Neutron 依赖插件配置文件中的配置来确定创建的网络类型。
在 ML2 配置文件中使用以下配置选项来确定网络类型、物理网络和分段 ID:
tenant_network_types = vlan,vxlan
network_vlan_ranges = physnet1:40:43
请记住,在此配置中,Neutron 将在创建网络之前消耗所有可用的 VLAN 分段 ID,然后才会转到 VXLAN 网络。
使用openstack subnet create命令,创建一个具有以下属性的子网:
-
名称:PROJECT_SUBNET
-
网络:192.168.200.0
-
子网掩码:255.255.255.0
-
网关:
-
DHCP 范围:
-
DNS Nameserver:8.8.8.8
输出应类似于以下内容:

将路由器连接到内部网络
使用openstack router add subnet命令,将PROJECT_SUBNET子网连接到MyLegacyRouter:
# openstack router add subnet MyLegacyRouter PROJECT_SUBNET
如果命令成功,则不会提供任何输出。使用openstack port list命令,确定路由器的内部 IP:

在这个示例中,分配给路由器内部接口的 IP 地址是192.168.200.1。当在将路由器连接到子网时没有指定端口 ID 或 IP 地址时,分配给路由器内部接口的 IP 地址默认作为该子网的gateway_ip地址。
在路由器命名空间内,已添加一个前缀为qr的新接口。qr接口是路由器的内部接口:

使用 Open vSwitch 接口驱动时,接口直接连接到集成桥。使用 Linux 桥接口驱动时,如本示例所示,每个qr接口是 veth 对的一端,另一端连接到主机上的桥接:

为了便于识别,桥接名称包含了相应 Neutron 网络 ID 的前十个字符。此外,veth 对的每一端还包括与接口关联的 Neutron 端口 ID 的前十个字符。
路由器命名空间能够通过桥接与同一子网中的其他设备通信。桥接中的eth2.43接口在流量离开桥并传送到父接口eth2时,将流量标记为VLAN 43。
创建实例
创建两个具有以下特征的实例:
| 名称 | 网络 | 镜像 | 规格 | 主机 |
|---|---|---|---|---|
| MyInstance1 | PROJECT_NET | cirros-0.4.0 | tiny | compute01 |
| MyInstance2 | PROJECT_NET | cirros-0.4.0 | tiny | compute02 |
如有需要,可以使用openstack image list命令来确定在第二章中下载的 CirrOS 镜像的 ID,安装 OpenStack:
使用以下openstack server create命令启动两个位于PROJECT_NET网络的compute节点上的实例:
openstack server create \
--flavor tiny \
--image cirros-0.4.0 \
--nic net-id=PROJECT_NET \
--availability-zone nova:compute01 \
MyInstance1
openstack server create \
--flavor tiny \
--image cirros-0.4.0 \
--nic net-id=PROJECT_NET \
--availability-zone nova:compute02 \
MyInstance2
可以使用openstack server list命令返回实例列表及其 IP 地址:

在compute01上,已创建一个与PROJECT_NET网络对应的 Linux 桥接器。当连接到该桥接器时,我们可以找到一个VLAN接口和与MyInstance1对应的 tap 接口:

当使用 Linux 桥接代理时,桥接器对应于各个网络,且其名称将带有 brq 前缀。
在compute02上,我们可以找到与MyInstance2对应的 tap 接口,该接口连接到专用的 Linux 桥接器,并且与相应端口相连接:

当与iptables_hybrid防火墙驱动程序一起使用 Open vSwitch 代理时,桥接器对应于各个端口,且其名称将带有qbr前缀。这些桥接器仅用于克服 iptables 在 Open vSwitch 虚拟交换机中的限制。
验证实例连接性
当创建网络和子网并启用 DHCP 时,DHCP 代理将创建一个网络命名空间,作为该网络的 DHCP 服务器。在运行 Neutron DHCP 代理服务的主机上,可以使用ip netns list命令查看命名空间。为了便于识别,DHCP 命名空间的名称与其所服务的网络 ID 相对应:

在命名空间内,已创建一个以ns为前缀的接口,并从子网的分配池中分配了一个地址:

当配置一个 DHCP 代理以使用 Open vSwitch 接口驱动时,命名空间内的ns接口将直接连接到集成桥接器。当 DHCP 代理配置为使用 Linux 桥接接口驱动时,如本例所示,ns接口是 veth 对的一端,另一端连接到主机上的桥接器。通过相应的桥接器和 VLAN,命名空间能够与同一子网中的其他设备进行通信。
随着实例上线,它们会发送一个 DHCP 请求,由 DHCP 命名空间中的dnsmasq进程处理。命名空间内填充的 ARP 表确认实例在 VLAN 的第二层(Layer 2)中正常工作:

L2 人口驱动程序用于预填充 ARP 和转发表,以减少覆盖网络上的开销,并且可能无法提供这些网络中连接的准确图景。如果条目处于永久状态,则表示它已被静态编程,可能无法反映实际的可达性。
在你连接到实例之前,必须更新安全组规则,以允许 ICMP 和 SSH。第八章,管理安全组,更详细地讲解了安全组规则的实现和管理。为了测试连接性,请向应用于实例的安全组添加 ICMP 和 SSH 访问。使用以下命令确定这些实例的安全组:
# openstack port list --server MyInstance1 --long -c 'Security Groups' # openstack port list --server MyInstance2 --long -c 'Security Groups'
输出可能类似于以下内容:

使用openstack security group rule create命令在相应的安全组内创建规则,允许入站的 ICMP 和 SSH:

使用 SSH 命令,从路由器或 DHCP 命名空间连接到实例MyInstance1。CirrOS 镜像内置了一个名为 cirros 的用户,密码为gocubsgo:

如下所示,观察实例内部的路由表:
$ ip r
default via 192.168.200.1 dev eth0
169.254.169.254 via 192.168.200.1 dev eth0
192.168.200.0/24 dev eth0 src 192.168.200.6
192.168.200.1的默认网关是我们在本章之前创建的 Neutron 路由器。从实例中 ping 外部资源应该会成功,只要 Neutron 路由器存在外部连接:

观察默认的 NAT 行为
Neutron 路由器的默认行为是当流量从路由器的外部或网关接口离开时,对没有浮动 IP 的实例进行源地址转换(NAT)。
在controller节点上执行 eth2.43 接口的数据包捕获,该接口对应于PROJECT_NET网络,我们可以观察到从实例发出的 ICMP 流量,这些流量的源地址为实例的实际或固定 IP 地址,流量朝向路由器发送,回复也会引用相同的固定 IP 地址:

从controller节点上对应于GATEWAY_NET网络的 eth2.30 接口,我们可以观察到从实例发出的 ICMP 流量,这些流量已经通过路由器并以路由器的外部地址10.30.0.106为源地址:

查看路由器命名空间中的 iptables 链表可以看到负责此行为的 NAT 规则:

在此配置中,实例可以通过路由器与外部资源通信,只要实例发起连接。外部资源不能直接通过固定 IP 地址向实例发起连接。
分配浮动 IP
要从外部网络发起到 Neutron 路由器后面的实例的连接,必须配置浮动 IP 地址并将其与实例关联。在 OpenStack 中,浮动 IP 与对应实例接受连接的接口的 Neutron 端口相关联。
使用 openstack port list 命令,确定每个最近启动实例的端口 ID。该命令允许按设备或实例 ID 过滤结果,如下所示:

使用 openstack floating ip create 命令,创建一个浮动 IP 地址,并将其与名为 MyInstance1 的实例端口关联:

在创建时,浮动 IP 可能会显示为 DOWN 状态。一旦更改应用到网络,状态应显示为 ACTIVE。
从虚拟机操作系统内,验证实例是否仍能与外部资源通信:

在 controller01 节点上对 eth2.30 接口进行数据包捕获,我们可以观察到来自实例通过路由器的 ICMP 流量,其源 IP 对应浮动 IP 地址 10.30.0.101:

在路由器命名空间内,浮动 IP 已配置为 qg 接口的二级地址:

当浮动 IP 配置为 qg 接口的二级网络地址时,路由器能够响应来自上游网关设备及其他 Neutron 路由器或同一外部网络中设备的 ARP 请求。这样就可以通过浮动 IP 实现与实例的入站连接。
查看路由器命名空间内的 iptables 链,显示已经添加规则,将浮动 IP 和 MyInstance1 的固定 IP 进行 1:1 NAT 转换,反之亦然:

如果我们的客户端工作站能够路由到外部提供商网络,则可以通过浮动 IP 直接发起流量到实例:

重新分配浮动 IP
Neutron 提供了快速将浮动 IP 从实例或其他网络资源上解除关联,并与其他资源关联的能力。浮动 IP 的列表显示当前的关联情况:

使用 openstack floating ip unset 和 openstack floating ip set 命令,解除浮动 IP 与 MyInstance1 的关联,并将其与 MyInstance2 关联。解除关联可以在这里看到:

如果命令成功执行,则不会返回任何输出。openstack floating ip list 命令显示浮动 IP 不再与端口关联:

浮动 IP 仍然归创建它的项目所有,必须先删除该浮动 IP,才能将其分配给另一个项目。
使用openstack floating ip set命令,将浮动 IP 与MyInstance2的端口关联,如下图所示:

如果命令成功执行,将不会返回任何输出。观察路由器命名空间中的 iptables 规则,NAT 关系已被修改,MyInstance2的流量现在将显示为浮动 IP:

由于新的关联,尝试通过浮动 IP 进行 SSH 连接时,可能会在客户端机器上看到以下消息:

警告信息是一个很好的指示,表明流量正在被发送到不同的主机。清除冲突的密钥并登录到实例后,可以发现它是MyInstance2:

此时,我们已经成功地将两个实例部署在同一个虚拟路由器后,并通过浮动 IP 验证了实例之间的连通性。在下一部分,我们将探讨如何在 Horizon 仪表盘中完成相同的任务。
仪表盘中的路由器管理
在 Horizon 仪表盘中,路由器可以在“项目 | 网络 | 路由器”面板中创建和管理:

登录用户可以在此页面查看可用的路由器。
在仪表盘中创建路由器
从路由器页面,点击右上角的“创建路由器”以创建一个路由器。接下来会弹出一个向导,类似于下图所示:

输入路由器名称,选择其管理员状态,并选择适当的外部网络。点击蓝色的“创建路由器”按钮以完成操作。
在仪表盘中附加内部接口
要在仪表盘中将内部接口附加到路由器,请点击路由器以显示路由器详细信息页面,如下所示:

点击“接口”标签,显示路由器接口的详细信息:

点击“添加接口”按钮,弹出一个向导,允许你选择要添加的接口的详细信息:

从子网菜单中选择一个你希望连接到路由器的子网,并点击蓝色的提交按钮以附加接口。新附加的接口将在接口面板中显示,如下所示:

在将接口添加到路由器后,接口状态显示为“Down”是正常现象。Neutron 不会将接口标记为“Active”,直到代理完成任务。刷新仪表盘将相应更新状态。
在仪表盘中查看网络拓扑
在仪表盘中,用户可以查看基于 Neutron 管理的网络配置的网络逻辑拓扑。
点击项目|网络面板下的“网络拓扑”,查看我们之前创建的网络、路由器和实例的逻辑图:

将鼠标悬停在路由器图标上,会弹出显示有关路由器的详细信息,例如连接的端口、IP 地址和端口状态:

在仪表盘中将浮动 IP 与实例关联
仪表盘中的浮动 IP 在项目|计算面板中的实例页面上进行管理。点击希望将浮动 IP 分配给的实例旁边的操作栏菜单:

要分配浮动 IP,点击“关联浮动 IP”。此时会出现一个向导,允许你管理浮动 IP 的分配:

如果没有可分配的浮动 IP 地址,请点击加号 (+) 以创建一个。点击“关联”按钮将浮动 IP 与端口关联。
在仪表盘中取消关联浮动 IP
要在仪表盘中将浮动 IP 与实例取消关联,请点击对应实例的操作栏菜单,并选择“取消关联浮动 IP”:

将会弹出一条消息,提醒您有待处理的操作:

点击蓝色的“取消关联浮动 IP”按钮以继续执行操作。
尽管浮动 IP 已与实例取消关联,但它仍归项目所有,直到被删除之前不会返回到分配池。
总结
Neutron 路由器是 OpenStack 网络的核心组件,为用户提供灵活的网络设计,以最适合他们的应用程序。使用浮动 IP 使用户能够快速且通过编程方式为应用程序提供直接连接,同时通过使用网络地址转换(NAT)来节省有限的 IPv4 地址空间。
独立路由器容易实现,但在任何网络设计中都是单点故障。如果 L3 代理出现故障,所有分配给该代理的路由器可能会变得不可用或不可靠。在下一章中,我们将讨论 Neutron 如何通过虚拟路由冗余协议(VRRP)实现高可用性路由器,以解决传统独立路由器的许多不足之处。
第十一章:使用 VRRP 的路由冗余
在 OpenStack 的 Juno 版本中,Neutron 社区引入了实现路由高可用性的两种方法。本章重点介绍使用虚拟路由冗余协议(即 VRRP)来实现两个或多个 Neutron 路由器之间冗余的方法。关于使用分布式虚拟路由器(DVR)实现的高可用性,将在第十二章《分布式虚拟路由器》中讨论。
在上一章中,我们探讨了独立路由器的概念以及它们如何允许用户在项目网络和外部网络之间路由流量,并为用户管理的实例提供网络地址转换。在本章中,我们将覆盖以下内容:
-
使用 keepalived 和 VRRP 提供高可用性的路由
-
安装和配置额外的 L3 代理
-
演示创建和管理高可用性路由器
使用 keepalived 和 VRRP 提供冗余
Keepalived 是一个 Linux 软件包,为基于 Linux 的软件和基础设施提供负载均衡和高可用性。
虚拟路由冗余协议(VRRP)是一种首跳冗余协议,旨在通过允许两个或更多的路由器为网络的默认网关提供备份,从而提供高可用性。如果主用路由器发生故障,备份路由器将在短时间内接管该地址。VRRP 是一个开放标准,基于 Cisco 开发的专有热备份路由协议(HSRP)。
Neutron 使用 keepalived,进而利用 VRRP,为多个路由器命名空间提供故障转移。
VRRP 组
使用 VRRP,可以将一组路由器配置为充当一个虚拟路由器。VRRP 组中的路由器选举一个主路由器作为活动网关设备,网络中的主机只需将虚拟路由器地址配置为其默认网关或下一跳地址。当发生故障切换时,组中的另一个路由器将接管路由工作,而网络中主机的配置保持不变。
VRRP 虚拟路由器不应与 Neutron 虚拟路由器混淆。前者代表一个逻辑实体,而后者实际上作为一个虚拟化的路由设备存在,通常实现为网络命名空间。
在下图中,路由器 A、路由器 B 和路由器 C 组成一个虚拟路由器。在此配置中,每个路由器都有自己的 IP 地址,而虚拟路由器有自己的 IP 地址。网络中的主机将虚拟路由器地址作为其默认网关:

在前面的图示中,作为主路由器的路由器 B 负责虚拟地址192.168.1.1,并为使用该地址作为网关的主机路由流量。主路由器通过多播地址224.0.0.18向组发送 VRRP 广告,广告中包括主路由器的优先级和状态。备份路由器使用多种定时器和配置选项来判断主路由器是否失败,并据此改变其状态。
组成虚拟路由器的路由器通过多播 IP 地址224.0.0.18和 IP 协议号 112 进行通信。该通信的网络设置是自动配置的,不受安全组规则的影响,且无法由用户或操作员进行管理。
VRRP 优先级
VRRP 组中的路由器根据优先级选举主路由器。具有最高优先级的路由器被选为主路由器,而组中的其他路由器则担任备份角色。当主路由器未能向组发送其 VRRP 广告时,VRRP 组中的备份路由器将选举新的主路由器来替代失败的主路由器。
VRRP 优先级的范围是 0 到 255,255 为最高优先级。Neutron 为组中的每个路由器配置相同的优先级 50。由于路由器之间的优先级相同,因此在故障切换时,选举过程将回退到最高 IP 地址。也就是说,HA 接口上具有 IP 地址192.168.1.200的备份路由器将被选为主路由器,而具有 IP 地址192.168.1.100的路由器将被替换。
VRRP 工作模式
VRRP 组中的路由器工作模式有两种:抢占模式和非抢占模式。
抢占模式
在抢占模式下,当主路由器发生故障时,它在重新加入组并且优先级高于新选举的主路由器时,会重新成为主路由器。
非抢占模式
在非抢占模式下,当 VRRP 组中的一个路由器成为主路由器时,它将在正常工作条件下继续作为主路由器工作。如果后来为一个备份路由器分配了更高的优先级,当前活动的主路由器将继续作为主路由器,直到它发生故障。
从 OpenStack Kilo 版本开始,Neutron 配置每个路由器以非抢占模式工作,尽管将来可能会有所变化。如果用于路由器间通信的 HA 网络发生故障,失败的主路由器可能无法检测到它已经故障。它仍然可以继续作为主路由器运行,即使另一个路由器已经被选为主路由器。路由器之间的连接丧失意味着所有路由器可能无法接收到 VRRP 广告。当连接恢复后,路由器可能会进行选举,选出一个主路由器。这种故障场景不常见,但在故障排查高可用路由器的问题时需要注意。
VRRP 定时器
VRRP 中使用的定时器包括广告间隔定时器和抢占延迟定时器。
广告间隔定时器
VRRP 组中的主路由器会定期发送广告,发送间隔由广告间隔定时器设定,用以通知组中的其他路由器其运行正常。如果备份路由器在三倍于该间隔的时间内没有收到广告,它会认为自己是主路由器,并发送 VRRP 广告以启动新的主路由器选举流程。Neutron 中处于主路由器状态的路由器配置为每两秒发送一次广告。
抢占延迟定时器
当一个备份路由器收到优先级低于自身的广告时,它会在由抢占延迟定时器设定的时间内等待,然后发送 VRRP 广告以启动新的主路由器选举。这个延迟有助于路由器避免在网络波动的情况下,频繁地改变 VRRP 组成员的状态。由于 Neutron 路由器中没有启用抢占机制,因此不会配置这个定时器。
高可用路由器的网络配置
当创建一个高可用路由器时,Neutron 默认会创建一个由至少两个路由器命名空间组成的 VRRP 组。这些命名空间分布在多个运行 Neutron L3 代理的主机上,每个命名空间都会运行一个自动生成配置的 keepalived 服务。路由器之间的流量通过一个专用的网络接口进行传输,具体内容将在下一节讨论。
专用高可用网络
VRRP 组中的路由器通过专用的高可用网络相互通信。高可用路由器会自动配置一个以该接口为前缀的接口,该接口仅用于此通信。
在项目中第一次创建高可用路由器时,Neutron 会使用 CIDR 169.254.192.0/18 配置一个网络和子网。所使用的网络类型基于默认项目网络类型。每个项目仅创建一个高可用网络,并且该网络会被该项目创建的所有高可用路由器使用。如果项目中的所有高可用路由器被删除,该高可用网络将保留,并且在该项目未来创建的所有其他高可用路由器中重新使用。
Neutron 为路由器之间的 VRRP 通信创建的网络实际上并不会分配给项目。因此,这些网络在 CLI 和 GUI 中对普通用户是隐藏的。然而,网络的名称反映了关联的项目,并被 L3 代理用于标识目的。在正常情况下,一个高可用网络应保持隐藏状态,且不应由用户或管理员修改。
限制
VRRP 利用虚拟路由器标识符(VRID)通过多播与使用相同 VRID 的其他路由器交换 VRRP 协议消息,以确定哪一个是主路由器。VRID 的长度为 8 位,有效范围为 1-255。由于每个项目使用一个单一的管理网络进行路由器之间的 VRRP 通信,每个项目的高可用路由器数量最多为 255 个。
虚拟 IP
VRRP 虚拟路由器具有一个虚拟 IP 地址,可以作为网络中主机的默认网关。主路由器拥有该 IP 地址,直到发生故障切换事件,此时备份路由器成为新的主路由器,并接管该 IP 和相关的路由职责。
由于 keepalived 的限制,Neutron HA 路由器并未完全遵循至此为止描述的 VRRP 网络规范。Neutron 为一个高可用路由器分配一个虚拟 IP,并且该虚拟 IP 仅在该组的主路由器上配置。在故障切换事件中,虽然该地址会在路由器之间进行切换,但它实际上并未作为任何网络的网关地址使用。随着高可用路由器的创建,一个新的虚拟 IP 地址将分配给相应的组。
默认情况下,Neutron 从169.254.0.0/24网络分配虚拟 IP 地址。如果高可用路由器的 VRID 为 5,则分配的虚拟 IP 将是169.254.0.5。在虚拟 IP 分配过程中使用 VRID 可以确保不同节点上的高可用路由器实例之间地址的一致性,而无需将其存储在数据库中。
Neutron 并不为每个连接的子网使用虚拟地址,而是通过在keepalived 配置文件中找到的virtual_ipaddress_excluded配置节来指定路由、地址及其各自的接口,这些内容将在路由器成为该组的主路由器时进行配置。同样,当路由器成为备份路由器时,接口配置将被移除。以下截图展示了将被修改的各种接口和路由:

本章稍后将详细讨论高可用路由器的 keepalived 配置文件。
这种行为的原因是因为 keepalived 服务对已配置的虚拟地址数量有限制(最多 20 个),这可能会人为地限制附加到 Neutron 路由器的子网数量。使用virtual_ipaddress_excluded是已知的解决该限制的变通方法。
确定主路由器
在以下截图中,一个没有连接任何网关或项目网络的高可用路由器被调度到三个 L3 代理上,这些 L3 代理运行在单一的控制器和两个计算节点上:

Neutron L3 代理通常安装在控制节点或网络节点上,但也可以安装在计算节点上。特别是在配置分布式虚拟路由器时,情况尤为如此。
在前面的示例中,一个路由器充当主路由器,其他两个则作为备份。HA 接口用于路由器之间的通信。任何时候,只有主路由器的 HA 接口上应该配置虚拟 IP 地址 169.254.0.1。
安装和配置额外的 L3 代理
要配置 HA 路由器,需要两个或更多 L3 代理。在前一章中,L3 代理已安装在 controller01 节点上。在所有剩余的 compute 节点上,运行以下命令安装 L3 代理:
# apt install neutron-l3-agent
定义接口驱动
Linux 桥接和 Open vSwitch 机制驱动都支持 HA 路由器,且必须配置 Neutron L3 代理,以使用与所选机制驱动相对应的接口驱动。
在 compute 节点上更新 Neutron L3 配置文件 /etc/neutron/l3_agent.ini,并指定以下接口驱动之一:
在 compute01 上运行 Linux 桥接代理:
[DEFAULT]
...
interface_driver = linuxbridge
在 compute02 上运行 Open vSwitch 代理:
[DEFAULT]
...
interface_driver = openvswitch
设置代理模式
Neutron L3 代理将 HA 路由器视为传统路由器,因为许多用于独立路由器的相同机制也适用于 HA 路由器。因此,agent_mode 的默认值为 legacy,在本章余下部分应保持不变。
重启 Neutron L3 代理
在修改 Neutron L3 代理的配置后,在 compute 节点上执行以下命令重启代理:
# systemctl restart neutron-l3-agent
服务重启后,额外的代理应会注册。使用以下 openstack network agent list 命令列出所有 L3 代理:
# openstack network agent list --agent-type l3
输出应类似于以下内容:

如果输出中未按预期列出代理,请排查 /var/log/neutron/l3-agent.log 日志文件中可能指示的任何错误。
配置 Neutron
Neutron 使用默认设置来确定用户允许创建的路由器类型。此外,这些设置还指定了组成 VRRP 组的路由器数量、默认 HA 网络 CIDR 以及默认网络类型。
以下设置在 Neutron 配置文件 /etc/neutron/neutron.conf 中指定,仅需在运行 Neutron API 服务的主机上进行修改。在此环境中,neutron-server 服务运行在 controller01 节点上:
# Enable HA mode for virtual routers. (boolean value)
#l3_ha = false
#
# Maximum number of L3 agents which a HA router will be scheduled
# on. If it is to 0 then the router will be scheduled on every
# agent. (integer value)
#max_l3_agents_per_router = 3
#
# Subnet used for the l3 HA admin network. (string value)
#l3_ha_net_cidr = 169.254.192.0/18
#
# The network type to use when creating the HA network for an HA
# router. By default or if empty, the first 'tenant_network_types'
# is used. This is helpful when the VRRP traffic should use a
# specific network which is not the default one. (string value)
#l3_ha_network_type =
#
要将 HA 路由器设置为项目的默认路由器类型,请在 neutron.conf 中将 l3_ha 配置选项设置为 True。对于本演示,默认值 False 已足够。
设置值为 False 时,只有具有管理员角色的用户才能创建 HA 路由器。普通用户将被限制为默认路由器类型,在大多数情况下是独立路由器。
要设置虚拟路由器使用的最大 L3 代理数,请相应地设置 max_l3_agents_per_router。在本示范中,默认值已足够,这意味着将构建三个网络命名空间来组成 VRRP 虚拟路由器。
要修改用于 HA 路由器的网络类型,请更改 l3_ha_network_type 的值。默认情况下,使用的是默认项目网络类型,这对于本示范来说已足够。
如果默认项目网络类型为 vlan,VLAN 可能会比预期更快地消耗,因为每个项目可以为 HA 网络消耗一个 VLAN。
修改完成后,需在 controller 节点上重启 neutron-server 服务才能使更改生效。
使用高可用路由器
除少数例外,创建和管理高可用路由器与独立路由器没有区别。Neutron 的路由器管理命令在上一章中已经介绍,例外情况可以在以下章节找到。
创建高可用路由器
拥有管理员角色的用户可以使用 --ha 参数和如下所示的 openstack router create 命令创建高可用路由器:
openstack router create --ha ROUTER
没有管理员角色的用户没有权限覆盖默认的路由器类型,也不能指定 --ha 参数。
删除高可用路由器
要删除高可用路由器,只需使用如下所示的 openstack router delete 命令:
openstack router delete ROUTER
当项目中的所有 HA 路由器被删除后,用于路由器之间通信的 HA 网络会留下来。该网络将在稍后创建 HA 路由器时被重用。
解构高可用路由器
使用之前章节演示的概念,让我们一起完成高可用路由器的创建与解构。以下示例中,我以一个名为 GATEWAY_NET 的外部提供商网络和一个名为 PROJECT_NET 的项目网络开始:

使用带有 --ha 参数的 openstack router create 命令,我们可以创建一个名为 MyHighlyAvailableRouter 的 HA 路由器:

在创建 HA 路由器时,在最多三台运行 Neutron L3 代理的主机上创建了网络命名空间。在本示范中,L3 代理运行在 controller01 和两台计算节点上。
在下图中,可以在每个主机上观察到与 MyHighlyAvailableRouter 路由器对应的路由器命名空间:

在创建项目中的第一个 HA 路由器时,Neutron 自动创建了一个专门用于路由器间通信的网络,该网络使用 L3 代理配置文件中的 l3_ha_net_cidr 配置选项定义的网络:

HA 网络与项目没有直接关联,除了管理员外,其他人无法看到该网络,管理员能够看到所有网络。这里的输出展示了该网络的详细信息:

如你所见,project_id 字段为空,而 HA 网络的名称中包含了项目的 ID。该网络由 Neutron 用于将来该项目创建的所有 HA 路由器。
HA 网络使用默认的项目网络类型,并将消耗该类型的分段 ID。
路由器已经连接了一个网关和内部接口。使用 openstack port list 命令可以查看与路由器相关联的网关、内部和 HA 端口:

这三个 HA 端口是 Neutron 自动创建的,用于在分布在各个主机上的路由器命名空间之间进行通信。在网络命名空间内部,我们可以找到相应的接口:



在前面的截图中,compute02 上的路由器命名空间已被选为主路由器,这可以通过命名空间内 HA 接口配置的虚拟 IP 169.254.0.1/24 得到验证。除了 HA 接口,qg 和 qr 接口只会在主路由器上完全配置。如果多个路由器拥有虚拟 IP,或者你看到 qg 和 qr 接口在多个路由器上都已完全配置,则可能会出现路由器之间的通信问题,特别是在 HA 网络上。
根据 Neutron 对 keepalived 的配置,虚拟 IP 并不作为网关地址使用,而是作为一个标准化的地址,用于在 VRRP 故障转移机制中切换到其他路由器。Neutron 不会将 qg 或 qr 接口上的地址视为虚拟 IP。虚拟 IP 与 qg 和 qr 接口应该仅在主路由器上配置并保持活动状态。
你可以使用 openstack network agent list 命令,结合 --router 和 --long 参数,来确定路由器调度到的代理,并查看给定代理的 HA 状态(如果适用):

检查 keepalived 配置
Neutron 已在每个 qrouter 命名空间中配置了 keepalived,以便这些命名空间能够共同作为一个虚拟路由器。每个命名空间中都运行一个 keepalived 服务,并使用以下配置文件,该文件位于运行 L3 代理的基础主机上:
/var/lib/neutron/ha_confs/<router_id>/keepalived.conf
查看 compute02 上活动路由器的配置文件,可以看到当前正在使用的 keepalived 和 VRRP 配置:

执行故障转移
在正常情况下,一个节点不太可能发生故障,路由器故障切换的可能性也较低。可以通过手动重启托管活动路由器的节点或将其物理接口置于停用状态来重现故障场景。
故障切换操作会记录在路由器命名空间中的以下位置:
/var/lib/neutron/ha_confs/<router_id>/neutron-keepalived-state-change.log
一旦检测到故障,可以在以下截图中看到一个路由器从备份状态切换到主状态的示例:

在上面的截图中,compute01上的路由器成为了新的主路由器。在日志中,通过state_master消息可以识别这一变化。一旦原主路由器恢复连接并检测到新主路由器被选举出来,它会转到备份状态,正如在此处看到的state_backup消息所示:

总结
高可用性路由器可以使用上一章讨论的相同路由器命令集进行创建和管理。Neutron L3 代理负责配置 VRRP 组中的路由器,路由器则根据其主备状态自行选举主路由器,并实现各自的 keepalived 配置。
虽然高可用性路由器(HA 路由器)提供了比独立路由器更高的冗余级别,但它们并非没有缺点。单一节点托管主路由器仍然是经过该路由器的流量瓶颈。此外,如果用于路由器之间专用 VRRP 流量的网络出现连接中断,路由器可能会发生脑裂现象。这会导致两个或多个路由器成为主路由器,并可能引发网络中的 ARP 和 MAC 抖动问题。连接跟踪在 Pike 版本中尚未实现,这意味着在故障切换事件中,实例之间的连接可能会中断。这些问题正在积极修复,并计划在 OpenStack 的未来版本中得到解决。
在下一章中,我们将探讨如何通过称为分布式虚拟路由器(DVR)技术,将虚拟路由器分布在计算节点上,并作为各自实例的网关。
第十二章:分布式虚拟路由器
在 OpenStack 的 Folsom 版本中引入 Neutron 之前,所有网络管理都内置于 Nova API 中,并被称为 nova-network。nova-network 提供了浮动 IP 功能,网络故障域仅限于单个计算节点 —— 这是早期版本 Neutron 所缺乏的功能。nova-network 已被弃用,并且其大部分功能已经在最新版本的 Neutron 中得到了实现和改进。在上一章中,我们通过使用 VRRP 提供高可用性的活动-待命路由器。在本章中,我们将讨论分布式虚拟路由器如何借鉴 nova-network 多主机模型的许多概念,以提供高可用性和更小的网络故障域,同时保留对 Neutron 提供的许多高级网络功能的支持。
传统路由器,包括独立路由器和活动-待命路由器,兼容多种机制驱动程序,包括 Linux 桥接和 Open vSwitch 驱动程序。而分布式虚拟路由器则需要 Open vSwitch,仅由 Open vSwitch 机制驱动程序和代理支持。其他驱动程序和代理,如 OVN 或 OpenContrail 的驱动程序,可能提供类似的分布式路由功能,但不在本书讨论范围之内。
在云中分布路由器
就像 nova-network 使用其多主机功能一样,Neutron 可以将虚拟路由器分布到计算节点,以便将故障域隔离到特定的计算节点,而不是集中式网络节点。通过消除集中式的 Layer 3 代理,之前在单一节点上执行的路由现在由计算节点本身处理。
传统路由使用集中式网络节点类似于以下图示:

在传统模型中,从蓝色虚拟机到位于不同网络中的红色虚拟机的流量会经过承载路由器的集中式网络节点。如果承载路由器的节点发生故障,实例之间或实例与外部网络之间的流量将被丢弃。
在本章中,我将讨论以下内容:
-
安装并配置额外的 L3 代理以支持分布式虚拟路由器
-
演示创建和管理分布式虚拟路由器
-
在同一路由器后面的网络之间进行路由
-
使用 SNAT 的出站连接
-
使用浮动 IP 的入站和出站连接
安装并配置 Neutron 组件
配置分布式虚拟路由器时,必须满足一些要求,包括以下内容:
-
ML2 插件
-
L2 人口机制驱动程序
-
Open vSwitch 机制驱动程序
-
在所有网络和计算节点上安装 Layer 3 代理
在本书构建的环境中,单一控制节点处理 OpenStack API 服务、DHCP 和元数据服务,并运行 Linux 桥接代理,用于独立路由器和高可用路由器(HA)。compute01运行 Linux 桥接代理,而compute02和compute03运行 Open vSwitch 代理。另一个节点snat01将运行 Open vSwitch 代理,并负责在使用分布式虚拟路由器时处理出站 SNAT 流量。
该配置的示意图如下:

尽管由于 ML2 核心插件的支持,节点之间可以混合使用驱动程序和代理,但这种设计在生产环境中并不常见。如果在使用分布式虚拟路由器的网络上部署,部署在compute01上的实例可能会遇到连接问题。
安装额外的 L3 代理
在snat01上运行以下命令以安装L3代理:
# apt install neutron-l3-agent
定义接口驱动程序
必须使用 Open vSwitch 和 Open vSwitch 机制驱动程序才能启用和使用分布式虚拟路由器。
更新snat01上/etc/neutron/l3_agent.ini中的 Neutron L3 代理配置文件,并指定以下接口驱动程序:
[DEFAULT]
...
interface_driver = openvswitch
启用分布式模式
操作分布式虚拟路由器需要安装 ML2 插件,并且必须进行相应的配置。
更新compute02、compute03和snat01上的/etc/neutron/plugins/ml2/openvswitch_agent.ini中的 OVS 配置文件,以使 OVS 代理支持分布式虚拟路由和L2人口填充:
[agent]
...
enable_distributed_routing = True
l2_population = True
设置代理模式
使用分布式虚拟路由器时,节点可以操作两种模式之一:dvr或dvr_snat。配置为dvr_snat模式的节点处理南北向 SNAT 流量,而dvr模式的节点处理南北向 DNAT(例如浮动 IP)流量以及实例之间的东西向流量。
运行 Open vSwitch 代理的计算节点处于 dvr 模式。集中式网络节点通常运行dvr_snat模式,并可能作为没有使用浮动 IP 的实例的网络单点故障。
Neutron 支持使用 VRRP 部署高可用的dvr_snat节点,但这超出了本书的范围。
在本书中,snat01节点将专门用于处理使用分布式虚拟路由器时的 SNAT 流量,因为controller01已经配置为 Linux 桥接代理,并且不适合作为 DVR 相关功能的主机。
在snat01节点上,通过修改 L3 代理配置文件中的agent_mode选项,将 L3 代理配置为运行dvr_snat模式:
[DEFAULT]
...
agent_mode = dvr_snat
在compute02和compute03节点上,将 L3 代理从legacy模式修改为dvr模式:
[DEFAULT]
...
agent_mode = dvr
在snat01、compute02和compute03节点上,将handle_internal_only_routers配置选项设置为false:
[DEFAULT]
...
handle_internal_only_routers = false
配置 Neutron
Neutron 使用默认设置来确定用户允许创建的路由器类型以及应该在 L3 代理中部署的路由器数量。
以下默认设置已在neutron.conf配置文件中指定,且仅需在运行 Neutron API 服务的主机上修改。在此环境中,neutron-server 服务运行在 controller01 节点上。默认值如下所示:
# System-wide flag to determine the type of router
# that tenants can create.
# Only admin can override. (boolean value)
#
# router_distributed = false
若要将分布式路由器设置为项目的默认路由器类型,请将 router_distributed 配置选项设置为 true。在本演示中,默认值 false 已足够。
一旦更改完成,在controller01上重启neutron-server服务以使更改生效:
# systemctl restart neutron-server
重新启动 Neutron L3 和 Open vSwitch 代理
在对 Neutron L3 和 L2 代理的配置进行更改后,在compute02、compute03 和 snat01 上执行以下命令以重新启动相应的代理:
# systemctl restart neutron-l3-agent neutron-openvswitch-agent
在服务重启后,额外的代理应该会登录。使用以下openstack network agent list命令返回所有 L3 代理的列表:
# openstack network agent list --agent-type="l3"
输出应类似于以下内容:

如果代理未按预期列出在输出中,请在相应节点的/var/log/neutron/l3-agent.log日志文件中排查可能的错误。
管理分布式虚拟路由器
除了一些例外,管理分布式路由器与管理独立路由器没有太大区别。Neutron 的路由器管理命令已在 第十章,使用 Neutron 创建独立路由器 中进行介绍。以下部分将介绍这些例外情况。
创建分布式虚拟路由器
拥有管理员角色的用户可以使用openstack router create命令的--distributed参数创建分布式虚拟路由器,示例如下:
openstack router create --distributed NAME
没有管理员角色的用户受限于 Neutron 配置文件中 router_distributed 配置选项指定的路由器类型。用户无法覆盖默认路由器类型,也不能指定 --distributed 参数。
在实例之间路由东西向流量
在网络世界中,东西向流量传统上定义为服务器到服务器的流量。在 Neutron 中,涉及分布式虚拟路由器时,东西向流量是指位于同一项目中不同网络的实例之间的流量。在 Neutron 的传统路由模型中,不同网络之间的流量会经过位于集中式网络节点的虚拟路由器。而使用 DVR(分布式虚拟路由器)时,流量会绕过网络节点,直接在托管虚拟机实例的计算节点之间进行路由。
审查拓扑结构
从逻辑上讲,分布式虚拟路由器是一个连接两个或多个项目网络的单一路由器对象,如下图所示:

在下面的示例中,一个名为 MyDistributedRouter 的分布式虚拟路由器已经创建,并连接到两个项目网络:BLUE_NET 和 RED_NET。每个网络中的虚拟机实例使用各自的默认网关,通过相同的路由器将流量路由到另一个网络。虚拟机实例并不知道路由器的位置。
然而,揭开它的外壳,却会得出不同的结论。在以下示例中,蓝色虚拟机(VM)向红色虚拟机(VM)发送 ping,流量会按预期路由和转发:

对用户来说,连接两个网络的路由器是一个名为 MyDistributedRouter 的单一实体:

使用 ip netns exec 命令,我们可以看到每个计算节点和 SNAT 节点上的命名空间内的 qr 接口共享相同的接口名称、IP 地址和 MAC 地址:

在上面的截图中,snat01 和 compute 节点上与分布式路由器相对应的 qrouter 命名空间包含相同的 qr-841d9818-bf 和 qr-d2ce8f82-d8 接口及其地址,这些接口分别对应 BLUE_NET 和 RED_NET 网络。通过巧妙使用路由表和 Open vSwitch 流规则,可以使同一分布式路由器后面的实例之间的流量直接在计算节点之间路由。这个功能背后的技巧将在接下来的章节中讨论。
连接它
当分布式虚拟路由器通过 OpenStack router add subnet 或 add port 命令连接到子网时,路由器会被调度到所有在子网上托管端口并运行 Open vSwitch 代理的节点,包括任何托管 DHCP 或负载均衡器命名空间的控制器或网络节点,以及任何托管虚拟机实例的计算节点。L3 代理负责在每个节点上创建相应的 qrouter 网络命名空间,而 Open vSwitch 代理则将路由器接口连接到桥接器并配置适当的流规则。
分配路由器端口
如果没有采取适当的预防措施,将具有相同 IP 和 MAC 地址的端口分配到多个计算节点会在网络中产生重大问题。可以想象一个物理拓扑,如下图所示:

在大多数网络中,由多个具有相同 IP 和 MAC 地址的路由器连接到交换机的环境,会导致交换机不断学习和重新学习 MAC 地址在不同交换机端口上的位置。这种行为通常被称为 MAC 颤动,最终导致网络不稳定和不可靠。
虚拟交换机可能表现出相同的行为,无论分割类型如何,因为虚拟交换机可能会学习到 MAC 地址同时存在于计算节点的本地和远程位置,导致观察到与物理交换机相似的行为。
让它工作
为了解决这种预期的网络行为,Neutron 为每个计算节点分配了一个唯一的 MAC 地址,每当来自分布式虚拟路由器的流量离开节点时使用。以下截图显示了在此演示中为节点分配的唯一 MAC 地址:

Open vSwitch 流规则用于在流量离开具有分配给各自主机的唯一 MAC 地址的路由器接口时重写数据包的源 MAC 地址。在下图中,查看compute02提供者桥上的流量,演示了将非唯一qr接口 MAC 地址重写为分配给compute02的唯一 MAC 地址的过程:

同样地,当流量进入与本地虚拟机实例的 MAC 地址和分割 ID 匹配的计算节点时,源 MAC 地址从唯一源主机 MAC 地址重写为本地实例网关 MAC 地址:

因为 Layer 2 头重写发生在流量进入和离开虚拟机实例之前,实例对帧的更改是不知情的,并且正常运行。以下部分详细演示了这个过程。
演示实例间的流量
想象一个场景,不同网络中的虚拟机存在于两个不同的计算节点上,如下图所示:

从计算节点 A 上的蓝色虚拟机实例到计算节点 B 上的红色虚拟机实例的流量将首先从实例转发到其本地网关,通过集成桥到达路由器命名空间,如下图所示:

| 源 MAC | 目的 MAC | 源 IP | 目的 IP |
|---|---|---|---|
| 蓝色虚拟机 | 蓝色路由器接口 | 蓝色虚拟机 | 红色虚拟机 |
计算节点 A 上的路由器将从蓝色虚拟机到红色虚拟机的流量路由,将源 MAC 地址替换为其红色接口,目的 MAC 地址替换为红色虚拟机的 MAC 地址:
| 源 MAC | 目的 MAC | 源 IP | 目的 IP |
|---|---|---|---|
| 红色路由器接口 | 红色虚拟机 | 蓝色虚拟机 | 红色虚拟机 |
然后路由器将数据包发送回集成桥,随后转发到提供者桥,如下图所示:

当流量到达 ComputeA 的提供商桥时,会处理一系列流规则,导致源 MAC 地址从路由器的红色接口更改为主机的唯一 MAC 地址:
| 源 MAC | 目的 MAC | 源 IP | 目的 IP |
|---|---|---|---|
| 源主机(Compute A) | 红色虚拟机 | 蓝色虚拟机 | 红色虚拟机 |
然后,流量被转发到物理网络,并传送到 Compute B:

当流量到达 Compute B 时,会通过提供商桥进行转发。一个流规则会添加一个本地 VLAN 头,允许流量在转发到集成桥时进行匹配:

| 源 MAC | 目的 MAC | 源 IP | 目的 IP |
|---|---|---|---|
| 源主机(Compute A) | 红色虚拟机 | 蓝色虚拟机 | 红色虚拟机 |
在集成桥接器中,一个流规则会去掉本地 VLAN 标签,并将源 MAC 地址更改回路由器的红色接口地址。然后,数据包将被转发到红色虚拟机:

| 源 MAC | 目的 MAC | 源 IP | 目的 IP |
|---|---|---|---|
| 红色路由器接口 | 红色虚拟机 | 蓝色虚拟机 | 红色虚拟机 |
从红色虚拟机到蓝色虚拟机的返回流量经过相应的路由器和每个计算节点上的桥接器,沿着类似的路由路径。
集中式 SNAT
源 NAT,简称 SNAT,是指在数据包离开路由器接口时更改其源地址的方法。当 Neutron 路由器从外部网络分配到一个 IP 地址时,该 IP 将用于表示来自路由器后方虚拟机实例的流量,这些虚拟机没有浮动 IP。在 Neutron 中的所有路由器,无论是独立的、高可用的,还是分布式的,都支持 SNAT,并且在没有使用浮动 IP 时,会伪装来自路由器后方的流量。
默认情况下,处理 SNAT 的路由器是集中在单个节点上的,并且不可高可用,这会导致给定网络的单点故障。作为解决方法,可以配置多个节点处于dvr_snat模式。Neutron 支持利用 VRRP 来提供高可用的 SNAT 路由器,但该功能仍处于实验阶段,本书中不讨论。
查看拓扑结构
在这个 DVR SNAT 演示中,将使用以下提供商和项目网络:

使用--distributed参数,创建了一个分布式虚拟路由器:

在这个环境中,主机snat01上的 L3 代理处于dvr_snat模式,并作为集中式SNAT节点。将路由器附加到项目网络GREEN_NET,会将该路由器调度到snat01主机:

当在GREEN_NET网络中启动实例时,路由器也会调度到相应的计算节点。
此时,snat01和compute03节点各自都有一个与MyOtherDistributedRouter路由器对应的qrouter命名空间。将路由器连接到外部网络后,会在snat01节点创建一个snat命名空间。现在,在snat01节点上,存在同一个路由器的两个命名空间——snat和qrouter:

这个配置可以通过以下图示表示:

snat01节点上的qrouter命名空间的配置与compute03节点上的qrouter命名空间相似。snat命名空间用于集中式 SNAT 服务。
在snat01节点上,查看qrouter命名空间内的接口:

与传统路由器的qrouter命名空间不同,即使路由器已连接到外部网络,qrouter命名空间中也没有qg接口。
然而,查看snat命名空间内的内容,我们可以找到qg接口,用于处理来自实例的出站流量:

除了qg接口之外,现在还有一个以sg为前缀的新接口。每个虚拟路由器会为它连接的每个内部网络配置一个qr接口和一个新的sg接口。sg接口用于在流量进行源 NAT 时作为额外的跳跃点,详细内容将在接下来的章节中解释。
使用路由策略数据库
当一个没有浮动 IP 的虚拟机实例向外部网络(如互联网)发送流量时,流量会进入计算节点上的本地qrouter命名空间,并被路由到集中式network节点上的snat命名空间。为了实现这个任务,qrouter命名空间内设置了特定的路由规则。
Linux 提供了一个由多个路由表和规则组成的路由策略数据库,允许基于目标和源地址、IP 协议、端口等进行智能路由。每个虚拟路由器连接的每个子网都有源路由规则。
在这个示例中,路由器连接到单个项目网络:172.24.100.0/24。查看compute01节点上qrouter命名空间中的主路由:

请注意,主路由表中没有默认路由。
在计算节点上,从qrouter命名空间中使用ip rule命令列出 Neutron 代理创建的额外路由表和规则:

2887279617号路由表是由 Neutron 创建的。查询额外的路由表后,找到默认路由:

从该输出中,我们可以看到 172.24.100.11 是默认网关地址,且对应于集中式节点中 snat 命名空间内的 sq 接口。当流量到达 snat 命名空间时,会执行源 NAT,并且流量会从 qg 接口路由出去。
跟踪数据包通过 SNAT 命名空间
在以下示例中,绿色虚拟机将流量发送到 8.8.8.8,一个 Google DNS 服务器:

| 源 MAC | 目标 MAC | 源 IP | 目标 IP |
|---|---|---|---|
| 绿色虚拟机 | 绿色路由器接口(qr1) |
绿色虚拟机 | 8.8.8.8(Google DNS) |
当流量到达本地 qrouter 命名空间时,会查询主路由表。目标 IP 8.8.8.8 并不匹配任何直接连接的子网,并且不存在默认路由。接下来会查询次级路由表,基于源接口找到匹配项。然后,路由器将流量从绿色虚拟机路由到 SNAT 命名空间的绿色接口 sg1,通过本章前面讨论的东西向路由机制:

| 源 MAC | 目标 MAC | 源 IP | 目标 IP |
|---|---|---|---|
| 绿色路由器接口(qr1) | 绿色 SNAT 接口(sg1) | 绿色虚拟机 | 8.8.8.8(Google DNS) |
当流量进入 snat 命名空间时,它会被路由到 qg 接口。命名空间内的 iptables 规则会将源 IP 和 MAC 地址更改为 qg 接口的地址,以确保流量能够正确地路由回去:

| 源 MAC | 目标 MAC | 源 IP | 目标 IP |
|---|---|---|---|
外部 SNAT 接口(qg) |
物理默认网关 | 外部 SNAT 接口(qg) |
8.8.8.8(Google DNS) |
当远程目标响应时,集中式网络节点和计算节点上的流规则与连接跟踪和 NAT 表中的数据相结合,确保响应能正确路由回绿色虚拟机,并且带有适当的 IP 和 MAC 地址。
通过分布式虚拟路由器的浮动 IP
在网络世界中,南北流量传统上被定义为客户端到服务器的流量。在 Neutron 中,涉及到分布式虚拟路由器时,南北流量指的是来自外部网络的流量,流向使用浮动 IP 的虚拟机实例,或反之亦然。
在传统模型中,所有来自外部客户端的流量都要通过托管有浮动 IP 路由器的集中式网络节点。使用 DVR 时,同样的流量避开了网络节点,直接路由到托管虚拟机实例的计算节点。此功能要求计算节点通过外部桥接直接连接到外部网络——这一配置直到现在仅见于托管独立路由器或高可用路由器的节点。
引入 FIP 命名空间
与 SNAT 流量不同,通过浮动 IP 与 DVR 的流量是在单独的计算节点上处理的,而不是在集中节点上处理。当浮动 IP 附加到虚拟机实例时,计算节点上的 L3 代理会创建一个新的fip命名空间,该命名空间对应于浮动 IP 所属的外部网络(如果该命名空间尚不存在):

连接到同一外部网络的计算节点上的任何路由器命名空间都共享一个单一的 fip 命名空间,并通过 veth 对与该命名空间相连。veth 对被视为 fip 命名空间与各个 qrouter 命名空间之间的点对点链接,并使用公共的169.254/16链路本地地址空间作为/31网络进行寻址。由于命名空间之间的网络连接仅存在于节点内部,并且作为点对点链接使用,因此不需要 Neutron 项目网络分配。
在qrouter命名空间中,veth 对的一端具有前缀rfp,表示路由器到 FIP:

在fip命名空间内部,veth 对的另一端具有前缀fpr,表示 FIP 到路由器:

除了fpr接口外,FIP 命名空间内部还可以找到一个前缀为 fg 的新接口。rfp、fpr和fg接口将在接下来的部分中讨论。
追踪数据包通过 FIP 命名空间
当浮动 IP 分配给实例时,会发生以下几件事:
-
如果外部网络的 fip 命名空间在计算节点上不存在,则会创建一个。
-
计算节点上 qrouter 命名空间中的路由表已被修改。
以下部分演示了如何处理浮动 IP 的进出流量。
从具有浮动 IP 的实例发送流量
想象一个场景,其中浮动 IP10.30.0.107已经分配给下图所示的绿色虚拟机:

当172.24.100.6的绿色虚拟机实例向外部资源发送流量时,它首先到达本地qrouter命名空间:

| 源 MAC | 目的 MAC | 源 IP | 目的 IP |
|---|---|---|---|
| 绿色虚拟机 | 绿色 qr 接口 | 绿色虚拟机固定 IP(172.24.100.6) | 8.8.8.8(Google DNS) |
当流量到达本地 qrouter 命名空间时,会查询路由策略数据库,以便可以相应地路由流量。在将浮动 IP 关联到端口时,会在 qrouter 命名空间的路由表中添加一个源路由规则:

在具有更高优先级的 qrouter 命名空间中的主要路由表没有默认路由,因此57481:来自172.24.100.6的查找 16 规则被匹配。
查看引用的路由表 16,可以看到 fip 命名空间的 fpr 接口是从实例固定 IP 源发送流量的默认路由:

qrouter 命名空间执行将固定 IP 转换为浮动 IP 的 NAT 翻译,并将流量发送到 fip 命名空间,以下图所示:

| 源 MAC | 目标 MAC | 源 IP | 目标 IP |
|---|---|---|---|
rfp 接口 |
fpr 接口 |
绿色 VM 浮动 IP(10.30.0.107) |
8.8.8.8(Google DNS) |
一旦流量到达 fip 命名空间,它会通过 fg 接口转发到其默认网关:

| 源 MAC | 目标 MAC | 源 IP | 目标 IP |
|---|---|---|---|
fg 接口 |
物理默认网关 | 绿色 VM 浮动 IP(10.30.0.107) |
8.8.8.8(Google DNS) |
将流量返回到浮动 IP
如果你还记得本章前面提到的,计算节点上的单个 fip 命名空间由连接到外部网络的该节点上的每个 qrouter 命名空间共享。就像独立或高可用路由器在其 qg 接口上有一个来自外部网络的 IP 地址一样,每个 fip 命名空间在其 fg 接口上也配置了来自外部网络的唯一 IP 地址。
在 compute03 上,IP 地址是 10.30.0.113:

与传统路由器不同,分布式路由器的 qrouter 命名空间无法直接连接到外部网络。然而,qrouter 命名空间仍然负责将固定 IP 转换为浮动 IP 的 NAT 操作。之后,流量被路由到 fip 命名空间,然后继续转发到外部网络。
使用代理 ARP
浮动 IP 被配置在 qrouter 命名空间的 rfp 接口上,但由于 fip 命名空间位于 qrouter 命名空间和外部网络之间,因此无法直接从外部网络的网关访问。
为了允许流量通过 fip 命名空间路由回 qrouter 命名空间,Neutron 依赖于代理 ARP 的使用。通过自动在 fg 接口上启用代理 ARP,fip 命名空间能够代表浮动 IP 响应来自上游网关设备的浮动 IP 的 ARP 请求。
当流量从网关设备路由到 fip 命名空间时,路由表会被查询,并且流量会被路由到相应的 qrouter 命名空间:

以下图演示了在这种情况下代理 ARP 是如何工作的:

fg 接口位于 fip 命名空间内,代表 qrouter 命名空间进行响应,因为 qrouter 并未直接连接到外部网络。通过使用单一的 fip 命名空间和代理 ARP,消除了为每个 qrouter 命名空间提供外部网络上自己 IP 地址的需求,从而减少了不必要的 IP 地址消耗,并使更多浮动 IP 可供虚拟机实例和其他网络资源使用。
总结
分布式虚拟路由器通过避免传统模型中出现的瓶颈和单点故障,对整个网络架构产生了积极影响。东西向和南北向流量可以在计算节点之间进行路由和转发,从而实现更高效、更具弹性的网络。SNAT 流量仅限于集中节点,但目前已经有高可用 SNAT 路由器处于实验状态,并将在 OpenStack 的未来版本中准备投入生产使用。
虽然分布式虚拟路由器有助于提供与 nova-network 的多主机能力一致的功能,但它们在操作上比较复杂,如果出现问题,相比独立路由器或高可用路由器,故障排除难度较大。
在下一章中,我们将介绍被称为负载均衡即服务(LBaaS)的高级网络服务及其参考架构,使用 haproxy 插件。LBaaS 允许用户创建和管理负载均衡器,这些负载均衡器可以在多个虚拟机实例之间分配工作负载。通过 Neutron API,用户可以快速扩展应用程序,同时提供弹性和高可用性。
第十三章:将流量负载均衡到实例
Neutron 的负载均衡即服务(LBaaS v2)插件,允许用户将流量负载均衡到运行在云中虚拟实例上的应用程序。Neutron 提供一个 API 来管理负载均衡器、监听器、池、成员和健康检查器。
本章将介绍一些基本的负载均衡概念,包括以下内容:
-
监听器、池和池成员
-
负载均衡算法
-
健康检查器
-
会话保持
Neutron 使用驱动程序与硬件或软件负载均衡器进行交互。在 Pike 版本中,参考驱动程序在网络命名空间内部署 HAProxy。HAProxy 是一个免费的开源负载均衡器,适用于大多数基于 Linux 的操作系统。Octavia 是另一个兼容 LBaaS v2 API 的开源负载均衡解决方案。然而,Octavia 不使用网络命名空间,而是启动并管理一组虚拟机、容器或裸机服务器,这些服务器被称为 amphorae,充当负载均衡器。这样,Octavia 可以实现横向扩展和按需扩展。部署 Octavia 和其他第三方驱动程序(如 F5、Citrix、Radware 等供应商提供的驱动程序)是可能的,但超出了本书的范围。
本章将详细讲解以下内容:
-
将负载均衡器集成到网络中
-
安装并配置 LBaaS v2 代理
-
创建负载均衡器
-
演示流量负载均衡到实例
负载均衡基础
负载均衡器是一个表示虚拟 IP 的对象,并与 Neutron 端口相关联。虚拟 IP 通常暴露到互联网,并映射到域名,以提供对面向互联网的负载均衡服务的访问。虚拟 IP 也可以为仅限内部客户端的服务创建。流量将被分配到池成员之间,并为应用程序提供扩展性和弹性。
Neutron 中负载均衡器有四个主要组件:
-
池成员
-
池
-
健康检查器
-
监听器
池成员是一个层 4 对象,表示服务或应用程序的 IP 地址和监听端口。例如,一个池成员可能是一个 Web 服务器,配置的 IP 地址为 192.168.0.2,监听 TCP 端口 80。
池是一个池成员的集合,池成员通常提供相同的内容。由 Web 服务器组成的池可能类似于以下成员配置:
-
服务器 A:192.168.0.2:80
-
服务器 B:192.168.0.4:80
-
服务器 C:192.168.0.6:80
健康检查器是一个对象,表示对池成员进行健康检查操作,该操作按定义的间隔时间运行。当健康检查失败时,池成员会被标记为 DOWN,并从池中移除,直到其通过后续的检查。与此同时,流量将被引导到健康的成员。
监听器是一个对象,表示与虚拟 IP 相关联的 4 层端口,用于监听传入到 VIP 的连接。负载均衡器可以在多个端口上监听连接,每个端口由一个监听器定义。
下图演示了这些对象之间的关系:

负载均衡算法
在 LBaaS API 的版本 2 中,可以将以下负载均衡算法应用于池:
-
轮询
-
最少连接
-
源 IP
使用轮询算法时,负载均衡器会将每个新连接传递给下一个服务器。随着时间的推移,所有连接会均匀分配到所有被负载均衡的机器上。轮询是资源消耗最少的算法,但没有机制判断某台机器是否因连接过多而超负荷。为了避免池成员过载,所有成员在处理速度、连接速度和内存等方面应该相等。
使用最少连接算法时,负载均衡器将新连接传递给当前连接数最少的服务器。这被认为是一种动态算法,因为系统会追踪每个服务器的连接数,并据此平衡流量。性能更高的池成员可能会接收到更多流量,因为它们能更快地处理连接。
使用源 IP 算法时,所有来自相同源 IP 地址的连接都会被发送到同一个池成员。连接最初使用轮询算法进行平衡,然后通过表格追踪这些连接,以便后续来自相同 IP 地址的连接进行查找。该算法适用于需要客户端始终连接到同一服务器的应用场景,比如在线购物车,它会在本地 Web 服务器上存储会话信息。
监控
LBaaS v2 API 支持多种监控类型,包括 TCP、HTTP 和 HTTPS。TCP 监控测试连接到池成员的 4 层连通性,而 HTTP 和 HTTPS 监控基于 7 层 HTTP 状态码测试池成员的健康状况。
会话持久性
LBaaS v2 支持虚拟 IP 上的会话持久性。会话持久性是一种负载均衡方法,它强制相同协议的多个客户端请求被定向到同一个节点。此功能通常用于许多 Web 应用程序,它们不在池成员之间共享应用状态。
HAProxy 驱动程序支持的会话持久性类型包括以下几种:
-
SOURCE_IP -
HTTP_COOKIE -
APP_COOKIE
使用 SOURCE_IP 持久性类型会在后端池配置中为 HAProxy 配置以下设置:
stick-table type ip size 10k
stick on src
客户端首次连接到虚拟 IP 时,HAProxy 会根据客户端的 IP 地址在粘性表中创建一条记录,并将来自相同 IP 地址的后续连接发送到同一个后端池成员。根据配置,粘性表中最多可以存在 10,000 条粘性记录。如果用户通过代理服务器连接,且该代理错误地将多个客户端识别为单一地址,可能会导致池成员之间的负载不均衡。
使用 HTTP_COOKIE 持久性类型将在后端池配置中为 HAProxy 配置以下设置:
cookie SRV insert indirect nocache
客户端首次连接到虚拟 IP 时,HAProxy 会将连接平衡到下一个池成员。当池成员发送响应时,HAProxy 会在响应中注入一个名为 SRV 的 cookie,然后将其发送给客户端。SRV cookie 的值是一个唯一的服务器标识符。当客户端发送后续请求到虚拟 IP 时,HAProxy 会从请求头中剥离该 cookie,并直接将流量发送到 cookie 中标识的池成员。与源 IP 持久性方法相比,这种持久性方法更为推荐,因为它不依赖于客户端的 IP 地址。然而,它可能并不与所有客户端兼容。
使用 APP_COOKIE 持久性类型将在后端池配置中为 HAProxy 配置以下设置:
appsession <CookieName> len 56 timeout 3h
当在后端配置中定义了应用程序 cookie 时,HAProxy 会检查服务器的响应,存储 cookie 的值在表中,并将其与服务器的标识符关联。最多会保留 cookie 值中的 56 个字符。在后续客户端连接时,HAProxy 会查找客户端请求中的 cookie。如果找到已知值,则客户端将被引导到与该值相关联的池成员。否则,将应用轮询负载均衡算法。当 cookie 长时间未被使用(超过三小时)时,HAProxy 会自动从内存中删除该 cookie。
将负载均衡器集成到网络中
在使用 HAProxy 驱动时,负载均衡器以单臂模式实现。在单臂模式下,负载均衡器不处于流向池成员的正常流量路径中。负载均衡器具有一个单一接口,用于处理来自客户端和池成员的进出流量。
以下是单臂模式下负载均衡器的逻辑图:

在上述图示中,负载均衡器配置为单臂模式,并与其所平衡流量的服务器处于同一子网中。
由于单臂模式下的负载均衡器不是池成员的网关,因此必须依赖源 NAT 来确保来自池成员的返回流量能通过负载均衡器返回到客户端。以下图示展示了流量的示例:

在上述示意图中,负载均衡器接收到来自客户端的请求并将其转发到 web1。负载均衡器将在转发请求到池成员之前修改请求的源 IP 为其自身的地址 192.168.200.12。这样可以确保池成员将响应发送回负载均衡器,然后负载均衡器将目标 IP 重写为客户端地址。如果服务器直接将响应发送到客户端,客户端将拒绝该数据包。
Neutron 配置 HAProxy 以向池成员发送HTTP ``X-Forwarded-For头,这样池成员可以看到原始客户端地址。如果没有这个头,所有流量将被标识为来自负载均衡器,这可能会扭曲应用程序报告数据和持久性设置。
除了单臂模式外,还可以使用路由模式和透明模式。在路由模式下,负载均衡器充当客户端和池成员之间的网关。大多数情况下,数据包的源地址无需更改,因为负载均衡器作为池成员的网关。
在透明模式下,负载均衡器充当配置有相同子网的两个 VLAN 之间的网络桥接。使用此模式可以让用户将负载均衡器引入网络,且对现有环境影响最小,因为池成员无需更改其网关。
当前没有办法更改基于 HAProxy 的负载均衡器如何集成到网络中。不过,某些第三方驱动可能不限于单臂模式,且可以在任何模式下工作。
网络命名空间
当使用 HAProxy 驱动时,Neutron 依赖于网络命名空间为每个负载均衡器提供单独的实例。每个负载均衡器都有一个对应的网络命名空间。负载均衡器在环境中被调度到 LBaaS v2 代理,这些代理负责创建相应的网络命名空间并进行适当的配置。用于负载均衡器的命名空间在ip netns list输出中以qlbaas为前缀。
安装 LBaaS v2
neutron-lbaasv2-agent服务通常在一个或多个网络节点上运行。在此环境中,服务将安装在controller01上。
在控制节点上执行以下命令,以安装 LBaaS v2 代理及其依赖项,包括 HAProxy:
# apt install neutron-lbaasv2-agent
配置 Neutron LBaaS 代理服务
Neutron 将 LBaaS v2 代理配置存储在/etc/neutron/lbaas_agent.ini文件中。最常用的配置选项将在接下来的章节中讨论。
定义接口驱动
与之前安装的代理一样,Neutron LBaaS v2 代理必须配置为使用与所选网络驱动相对应的接口驱动。在此配置中,有两个选项:
-
Linux 桥接
-
Open vSwitch
更新控制节点上/etc/neutron/lbaas_agent.ini的 Neutron LBaaS 代理配置文件,使用以下驱动之一。
对于 Linux 桥接:
[DEFAULT]
...
interface_driver = linuxbridge
对于 Open vSwitch:
[DEFAULT]
...
interface_driver = openvswitch
本书中指定了控制节点运行 Linux 桥接代理。因此,LBaaS v2 代理应配置为使用 Linux 桥接接口驱动程序。
定义设备驱动程序
要管理负载均衡器,Neutron LBaaS v2 代理必须配置为使用提供 Neutron API 与负载均衡器编程之间接口的设备驱动程序。
更新位于/etc/neutron/lbaas_agent.ini的 Neutron LBaaS v2 代理配置文件节点,以使用 HAProxy 设备驱动程序:
[DEFAULT]
...
device_driver = neutron_lbaas.drivers.haproxy.namespace_driver.HaproxyNSDriver
定义用户组
根据所使用的操作系统(包括本书中使用的 Ubuntu 16.04 LTS),可能需要将 LBaaS v2 代理配置为以某个用户组名称操作 HAProxy。在 controller01 节点上,使用以下配置更新 LBaaS v2 配置文件:
[haproxy]
...
user_group = haproxy
配置 Neutron
除了配置 LBaaS 代理之外,在使用 API 创建 LBaaS 对象之前,Neutron 还必须配置为使用 LBaaS 服务插件和驱动程序。
定义服务插件
在 controller01 节点上,将 LBaaS v2 服务插件添加到 Neutron 配置文件 /etc/neutron/neutron.conf 中现有的 service_plugins 列表中:
[DEFAULT]
...
service_plugins = router,neutron_lbaas.services.loadbalancer.plugin.LoadBalancerPluginv2
确保将插件附加到现有的插件列表中,而不是替换列表内容,以避免与 API 和现有网络对象发生问题。
定义服务提供者
自 OpenStack 的 Kilo 版本以来,许多高级服务配置选项已从主要的 Neutron 配置文件中移出,转而放入各自的文件中。在 controller01 节点上,创建或更新位于 /etc/neutron/neutron_lbaas.conf 的 Neutron LBaaS 配置文件,并为 LBaaS 定义 HAProxy 服务提供者驱动程序:
[service_providers]
...
service_provider = LOADBALANCERV2:Haproxy:neutron_lbaas.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default
更新数据库模式
在重启 Neutron API 服务器以提供 LBaaS API 之前,必须更新数据库模式,以支持负载均衡对象。
在 controller01 节点上,运行以下命令以执行数据库迁移:
# neutron-db-manage --subproject neutron-lbaas upgrade head
重启 Neutron LBaaS 代理和 API 服务
一旦数据库迁移完成,必须重启 neutron-lbaasv2-agent 和 neutron-server 服务,以使更改生效。请在控制节点上执行以下命令以重启服务:
# systemctl restart neutron-server neutron-lbaasv2-agent
使用 openstack network agent list 命令验证代理是否正在运行并已签到:

如果遇到任何问题,请务必在继续操作之前检查位于/var/log/neutron/neutron-lbaasv2-agent.log的 LBaaS v2 代理日志。
在 CLI 中管理负载均衡器
Neutron 提供了一些命令,用于创建和管理负载均衡目的的监听器、虚拟 IP、池、成员和健康监控器。然而,从 OpenStack 的 Pike 版本开始,负载均衡相关的命令在 openstack 客户端中不可用。相反,应使用 neutron 客户端或 API。
创建基本负载均衡器的工作流程如下:
-
创建负载均衡器对象
-
创建并关联池
-
创建并关联池成员(可选)
-
创建并关联健康检查器(可选)
-
创建并关联监听器
在 CLI 中管理负载均衡器
负载均衡器是占用 Neutron 端口并从子网分配 IP 作为虚拟 IP 的对象。以下命令用于在 CLI 中管理负载均衡器对象:
| 负载均衡器管理命令 | 描述 |
|---|---|
lbaas-loadbalancer-create |
创建负载均衡器 |
lbaas-loadbalancer-delete |
删除指定负载均衡器 |
lbaas-loadbalancer-list |
列出属于指定租户的负载均衡器 |
lbaas-loadbalancer-list-on-agent |
列出负载均衡器 v2 代理上的负载均衡器 |
lbaas-loadbalancer-show |
显示指定负载均衡器的信息 |
lbaas-loadbalancer-stats |
获取指定负载均衡器的统计信息 |
lbaas-loadbalancer-status |
获取指定负载均衡器的状态 |
lbaas-loadbalancer-update |
更新指定负载均衡器 |
lbaas-agent-hosting-loadbalancer |
获取托管负载均衡器的 lbaas v2 代理 |
在 CLI 中创建负载均衡器
要创建负载均衡器,请使用以下命令:neutron lbaas-loadbalancer-create:
neutron lbaas-loadbalancer-create
[--tenant-id TENANT_ID]
[--description DESCRIPTION]
[--name NAME]
[--admin-state-down]
[--provider PROVIDER]
[--flavor FLAVOR]
[--vip-address VIP_ADDRESS]
VIP_SUBNET
--tenant-id参数是可选的,可以用来将负载均衡器与非创建者的项目关联。
--description参数是可选的,可以用来为负载均衡器提供描述。
--name参数是可选的,可以用来为负载均衡器指定一个名称。
--admin-state-down参数是可选的,可以用来在创建时将负载均衡器设置为 DOWN 状态。
--provider参数是可选的,可以用来指定负载均衡器提供程序驱动程序,而不是使用默认的提供程序。此环境中的默认提供程序是 HAProxy。
--vip-address参数是可选的,可以用来指定 VIP 的特定 IP 地址。
VIP_SUBNET参数用于指定从中获取负载均衡器 VIP 的子网。
删除 CLI 中的负载均衡器
要删除负载均衡器,请使用以下命令:neutron lbaas-loadbalancer-delete:
neutron lbaas-loadbalancer-delete LOADBALANCER [LOADBALANCER...]
LOADBALANCER参数指定要删除的负载均衡器的名称或 ID。可以使用空格分隔的列表同时删除多个负载均衡器。
在 CLI 中列出负载均衡器
要列出所有负载均衡器,请使用以下命令:neutron lbaas-loadbalancer-list:
neutron lbaas-loadbalancer-list
在 CLI 中显示负载均衡器详情
要显示负载均衡器的详细信息,请使用以下命令:neutron lbaas-loadbalancer-show:
neutron lbaas-loadbalancer-show LOADBALANCER
LOADBALANCER参数指定要显示的负载均衡器的名称或 ID。
在 CLI 中显示负载均衡器统计信息
要显示负载均衡器的统计信息,请使用以下命令:neutron lbaas-loadbalancer-stats:
neutron lbaas-loadbalancer-stats LOADBALANCER
LOADBALANCER 参数指定要显示的负载均衡器的名称或 ID。
在命令行界面(CLI)显示负载均衡器的状态
要显示负载均衡器的状态,使用如下命令:neutron lbaas-loadbalancer-status。
neutron lbaas-loadbalancer-status LOADBALANCER
LOADBALANCER 参数指定要显示的负载均衡器的名称或 ID。
在 CLI 中更新负载均衡器
要更新负载均衡器的属性,使用如下命令:neutron lbaas-loadbalancer-update。
neutron lbaas-loadbalancer-update
[--description DESCRIPTION]
[--name NAME]
LOADBALANCER
--description 参数是可选的,可用于更新负载均衡器的描述。
--name 参数是可选的,可用于更新负载均衡器的名称。
LOADBALANCER 参数指定要更新的负载均衡器的名称或 ID。
在 CLI 中管理池
池是一组设备,例如 Web 服务器,这些设备被组合在一起,用于接收和处理流量。当流量被发送到虚拟 IP 时,负载均衡器将请求发送到该池中的任何一台服务器。
以下命令用于在 CLI 中管理负载均衡器池:
| 池命令 | 描述 |
|---|---|
lbaas-pool-create |
创建一个池 |
lbaas-pool-delete |
删除指定池 |
lbaas-pool-list |
列出属于指定租户的池 |
lbaas-pool-show |
显示指定池的信息 |
lbaas-pool-update |
更新指定池 |
在 CLI 中创建池
要创建池,使用如下命令:neutron lbaas-pool-create。
neutron lbaas-pool-create
[--tenant-id TENANT_ID]
[--description DESCRIPTION]
[--name NAME] --lb-algorithm
{ROUND_ROBIN,LEAST_CONNECTIONS,SOURCE_IP}
[--admin-state-down]
[--listener LISTENER]
[--loadbalancer LOADBALANCER] --protocol {HTTP,HTTPS,TCP}
[--session-persistence type=TYPE[,cookie_name=COOKIE_NAME]]
--tenant-id 参数是可选的,可用于将池与除创建者之外的项目关联。指定的租户或项目 ID 应与相应的负载均衡器匹配。
--description 参数是可选的,可用于为池提供描述。
--name 参数是可选的,可用于为池设置名称。
--lb-algorithm 参数是必需的,用于指定分配流量到池成员时使用的负载均衡算法。可选的算法包括 ROUND_ROBIN、LEAST_CONNECTIONS 和 SOURCE_IP。
--admin-state-down 参数是可选的,可用于在创建池时将其设置为 DOWN 状态。
--listener 参数是可选的,用于将池与监听器关联。
--loadbalancer 参数是可选的,可用于指定关联的负载均衡器。
--protocol 参数是必需的,用于指定负载均衡协议。可选的协议包括 HTTP、HTTPS 和 TCP。
--session-persistence 参数是可选的,用于指定会话保持方法和/或 Cookie 类型。
在 CLI 中删除池
要删除池,使用如下命令:neutron lbaas-pool-delete。
neutron lbaas-pool-delete POOL [POOL ...]
POOL 参数指定要删除的池的名称或 ID。可以通过空格分隔的列表一次删除多个池。
在 CLI 中列出池
要列出所有池,使用如下命令:neutron lbaas-pool-list。
neutron lbaas-pool-list
在 CLI 中显示池的详细信息
要显示池的详细信息,请使用如下所示的 neutron lbaas-pool-show 命令:
neutron lbaas-pool-show POOL
POOL 参数指定要显示的池的名称或 ID。
在 CLI 中更新池
要更新池,使用如下所示的 neutron lbaas-pool-update 命令:
neutron lbaas-pool-update
[--admin-state-up {True,False}]
[--session-persistence type=TYPE [,cookie_name=COOKIE_NAME]
| --no-session-persistence]
[--description DESCRIPTION]
[--name NAME]
[--lb-algorithm {ROUND_ROBIN,LEAST_CONNECTIONS,SOURCE_IP}]
POOL
--admin-state-up 参数是可选的,可以用来更改池的状态。
--session-persistence 参数是可选的,用于修改会话持久性方法和/或 cookie 类型。
--no-session-persistence 参数是可选的,用于从池中移除会话持久性。
--description 参数是可选的,用于更新池的描述。
--name 参数是可选的,用于更新池的名称。
--lb-algorithm 参数是可选的,用于修改负载均衡算法,该算法用于在池成员之间分配流量。
POOL 参数指定要更新的池的名称或 ID。
在 CLI 中管理池成员
以下命令用于在 CLI 中管理池成员:
| 池成员命令 | 描述 |
|---|---|
lbaas-member-create |
创建一个成员 |
lbaas-member-delete |
删除给定成员 |
lbaas-member-list |
列出属于给定池的成员 |
lbaas-member-show |
显示给定成员的信息 |
lbaas-member-update |
更新给定成员 |
在 CLI 中创建池成员
要创建池成员,使用如下所示的 neutron lbaas-member-create 命令:
neutron lbaas-member-create
[--tenant-id TENANT_ID]
[--name NAME]
[--weight WEIGHT]
[--admin-state-down]
--subnet SUBNET
--address ADDRESS
--protocol-port
PROTOCOL_PORT
POOL
--tenant-id 参数是可选的,用于将池成员与创建者以外的项目关联。指定的租户或项目 ID 应该与相应的负载均衡器匹配。
--name 参数是可选的,用于设置池成员的名称。
--weight 参数允许您为池成员关联一个权重。设置后,池成员可能会比同池中的其他成员接收更多或更少的流量。例如,一个权重为 2 的池成员将接收比权重为 1 的池成员多两倍的流量。一个权重为 3 的池成员将接收比权重为 1 的池成员多三倍的流量,以此类推。
--admin-state-down 参数是可选的,可以在创建时将池成员设置为 DOWN 状态。
--subnet 参数是必需的,用于指定池成员的子网。
--address 参数是必需的,用于指定池成员的 IP 地址。IP 地址必须位于指定的子网 CIDR 范围内。
--protocol-port 参数是必需的,用于指定正在负载均衡的应用程序的监听端口。例如,如果您正在负载均衡 HTTP 流量,指定的监听端口将是 80。如果是 SSL 流量,指定的端口将是 443。在大多数情况下,关联池的 VIP 将使用相同的应用程序端口号。
POOL 参数是必需的,用于将池成员与指定的池关联。
删除池成员
要删除池成员,请使用如下的 neutron lbaas-member-delete 命令:
neutron lbaas-member-delete MEMBER [MEMBER ...] POOL
MEMBER 参数指定要从指定池中删除的池成员的名称或 ID。可以使用空格分隔的列表同时删除多个池成员。
列出池成员
要获取特定池的池成员列表,请使用如下的 neutron lbaas-member-list 命令:
neutron lbaas-member-list POOL
显示池成员详情
要显示池成员的详细信息,请使用如下的 neutron lbaas-member-show 命令:
neutron lbaas-member-showMEMBERPOOL
MEMBER 参数表示指定池的成员 ID 或名称。
更新池成员
要更新池成员的属性,请使用如下的 neutron lbaas-member-update 命令:
neutron lbaas-member-update
[--admin-state-up {True,False}]
[--name NAME] [--weight WEIGHT]
MEMBER POOL
--admin-state-up 参数是可选的,可以用来改变池成员的状态。
--name 参数是可选的,可以用来更新池成员的名称。
--weight 参数是可选的,可以用来更新池成员的权重。
MEMBER 参数是必需的,表示指定池的成员 ID 或名称。
在 CLI 中管理健康监控器
Neutron 中的 LBaaS 提供了监控池成员健康状态的能力,以确保应用程序的可用性。如果池成员处于不健康状态,Neutron 可以将该成员从轮询中移除,从而限制客户端与应用程序之间问题的影响。
以下命令用于在 CLI 中管理健康监控器:
| 健康监控器命令 | 描述 |
|---|---|
lbaas-healthmonitor-create |
创建健康监控器 |
lbaas-healthmonitor-delete |
删除指定的健康监控器 |
lbaas-healthmonitor-list |
列出属于指定租户的健康监控器 |
lbaas-healthmonitor-show |
显示指定健康监控器的信息 |
lbaas-healthmonitor-update |
更新指定的健康监控器 |
在 CLI 中创建健康监控器
要创建健康监控器,请使用如下的 neutron lbaas-healthmonitor-create 命令:
neutron lbaas-healthmonitor-create
[--tenant-id TENANT_ID] --delay DELAY
[--name NAME] --timeout TIMEOUT
[--http-method HTTP_METHOD]
[--url-path URL_PATH] --max-retries MAX_RETRIES
[--expected-codes EXPECTED_CODES]
[--admin-state-down]
--type {PING,TCP,HTTP,HTTPS} --pool
POOL
--tenant-id 参数是可选的,可以用来将健康监控器与创建者之外的项目关联。指定的租户或项目 ID 应与相应的负载均衡器匹配。
--delay 参数是必需的,用于指定每次发送给成员的健康检查之间的时间间隔(秒)。常见的起始值为 5 秒。
--name 参数是可选的,可以用来设置健康监控器的名称。
--timeout 参数是必需的,用于指定监控器等待建立连接的秒数。该值必须小于延迟值。
--http-method 参数是可选的,并且与 --expected-codes 和 --url-path 一起使用。它用于指定正在发出的 HTTP 请求类型。常见的类型包括 GET 和 POST。默认值是 GET。
--url-path 参数是可选的,与 --expected-codes 和 --http-method 一起使用。当指定时,系统将针对池成员执行由 --http-method 定义的 HTTP 请求。默认值为根路径或 /。
--max-retries 参数是必需的,用于指定在池成员被标记为 DOWN 之前允许的最大连续失败次数。常见的初始值是 3 次重试。
--expected-codes 参数是可选的,允许你指定 HTTP 状态码,这些状态码表示池成员在监视器向池成员的指定 URL 发送 HTTP 请求时工作正常。例如,如果向池成员发送一个 GET 请求,服务器预期返回 200 OK 状态,表示页面成功获取。如果列出了 200 作为预期代码,监视器会将池成员标记为 UP,池成员将能够接收连接。如果返回 500 状态码,可能表示服务器未能正确处理连接,健康监视器会将池成员标记为 DOWN 并暂时将其从池中移除。默认值是 200。
--type 参数是必需的,用于指定正在配置的监视器类型。四种类型包括以下内容:
- PING:所有监视器类型中最简单的一种,PING 使用 ICMP 来确认与池成员的连接。
PING 类型不受 HAProxy 驱动程序支持,且表现与 TCP 监视器类型相同。
-
TCP:这指示负载均衡器向池成员发送一个 TCP SYN 数据包。在收到 SYN ACK 后,负载均衡器重置连接。这种类型的监视器通常称为半开 TCP 监视器。
-
HTTP:这指示监视器根据这里描述的
expected_codes、url_path和http_method属性向池成员发起 HTTP 请求。 -
HTTPS:这指示监视器根据这里描述的
expected_codes、url_path和http_method属性向池成员发起 HTTPS 请求。
--pool 参数是必需的,用于将健康监视器与指定池关联。每个池只能有一个健康监视器。
在 CLI 中删除健康监视器
要删除健康监视器,请使用如下所示的 neutron lbaas-healthmonitor-delete 命令:
neutron lbaas-healthmonitor-delete HEALTHMONITOR
HEALTHMONITOR 参数指定要删除的健康监视器的名称或 ID。可以使用以空格分隔的列表同时删除多个健康监视器。
在 CLI 中列出健康监视器
要获取健康监视器的列表,请使用如下所示的 neutron lbaas-healthmonitor-list 命令:
neutron lbaas-healthmonitor-list
显示健康监视器详细信息
要显示健康监视器的详细信息,请使用如下所示的 neutron lbaas-healthmonitor-show 命令:
neutron lbaas-healthmonitor-show HEALTHMONITOR
返回的详细信息包括延迟、预期代码、HTTP 方法、最大重试次数、池、超时、类型和 URL 路径。
更新健康监视器
要更新健康监控器的属性,请使用如下所示的neutron lbaas-healthmonitor-update命令:
neutron lbaas-healthmonitor-update
[--delay DELAY] [--name NAME]
[--timeout TIMEOUT]
[--http-method HTTP_METHOD]
[--url-path URL_PATH]
[--max-retries MAX_RETRIES]
[--expected-codes EXPECTED_CODES]
[--admin-state-up {True,False}]
HEALTHMONITOR
可更新的属性包括延迟、期望的代码、HTTP 方法、最大重试次数、超时和 URL 路径。
在 CLI 中管理监听器
以下命令用于在 CLI 中管理监听器:
| 监听器命令 | 描述 |
|---|---|
lbaas-listener-create |
创建一个监听器 |
lbaas-listener-delete |
删除指定的监听器 |
lbaas-listener-list |
列出属于指定租户的监听器 |
lbaas-listener-show |
显示指定监听器的信息 |
lbaas-listener-update |
更新指定的监听器 |
在 CLI 中创建监听器
要创建监听器,请使用下面显示的neutron lbaas-listener-create命令:
neutron lbaas-listener-create
[--tenant-id TENANT_ID]
[--description DESCRIPTION]
[--connection-limit CONNECTION_LIMIT]
[--default-pool DEFAULT_POOL]
[--admin-state-down]
[--name NAME]
[--default-tls-container-ref DEFAULT_TLS_CONTAINER_REF]
[--sni-container-refs SNI_CONTAINER_REFS [SNI_CONTAINER_REFS ...]]
[--loadbalancer LOADBALANCER] --protocol
{TCP,HTTP,HTTPS,TERMINATED_HTTPS}
--protocol-port PORT
--tenant-id参数是可选的,可用于将监听器与非创建者的项目关联。指定的租户或项目 ID 应与相应的负载均衡器匹配。
--description参数是可选的,可用于为监听器提供描述。
--connection-limit参数是可选的,可用于限制每秒到监听器的连接数。默认值为无限制(-1)。
--default-pool参数是可选的,用于为监听器设置默认池。
--admin-state-down参数是可选的,可用于在创建时将监听器设置为 DOWN 状态。
--name参数是可选的,可用于为监听器设置名称。
--loadbalancer参数是可选的,可用于指定关联的负载均衡器。
--protocol参数是必需的,用于指定监听器的协议。选项包括TCP、HTTP、HTTPS和TERMINATED_HTTPS。
--protocol-port参数是必需的,用于指定监听器的端口。
在 CLI 中删除监听器
要删除负载均衡器,请使用下面显示的neutron lbaas-loadbalancer-delete命令:
neutron lbaas-listener-delete LISTENER [LISTENER ...]
LISTENER参数指定要删除的监听器的名称或 ID。可以通过空格分隔的列表同时删除多个监听器。
在 CLI 中列出监听器
要列出所有监听器,请使用下面显示的neutron lbaas-listener-list命令:
neutron lbaas-listener-list
在 CLI 中显示监听器详细信息
要显示监听器的详细信息,请使用下面显示的neutron lbaas-listener-show命令:
neutron lbaas-listener-show LISTENER
LISTENER参数指定要显示的监听器的名称或 ID。
在 CLI 中更新监听器
要更新监听器的属性,请使用下面显示的neutron lbaas-listener-update命令:
neutron lbaas-listener-update
[--description DESCRIPTION]
[--connection-limit CONNECTION_LIMIT]
[--default-pool DEFAULT_POOL]
[--name NAME]
[--admin-state-up {True,False}]
LISTENER
--description参数是可选的,可用于更新监听器的描述。
--connection-limit参数是可选的,可用于更新连接限制。
--default-pool参数是可选的,可用于更新监听器的默认池。
--name参数是可选的,可用于为监听器设置名称。
--admin-state-up 参数是可选的,可用于设置侦听器的状态。
LISTENER 参数指定要更新的侦听器的名称或 ID。
构建负载均衡器
为了演示在 Neutron 中创建和使用负载均衡器,本节专门讨论根据以下情景构建功能负载均衡器的过程:
“项目具有由路由器连接的简单 Neutron 网络架构,连接到外部提供者网络和内部租户网络。 用户希望在两个实例之间负载均衡 HTTP 流量,每个实例在端口 80 上运行 Web 服务器。 每个实例都配置有包含唯一服务器标识符的 index.html 页面。”
请求的拓扑结构示意图如下:

本演示假设已在环境中部署了两个名为 web1 和 web2 的实例,并连接到项目网络。 该网络连接到一个提供通过浮动 IP 的出站和入站访问的 Neutron 路由器。 可以使用早期章节中解释的概念来构建此拓扑结构。
要消除 Web 服务器的安装和配置,您可以通过使用实例上的 SimpleHTTPServer Python 模块来模仿其行为,如下所示:
ubuntu@web1:~$ echo "This is web1" > ~/index.html
ubuntu@web1:~$ sudo python -m SimpleHTTPServer 80
Serving HTTP on 0.0.0.0 port 80 ...
在 index.html 文件中,重复上述命令以创建第二个实例,将 web1 替换为 web2。
创建负载均衡器
构建功能负载均衡器的第一步是首先创建负载均衡器对象。 使用 neutron 客户端,使用以下属性创建负载均衡器对象:
-
名称:
LB_WEB -
子网 ID:<池成员的子网 ID>
可以使用以下命令:
neutron lbaas-loadbalancer-create PROJECT_SUBNET --name LB_WEB
输出结果将类似于以下内容:

创建负载均衡器时,OpenStack 分配一个称为虚拟 IP(VIP)的 IP 地址。 VIP 将由客户端用于访问负载平衡应用程序。 创建负载均衡器对象只是将流量负载均衡到实例的第一步。
创建池
池与负载均衡器关联,并表示接收发送到 VIP 的流量的一组实例的对象。 使用 neutron 客户端,使用以下属性创建池:
-
名称:
WEB_POOL -
负载均衡方法:
ROUND_ROBIN -
协议:HTTP
-
子网 ID:<池成员所在的子网 ID>
可以使用以下命令:
neutron lbaas-pool-create \ --lb-algorithm ROUND_ROBIN \ --protocol HTTP \ --loadbalancer LB_WEB \ --name POOL_WEB
输出结果将类似于以下内容:

创建池成员
构建功能负载均衡器的下一步是创建并将池成员与池关联起来。 池成员是代表监听特定 IP 和端口的后端应用程序的对象。
在此环境中,有两个实例符合池中的使用条件:

使用 neutron 客户端,使用以下属性创建池成员:
| 名称 | 地址 | 端口 | 池 |
|---|---|---|---|
| web1 | 192.168.200.9 | 80 | POOL_WEB |
| web2 | 192.168.200.7 | 80 | POOL_WEB |
以下截图展示了创建第一个池成员的过程:

重复前面截图中所示的过程,创建第二个池成员,如下所示:

neutron lbaas-member-list 命令可以用来返回 POOL_WEB 池的池成员:

创建健康监控器
为了向客户端提供应用程序的高可用性,建议为池创建并应用健康监控器。没有监控器时,负载均衡器将继续向可能不可用的成员发送流量。
使用 neutron lbaas-healthmonitor-create 命令,创建一个具有以下属性的健康监控器:
-
名称:
MONITOR_WEB -
延迟:
5 -
最大重试次数:
3 -
超时:
4 -
类型:
TCP -
池:
POOL_WEB

创建一个监听器
创建功能负载均衡器的最后一步是创建监听器。使用neutron lbaas-listener-create命令,创建具有以下属性的监听器:
-
名称:
LISTENER_WEB -
端口:
80 -
协议:
HTTP -
池:
POOL_WEB

可以为每个负载均衡器创建多个监听器,使用户能够在同一个虚拟 IP 上为多个协议和应用程序平衡流量。
LBaaS 网络命名空间
在运行 LBaaS v2 代理的主机上列出网络命名空间时,显示了一个与我们刚才创建的负载均衡器对应的网络命名空间:

命名空间内的 IP 配置揭示了一个与虚拟 IP 子网对应的接口:

Neutron 为每个由用户创建的负载均衡器创建一个特定的 HAProxy 配置文件。负载均衡器配置文件可以在运行 LBaaS v2 代理的主机的 /var/lib/neutron/lbaas/v2/ 目录中找到。
由 Neutron 构建的此负载均衡器的配置文件可以在以下截图中看到:

确认负载均衡器功能
从 qlbaas 命名空间内,通过使用 curl 确认与 web1 和 web2 的直接连接:

通过连接到 VIP 地址,而不是单独的池成员,可以观察到默认的轮询负载均衡算法正在生效:

使用轮询负载均衡,每个连接在两个池成员之间均匀分配。
观察健康监控器
对web1的包捕获显示负载均衡器每 5 秒执行一次 TCP 健康检查:

在上面的输出中,负载均衡器每 5 秒发起一次连接,并执行健康监控程序规定的健康检查:“发出 GET 请求:对 /”。
为了观察监控程序将池成员从可用性中移除,停止 web1 上的 Web 服务,并观察 web1 上的包捕获及 controller 节点的日志:

在上面的输出中,Web 服务已停止,且拒绝连接到端口 80。在第三次失败后,负载均衡器将池成员标记为 DOWN:

当 web1 停机时,所有后续连接到 VIP 的请求都会发送到 web2:

在重启 web1 上的 Web 服务后,负载均衡器会在下次健康检查成功时将服务器重新加入池中:

外部连接到虚拟 IP
要外部连接到虚拟 IP,必须将浮动 IP 与 VIP 关联,因为虚拟 IP 存在于路由器后面的子网内,无法直接访问。
使用 openstack floating ip create 命令,分配一个浮动 IP 用于虚拟 IP:

从工作站到浮动 IP 的测试确认了外部对负载均衡器及其池成员的连接:

如果连接不成功,请确保安全组允许连接到端口 80。
仪表板中的负载均衡器管理
默认情况下,Horizon 中的负载均衡器管理面板(LBaaS 面板)未安装。要安装面板,请执行以下操作:
在控制节点上,安装 python-neutron-lbaas-dashboard 包:
# apt install python-neutron-lbaas-dashboard
然后,更新 OpenStack 仪表板配置文件 /etc/openstack-dashboard/local_settings.py 以启用面板。在 OPENSTACK_NEUTRON_NETWORK 字典中搜索 enable_lb,并将值从 False 更改为 True:
OPENSTACK_NEUTRON_NETWORK = {
'enable_router': True,
'enable_quotas': False,
'enable_ipv6': False,
'enable_distributed_router': False,
'enable_ha_router': False,
'enable_lb': True,
'enable_firewall': False,
'enable_vpn': False,
'enable_fip_topology_check': False,
}
最后,重启 Apache 服务:
# systemctl restart apache2
安装并激活面板后,可以通过点击屏幕左侧菜单中的 网络 | 负载均衡器 来在项目面板中管理负载均衡器:

在 Horizon 中,负载均衡器作为一个整体进行创建和管理,其中包括池、成员和监控器。这与 LBaaS v1 不同,在 LBaaS v1 中,成员和监控器可能会在各自的面板中分别管理。
在仪表板中创建负载均衡器
要创建负载均衡器,请执行以下步骤:
- 在负载均衡器面板中点击“创建负载均衡器”按钮。将会出现一个向导,如下图所示:

- 在负载均衡器详细信息面板中,您可以为负载均衡器输入名称、描述、IP 地址,并选择相应的子网以配置虚拟 IP:

- 在监听器面板中,您可以为监听器输入名称、描述,并选择协议和端口:

- 在池详细信息面板中,您可以为池输入名称、描述,并选择负载均衡方法:

- 在池成员面板中,您可以选择将构成池的池成员:

- 点击池成员旁边的“添加”按钮将其添加到池中:

- 在监控器详细信息面板中,您可以设置监控类型、间隔、重试次数和超时值:

- 一旦负载均衡器配置完成,点击蓝色的“创建负载均衡器”按钮以完成向导。负载均衡器将出现在负载均衡器列表中:

为负载均衡器分配浮动 IP
要在 Horizon 控制面板中为负载均衡器分配浮动 IP:
- 点击负载均衡器旁边操作菜单下的箭头,选择关联浮动 IP:

- 会弹出一个向导,允许您选择一个现有的浮动 IP 或选择一个网络以创建新的浮动 IP:

- 选择浮动 IP 或网络后,点击蓝色的“关联”按钮,将浮动 IP 与负载均衡器的虚拟 IP 关联。
负载均衡器的详细信息将更新,以反映新的浮动 IP。
概述
负载均衡即服务(LBaaS)为用户提供了通过 Neutron API 程序化扩展应用程序的能力。用户可以将流量均衡到由多个应用服务器组成的池,并且可以通过使用智能健康监控器提供应用程序的高可用性。LBaaS v2 API 甚至支持使用由 Barbican(另一个 OpenStack 项目)管理的证书进行 SSL 卸载,以及证书捆绑和 SNI 支持。
HAProxy 驱动程序提供了可以满足基本负载均衡需求的功能,但可能不足以满足大多数生产环境的需求。负载均衡器并非高度可用,可能会在应用程序的网络架构中存在弱点。建议在生产级云环境中使用 Octavia 而非 HAProxy 驱动程序,并且它兼容 LBaaS v2 API。
有关 Octavia 以及如何实现它的更多信息,可以在以下网址找到:docs.openstack.org/octavia/pike/reference/introduction.html。
在下一章中,我们将介绍一些其他高级的 Neutron 功能,包括 802.1q VLAN 标记(vlan-aware-vms)和 BGP 对等功能。
第十四章:高级网络话题
OpenStack 网络提供了许多网络功能,使用户能够开发最佳支持其应用程序的拓扑。虽然本书重点介绍了 OpenStack 网络的许多核心功能,但某些用例有时需要高级功能。在本章中,我们将探讨一些高级的 OpenStack 网络功能,包括以下内容:
-
VLAN 感知虚拟机
-
BGP Speaker
-
网络可用性区域
VLAN 感知虚拟机
VLAN 标记是一种方法,在以太网头部添加 VLAN 标签,以帮助区分通过同一接口传输的多个网络的流量。在本书中迄今为止描述的架构中,一个连接到多个网络的实例为每个网络都有一个相应的接口。这在小规模环境中有效,但 PCI 限制可能会限制可以附加到实例的接口数量。此外,当附加新网络时,热插拔接口到正在运行的虚拟机可能会产生意外结果。
以下图示化了每个网络一个虚拟网络接口卡(vNIC)的概念:

图 14.1
在图 14.1 中,一个单独的 vNIC 与 Neutron 端口关联。Neutron 通常根据各个 VLAN 网络的 segmentation_id 提供程序属性在虚拟交换机上执行 VLAN 标记。在这种情况下,实例不需要自行执行 VLAN 标记,任何来自实例的标记流量可能会被计算节点丢弃。
Neutron 的 trunk 服务插件允许 VLAN 感知的虚拟机实例在客户操作系统内标记流量,从而实现快速添加和移除网络子接口,并配置 网络功能虚拟化(NFV) 等高级用例。
配置 trunk 插件
trunk 服务插件首次出现在 OpenStack Networking 的 Newton 版本中,支持 Open vSwitch 和 Linux bridge ML2 机制驱动程序。其他驱动程序可能也得到支持,但不在本书的讨论范围内。
要安装 trunk 服务插件,请修改托管 Neutron API 服务的 controller 节点上的 Neutron 配置文件。在此环境中,API 服务运行在 controller01 上。将 trunk 添加到现有服务插件列表中,如下所示:
[DEFAULT]
...
service_plugins = router,
neutron_lbaas.services.loadbalancer.plugin.LoadBalancerPluginv2, trunk
请确保将 trunk 添加到现有插件列表中,而不是替换列表内容,以避免与 API 和现有网络对象发生冲突。
关闭文件并重启 neutron-server 服务:
# systemctl restart neutron-server
定义工作流
在 OpenStack 网络中引入了 trunking,带来了一些在将 trunk 附加到实例时需要的工作流相关概念。这些概念包括以下内容:
-
Trunk
-
父端口
-
子端口
Trunk 是将父端口与子端口绑定的对象。
父端口是附加到实例的端口,并代表客户操作系统中的 trunk 链接。该接口看起来像一个正常接口,并继承父端口的 MAC 和 IP 地址。通过客户操作系统内相关接口发送的任何流量都被视为未标记流量,并遵循正常的 Neutron 端口行为。
子端口与网络和子网关联,并且不会直接连接到实例。相反,子端口与 trunk 对象关联。可以在客户操作系统中使用子端口和网络的属性配置 VLAN 子接口,包括唯一的 MAC 地址、IP 地址和 802.1q VLAN 标签。通过子接口发送的流量会被客户操作系统标记,并通过父端口转发。
以下图示化展示了每个实例使用 802.1q VLAN 封装的一个 vNIC 概念:

图 14.2
在图 14.2 中,一个 vNIC 与一个父端口关联。父端口和多个子端口与 trunk 关联。实例可以使用 802.1q 封装标记流量,Neutron 代理会配置底层桥接器来支持这些标记流量。
在 OpenStack 中使用 trunk 时,应遵循以下工作流程:
-
为 trunk 和子端口创建网络和子网
-
创建 trunk
-
向 trunk 添加子端口
-
启动一个连接到 trunk 的实例
一旦实例处于活动状态,可以将更多子端口与 trunk 关联,并在实例中进行配置。
在 CLI 中管理 trunks
以下命令用于在 CLI 中管理 trunk 对象:
| Trunk 管理命令 | 描述 |
|---|---|
network trunk create |
创建一个 trunk。 |
network trunk delete |
删除给定 trunk。 |
network trunk list |
列出属于某个项目的 trunks。 |
network trunk set |
更新给定 trunk 的属性。 |
network trunk show |
显示给定 trunk 的详细信息。 |
network trunk unset |
取消设置给定 trunk 的属性。 |
在 CLI 中创建 trunk
要创建一个 trunk,请使用如下所示的 openstack network trunk create 命令:
openstack network trunk create
[--description <description>]
--parent-port <parent-port>
[--subport <port=,segmentation-type=,segmentation-id=>]
[--enable | --disable]
[--project <project>]
[--project-domain <project-domain>]
<name>
--description 参数是可选的,可以用于为 trunk 提供描述。
--parent-port 参数是必需的,用于将父端口与 trunk 关联。父端口是附加到实例上的端口,并在客户操作系统中充当 trunk。
--subport 参数是可选的,用于将子端口与 trunk 关联。子端口对应于客户操作系统中的 802.1q 子接口。如果没有指定子端口,则来自实例的所有标记流量将被丢弃。
--project 和 --project-domain 参数是可选的,可以用于将 trunk 与创建项目以外的项目和/或域关联。
name 参数是必需的,可用于指定 trunk 的名称。
在 CLI 中删除 trunks
要删除 trunk,请使用如下的 openstack network trunk delete 命令:
openstack network trunk delete <trunk> [<trunk> ...]
trunk 参数指定要删除的 trunk 的名称或 ID。可以使用空格分隔的列表同时删除多个 trunks。
在 CLI 中列出 trunks
要列出所有负载均衡器,使用如下 openstack network trunk list 命令:
openstack network trunk list
在 CLI 中显示 trunk 详细信息
要显示 trunk 的详细信息,请使用如下的 openstack network trunk show 命令:
openstack network trunk show <trunk>
trunk 参数指定要显示的 trunk 的名称或 ID。
在 CLI 中更新 trunk
要更新 trunk 的属性,请使用如下的 openstack network trunk set 或 openstack network trunk unset 命令:
openstack network trunk set
[--name <name>]
[--description <description>]
[--subport <port=,segmentation-type=,segmentation-id=>]
[--enable | --disable]
<trunk>
openstack network trunk unset --subport <subport> <trunk>
可以使用 set 和 unset 命令在不影响运行实例的情况下向 trunk 添加或删除子端口。
构建 trunk
为了演示在 OpenStack 网络中创建和使用 trunks,我配置了以下网络:

客户端实例将运行 Ubuntu 16.04 LTS 操作系统,并将连接到单个接口。
创建父端口
构建一个功能性 trunk 的第一步是首先创建父端口。父端口应与处理未标记流量的网络相关联,换句话说,就是原生 VLAN。使用 OpenStack 客户端,创建具有以下属性的端口:
-
名称:
parent0 -
网络:
GREEN_NET
可以使用以下命令:
openstack port create --network GREEN_NET parent0
输出将类似于以下内容:

创建子端口
子端口应与将在实例内使用 802.1q VLAN 封装进行标记的网络关联。子端口随后与 trunk 关联,并对应于客操作系统中的标记子接口。使用 OpenStack 客户端,创建具有以下属性的子端口:
-
名称:
child-p0c1 -
网络:
RED_NET
可以使用以下命令:
openstack port create --network RED_NET child-p0c1
输出将类似于以下内容:

与其他端口一样,创建子端口时,Neutron 会动态分配一个 MAC 地址。然而,在实例内部创建 VLAN 子接口时,子接口可能会继承父接口的 MAC 地址。由于接口位于两个不同的网络中且 MAC 地址不会跨越 Layer 2 边界,因此这种行为是可以接受的。然而,从端口安全性角度来看,可能会存在问题。创建实例中的子接口时,您需要指定 Neutron 分配给子端口的 MAC 地址,或者使用父端口的相同 MAC 地址创建子端口。
创建 trunk
创建功能性 trunk 的最后一步是创建 trunk 对象并关联父端口和子端口。trunk 所需的信息包括名称、带有段信息的父端口和带有段信息的子端口。使用 OpenStack 客户端,创建一个具有以下属性的 trunk 对象:
-
名称:
trunk0 -
父端口:
parent0 -
子端口:
child-p0c1 -
子端口 VLAN:
42
可以使用以下命令:
openstack network trunk create \ --parent-port parent0 \ --subport port=child-p0c1,segmentation-type=vlan,segmentation-id=42 \ trunk0
输出将类似于以下内容:

启动带有 trunk 的实例
现在 trunk 已创建并与父端口和子端口关联,实例可以启动并仅附加到父端口。由于没有为子接口创建 VIF,因此在启动时不需要附加它们。Neutron 内部的逻辑将会把来自实例内子接口的流量与父接口关联。
以下 OpenStack 命令语法可以用于启动附加父端口的实例:
openstack server create \ --image <image> \ --flavor<flavor> \ --key-name <keypair name> \ --nic port-id=<parent port> \ <name>

配置实例
启动后,实例应通过父端口的 IP 地址可用,并且如果路由正确设置,可以从命名空间或工作站访问。从相应的 qdhcp 命名空间内,确认与实例的连接:

使用 ip addr list 命令确认父端口的 IP 地址已通过 DHCP 配置,并且我们能够连接到实例,证明 trunk 的父端口上的流量是未标记的,并表现得像普通端口。
使用来自 iproute2 包的工具,我们可以使用以下子端口的属性配置子接口:
-
MAC 地址:
fa:16:3e:a9:48:cc -
VLAN ID:
42
为了方便,可以使用 ip link 命令创建 802.1q VLAN 子接口。或者,在 Ubuntu 系统上,可以修改 /etc/network/interfaces 文件以进行持久的接口配置。
使用 ip link add 命令,创建子接口并使用以下命令修改 MAC 地址:
# ip link add link ens3 name ens3.42 type vlan id 42 # ip link set dev ens3.42 address fa:16:3e:a9:48:cc # ip link set ens3.42 up
使用 ip addr list 命令,新的配置接口应处于 UP 状态并具有指定的 MAC 地址:

该接口尚未拥有 IP 地址,因此暂时无法确认连接性。IP 地址配置有两种可选方案:
-
DHCP
-
静态地址配置
要使用 DHCP,只需以 root 用户身份或使用 sudo 权限运行 dhclient ens3.42 命令。操作正常时,Neutron DHCP 服务器应返回分配的地址,并且接口会自动配置,如下所示:

动态或静态(但持久的)接口配置的具体实现将根据安装的来宾操作系统有所不同。
对RED_NET网络的 DHCP 服务器进行快速 ping 操作,证明来自实例接口的标记流量正确地穿越网络:

审查网络结构
在承载实例的compute节点上,使用brctl show查看桥接设备,未发现任何与实例内标记支持相关的独特配置:

然而,深入查看与子端口对应的tap接口,发现该接口已被配置为使用 VLAN ID 42,从父端口划分出的 VLAN 接口:

对与父端口关联的tap接口进行数据包捕获,可以看到流量从实例的子接口离开并通过父接口时,带有802.1q VLAN ID 42标记:

compute节点会去除VLAN ID,并将流量以未标记的形式通过与子端口关联的tap接口转发:

此时,正常的 Linux 桥接相关流量操作开始进行,流量通过前面本书中描述的物理网络基础设施转发。
当使用 Open vSwitch 网络代理时,可能会使用流规则而不是此处描述的方法。
BGP 动态路由
BGP 动态路由使得能够将自服务 IPv4 和 IPv6 网络前缀广告发送给支持 BGP 的网络设备,包括许多物理和虚拟路由器以及防火墙设备。通过向 Neutron 路由器附加的自服务网络进行广告,可以避免使用浮动 IP。
BGP 发言人功能依赖于地址范围,并需要了解其操作以便正确部署。
BGP 动态路由由一个 Neutron API 服务插件组成,该插件实现了网络服务扩展,以及一个管理 BGP 对等会话的代理。云管理员通过 CLI 或 API 创建并配置 BGP 发言人,并手动将其调度到一个或多个运行代理的主机上。
下图展示了 BGP 代理与物理路由器的对等关系,该对等关系使得物理路由能够通过共同的提供商网络到达 Neutron 路由器后面的自服务网络:

前缀广告要求
BGP 动态路由将自服务网络的前缀和浮动 IP 地址的主机路由进行广告。广告自服务网络时,必须满足以下条件:
-
外部网络和自服务网络必须位于同一地址范围内。
-
Neutron 路由器必须在自服务子网中包含一个接口,并在外部提供商网络中包含一个网关。
-
BGP 发言人必须与连接到与 Neutron 路由器相同外部提供商网络的设备建立对等关系。
-
BGP 交换机的
advertise_tenant_networks属性设置为True。
广播浮动 IP 地址需要满足以下条件:
-
BGP 交换机必须与连接到与托管浮动 IP 的 Neutron 路由器相同外部提供商网络的设备建立对等连接。
-
BGP 交换机的
advertise_floating_ip_host_routes属性设置为True。
与分布式虚拟路由器的操作
在使用分布式虚拟路由器的部署中,BGP 交换机以不同的方式广播浮动 IP 地址和自服务网络。对于浮动 IP 地址,BGP 交换机将相应计算节点上的浮动 IP 代理网关广播为下一跳 IP 地址。对于使用 SNAT 的自服务网络,BGP 交换机将 DVR SNAT 节点广播为下一跳 IP 地址。这意味着,指向分布式虚拟路由器后面的自服务网络的流量必须经过一个 network 节点,而指向浮动 IP 的流量将绕过 network 节点。
配置 BGP 动态路由
BGP 动态路由插件首次在 OpenStack Networking 的 Mitaka 版本中引入,并支持 Neutron 提供的原生 L3 代理。
要安装 BGP 服务插件,请修改托管 Neutron API 服务的控制节点上的 Neutron 配置文件。在此环境中,API 服务在 controller01 上运行。按照如下所示,将 BGP 插件添加到现有服务插件列表中:
[DEFAULT]
...
service_plugins = router,
neutron_lbaas.services.loadbalancer.plugin.LoadBalancerPluginv2,
trunk,neutron_dynamic_routing.services.bgp.bgp_plugin.BgpPlugin
确保将插件添加到现有插件列表中,而不是替换列表内容,以避免与 API 和现有网络对象出现问题。
安装代理
要安装 Neutron BGP 代理,请在 controller01 节点上运行以下命令:
# apt install neutron-bgp-dragent
Neutron 将 BGP 代理配置存储在 /etc/neutron/bgp_dragent.ini 文件中。以下部分将介绍最常见的配置选项。
配置代理
编辑 BGP 代理配置文件,并根据需要将 bgp_router_id 值替换为相应控制节点的 IP 地址:
[bgp]
...
bgp_speaker_driver =
neutron_dynamic_routing.services.bgp.agent.driver.ryu.driver.RyuBgpDriver
bgp_router_id = 10.10.0.100
在此示例中,使用的是主机的管理 IP 地址。可以使用专门用于路由器广播的 IP 地址和接口,但超出了本书的范围。
重启服务
要使配置更改生效,请使用以下命令重启 Neutron API 服务和 Neutron BGP 代理:
# systemctl restart neutron-server neutron-bgp-dragent
使用 OpenStack 客户端验证 BGP 代理是否已检查并准备好使用:

在 CLI 中管理 BGP 交换机
从 OpenStack 客户端的 Pike 版本开始,BGP 交换机相关的命令尚不可用。以下 neutron 客户端命令用于在 CLI 中管理 BGP 交换机对象:
| BGP 交换机管理命令 | 描述 |
|---|---|
bgp-dragent-list-hosting-speaker |
列出托管 BGP 交换机的动态路由代理。 |
bgp-dragent-speaker-add |
向动态路由代理添加 BGP 说话人。 |
bgp-dragent-speaker-remove |
从动态路由代理中移除 BGP 说话人。 |
bgp-peer-create |
创建 BGP 对等体。 |
bgp-peer-delete |
删除 BGP 对等体。 |
bgp-peer-list |
列出 BGP 对等体。 |
bgp-peer-show |
显示给定 BGP 对等体的信息。 |
bgp-peer-update |
更新 BGP 对等体信息。 |
bgp-speaker-advertiseroute-list |
列出由给定 BGP 说话人广告的路由。 |
bgp-speaker-create |
创建 BGP 说话人。 |
bgp-speaker-delete |
删除 BGP 说话人。 |
bgp-speaker-list |
列出 BGP 说话人。 |
bgp-speaker-list-on-dragent |
列出由动态路由代理托管的 BGP 说话人。 |
bgp-speaker-network-add |
向 BGP 说话人添加网络。 |
bgp-speaker-network-remove |
从 BGP 说话人中移除网络。 |
bgp-speaker-peer-add |
向 BGP 说话人添加一个对等体。 |
bgp-speaker-peer-remove |
从 BGP 说话人中移除对等体。 |
bgp-speaker-show |
显示给定 BGP 说话人的信息。 |
bgp-speaker-update |
更新 BGP 说话人信息。 |
请参考上游文档,了解如何配置用于 BGP 动态路由的地址范围和子网池。以下 URL 提供了演示 BGP 动态路由的工作示例:docs.openstack.org/neutron/pike/admin/config-bgp-dynamic-routing.html。
网络可用区
网络可用区是一个逻辑构造,用于定义一组共享相似电力、网络和冷却系统的网络节点。网络资源可以调度到多个可用区,以确保在某个区域发生故障时,系统具有较高的可靠性。这类似于 Nova 可用区的工作方式,它们用于将计算节点分组,确保应用程序的组件不在同一故障域内。
配置网络可用区
Neutron 的可用区支持首次在 OpenStack Networking 的 Mitaka 版本中引入,并支持 Neutron 中包含的 DHCP 和 L3 代理。其他驱动程序可能被支持,但超出了本书的范围。
在本书所构建的环境中,Neutron L3 代理已安装在大多数节点上,以演示独立、高可用和分布式虚拟路由器。快速查看 Neutron 代理列表显示,它们都共享一个基于默认代理配置选项的公共可用区:

要修改特定 L3 代理的可用区,请编辑位于 /etc/neutron/l3_agent.ini 的相应代理配置文件,并按如下所示修改 availability_zone 配置选项:
[agent]
...
# Availability zone of this node (string value)
# availability_zone = nova
availability_zone = AZ1
使用以下命令重新启动 L3 代理:
# systemctl restart neutron-l3-agent
再次查看代理列表,反映了变化:

DHCP 代理也可以以类似方式与可用区关联。要修改特定 DHCP 代理的可用区,请编辑/etc/neutron/dhcp_agent.ini中的相应代理配置文件,并修改availability_zone配置选项,如下所示:
[agent]
...
# Availability zone of this node (string value)
# availability_zone = nova
availability_zone = AZ1
使用以下命令重启DHCP代理:
# systemctl restart neutron-dhcp-agent
将路由器调度到可用区
在路由器创建过程中,可以将 Neutron 路由器定向到特定的可用区。使用openstack router create命令,我们可以通过--availability-zone-hint参数将路由器调度到可用区AZ1,如下面所示:

在将路由器连接到外部提供者网络GATEWAY_NET之后,我们可以看到路由器被调度到可用区AZ1中的L3代理:

将路由器调度到特定可用区并不能确保它会被调度到该区的 L3 代理,因为该指令更像是一个调度提示,而非明确的要求。Neutron 使用可用区提示进行最佳努力调度。如果需要,可以通过重复--availability-zone-hint参数来指定多个可用区。
将 DHCP 服务调度到可用区
给定网络的 DHCP 服务通常是被视为理所当然的,用户或操作员通过 API 无法直接看到或配置它。Neutron 已经使用以下配置选项在 Neutron 配置文件/etc/neutron/neutron.conf中将 DHCP 服务调度到多个 DHCP 代理:
# Number of DHCP agents scheduled to host a tenant network.
# If this number isgreaterthan 1, the scheduler automatically
# assigns multiple DHCP agents for a given tenant network,
# providing high availability for DHCP service.
# (integer value)
# dhcp_agents_per_network = 1
当dhcp_agents_per_network大于1,且环境中存在多个 DHCP 代理时,Neutron 将自动将网络调度到多个DHCP代理,直到指定的值为止。使用带有--availability-zone-hint参数的openstack network create命令,我们可以建议调度器将DHCP服务分配到多个可用区,如下所示:
openstack network create network01
--availability-zone-hint AZ1
--availability-zone-hint AZ2
将网络的 DHCP 服务调度到特定可用区并不能确保它会被调度到该区的 DHCP 代理,因为该指令更像是一个调度提示,而非明确的要求。Neutron 使用可用区提示进行最佳努力调度。如果需要,可以通过重复--availability-zone-hint参数来指定多个可用区。
有关使用网络可用区的更多信息,请参阅上游文档,网址:docs.openstack.org/neutron/pike/admin/config-az.html。
总结
随着基于 OpenStack 的云工作负载的发展,OpenStack 网络功能也不断演进。VLAN 感知虚拟机、BGP 交换机和网络可用性区域只是 Neutron 在过去几个发布周期中引入的一些高级网络功能,未来的版本还将带来更多功能。将这些功能结合使用,可以为用户提供定义丰富网络拓扑的能力,并为云中的多种应用和工作负载提供高可用性。
OpenStack 网络的发布说明是查找最近发布的功能和现有功能的 bug 修复的绝佳来源。要查找给定版本的发布说明,请访问以下网址:docs.openstack.org/releasenotes/neutron/index.html。


浙公网安备 33010602011771号