Openstack-云计算秘籍-全-
Openstack 云计算秘籍(全)
原文:
annas-archive.org/md5/2ca02d976e2dad8eba9e4b7090f2058d译者:飞龙
序言
OpenStack 是用于构建公共和私有云以及私有托管软件定义基础设施服务的开源软件。它是一个全球性的开源成功案例,由全球成千上万的人开发和支持,并得到了云计算领域领先企业的支持。本书专门设计旨在快速帮助你掌握 OpenStack,并提供信心与理解,以便将其部署到自己的数据中心。本书涵盖了使用 Ansible 安装 OpenStack 到数据中心的过程,并提供了运行的步骤,帮助你快速获取所需的知识,以便当下能够安装并操作 OpenStack。本书由 Rackspace 的四位高级 OpenStack 工程师和架构师编写,涵盖了广泛的主题,帮助你安装和配置 OpenStack 环境。本书将指导你完成以下内容:
-
如何使用 OpenStack-Ansible 安装和配置 OpenStack 的所有核心组件
-
如何掌握完整的私有云技术栈,从扩展计算资源到管理面向高冗余、高可用存储的对象存储服务
-
使用 Heat 和 Ansible 编排在 OpenStack 上运行的工作负载的示例
-
每一章都有实际的、基于真实场景的服务示例,确保你在自己的环境中也能顺利实现。
本书为你提供清晰、逐步的指导,帮助你成功安装和运行自己的私有云。内容中包含了大量实用且可操作的方案,使你能够使用 OpenStack 的最新功能并加以实现。
本书适用对象
本书面向从虚拟化环境转向云环境的系统管理员和技术架构师,要求读者熟悉云计算平台。预期读者具备虚拟化和管理 Linux 环境的知识。尽管有助于理解,但不要求具备 OpenStack 的前置知识或经验。
本书涵盖内容
第一章,使用 Ansible 安装 OpenStack,带领你通过实际操作安装 OpenStack,使用 OpenStack-Ansible。
第二章,OpenStack 客户端,介绍了如何安装操作 OpenStack 所需的工具,并提供了常用命令的快速参考。
第三章,Keystone – OpenStack 身份认证服务,介绍了如何使用 Keystone 配置和维护 OpenStack 中的服务和项目。
第四章,Neutron – OpenStack 网络,涵盖了软件定义网络服务及其插件的介绍与使用。
第五章,Nova – OpenStack 计算,通过一系列示例讲解如何运行和操作虚拟机实例以运行您的应用程序。
第六章,Glance – OpenStack 镜像服务,探讨了用于启动实例的机器镜像的使用方法。
第七章,Cinder – OpenStack 块存储,介绍了如何使用块存储卷并将其附加到您的实例。
第八章,Swift – OpenStack 对象存储,展示了如何使用高可用且冗余的对象存储服务。
第九章,使用 Heat 和 Ansible 进行 OpenStack 编排,讨论了如何开始使用 Heat 和 Ansible 在 OpenStack 内编排工作负载。
第十章,使用 OpenStack 仪表盘,展示了如何浏览 Horizon 用户界面仪表盘。
为了充分利用本书
使用本书时,您需要访问具有硬件虚拟化功能的计算机或服务器。预计您具有 Linux 操作系统的基础知识,并能通过 SSH 访问 Linux 服务器。
要设置第一章,使用 Ansible 安装 OpenStack,末尾描述的实验环境,您需要安装并使用 Oracle 的 VirtualBox 和 Vagrant。您可以访问github.com/OpenStackCookbook/vagrant-openstack查看如何使用 VirtualBox 和 Vagrant 设置计算机的详细信息。
获取更多启动实验环境的附加资源,请访问www.openstackcookbook.com。参考该网站以获取有关安装支持软件(如 MariaDB/MySQL)的信息。更多信息请见bit.ly/OpenStackCookbookPreReqs。
下载示例代码文件
你可以从www.packtpub.com的账户下载本书的示例代码文件。如果你在其他地方购买了本书,可以访问www.packtpub.com/support,注册后直接将文件发送到你的邮箱。
你可以通过以下步骤下载代码文件:
-
登录或注册
www.packtpub.com。 -
选择支持标签。
-
点击代码下载与勘误表。
-
在搜索框中输入书名,并按照屏幕上的指示操作。
一旦文件下载完成,确保使用以下最新版本的其中一个解压或解压文件夹:
-
适用于 Windows 的 WinRAR / 7-Zip
-
适用于 Mac 的 Zipeg / iZip / UnRarX
-
适用于 Linux 的 7-Zip / PeaZip
本书的代码包也托管在 GitHub 上,网址为github.com/PacktPublishing/OpenStack-Cloud-Computing-Cookbook-Fourth-Edition。我们还拥有其他来自我们丰富书籍和视频目录的代码包,网址为github.com/PacktPublishing/。快来看看吧!
下载彩色图片
我们还提供了一个 PDF 文件,里面包含了本书中使用的截图/图表的彩色图片。你可以在这里下载:www.packtpub.com/sites/default/files/downloads/OpenStackCloudComputingCookbookFourthEdition_ColorImages.pdf。
使用的约定
本书中使用了一些文本约定。
CodeInText:表示文本中的代码字、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟网址、用户输入和 Twitter 账户名。这里有一个例子:在 Ubuntu 系统上,主机网络配置通过编辑/etc/network/interfaces文件来完成。代码块如下所示:
# Shared infrastructure parts
shared-infra_hosts:
controller-01:
ip: 172.29.236.110
controller-02:
ip: 172.29.236.111
controller-03:
ip: 172.29.236.112
# Compute Hosts
compute_hosts:
compute-01:
ip: 172.29.236.113
compute-02:
ip: 172.29.236.114
当我们希望特别提醒你注意代码块的某一部分时,相关行或项目会用粗体显示:
# Shared infrastructure parts
shared-infra_hosts:
controller-01:
ip: 172.29.236.110
controller-02:
ip: 172.29.236.111
controller-03:
ip: 172.29.236.112
# Compute Hosts
compute_hosts:
compute-01:
ip: 172.29.236.113
compute-02:
ip: 172.29.236.114
任何命令行输入或输出都如下所示:
cd /opt/openstack-ansible/scripts
粗体:表示一个新术语、一个重要的词或你在屏幕上看到的词,例如在菜单或对话框中,也会像这样出现在文本中。这里有一个例子:“接下来从左侧菜单中选择高级系统设置。”
注意
警告或重要说明将以框的形式显示,如下所示。
提示
小贴士和技巧将以这种形式出现。
各部分
在本书中,你会经常看到一些标题(准备工作、如何做...、它是如何工作的...、还有更多... 和 另见)。
为了清楚地说明如何完成一个食谱,请使用以下部分:
准备工作
本节告诉你在食谱中可以期待什么,并描述如何设置所需的软件或任何预备设置。
如何操作……
本节包含遵循食谱所需的步骤。
工作原理…
本节通常包含对上一节内容的详细解释。
还有更多…
本节包含有关该食谱的额外信息,帮助你更好地了解该食谱。
另见
本节提供有关食谱的有用链接,帮助你获得更多相关信息。
联系我们
我们欢迎读者的反馈。
一般反馈:发送电子邮件至 <feedback@packtpub.com>,并在邮件的主题中提及书名。如果你对本书的任何方面有疑问,请通过 <questions@packtpub.com> 与我们联系。
勘误:虽然我们已经尽力确保内容的准确性,但错误仍然可能发生。如果你在本书中发现了错误,我们将非常感激你向我们报告。请访问 www.packtpub.com/submit-errata,选择你的书籍,点击勘误提交表单链接,并输入相关细节。
盗版:如果你在互联网上发现任何形式的非法复制品,我们将感激你提供相关的地址或网站名称。请通过 copyright@packtpub.com 联系我们,并附上相关资料的链接。
如果你有兴趣成为一名作者:如果你在某个领域有专业知识,并且有兴趣写书或为书籍做贡献,请访问 authors.packtpub.com。
评论
请留下评论。阅读并使用本书后,为什么不在你购买书籍的网站上留下评论呢?潜在读者可以通过你的公正意见做出购买决策,我们 Packt 也可以了解你对我们产品的看法,而我们的作者则能看到你对他们书籍的反馈。谢谢!
想了解更多关于 Packt 的信息,请访问 packtpub.com。
第一章. 使用 Ansible 安装 OpenStack
本章将涵盖以下主题:
-
介绍 – OpenStack 架构
-
主机网络配置
-
根 SSH 密钥配置
-
安装 Ansible、剧本和依赖项
-
配置安装
-
运行 OpenStack-Ansible 剧本
-
故障排除安装
-
手动测试安装
-
修改 OpenStack 配置
-
虚拟实验室 - vagrant up!
介绍 – OpenStack 架构
OpenStack 是一套项目集合,通过软件定义环境结合起来,用户可以通过云计算友好的工具和技术进行消费。这款流行的开源软件使得用户能够轻松地消费计算、网络和存储资源,这些资源传统上由不同的 IT 团队使用各种方法和工具来管理,不论是大型还是小型团队。尽管可以通过 OpenStack 版本之间 API 的一致性来实现兼容,管理员仍然可以自由选择安装 OpenStack 的哪些功能,因此没有单一的安装方法或架构来安装该软件。这种灵活性可能会导致在选择如何部署 OpenStack 时产生困惑。尽管如此,全球一致认为,最终用户交互的服务—即 OpenStack 服务、支持软件(如数据库)和 API—必须具备高可用性。
安装 OpenStack 的一种非常流行的方法是 OpenStack-Ansible 项目(github.com/openstack/openstack-ansible)。这种安装方法允许管理员定义高度可用的控制节点以及计算和存储阵列,并通过使用 Ansible,以非常一致的方式部署 OpenStack,且所需的依赖项较少。Ansible 是一种通过标准 SSH 连接进行系统配置和管理的工具。Ansible 本身依赖项很少,而且由于它使用 SSH 进行通信,大多数 Linux 发行版和网络都能够很好地支持这个工具。它在全球许多系统管理员中非常受欢迎,因此在他们已有的知识基础上安装 OpenStack,降低了为企业用户设置云环境的门槛。
OpenStack 可以以多种方式进行架构设计;OpenStack-Ansible 并不直接解决架构问题:用户可以自由定义任意数量的控制服务(如 Horizon、Neutron Server、Nova Server 和 MySQL)。通过 Rackspace 的经验和用户反馈,定义了一种流行的架构,示例如下:

图 1:本书推荐的 OpenStack 架构
如前图所示(图 1),首先需要了解一些概念。这些概念如下所述。
控制节点
控制器(也称为基础设施节点或infra 节点)运行 OpenStack 服务的核心部分,是唯一通过负载均衡池对外暴露的服务器(通过负载均衡池)供最终用户使用。控制器运行 API 服务,例如 Nova API、Keystone API 和 Neutron API,以及核心支持服务,如用于运行 OpenStack 所需数据库的MariaDB和用于消息传递的 RabbitMQ。正因为如此,在生产环境中,这些服务器必须按照需求配置为高可用性。这意味着这些服务器作为集群部署在(高可用)负载均衡器后面,集群中至少有 3 台服务器。使用从 3 开始的奇数集群,可以使集群在丧失一台服务器的情况下仍然保持服务不受影响,并且仍能保持法定人数(即需要的最小投票数)。这意味着,当不健康的服务器重新上线时,数据可以从剩余的 2 台服务器中复制(它们之间是一致的),从而确保数据的一致性。
网络建议具有高度的弹性,因此需要确保 Linux 已配置为绑定或聚合网络接口,以便在发生交换机端口故障或电缆损坏时,您的服务仍然可用。Ubuntu 的示例网络配置可以在附录 A中找到。
计算节点
这些是运行虚拟化管理程序或容器服务的服务器,当用户请求 Nova 资源(例如虚拟机)时,OpenStack 将工作负载调度到这些服务器上。它们与运行虚拟化管理程序的主机(如 ESXi 或 Hyper-V)没有太大区别,OpenStack 计算服务器的配置方式也非常相似,可以选择使用共享存储。然而,大多数 OpenStack 安装都会避免在架构中使用共享存储。这个不使用共享存储的小细节意味着虚拟机直接从计算主机的硬盘上运行,这对于讨论环境中应用的弹性时,会对 OpenStack 环境的用户产生较大影响。像这样设置的环境将大部分应用正常运行的责任交给开发者,这为长期云策略提供了最大的灵活性。当一个应用依赖于底层基础设施 100%可用时,基础设施所施加的重力会将应用绑定到特定的数据中心技术上以确保其运行。然而,OpenStack 可以配置为引入共享存储,例如 Ceph(ceph.com/),以支持像实时迁移(在不中断的情况下将正在运行的实例从一个虚拟化管理程序迁移到另一个虚拟化管理程序)的操作特性,这样可以非常安全地将企业用户的应用迁移到云环境中。这些概念将在后续的计算和存储章节中详细讨论。因此,计算节点的参考架构是预期虚拟机将直接运行在服务器本身的硬盘上。
关于网络配置,像控制器一样,网络也必须配置为高可用性。一个没有可用网络的计算节点可能非常安全,但对于云环境来说同样毫无用处!请像配置控制器一样配置绑定接口。有关在 Ubuntu 下配置绑定接口的更多信息,请参见附录 A。
存储
OpenStack 中的存储指的是块存储和对象存储。块存储(为虚拟机提供 LUN 或 硬盘)由 Cinder 服务提供,而对象存储(由 API 驱动的对象或数据块存储)由 Swift 或 Ceph 提供。Swift 和 Ceph 管理服务器中每个被指定为对象存储节点的独立硬盘,就像 RAID 卡管理典型服务器中的硬盘一样。每个硬盘都是一个独立的实体,Swift 或 Ceph 用它来写入数据。例如,如果一个存储节点有 24 块 2.5 英寸的 SAS 硬盘,Swift 或 Ceph 会配置为写入这 24 块硬盘中的任何一块。然而,Cinder 可以使用多种后端来存储数据。例如,Cinder 可以配置为与第三方供应商(如 NetApp 或 Solidfire 存储阵列)通信,或者它可以配置为与 Sheepdog 或 Ceph 通信,还可以与像 LVM 这样的简单服务通信。事实上,OpenStack 可以配置为让 Cinder 使用多个后端,从而使用户能够选择适用于他们所需服务的存储。这为最终用户和操作员提供了极大的灵活性,因为这意味着工作负载可以针对特定的后端进行优化,适合该工作负载或存储需求。
本书简要介绍了 Ceph 作为 Cinder 的后台存储引擎。Ceph 是一个非常流行、高可用的开源存储服务。Ceph 有其自身的磁盘要求,以提供最佳的性能。在前面的图示中,每个 Ceph 存储节点被称为Ceph OSD(Ceph 对象存储守护进程)。我们建议从 5 个节点开始,尽管这不是硬性规定。Ceph 性能调优超出了本书的范围,但至少,我们强烈推荐使用 SSD 来进行 Ceph 日志存储,OSD(物理存储单元)则可以使用 SSD 或 SAS 驱动器。
在此架构中,Swift 节点和 Ceph 节点之间的区别非常小。两者都需要一个用于存储集群中数据复制的接口(为提高容错性,接口通常是绑定的),以及一个用于从客户端或服务读取和写入数据的接口(同样为了容错性,接口通常是绑定的)。
主要的区别在于建议使用 SSD(或 NVMe)作为日志磁盘。
负载均衡
OpenStack 环境的最终用户期望服务具有高度可用性,OpenStack 为其所有功能提供 REST API 服务。这使得 REST API 服务非常适合放置在负载均衡器后面。在大多数部署中,负载均衡器通常是高度可用的硬件设备,例如 F5。为了本书的目的,我们将使用 HAProxy。不过,背后的前提是相同的——确保服务在 控制器 节点故障的情况下仍然可用,以便最终用户可以继续工作。
OpenStack-Ansible 安装要求
操作系统:Ubuntu 16.04 x86_64
最小的数据中心部署要求
对于物理安装,以下是所需的:
-
控制器服务器(也称为基础设施节点)
-
至少 64 GB 内存
-
至少 300 GB 硬盘(RAID)
-
4 个网络接口卡(用于创建两组绑定接口;一组用于基础设施和所有 API 通信,包括客户端,另一组专用于 OpenStack 网络:Neutron)
-
共享存储或对象存储服务,提供基础 OS 镜像的后端存储
-
-
计算服务器
-
至少 64 GB 内存
-
至少 600 GB 硬盘(RAID)
-
4 个网络接口卡(用于创建两组绑定接口,和控制器服务器使用相同方式)
-
-
可选(如果使用 Ceph 作为 Cinder)5 台 Ceph 服务器(Ceph OSD 节点)
-
至少 64 GB 内存
-
2 个 400 GB SSD(RAID1)用于日志记录
-
8 个 300 GB SAS 或 SSD(不使用 RAID)用于 OSD(根据需求调整大小)
-
4 个网络接口卡(用于创建两组绑定接口;一组用于复制,另一组用于在 Ceph 中的数据进出传输)
-
-
可选(如果使用 Swift)5 台 Swift 服务器
-
至少 64 GB 内存
-
8 个 300 GB SAS(不使用 RAID)(根据需求调整大小)
-
4 个网络接口卡(用于创建两组绑定接口;一组用于复制,另一组用于在 Swift 中的数据进出传输)
-
-
负载均衡器
-
配置为一对的 2 台物理负载均衡器
-
或者 2 台运行 HAProxy 和 Keepalived VIP 的服务器,作为 API 端点的 IP 地址:
-
至少 16 GB 内存
-
HAProxy + Keepalived
-
2 个网络接口卡(绑定)
-
-
提示
提示:在设置物理实验室时,请确保你有一个管理型交换机,以便接口可以打上 VLAN 标签。
主机网络配置
使用如 Ansible 这样的编排和配置工具安装 OpenStack 可以自动化很多原本需要手动完成的任务。然而,我们只能在服务器以一致的方式配置并且已向 Ansible 描述时,使用编排工具。
以下部分将描述一种典型的服务器配置,使用两组活动/被动绑定接口供 OpenStack 使用。确保这些接口连接正确。
我们假设每台服务器都已安装以下物理网络卡;根据你的环境进行调整:
-
p2p1和p2p2 -
p4p1和p4p2
我们假设 主机 网络当前使用 p2p1。主机 网络是每台服务器当前所在的基础网络,允许你通过 SSH 访问每台服务器。假设该网络已经配置了默认网关,并且可以访问互联网。在这一阶段,应该不需要其他网络,因为服务器尚未配置,也未运行 OpenStack 服务。
在本节末尾,我们将创建以下绑定接口:
-
bond0:这由物理接口p2p1和p4p1组成。bond0接口将用于主机、OpenStack 管理和存储流量。 -
bond1:这由物理接口p2p2和p4p2组成。bond1接口将用于 OpenStack 中的 Neutron 网络。
我们将创建以下 VLAN 标记的接口:
-
bond0.236:该接口将用于容器网络。 -
bond0.244:该接口将用于存储网络。 -
bond1.240:该接口将用于VXLAN 隧道网络。
以及以下桥接:
-
br-mgmt:该桥接将使用bond0.236VLAN 接口,并将配置来自172.29.236.0/24范围内的 IP 地址。 -
br-storage:该桥接将使用bond0.244VLAN 接口,并将配置来自172.29.244.0/24范围内的 IP 地址。 -
br-vxlan:该桥接将使用bond1.240 VLAN接口,并将配置来自172.29.240.0/24范围内的 IP 地址。 -
br-vlan:该桥接将使用未标记的bond1接口,并且不会配置 IP 地址。
提示
提示:确保你的子网足够大,既能满足当前需求,也能支持未来的扩展!
以下图示展示了我们在开始安装 OpenStack 之前设置的网络、接口和桥接:

准备开始
我们假设每台服务器都已安装 Ubuntu 16.04。
以 root 身份登录到将安装 OpenStack 的每台服务器。
如何操作…
在 Ubuntu 系统上配置主机网络是通过编辑/etc/network/interfaces文件完成的。
-
首先,确保每台服务器上已安装正确的网络包。由于我们使用 VLAN 和桥接,必须安装以下软件包:
apt update apt install vlan bridge-utils -
现在使用你喜欢的编辑器编辑第一个服务器上的
/etc/network/interfaces文件:vi /etc/network/interfaces -
我们将首先配置绑定接口。文件的第一部分将描述这一点。编辑此文件,使其开始时看起来像以下内容:
# p2p1 + p4p1 = bond0 (used for host, container and storage) auto p2p1 iface p2p1 inet manual bond-master bond0 bond-primary p2p1 auto p4p1 iface p4p1 inet manual bond-master bond0 # p2p2 + p4p2 = bond1 (used for Neutron and Storage Replication) auto p2p2 iface p2p2 inet manual bond-master bond1 bond-primary p2p2 auto p4p2 iface p4p2 inet manual bond-master bond1 -
现在我们将配置与这些绑定接口相关联的 VLAN 接口。继续编辑文件,添加以下标记的接口。请注意,我们尚未为 OpenStack 的绑定接口分配 IP 地址:
# We're using bond0 on a native VLAN for the 'host' network. # This bonded interface is likely to replace the address you # are currently using to connect to this host. auto bond0 iface bond0 inet static address 192.168.100.11 netmask 255.255.255.0 gateway 192.168.100.1 dns-nameserver 192.168.100.1 # Update to suit/ensure you can resolve DNS auto bond0.236 # Container VLAN iface bond0.236 inet manual auto bond1.240 # VXLAN Tunnel VLAN iface bond1.240 inet manual auto bond0.244 # Storage (Instance to Storage) VLAN iface bond0.244 inet manual提示
提示:根据你自己的环境,使用适当的 VLAN。这里使用的 VLAN 标签仅供参考。
确保正确的 VLAN 标签配置在正确的绑定接口上。
bond0用于主机类型的流量,bond1主要用于基于 Neutron 的流量,存储节点除外,在这种情况下它用于存储复制。 -
现在我们将创建桥接,并根据需要在其上配置 IP 地址(请注意,
br-vlan没有分配 IP 地址)。继续编辑相同的文件,添加以下行:# Container bridge (br-mgmt) auto br-mgmt iface br-mgmt inet static address 172.29.236.11 netmask 255.255.255.0 bridge_ports bond0.236 bridge_stp off # Neutron's VXLAN bridge (br-vxlan) auto br-vxlan iface br-vxlan inet static address 172.29.240.11 netmask 255.255.255.0 bridge_ports bond1.240 bridge_stp off # Neutron's VLAN bridge (br-vlan) auto br-vlan iface br-vlan inet manual bridge_ports bond1 bridge_stp off # Storage Bridge (br-storage) auto br-storage iface br-storage inet static address 172.29.244.11 netmask 255.255.255.0 bridge_ports bond0.244 bridge_stp off提示
这些桥接名称会在 OpenStack-Ansible 配置文件中被引用,因此确保你正确命名它们。
小心确保正确的桥接被分配到正确的绑定接口。
-
保存并退出文件,然后执行以下命令:
restart networking -
由于我们正在配置 OpenStack 环境,使其尽可能具有高可用性,因此建议你此时重新启动服务器,以确保基本的服务器,带有冗余网络,能够按预期重新启动:
reboot -
现在对你网络中的每台服务器执行相同操作。
-
一旦所有服务器完成配置,确保你的服务器能够通过这些新创建的接口和子网互相通信。类似下面的测试可能会很方便:
apt install fping fping -a -g 172.29.236.0/24 fping -a -g 172.29.240.0/24 fping -a -g 172.29.244.0/24
提示
提示:我们还建议你执行一个网络电缆拔除练习,以确保从一个活动接口切换到另一个接口的故障转移功能按预期工作。
它是如何工作的…
我们已经配置了主机的物理网络,以确保在运行 OpenStack 时有一个良好的已知状态和配置。这里配置的每个接口都是 OpenStack 特定的—要么由 OpenStack 直接管理(例如,br-vlan),要么用于服务间通信(例如,br-mgmt)。在前一种情况下,OpenStack 使用 br-vlan 桥接并直接在 bond1 上配置标记接口。
请注意,这里使用的约定,VLAN 标签 ID 使用子网的一部分,仅用于突出 VLAN 到特定子网的分离(例如,bond0.236 用于 172.29.236.0/24 子网)。此 VLAN 标签 ID 是任意的,但必须根据你的具体网络需求进行设置。
最后,我们进行了一个相当基础的网络测试。这可以让你确信,OpenStack 云生命周期中将使用的网络配置是合适的,并且在网络电缆或网卡发生故障时,能够提供保障。
Root SSH 密钥配置
Ansible 旨在通过使用编排剧本配置和操作多台服务器,帮助系统管理员提高数据中心的效率。为了使 Ansible 能够履行其职责,它需要在其管理的 Linux 系统上建立 SSH 连接。此外,为了获得更大的自由度和灵活性,必须使用 SSH 公私钥对的无人值守方法。
由于 OpenStack 的安装预计以 root 身份运行,因此此阶段需要将部署主机的 root 公钥传播到所有服务器。
准备工作
确保你在部署主机上是root用户。在大多数情况下,这是我们为本书目的命名的第一个基础设施控制器节点,命名为infra01。我们将假设所有的 Ansible 命令都将在这个主机上运行,并且它预计能够通过 SSH 通过主机网络连接到网络上的其他服务器。
如何操作…
为了实现无需人工干预的自动化 OpenStack-Ansible 部署,请按照以下步骤创建并传播 infra01 的 root SSH 公钥至所有安装所需的服务器:
-
作为 root,执行以下命令来创建 SSH 密钥对:
ssh-keygen -t rsa -f ~/.ssh/id_rsa -N ""输出应类似于以下内容:
Generating public/private rsa key pair. Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: SHA256:q0mdqJI3TTFaiLrMaPABBboTsyr3pRnCaylLU5WEDCw root@infra01 The key's randomart image is: +---[RSA 2048]----+ |ooo .. | |E..o. . | |=. . + | |.=. o + | |+o . o oS | |+oo . .o | |B=++.o+ + | |*=B+oB.o | |o+.o=.o | +----[SHA256]-----+ -
这在
/root/.ssh目录下创建了两个文件,分别叫做id_rsa和id_rsa.pub。文件id_rsa是私钥,必须避免通过网络进行复制。它只需要存在于该服务器上。文件id_rsa.pub是公钥,可以共享到网络上的其他服务器。如果你有其他节点(例如名为 infra02),可以使用以下命令将此密钥复制到你环境中的该节点:ssh-copy-id root@infra02提示
提示:确保你能解析
infra02和其他服务器,否则修改前面的命令,使用主机的 IP 地址代替。 -
现在,对你网络上的所有服务器重复步骤 2。
-
重要:最后,确保执行以下命令,以便能够进行自我 SSH 连接:
ssh-copy-id root@infra01 -
测试你能否作为 root 用户,从
infra01使用ssh连接到网络上的其他服务器。如果成功,应该会显示一个终端,准备接受命令,而不会要求输入密码。如果此行为不正常,请查看远程服务器上的/var/log/auth.log。
其工作原理…
我们首先生成了一个密钥对文件供 SSH 使用。-t 选项指定了 rsa 类型加密,-f 指定了私钥的输出路径,公钥部分将以 .pub 为文件名后缀,-N "" 表示不使用密码短语。若选项与贵公司要求不符,请参照贵公司安全标准。
安装 Ansible、剧本和依赖项
为了成功通过 Ansible 安装 OpenStack,我们需要确保在部署主机上安装了 Ansible 及所有预期的依赖项。OpenStack-Ansible 项目为我们提供了一个方便的脚本来完成这项工作,该脚本是我们将要部署的 OpenStack-Ansible 版本的一部分。
准备就绪
确保你在部署主机上以 root 身份登录。在大多数情况下,这将是第一个基础设施控制节点 infra01。
此时,我们将从 GitHub 检出 OpenStack-Ansible 的版本。
如何操作...
为了设置 Ansible 及其依赖项,请按照以下步骤操作:
-
我们首先需要使用
git从 GitHub 检出 OpenStack-Ansible 代码,因此确保安装了以下包(以及其他所需的依赖项):apt update apt install git python-dev bridge-tools lsof lvm2 tcpdump build- essential ntp ntpdate python-dev libyaml-dev libpython2.7-dev libffi-dev libssl-dev python-crypto python-yaml -
然后我们需要从 GitHub 获取 OpenStack-Ansible 代码。写作时,Pike 发布分支(16.X)描述如下,但在可预见的未来步骤将保持不变。建议访问
github.com/openstack/openstack-ansible/tags来使用最新的稳定标签。此处我们使用的是最新的 16(Pike)标签,即16.0.5:提示
提示:要使用 Queens 发布的某个分支,请使用以下命令:
-b 17.0.0。当 Rocky 发布可用时,请使用-b 18.0.0。git clone -b 16.0.5 https://github.com/openstack/openstack-ansible.git /opt/openstack-ansible -
Ansible 和成功安装 OpenStack 所需的依赖项可以在
/opt/openstack-ansible/scripts目录中找到。运行以下命令以引导环境:cd /opt/openstack-ansible scripts/boot strap-ansible.sh
工作原理…
OpenStack-Ansible 项目提供了一个便捷的脚本,以确保在部署主机上安装了 Ansible 和正确的依赖项。这个脚本(bootstrap-ansible.sh)位于检出的 OpenStack-Ansible 代码的 scripts/ 目录中,因此此时我们需要使用 Git 获取我们想要部署的版本。一旦获得代码,我们可以执行脚本并等待其完成。
还有更多内容…
访问 docs.openstack.org/project-deploy-guide/openstack-ansible/latest 获取更多信息。
配置安装
OpenStack-Ansible 是一组官方的 Ansible playbook 和角色,它以最小的先决条件部署 OpenStack。像任何编排工具一样,大部分工作是在配置阶段完成的,然后在 playbook 运行时实现免手动操作。最终的结果是一个经过多次验证的 OpenStack 安装,适用于任何规模的环境,从测试到生产环境。
当我们使用 OpenStack-Ansible 时,实际上是在将 playbooks 从 GitHub 下载到指定的 部署服务器。部署服务器是通过 SSH 访问环境中所有机器的主机(为了便利以及提供无缝的体验,通常通过密钥进行访问)。这个部署服务器可以是你指定的任何一台机器,因为一旦运行,Ansible 不会占用任何持续的资源。
提示
提示:在重新安装 Ubuntu 之前,记得备份与 OpenStack-Ansible 相关的配置目录!
准备工作
确保你是 部署主机 上的 root 用户。在大多数情况下,这将是第一个基础设施控制节点 infra01。
如何操作…
假设你使用的是第一个基础设施节点 infra01 作为部署服务器。
如果你没有按照前面的 安装 Ansible、playbooks 和依赖项 章节进行操作,请作为 root 执行以下操作(如有必要):
git clone -b 16.05 https://github.com/openstack/openstack-ansible.git /opt/openstack-ansible
这将把 OpenStack-Ansible playbook 下载到 /opt/openstack-ansible 目录。
要配置 OpenStack 部署,请执行以下步骤:
-
我们首先将
etc/openstack_deploy文件夹从下载的仓库复制到/etc:cd /opt/openstack-ansible cp -R /etc/openstack_deploy /etc -
现在,我们必须通过编辑
/etc/openstack_deploy/openstack_user_config.yml文件,告诉 Ansible 哪些服务器将执行哪些 OpenStack 功能,如下所示:cp /etc/openstack_deploy/openstack_user_variables.yml.example /etc/openstack_deploy_openstack_user_variables.yml vi /etc/openstack_deploy/openstack_user_variables.yml -
第一部分,
cidr_networks,描述了 OpenStack 在此安装中使用的子网。在这里,我们描述了 容器 网络(每个 OpenStack 服务都运行在一个容器中,并且每个服务有自己的网络,以便它们之间可以相互通信)。我们描述了隧道网络(当用户在 OpenStack 安装中创建租户网络时,这将创建一个在物理网络上隔离的 VXLAN 网络)。最后,我们描述了存储网络子网。编辑此文件,使其看起来如下所示:cidr_networks: container: 172.29.236.0/24 tunnel: 172.29.240.0/24 storage: 172.29.244.0/24 -
继续编辑文件,包含已在 OpenStack 将要部署的环境中由现有物理主机使用的任何 IP 地址(并确保已包含用于物理扩展的任何保留 IP 地址)。包括我们在此章节前已经配置的地址。可以在此处添加单个 IP 地址或地址范围(起始和结束地址用 ',' 分隔)。编辑此部分,使其看起来如下所示,按你的环境和任何保留的 IP 进行调整:
used_ips: - "172.29.236.20" - "172.29.240.20" - "172.29.244.20" - "172.29.236.101,172.29.236.117" - "172.29.240.101,172.29.240.117" - "172.29.244.101,172.29.244.117" - "172.29.248.101,172.29.248.117" -
global_overrides部分描述了用于环境的桥接和其他接口的具体细节——特别是容器网络如何连接到物理网络接口。对于本书中使用的示例架构,可以使用以下输出。在大多数情况下,除了开始时的负载均衡器信息外,本节内容无需编辑,因此根据需要调整:global_overrides: internal_lb_vip_address: 172.29.236.117 external_lb_vip_address: 192.168.100.117 lb_name: haproxy tunnel_bridge: "br-vxlan" management_bridge: "br-mgmt" provider_networks: - network: group_binds: - all_containers - hosts type: "raw" container_bridge: "br-mgmt" container_interface: "eth1" container_type: "veth" ip_from_q: "management" is_container_address: true is_ssh_address: true - network: group_binds: - neutron_linuxbridge_agent container_bridge: "br-vxlan" container_type: "veth" container_interface: "eth10" ip_from_q: "tunnel" type: "vxlan" range: "1:1000" net_name: "vxlan" - network: group_binds: - neutron_linuxbridge_agent container_bridge: "br-vlan" container_type: "veth" container_interface: "eth11" type: "vlan" range: "1:1" net_name: "vlan" -
本文件的剩余部分描述了每个服务运行的服务器。大部分章节内容重复,仅在服务名称上有所不同。这是可以接受的,因为此处的目的是告诉 OpenStack-Ansible 每个服务(我们为它起一个名字,便于 Ansible 通过名称引用,并引用与其关联的 IP 地址)在哪个服务器上运行,例如 Nova API、RabbitMQ 或 Glance 服务等。由于这些示例服务运行在我们的控制节点上,而在生产环境中至少有三个控制节点,所以你可以很快明白为什么这些信息会重复。其他章节则专门提到其他服务,如 OpenStack 计算服务。为了简洁起见,这里展示了几个章节,继续编辑文件以适应你的网络配置:
# Shared infrastructure parts shared-infra_hosts: controller-01: ip: 172.29.236.110 controller-02: ip: 172.29.236.111 controller-03: ip: 172.29.236.112 # Compute Hosts compute_hosts: compute-01: ip: 172.29.236.113 compute-02: ip: 172.29.236.114 -
保存并退出文件。接下来,我们需要为 OpenStack 中运行的各个服务生成一些随机密码短语。在 OpenStack 中,每个服务——如 Nova、Glance 和 Neutron(本书中有描述)——都必须向 Keystone 进行身份验证,并授权它们作为服务进行操作。为此,它们自己的用户帐户需要生成密码短语。执行以下命令以生成所需的密码短语,这些密码短语将在稍后执行 OpenStack playbook 时使用:
cd /opt/openstack-ansible/scripts python pw-token-gen.py --file /etc/openstack_deploy/user_secrets.yml -
最后,还有另一个文件允许你对 OpenStack 服务的参数进行微调,例如 Glance(OpenStack 镜像服务)将使用的后端存储,并在安装之前配置代理服务。这个文件叫做
/etc/openstack_deploy/user_variables.yml。让我们查看并编辑这个文件:cd /etc/openstack_deploy vi user_variables.yml -
在一个典型的高可用部署中——即我们有三个控制节点的部署——我们需要配置 Glance 使用共享存储服务,这样三个控制节点就可以对文件系统有相同的视图,从而使启动实例时使用的镜像一致。Glance 可以使用的一些共享存储后端系统包括 NFS 和 Swift。我们甚至可以允许一个私有云环境通过公共网络连接并连接到像 Rackspace Cloud Files 这样的公共服务。如果你有可用的 Swift,可以将以下行添加到
user_variables.yml文件中,配置 Glance 使用 Swift:glance_swift_store_auth_version: 3 glance_default_store: swift glance_swift_store_auth_address: http://172.29.236.117:5000/v3 glance_swift_store_container: glance_images glance_swift_store_endpoint_type: internalURL glance_swift_store_key: '{{ glance_service_password }}' glance_swift_store_region: RegionOne glance_swift_store_user: 'service:glance'提示
提示:OpenStack-Ansible 的最新版本足够智能,能够自动检测是否使用了 Swift,并会相应地更新其配置。
-
查看文件中其他被注释掉的详细信息,看看是否需要根据你的环境进行编辑,然后保存并退出。现在你可以开始安装 OpenStack 了!
它是如何工作的……
Ansible 是一个非常流行的服务器配置工具,非常适合安装 OpenStack。Ansible 使用一组配置文件,Playbooks(一组在服务器上执行的步骤)用来控制它们的执行方式。对于 OpenStack-Ansible,配置分为两个领域:描述物理环境和描述如何配置 OpenStack。
第一个配置文件/etc/openstack_deploy/openstack_user_config.yml描述了物理环境。每个部分在这里都有描述:
cidr_networks:
container: 172.29.236.0/24
tunnel: 172.29.240.0/24
storage: 172.29.244.0/24
本节描述了基于 OpenStack-Ansible 安装所需的网络。查看下面的图示,了解不同的网络和子网。
-
容器:每个部署的容器都会从这个子网中获取一个 IP 地址。负载均衡器也会从这个范围内获取一个 IP 地址。
-
隧道:这是形成 VXLAN 隧道网格的子网。每个参与 VXLAN 隧道的容器和计算主机都会从这个范围内获得一个 IP(当操作员创建一个指定
vxlan类型的 Neutron 子网时,VXLAN 隧道会被使用,这在这个底层子网上创建了一个虚拟网络)。有关 OpenStack 网络的更多细节,请参阅 第四章,Neutron – OpenStack Networking。 -
存储:这是在 OpenStack 中启动客户端实例时使用的子网,要求 Cinder 块存储:
used_ips: - "172.29.236.20" - "172.29.240.20" - "172.29.244.20" - "172.29.236.101,172.29.236.117" - "172.29.240.101,172.29.240.117" - "172.29.244.101,172.29.244.117" - "172.29.248.101,172.29.248.117"
used_ips: 部分指的是已经在该子网中使用的 IP 地址,或为静态设备保留的 IP 地址。此类设备包括负载均衡器或其他属于子网的主机,否则 OpenStack-Ansible 会将这些 IP 随机分配给容器:
global_overrides:
internal_lb_vip_address: 172.29.236.117
external_lb_vip_address: 192.168.1.117
tunnel_bridge: "br-vxlan"
management_bridge: "br-mgmt"
storage_bridge: "br-storage"
global_overrides: 部分描述了容器与桥接网络的设置细节。OpenStack-Ansible 的默认文档假设使用 Linux Bridge;但是,也可以使用 Open vSwitch。有关更多细节,请参考第四章,Neutron – OpenStack 网络。
internal_lb_vip_address: 和 external_lb_vip_address: 部分指的是典型负载均衡器的 私有 和 公共 端口。私有端口(internal_lb_vip_address)由 OpenStack 内的服务使用(例如,Nova 调用与 Neutron API 的通信时会使用 internal_lb_vip_address,而用户在 OpenStack 环境安装后进行通信时则会使用 external_lb_vip_address)。请参见以下图示:

为某个 虚拟 IP (VIP) 地址将创建多个负载均衡池,描述与特定服务相关的 IP 地址和端口,对于每个池——一个将在公共/外部网络上创建(在示例中,已为此目的创建了 VIP 地址 192.168.100.117),另一个 VIP 将供 OpenStack 内部使用(在前面的示例中,已为此目的创建了 VIP 地址 172.29.236.117)。
tunnel_bridge: 部分是为连接参与 VXLAN 隧道网络的物理接口而设定的桥接名称。
management_bridge: 部分是为所有在容器网络上安装的 OpenStack 服务设定的桥接名称,容器网络如图所示。
storage_bridge: 部分是为与实例连接存储或 Swift 代理的流量而设定的桥接名称。
上述每个桥接名称必须与在每台服务器的 /etc/network/interfaces 文件中配置的名称匹配。
接下来的部分,provider_networks,相对静态且未更改,它描述了容器网络与物理环境之间的关系。请勿调整此部分。
provider_networks 部分后面是描述哪个服务器或服务器组运行特定服务的部分。每个块的语法如下:
service_name:
ansible_inventory_name_for_server:
IP_ADDRESS
ansible_inventory_name_for_server:
IP_ADDRESS
提示
提示:确保每个服务器名称(ansible_inventory_name_for_server)的拼写正确一致,以确保 Ansible playbook 的正确执行。
这里列出了若干部分及其用途:
-
shared-infra_hosts:这些支持共享基础设施软件,如 MariaDB/Galera 和 RabbitMQ。 -
repo-infra_hosts:这是指定的 OpenStack-Ansible 容器版本。 -
haproxy_hosts:在使用 HAProxy 进行负载均衡时,指示 playbook 安装和配置此服务的位置。 -
os-infra_hosts:这些包括 OpenStack API 服务,如 Nova API 和 Glance API。 -
log_hosts:这是运行 rsyslog 服务器的地方。 -
identity_hosts:这些是运行 Keystone(OpenStack Identity)服务的服务器。 -
storage-infra_hosts:这些是运行 Cinder API 服务的服务器。 -
storage_hosts:这是描述 Cinder LVM 节点的部分。 -
swift-proxy_hosts:这些是将托管 Swift Proxy 服务的主机。 -
swift_hosts:这些是 Swift 存储节点。 -
compute_hosts:这是组成虚拟化服务器的主机列表。 -
image_hosts:这些是运行 Glance(OpenStack Image)服务的服务器。 -
orchestration_hosts:这些是运行 Heat API(OpenStack Orchestration)服务的服务器。 -
dashboard_hosts:这些是运行 Horizon(OpenStack Dashboard)服务的服务器。 -
network_hosts:这些是运行 Neutron(OpenStack Networking)代理和服务的服务器。 -
metering-infra_hosts:这些是运行 Ceilometer(OpenStack Telemetry)服务的服务器。 -
metering-alarm_hosts:这些是运行与告警相关的 Ceilometer(OpenStack Telemetry)服务的服务器。 -
metrics_hosts:运行 Ceilometer 组件(Gnocchi)的服务器。 -
metering-compute_hosts:使用 Ceilometer 时,这些是需要安装计量代理的计算主机列表。
运行 OpenStack-Ansible playbook。
安装 OpenStack 时,我们只需运行相关的 playbook。总共有三个主要的 playbook,我们将依次使用:
-
setup-hosts.yml。 -
setup-infrastructure.yml。 -
setup-openstack.yml。
准备工作。
确保你是部署主机上的 root 用户。在大多数情况下,这将是第一个基础设施控制节点,infra01。
如何操作……
要使用 OpenStack-Ansible playbook 安装 OpenStack,首先导航到已克隆 Git 仓库的 playbooks 目录,然后依次执行每个 playbook:
-
首先通过执行以下命令切换到
playbooks目录:cd /opt/openstack-ansible/playbooks -
第一步是对你的脚本和配置进行语法检查。由于我们将执行三个 playbook,我们将针对每个 playbook 执行以下操作:
openstack-ansible setup-hosts.yml --syntax-check openstack-ansible setup-infrastructure.yml --syntax-check openstack-ansible setup-openstack.yml --syntax-check -
现在我们将使用一个特殊的 OpenStack-Ansible 包装脚本来运行第一个 playbook,配置我们在
/etc/openstack_deploy/openstack_user_config.yml文件中描述的每个主机:openstack-ansible setup-hosts.yml -
稍等片刻后,你应该看到一个完全绿色的 PLAY RECAP 输出(其中黄色/蓝色的行表示做出的任何更改),并且输出显示所有更改都成功。如果有问题,请通过滚动回输出内容来查看并留意任何红色输出的内容。请参考本章后面的故障排除安装部分。如果一切正常,我们可以继续运行下一个 Playbook 以设置负载均衡。在此阶段,配置负载均衡器非常重要。OpenStack-Ansible 将 OpenStack 服务安装在每台服务器的 LXC 容器中,到目前为止,我们还没有明确说明哪个容器网络的 IP 地址将安装哪个服务。这是因为我们让 Ansible 为我们管理这一切。因此,虽然在此阶段设置负载均衡似乎有些反直觉——因为我们还不知道每个服务会安装在哪个容器上——但 Ansible 已经在未来的工作之前生成了动态清单,所以它已经知道涉及多少个容器,并知道哪个容器会安装该服务。如果你使用的是 F5 LTM、Brocade 或类似的企业级负载均衡设备,建议你暂时使用 HAProxy,并查看生成的配置,以便手动转移到物理设备上。为了临时设置 HAProxy,使 OpenStack 的安装能够继续,修改你的
openstack_user_config.yml文件,包含一个 HAProxy 主机,然后执行以下命令:openstack-ansible install-haproxy.yml -
如果一切正常,我们可以继续运行下一个 Playbook 来设置共享基础设施服务,如下所示:
openstack-ansible setup-infrastructure.yml -
这个步骤比第一个 Playbook 花费的时间稍长。如同之前一样,检查输出是否有失败。在此阶段,我们应该在每个基础设施节点(也称为控制节点)上运行多个容器。在这些容器中,像 Galera 或 RabbitMQ 这样的容器上,我们应该看到服务在正常运行,等待 OpenStack 对其进行配置。现在,我们可以通过运行最大的 Playbook 来继续安装 OpenStack 本身。为此,请执行以下命令:
openstack-ansible setup-openstack.yml -
这个过程可能需要一段时间——可能长达数小时——因此请确保你的 SSH 会话在长时间后不会中断,并通过像
tmux或screen这样的工具来防止断开连接,做好准备。在 Playbook 执行结束时,如果一切正常,恭喜你,OpenStack 已经安装完成!
它是如何工作的……
使用 OpenStack-Ansible 安装 OpenStack 是通过多个 Playbooks 完成的。第一个 Playbook setup-hosts.yml 配置主机,设置容器配置。在此阶段,Ansible 已经知道将来会在哪些地方放置所有与 OpenStack 相关的服务,因此我们使用动态清单信息来安装 HAProxy,并将其配置为所有 OpenStack 服务(这些服务尚未安装)使用的代理服务。下一个 Playbook setup-infrastructure.yml 配置并安装 OpenStack 期望存在的基础设施服务容器,如 Galera。最后一个 Playbook 是主 Playbook——它安装我们在配置中指定的所有 OpenStack 服务。该过程会运行一段时间,但最终你会得到一个完整的 OpenStack 安装。
OpenStack-Ansible 项目提供了一个包装脚本,包装了通常用于执行 Playbooks 的 ansible 命令。这个脚本叫做 openstack-ansible。本质上,它确保将正确的清单和配置传递给 ansible 命令,以确保正确运行 OpenStack-Ansible 的 Playbooks。
安装故障排除
Ansible 是一款由人编写的工具,运行由人编写的 Playbooks,来配置通常需要人为手动操作的系统,因此错误是难免发生的。最终结果的质量取决于输入的质量。
常见的故障通常会很快出现,例如连接问题,这些问题会比较明显,或者在长时间运行的任务后出现,可能是由于负载或网络超时导致的。无论如何,OpenStack-Ansible 的 Playbooks 提供了一种高效的机制,可以在不重复已经完成的任务的情况下重新运行 Playbooks。
在失败时,Ansible 会在 /root 目录下生成一个文件(因为我们是以 root 身份运行这些 Playbooks),文件名为 Playbook 的名称,文件扩展名为 .retry。该文件简单列出了失败的主机,方便在重新运行 Playbook 时参考。这样可以仅针对少数几个失败的主机重新执行,而不是对已经成功完成的大型集群进行重复操作,这样更加高效。
如何操作...
我们将逐步解决导致其中一个 Playbook 失败的问题。
注意失败的 Playbook,然后按照以下步骤重新执行:
-
确保你在
playbooks目录下,如下所示:cd /opt/openstack-ansible/playbooks -
现在重新运行该 Playbook,但指定
retry文件:ansible-openstack setup-openstack.yml --retry /root/setup-openstack.retry -
在大多数情况下,这足以解决问题,然而,OpenStack-Ansible 已经编写成幂等的——这意味着可以重新运行整个 Playbook,只修改需要的部分。因此,你可以在不指定
retry文件的情况下再次运行 Playbook。
如果在第一阶段发生故障,请执行以下操作:
-
首先删除生成的
inventory文件:rm -f /etc/openstack_deploy/openstack_inventory.json rm -f /etc/openstack_deploy/openstack_hostnames_ips.yml -
现在重新运行
setup-hosts.ymlPlaybook:cd /opt/openstack-ansible/playbooks openstack-ansible setup-hosts.yml
在某些情况下,销毁安装并重新开始可能是适用的。由于每个服务都安装在 LXC 容器中,因此很容易擦除安装并从头开始。要执行此操作,请按照以下步骤操作:
-
首先,我们销毁环境中的所有容器:
cd /opt/openstack-ansible/playbooks openstack-ansible lxc-containers-destroy.yml您将被要求确认此操作。按照屏幕上的提示操作。
-
我们建议您卸载以下软件包,以避免与将来运行 playbooks 时的任何冲突,并清理每个主机上的任何残留容器:
ansible hosts -m shell -a "pip uninstall -y appdirs" -
最后,删除清单信息:
rm -f /etc/openstack_deploy/openstack_inventory.json /etc/openstack_deploy/openstack_hostnames_ips.yml
工作原理…
Ansible 并不完美,计算机也不是。有时由于 SSH 超时或其他瞬时故障,环境中会发生失败。此外,尽管 Ansible 尝试重新执行 playbook,但结果可能是失败。Ansible 失败非常明显——通常会在屏幕上以红色文本输出。在大多数情况下,重新运行有问题的 playbook 可能会解决一些瞬时问题。每个 playbook 运行一个特定的任务,Ansible 会说明哪个任务失败了。排除为何特定任务失败的故障将最终导致良好的结果。最坏的情况是,您可以从头开始重置安装。
手动测试安装
安装成功后的第一步是测试安装。测试 OpenStack 涉及自动化和手动检查。
手动测试验证用户旅程,这些旅程通常不会通过自动化测试检测到,例如确保 horizon 正确显示。
可以使用诸如 tempest 或 OpenStack 基准测试工具(rally)之类的测试框架调用自动化测试。
准备工作完成后
确保您是第一个基础架构控制器节点infra01上的root用户。
如何操作…
OpenStack-Ansible 的安装在每个基础架构节点上创建了几个utility容器。这些实用程序主机提供了所有必需的命令行工具,用于尝试 OpenStack,当然是使用命令行。按照以下步骤访问实用程序主机并手动验证 OpenStack 的安装:
-
首先,通过执行以下命令查看正在运行的容器:
lxc-ls -f -
正如您所看到的,这里列出了许多容器,因为 OpenStack-Ansible 安装使用隔离的 Linux 容器来运行每个服务。在每个容器旁边,将列出其 IP 地址和运行状态。您可以在这里看到本章中使用的容器网络为
172.29.236.0/24,以及为什么这样命名。这里的一个容器是实用程序容器,采用以下格式命名:nodename_utility_container_randomuuid。要访问此容器,您可以通过 SSH 连接,或者可以执行以下命令:lxc-attach -n infra01_utility_container_34u477d -
现在,您将在这个容器内运行一个终端,只能访问属于该容器的工具和服务。在这种情况下,我们可以访问所需的 OpenStack 客户端。您需要做的第一件事是载入您的 OpenStack 凭证。OpenStack-Ansible 项目会生成一个 bash 环境文件,其中包含安装过程中设置的
admin用户和项目。使用以下命令将其加载到 bash 环境中:source openrc提示
提示:您还可以在 Bash 中使用以下语法: .
openrc -
现在,您可以使用 OpenStack CLI 查看服务和环境状态,创建网络并启动实例。以下是一些常用命令:
openstack server list openstack network list openstack endpoint list openstack network agent list
它是如何工作的…
OpenStack-Ansible 安装 OpenStack 的方法会将 OpenStack 服务安装到我们 Linux 服务器上的隔离容器中。在每个控制节点(或基础设施节点)上大约有 12 个容器,每个容器运行一个单独的服务,如 nova-api 或 RabbitMQ。您可以通过以 root 身份登录任一服务器并执行lxc-ls -f命令来查看运行中的容器。-f参数将显示完整的列表,展示实例的状态,例如它是运行中还是已停止。
基础设施节点上的一个容器名称中包含utility,在 OpenStack-Ansible 术语中称之为实用容器。这个容器安装了 OpenStack 客户端工具,非常适合手动测试 OpenStack 的安装。在这个容器中,每个容器至少有一个 IP 地址,在本章使用的示例中,IP 地址属于172.29.236.0/24子网。您可以 SSH 连接到该容器的 IP 地址,或者使用另一个lxc命令附加到容器:lxc-attach -n <name_of_container>。一旦进入容器内部,您可以像使用其他系统一样使用它,前提是容器内可以使用相应的工具。但是,要使用 OpenStack 命令,您首先需要载入名为openrc的资源环境文件。这是一个标准的 bash 环境文件,在安装过程中已预先填充,并提供了使用 OpenStack 所需的所有凭证。
修改 OpenStack 配置
如果认为为了像将 CPU 争用比率从 4:1 更改为 8:1 这样的小改动而需要重新运行所有的 playbook,那简直是荒谬的。因此,playbook 已被开发并标记,以便可以运行与特定项目关联的 playbook,重新配置并重启相关服务,以便应用更改。
准备工作
确保您在部署主机上是root用户。在大多数情况下,这将是第一个基础设施控制节点infra01。
如何操作...
以下是常见的更改及其如何通过 Ansible 进行修改。在调整配置时,所有这些命令都将在你用于执行安装的同一主机上执行。
要调整 CPU 超分配/分配比率,请执行以下步骤:
-
编辑
/etc/openstack_deploy/user_variables.yml文件,并修改(或添加)以下行(根据需要调整数字):nova_cpu_allocation_ratio: 8.0 -
现在执行以下命令以对环境进行更改:
cd /opt/openstack-ansible/playbooks openstack-ansible os-nova-install.yml --tags 'nova-config'
对于更复杂的更改,例如添加不是简单单行更改的配置,我们可以使用覆盖的替代方法。要更改默认的 Nova 配额,请按以下示例操作:
-
编辑
/etc/openstack_deploy/user_variables.yml文件,并修改(或添加)以下行(根据需要调整数字):nova_nova_conf_overrides: DEFAULT: quota_fixed_ips = -1 quota_floating_ips = 20 quota_instances = 20 -
现在执行以下命令以对环境进行更改:
cd /opt/openstack-ansible/playbooks openstack-ansible os-nova-install.yml --tag 'nova-config'
对 Neutron、Glance、Cinder 及所有其他服务的更改方式类似。只需在使用的语法中调整服务名称。例如,要更改neutron.conf文件中的配置项,可以使用以下语法:
neutron_neutron_conf_overrides:
DEFAULT:
dhcp_lease_duration = -1
然后执行以下命令:
cd /opt/openstack-ansible/playbooks
openstack-ansible os-neutron-install.yml --tag 'neutron-config'
它是如何工作的…
我们修改了与安装配置章节相同的 OpenStack-Ansible 配置文件,并执行了openstack-ansible playbook命令,指定了与我们想要更改的服务相对应的 playbook。当我们进行配置更改时,通过--tag参数通知 Ansible。
有关每个服务的所有配置选项,请参考docs.openstack.org/。
虚拟实验室 - vagrant up!
在理想的世界里,我们每个人都会有物理服务器和网络设备,以便学习、测试和实验 OpenStack。然而,实际情况往往并非如此。通过使用 Vagrant 和 VirtualBox 创建的虚拟实验室,可以让你在自己的笔记本电脑上体验本章关于 OpenStack-Ansible 的内容。
以下 Vagrant 实验室可以在openstackbook.online/找到。
这是基于 Vagrant 的 OpenStack 环境架构:

本质上,创建了三个虚拟机(一个控制节点,一个计算节点和一个客户端机器),每个主机有四个网络卡(加上 VirtualBox 本身使用的内部桥接接口)。这四个网络卡表示本章描述的网络:
-
Eth1:它包含在
br-mgmt桥接中,并由容器网络使用。 -
Eth2:它包含在
br-vlan桥接中,并在 OpenStack 启动并运行后,用于创建基于 VLAN 的 Neutron 网络。 -
Eth3:这是客户端或主机网络——我们用来与 OpenStack 服务交互的网络(例如,负载均衡器的公共/外部端)。
-
Eth4:该接口包含在
br-vxlan桥接中,并在 OpenStack 启动并运行后用于创建基于 VXLAN 的 Neutron 覆盖网络。
请注意,在此实验中创建的虚拟机 openstack-client 为您提供所有命令行工具,方便您开始使用 OpenStack。
准备就绪
为了在笔记本或指定的主机上运行多节点的 OpenStack 环境作为虚拟环境,以下一组要求是必须的:
-
一台 Linux、Mac 或 Windows 桌面、笔记本电脑或服务器。本书的作者使用 macOS 和 Linux,Windows 作为主机桌面的配置测试较少。
-
至少 16GB 内存,推荐 24GB。
-
大约需要 50GB 的磁盘空间。提供基础设施和计算节点的虚拟机是薄配置的,因此这个要求仅作为参考,具体取决于你的使用情况。
-
需要一个互联网连接。连接速度越快越好,因为安装过程依赖于从互联网直接下载文件和软件包。
如何操作……
要在虚拟环境中运行 OpenStack 环境,我们需要安装几个程序,所有这些程序都可以免费下载安装:VirtualBox、Vagrant 和 Git。VirtualBox 提供虚拟服务器,代表正常 OpenStack 安装中的服务器;Vagrant 以完全自动化的方式描述安装过程;Git 允许我们检出本书中提供的所有脚本,轻松测试虚拟的 OpenStack 安装。以下说明描述了在 Ubuntu Linux 上安装这些工具的步骤。
如果还没有安装 VirtualBox,首先需要安装它。我们建议下载该软件的最新版本。在 Ubuntu Linux 上以 root 用户执行以下步骤:
-
首先使用以下命令添加
virtualbox.org仓库密钥:wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc -O- | sudo apt-key add – -
接下来,我们通过创建一个名为
/etc/apt/sources.list.d/virtualbox.conf的文件,并包含以下内容,将仓库文件添加到apt配置中:deb http://download.virtualbox.org/virtualbox/debian xenial contrib -
现在执行
apt update以刷新并更新apt缓存,使用以下命令:apt update -
现在使用以下命令安装 VirtualBox:
apt install virtualbox-5.1
安装 VirtualBox 后,我们可以安装 Vagrant。请按照以下步骤安装 Vagrant:
-
Vagrant 从
www.vagrantup.com/downloads.html下载。我们需要的版本是 Debian 64 位版本。本文写作时,版本为 2.0.1。要在桌面上下载,执行以下命令:wget https://releases.hashicorp.com/vagrant/2.0.1/vagrant_2.0.1_x86_64.deb -
现在可以使用以下命令安装该文件:
dpkg -i ./vagrant_2.0.1_x86_64.deb
该实验使用了两个 vagrant 插件:vagrant-hostmanager 和 vagrant-triggers。要安装这些插件,请执行以下步骤:
-
使用
vagrant工具安装vagrant-hostmanager:vagrant plugin install vagrant-hostmanager -
使用
vagrant工具安装vagrant-triggers:vagrant plugin install vagrant-triggers
如果 Git 目前没有安装,可以通过以下命令在 Ubuntu 机器上安装 git:
apt update
apt install git
现在我们拥有了所需的工具,可以使用OpenStackCookbook Vagrant 实验环境在 VirtualBox 环境中执行一个完全协调的 OpenStack 安装:
-
我们将首先通过
git检出实验环境脚本和支持文件,使用以下命令:git clone https://github.com/OpenStackCookbook/vagrant-openstack -
我们将切换到刚刚创建的
vagrant-openstack目录:cd vagrant-openstack -
我们现在可以使用一个简单的命令来协调虚拟机的创建和 OpenStack 的安装:
vagrant up
提示
提示:这将需要一段时间,因为它将创建虚拟机并执行本章中描述的所有相同的剧本步骤。
它是如何工作的……
Vagrant 是一个很棒的工具,可以协调许多不同的虚拟和云环境。它允许我们描述需要创建的虚拟服务器,利用 Vagrant 的配置器,在虚拟机创建后运行脚本。
Vagrant 的环境文件名为Vagrantfile。你可以编辑这个文件来调整虚拟机的设置,例如增加内存或可用的 CPU 数量。
这使得我们可以通过一个命令描述一个完整的 OpenStack 环境:
vagrant up
该环境包含以下组件:
-
一个控制节点,
infra-01 -
一个计算节点,
compute-01 -
一个客户端虚拟机,
openstack-client
一旦环境安装完成,你可以通过在浏览器中访问http://192.168.100.10/来使用该环境。要获取管理员密码,请按照此处给出的步骤,并查看名为openrc的文件。
这里有一个单独的控制节点,它配置了一个utility容器,供本环境使用。可以使用以下命令连接:
vagrant ssh controller-01
sudo -i
lxc-attach -n (lxc-ls | grep utility)
openrc
获取openrc详情后,将其复制到你的openstack-client虚拟机中。从这里,你可以像在桌面机器上操作一样,使用命令行访问并操作 OpenStack。
vagrant ssh openstack-client
openrc
现在你应该能够使用 OpenStack CLI 工具来操作该环境。
第二章:OpenStack 客户端
在本章中,我们将涵盖以下主题:
-
介绍——使用 OpenStack
-
在 Windows 上安装 Python
-
安装 OpenStack 客户端
-
配置您的 Linux 或 macOS 环境
-
配置您的 Windows 环境
-
常见的 OpenStack 网络任务
-
常见的 OpenStack 服务器(实例)任务
-
常见的 OpenStack 镜像任务
-
常见的 OpenStack 身份管理任务
-
常见的 OpenStack 存储任务
-
常见的 OpenStack 编排任务
介绍——使用 OpenStack
OpenStack 可以通过多种方式进行交互——从使用 Horizon(OpenStack 控制面板)Web 界面到命令行的强大功能,再到使用第三方软件,这些都与 OpenStack 透明集成。在本章中,我们将介绍 OpenStack 命令行接口(CLI),并了解如何为您安装的 OpenStack 配置它。OpenStack 命令行工具和大多数 OpenStack 组件一样,都是用 Python 编写的。这意味着计算机上必须安装 Python,才能运行这些客户端。
当我们与 OpenStack 交互时,实际上是在向运行服务API(应用程序编程接口)的服务发起 REST API 调用。REST API 定义了一组函数,开发者可以通过 HTTP 协议(如 GET 和 POST)进行请求并接收响应。OpenStack 命令行客户端将您的直观命令转化为这些 HTTP 调用。在典型的 OpenStack 部署中,并且在第一章,使用 Ansible 安装 OpenStack中描述的那种部署中,通过 Ansible,我们的 OpenStack API 服务已经部署在三个 Controller 节点上。为了使我们能够与这三个 Controller 节点中的任意一个进行交互,以便每个节点可以独立响应,我们将这些服务放置在负载均衡器后面。作为 OpenStack 用户,我们关注的是负载均衡器的VIP(虚拟 IP),即我们为每个配置的池关联的 IP 地址。
在配置环境以便与 OpenStack 配合使用时,有一个特定的服务是用户感兴趣的,那就是 Keystone 服务。
Keystone 服务(OpenStack 身份服务)在 OpenStack 中本质上执行两个功能。它授权用户允许他们执行所请求的操作,并向用户提供服务目录。该目录是 OpenStack 服务地址端点的映射。因此,我们不需要配置客户端来知道如何找到每一个 OpenStack 服务。当用户配置环境以便从命令行使用 OpenStack 时,他们唯一需要知道的信息是 Keystone 所安装的 IP 地址和端口。请参阅以下图示,了解用户如何从概念上看到这一点:

提示
本章旨在作为一个快速参考指南,介绍本书中更详细解释的命令。
在 Windows 上安装 Python
为了能够在 Windows 上安装所需的 OpenStack 客户端工具,我们必须首先为 Windows 桌面计算机准备 Python。以下内容适用于 Windows 10。
准备工作
确保你已登录到桌面,并安装了以下内容:
-
PowerShell
-
从此处下载 Python 2.7:
www.python.org/downloads/windows/ -
微软 Visual C++ 构建工具,包含 Windows 10 SDK 功能
如何操作…
配置你的 Windows 环境可以通过你 PC 的 属性 来实现。按照以下说明确保 Python 在你的系统路径中可用,并在 PowerShell 中设置适当的环境变量:
-
转到桌面上的 此电脑 图标并选择 属性,如图所示:
![如何操作…]()
-
接下来,从左侧菜单中选择 高级系统设置:
![如何操作…]()
-
现在,从 系统属性 窗口的 高级 标签中选择 环境变量,如图所示:
![如何操作…]()
-
要设置 Python 的路径,双击 Path 条目,如下所示:
![如何操作…]()
-
现在,按如下所示向路径添加 新 行。我们假设你进行了 Python 2.7 的默认安装,并且安装在
C:\Python27目录下:![如何操作…]()
-
现在点击 确定。当你加载 PowerShell 会话时,你现在应该能够测试 Python 是否按预期工作,如下所示:
![如何操作…]()
-
现在,你应该能够按照接下来的步骤安装 OpenStack 客户端。
工作原理…
配置 Windows 环境比配置 Unix/Linux 环境稍微复杂一些。我们首先需要确保 Python 配置正确,并且可以在 Shell 中使用。接下来,我们需要一种机制将环境变量加载到 Shell 中,而这并不是 Windows 的本地功能。我们通过 PowerShell 脚本实现这一点。然而,由于 PowerShell 功能强大,我们需要移除一些限制以使其正常工作。一旦正确设置好这些内容,就可以在 Windows 桌面上使用 OpenStack 环境。
安装 OpenStack 客户端
有多个 OpenStack 客户端可用于从命令行与 OpenStack 交互。历史上,OpenStack 中的每个服务都有自己的客户端。例如,OpenStack 计算项目 Nova 有自己的 nova 客户端。同样,OpenStack 网络项目 Neutron 也有自己的名为 neutron 的客户端,依此类推。
官方上,OpenStack 客户端正在趋向统一使用一个客户端:OpenStack 客户端。然而,并非所有命令和功能都可以通过这个工具使用。此外,OpenStack 客户端仍然需要安装每个独立项目的命令行工具才能正常工作;但它提供了一个更一致的界面,而不需要记住每个单独项目的名称。
准备工作
由于我们正在为从命令行与 OpenStack 交互准备桌面,您会发现,针对您选择的桌面操作系统,有多种选择。本节将描述如何安装 OpenStack 客户端。
由于我们将使用 pip 安装 OpenStack 客户端,请确保按照以下步骤安装它:
-
首先,打开终端并使用以下命令切换到 root 用户:
sudo -i -
我们将使用
pip安装客户端。如果pip未安装,请按照以下步骤操作:在 macOS 或其变种上使用以下命令:
wget https://bootstrap.pypa.io/get-pip.py python get-pip.py -
在流行的 Linux 系统上,使用您的包管理器安装这些软件包:
Ubuntu:确保安装了
python-dev和python-pipRed Hat:确保安装了
python-devel和python-pip
注意
Windows:确保已安装 Python 并且它在 PATH 中,并已安装 Microsoft Visual C++ Build Tools。
如何操作…
在系统上安装了 pip 后,我们可以通过以下简单步骤安装客户端:
-
要安装 OpenStack 客户端,请执行以下命令:
pip install python-openstackclient -
要安装各个客户端,请执行以下命令:
pip install python-novaclient pip install python-neutronclient pip install python-glanceclient pip install python-heatclient pip install python-keystoneclient pip install python-cinderclient pip install python-swiftclient
提示
每个项目都有自己的客户端,因此语法为:
pip install python-PROJECTclient
替代方法 – 使用预配置的 OpenStack 客户端虚拟机
有时客户端的开发进度与环境中已安装的项目不同,这可能导致版本不兼容。为了解决这个问题,可以使用 virtualenv(pypi.python.org/pypi/virtualenv)或者使用一个已经为访问 OpenStack 环境预配置的虚拟机(在 VirtualBox 中)。使用预构建的虚拟环境,请执行以下操作:
-
克隆客户端 VirtualBox Vagrant 环境:
git clone https://github.com/OpenStackCookbook/openstack-client.git -
启动客户端:
cd openstack-client vagrant up -
访问虚拟机:
vagrant ssh
它是如何工作的…
安装 OpenStack 客户端非常简单,只需要使用 pip 命令行工具,它用于安装 Python 包。用于在命令行中操作 OpenStack 的主要工具叫做 OpenStack 客户端。这个工具用于控制 OpenStack 的各个方面。然而,仍然有一些命令和选项没有加入到主流的 OpenStack 客户端中。为了解决这个问题,可以继续使用旧版的遗留项目工具。确保也使用以下语法安装这些工具:
pip install python-PROJECTclient
将 PROJECT 替换为 OpenStack 项目的具体名称,例如 glance 或 neutron。
或者,可以将这些工具创建在小型虚拟机中,这样工具始终可用。可以从 github.com/OpenStackCookbook/ope 获取一个 Vagrant OpenStack 客户端环境。
配置你的 Linux 或 macOS 环境
OpenStack 工具通过在你的 shell 或桌面设置环境变量来进行配置。
准备工作
确保已按照本章中第一部分 介绍 - 使用 OpenStack 中的说明安装 OpenStack 客户端。
如何操作…
通过设置环境变量来配置你的命令行环境;然而,将这些变量放入一个文件中,以便以后加载到环境中,会更简单和方便。在安装过程中,OpenStack-Ansible 会创建一个名为 openrc 的纯文本文件,并将其放置在所有创建的容器的 /root 目录中。这个文件是配置环境的一个很好的起点,因为它包含了操作命令行环境所需的所有必需元素。
在你自己的客户端上,例如基于 Linux 或 Mac 的系统,选择一个工作目录,例如 $HOME/openstack,并创建一个名为 openrc(或你选择的具有意义的名称)的文件,内容如下:
export OS_USERNAME=admin
export OS_PASSWORD=secrete
export OS_TENANT_NAME=admin
export OS_AUTH_URL=http://192.168.100.117:5000/v3
export OS_NO_CACHE=1
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_DOMAIN_NAME=Default
export OS_IDENTITY_API_VERSION=3
export OS_AUTH_VERSION=3
现在通过以下方式在你的 shell 中加载该文件:
source openrc
提示
在 Bash 中,你也可以使用以下语法:
. openrc
该文件包含了访问你云环境的认证信息。请确保文件安全,并且权限设置不允许其他用户读取此文件。如果不确定,建议按以下方式设置权限:
chmod 0600 openrc
这将使文件仅对你(用户)可读写。
现在,您可以使用命令行工具了。如果在执行书中命令时出现任何问题,请检查文件中的凭证——确保您设置了正确的租户/项目、用户名和密码,并确保指定了正确的 OpenStack 认证 URL 端点。一旦对文件做出任何更改,请记得将其重新加载到 shell 中。
它是如何工作的…
本质上,我们只是在 shell 中设置一些环境变量,客户端工具用这些变量来进行 OpenStack 环境的身份验证。不过,为了简化操作,我们将这些环境变量存储在一个文件中。这样,我们只需要运行一个命令即可设置所有必需的凭证,方便访问环境。
配置 Windows 环境
配置 Windows 环境以使用 OpenStack 需要稍微多一点的工作,但基本前提依然不变:我们正在配置桌面,使其能够访问环境变量,并确保我们用 Python 编写的工具能够正确执行。
准备就绪
以下内容适用于 Windows 10。请确保您已按照步骤安装了 Python。
如何操作…
执行以下操作,将所需的环境变量加载到您的 Windows 会话中:
-
为了能够像在 Unix/Linux 平台上一样加载所需的 OpenStack 环境功能,我们可以使用 PowerShell 实现类似的效果。在 PowerShell 终端中,获取以下 PowerShell 脚本并将其下载到您的工作客户端目录中(例如
C:\Users\Username\OpenStack):mkdir OpenStack cd OpenStack wget https://raw.githubusercontent.com/OpenStackCookbook/vagrant-openstack/master/Source-OpenRC.ps1 -UseBasicParsing -OutFile Source-OpenRC.ps1 -
使用与配置您的 Linux 或 macOS 环境部分中描述的相同 OpenStack 凭证,确保将其命名为
openrc,以与以下示例匹配,然后在 PowerShell 中执行以下操作:.\Source-OpenRC.ps1 .\openrc注意
警告:执行 PowerShell 脚本时,可能会遇到错误。大多数 Windows 10 桌面似乎默认有一个受限策略,这排除了运行未签名的 PowerShell 脚本——即使是您自己创建的脚本。要移除此限制,请执行以下操作并确认警告:
Set-ExecutionPolicy –ExecutionPolicy RemoteSigned Unrestricted -Scope CurrentUser -
现在,您应该能够在 Windows 桌面的 PowerShell 终端中使用 OpenStack 客户端。
它是如何工作的…
配置 Windows 环境比配置 Unix/Linux 环境稍微复杂一些。我们需要一个机制来将环境变量加载到 shell 中,而这是 Windows 的原生功能所不具备的。我们通过 PowerShell 脚本来实现这一点。但为了使其工作,我们必须移除一个限制。一旦正确设置好所有内容,便能够从 Windows 桌面使用 OpenStack 环境。
常见的 OpenStack 网络任务
本节仅简要列出了常见的 OpenStack 网络任务,供快速参考。如需详细了解如何使用 Neutron 及其工作原理——包括浮动 IP 和路由器等特性的使用场景和细节,请参阅第四章,Neutron – OpenStack 网络。
准备工作
确保您已安装 OpenStack 客户端,具体安装方法请参考本章的第一部分。
如何操作…
执行以下步骤以在 OpenStack 中创建和修改网络:
创建网络
通常,创建网络有两个步骤:创建一个相当于 L2 网络的网络,接着为其分配子网(及相关详细信息)。
-
首先,创建网络:
openstack network create NETWORK_NAME -
现在在此网络上创建子网:
openstack subnet create SUBNET_NAME --network NETWORK_NAME--subnet-range CIDR
创建提供者网络(用于浮动 IP)
要创建一个浮动 IP 提供者网络,请执行以下命令。此命令假设我们的提供者接口(在 OpenStack 中查看并在 Neutron 中配置)正在使用“flat”接口。在数据中心的典型部署中,可能会使用“vlan”作为提供者类型和设备,因此请根据您的环境调整配置。
-
首先,创建网络(在本示例中,我们指定了
flat的提供者类型):openstack network create --share --project admin --external --default --provider-network-type flat --provider-physical-network flat GATEWAY_NET -
现在,我们指定一些子网选项,以使得该网络能够从 OpenStack 外部进行访问:
openstack subnet create --project admin --subnet-range 192.168.100.0/24 --dhcp --gateway 192.168.100.1 --allocation-pool start=192.168.100.200,end=192.168.100.250 --network GATEWAY_NET GATEWAY_SUBNET
创建一个新的安全组
在development项目中创建一个新的安全组,例如webserver,可以通过以下方式实现:
openstack security group create
--project development
webserver
向安全组添加规则
要向前面创建的名为webserver的安全组添加规则,例如允许来自任何地方的端口80的入站访问,请执行以下操作:
openstack security group rule create
--remote-ip 0.0.0.0/0
--dst-port 80:80
--protocol tcp
--ingress
--project development
webserver
创建路由器
要在我们的项目中创建一个名为myRouter的路由器,请执行以下命令:
openstack router add myRouter
向路由器添加子网
要向我们的路由器myRouter添加一个名为private-subnet的私有租户子网,请执行以下命令:
openstack router add subnet myRouter private-subnet
设置路由器上的网关
要为我们的路由器添加网关,首先必须确保网关网络已创建,并使用--external标志,如本章“创建提供者网络”部分所述(用于浮动 IP)。然后,我们将执行以下命令,将外部网关网络设置为GATEWAY_NET,并应用到我们名为myRouter的路由器上:
openstack router set myRouter
--external-gateway GATEWAY_NET
常见的 OpenStack 服务器(实例)任务
本节概述了一些常见命令,这些命令可以在操作实例(例如虚拟机)时执行。有关每个任务的详细信息和解释,请参阅第五章,Nova – OpenStack 计算。
准备工作
确保您已安装 OpenStack 客户端,具体安装方法请参考本章的第一部分。
如何操作…
执行以下操作以启动和操作正在运行的实例:
启动实例
要通过命令行启动实例,您需要以下信息:
-
一个镜像
-
一个网络
-
一个规格
-
一个可选的安全组(如果没有指定,默认使用)
-
一个可选的密钥(如果您打算访问该实例)
执行以下步骤以通过命令行启动实例:
-
首先,列出可用的镜像:
openstack image list -
现在,我们列出可用的网络(这将是我们将使用的网络的 UUID):
openstack network list -
我们需要一个规格,如果需要提醒,请使用以下命令列出它们:
openstack flavor list -
如果您需要特定的安全组,请使用以下命令列出它们:
openstack security group list -
如果您需要获取要使用的密钥对的名称,请使用以下命令:
openstack keypair list -
现在,您可以使用以下命令启动实例:
openstack server create --image IMAGE --flavor FLAVOR --security-group SECGROUP --nic net-id=NETWORK_UUID --key-name KEYPAIR_NAME INSTANCE_NAME
列出 OpenStack 实例
要列出已启动的 OpenStack 实例,请执行以下命令:
openstack server list
创建实例快照
要创建正在运行的实例的快照,请执行以下命令:
openstack server image create
--name snapshotRunningWebserver1
myRunningWebserver1
调整实例大小
要修改正在运行的实例的规格并使用新设置重新启动,请执行以下命令:
-
首先,我们使用以下命令指定新的规格大小:
openstack server resize --flavor m1.small myWebserver1 -
接下来,列出正在运行的实例以确认状态。状态应为
VERIFY_RESIZE:openstack server list输出将显示如下内容:
![调整实例大小]()
-
然后,我们使用以下命令确认操作:
openstack server resize --confirm myWebserver1
创建规格
要创建一个规格,名为 m1.tiny,包含 512 MB 的 RAM、1 个 vCPU 和没有固定大小的磁盘,请执行以下命令:
openstack flavor create
--ram 512
--disk 0
--vcpus 1
--public
m1.tiny
常见的 OpenStack 镜像任务
本节概述了一些步骤,作为快速概述,仅用于操作 OpenStack 镜像服务(称为 Glance)时的参考。如需更详细的信息和每个任务的解释,请参见 第六章,Glance – OpenStack 镜像服务。
准备工作
确保您已经安装了 OpenStack 客户端,安装方法请参考本章开头的配方。
如何做…
执行以下步骤以在 OpenStack 中创建和修改镜像:
上传镜像到 Glance
将镜像上传到 OpenStack 可通过以下命令完成。要上传一个 QCOW2 镜像(如 CirrOS 提供的用于测试的镜像),请执行以下命令:
openstack image create
--container-type bare
--disk-format qcow2
--public
--file
/path/to/cirros-0.3.5-x86_64-disk.img
从 Glance 下载镜像或快照作为文件
要从 Glance 下载镜像,可能是为了复制到其他环境或作为异地备份存储,请执行以下命令:
openstack image save
--file myImage.qcow2 myImage
在项目间共享镜像
在大多数情况下,镜像要么是公开的(对所有项目可用),要么是私有的(仅对上传该镜像的项目可用)。但是,您可以将一个私有镜像共享给您选择的隔离项目。要做到这一点,您需要以下内容:
-
您将要共享的镜像的 UUID
-
您将与之共享镜像的项目的 UUID
执行以下步骤以将镜像与另一个项目共享。在以下示例中,我们将共享当前仅在 admin 项目中可用的 cirros-image,并将其共享到 anotherProject 项目:
-
首先,查询项目列表:
openstack project list这将返回类似以下内容的输出:
![在项目之间共享镜像]()
-
我们将设置要共享的镜像:
openstack image set cirros-image --shared -
然后,我们将告诉 OpenStack 通过以下命令共享哪个项目:
openstack image add project anotherProject这将返回类似以下内容的输出 —— 我们将在下一步中使用 image_id:
![在项目之间共享镜像]()
-
重要提示:作为 接收(anotherProject)项目中的用户,执行以下操作:
openstack image set --accept f6578a80-5f6f-4f2d-9a8a-9d84cec8a60d -
现在,作为该用户,您可以通过执行镜像列表命令来确认自己能看到这个共享的镜像:
openstack image list这将返回类似以下内容的输出,显示可用的镜像:
![在项目之间共享镜像]()
常见的 OpenStack 身份任务
本节概述了使用 OpenStack 身份服务执行一些常见操作的常见步骤。此部分仅作为快速参考指南。如需更详细的信息和每个任务的解释,请参阅第三章,Keystone – OpenStack 身份服务。
准备工作
确保您已安装 OpenStack 客户端,如本章第一部分所述。
如何执行…
执行以下步骤以在 OpenStack 中创建和修改用户和项目:
创建新项目
在项目中创建新用户通过以下命令实现。例如,要创建名为 development 的项目,请执行以下命令:
openstack project create development
创建用户
要创建一个名为 developer 的用户,并设置密码为 password123,请执行以下命令:
openstack user create
--domain default
--password password123
--enable
developer
向项目中添加用户
要将具有 _member_ 角色(普通用户)的用户添加到 development 项目中,请执行以下命令:
openstack role add
--project development
--user developer
_member_
作为管理员更改用户密码
作为管理员,您有权更改他人的密码。要为 developer 用户更改密码,请执行以下命令:
openstack user set --password cookbook4 developer
更改自己的密码
要将自己的密码更改为其他内容,请执行以下命令:
openstack user password set --password cookbook4
常见的 OpenStack 存储任务
本节概述了使用 OpenStack 块存储和对象存储服务执行的一些常见任务。如需更多存储信息,请参阅第七章,Cinder – OpenStack 块存储 和 第八章,Swift – OpenStack 对象存储。
准备工作
确保您已安装 OpenStack 客户端,如本章第一部分所述。
如何执行…
执行以下步骤在 OpenStack 中创建和修改用户和项目:
创建一个新的 Cinder 卷
要创建一个新的 Cinder 块存储卷,请执行以下命令。大小以千兆字节为单位:
openstack volume create --size 5 my5GVolume
附加一个卷
要将卷附加到运行中的实例,请执行以下命令。使用运行中的 实例 UUID,并可以通过列出运行中的实例找到:
openstack server add volume my5GVolume 58ea640b-16ba-447c-85db-952174d70f7c
分离一个卷
要分离一个卷,首先像平常一样将其从运行中的实例中卸载,然后执行以下命令:
openstack server remove volume my5GVolume 58ea640b-16ba-447c-85db-952174d70f7c
创建一个卷快照
要创建卷的快照,请执行以下步骤。首先,您必须将卷从运行中的实例中分离,以确保数据一致性。该操作在前面的任务中已经描述。
现在,分离后,执行以下命令
openstack snapshot create --name myVolumeSnapshot myVolume
列出对象存储统计信息
要显示有关对象存储容器的信息,请执行以下命令:
openstack object store account show
列出对象存储容器及其内容
要列出对象存储的内容,请执行以下命令:
openstack object store list
openstack object store list myContainer
创建并上传文件到对象存储服务
要创建一个对象存储容器,请执行以下命令:
openstack object create myContainer
要将文件上传到对象存储容器,请执行以下命令:
openstack object create myContainer myFile
从对象存储下载
要从对象存储容器下载文件,请使用此命令
openstack object save myContainer myFile
要从对象存储容器下载所有文件,请执行以下命令:
openstack object save myContainer
常见的 OpenStack 编排任务
本节概述了使用 OpenStack 编排(Heat)服务启动 堆栈(使用 Heat 编排的环境)的一些常见任务。有关 Heat 和编排的更多信息,请参考 第九章,使用 Heat 和 Ansible 的 OpenStack 编排。
准备工作
确保您已安装 OpenStack 客户端,安装方法请参考本章的前几个食谱。
如何操作…
执行以下步骤,在 OpenStack 中创建并使用 Heat 模板来创建编排环境:
从模板和环境文件启动堆栈
要从 Heat 编排模板(hot)启动堆栈,请执行以下命令:
openstack stack create
--template myStack.yml
--environment myStack-Env.yml
myStack
列出堆栈
要列出运行中的堆栈,请执行以下命令:
openstack stack list
删除一个运行中的堆栈
要销毁名为 myStack 的运行中堆栈,请执行以下命令:
openstack stack delete myStack
列出堆栈中的资源
要列出运行中的堆栈中的资源,请执行以下命令:
openstack stack resource list
要列出特定资源的详细信息,例如名为 myResource 的资源,请执行以下命令:
openstack stack resource show myResource
查看运行中堆栈的输出
要查看堆栈生成的输出,请执行以下命令:
openstack stack output list
要查看特定输出的详细信息,请执行以下命令:
openstack stack output show myOutput
第三章. Keystone – OpenStack 身份服务
本章我们将讨论以下主题:
-
介绍 – OpenStack 身份
-
在 Keystone 中创建 OpenStack 域
-
在 OpenStack 仪表盘中启用域
-
在 Keystone 中创建 OpenStack 项目
-
配置 Keystone 中的角色
-
在 Keystone 中添加用户
-
配置 Keystone 中的组
-
删除项目
-
删除用户
-
删除角色
-
删除组
-
删除域
-
OpenStack 端点信息
介绍 – OpenStack 身份
OpenStack 身份服务,称为Keystone,提供身份验证和管理用户帐户及角色信息的服务,适用于我们的 OpenStack 云环境。
这是一个至关重要的服务,支撑着我们所有 OpenStack 云服务之间的认证与验证,是在 OpenStack 环境中需要首先安装的服务。OpenStack 身份服务通过在所有 OpenStack 服务之间传递一个经过验证的授权令牌来验证用户和项目。这个令牌会传递给其他服务,如存储和计算服务,以授予用户对特定功能的访问权限。因此,必须首先完成 OpenStack 身份服务的配置,才能使用其他任何服务。设置身份服务涉及为用户和服务、项目、用户帐户以及构成云基础设施的服务 API 端点创建适当的角色。由于我们使用 Ansible 来部署环境(更多细节请参见第一章,使用 Ansible 安装 OpenStack),所有基本配置都已经在 Ansible 剧本中为我们完成。
在 Keystone 中,我们有域、项目、角色、用户和用户组的概念。Keystone 域(不要与 DNS 域混淆)是一个高层次的 OpenStack 身份资源,其中包含项目、用户和组。一个项目有用户、镜像、实例等资源,并且其中的网络可以仅限于该项目,除非显式与其他项目共享。一个用户可以属于一个或多个项目,并能够在这些项目之间切换,以访问相应的资源。项目中的用户可以分配不同的角色。用户可以组织成用户组,并且组可以被分配角色。在最基本的场景下,用户可以被分配管理员角色或仅是成员。当一个用户在项目中拥有管理员权限时,管理员能够利用可以影响项目的功能(例如修改外部网络),而普通用户则被分配成员角色。这个成员角色通常用于执行与用户相关的任务,如启动实例、创建卷和创建隔离的项目专用网络。
注意
项目在早期版本的 OpenStack 中被称为租户。
在 Keystone 中创建 OpenStack 域
如果您希望在 OpenStack 部署中使用多个域名,请考虑使用单独的域。在大型组织中,域可以视为单独的账户或部门。在本节中,我们将为我们的项目创建一个名为 bookstore 的域。
准备工作
确保您已以具有管理员权限的用户身份登录到正确配置的 OpenStack 客户端,并能够访问 OpenStack 环境。
参考 第二章,OpenStack 客户端,以了解设置您的环境以使用 OpenStack 命令行客户端的详细信息。
如何做…
要在我们的 OpenStack 环境中创建一个域,请执行以下步骤:
-
我们首先创建一个名为
bookstore的域,如下所示:openstack domain create --description "Book domain" bookstore输出将类似于以下内容:
![如何做…]()
工作原理…
在 OpenStack 中,高级别的身份资源可以分组到不同的域下。如果您需要在 OpenStack 环境中管理不同的组织,为它们管理的资源使用单独的域可能非常有益。默认情况下,您的 OpenStack 环境很可能有一个名为 "Default" 的默认域。通过运行上述命令,我们刚刚创建了一个额外的域,用于管理与本书相关的资源。语法如下:
openstack domain create --description <description> <name>
description 参数也是可选的,但强烈推荐。域名必须与环境中的其他域名唯一。
注意
在我们的操作中,我们将使用 --domain 参数并指定域名。如果未指定域,则 OpenStack 命令行客户端将使用在 openrc 文件中指定的当前用户的域,最可能是 default 域。
在 OpenStack 仪表板中启用域
如果您在 OpenStack 环境中使用多个域,还需要在 OpenStack 仪表板(Horizon)中启用它们。为此,需要将 Horizon 设置中的 OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT 变量设置为 True。在此示例中,我们将展示如何使用 OpenStack Ansible playbook 完成此操作。
准备工作
我们将使用 Ansible 更新 Horizon 设置。确保您可以访问您的 openstack-ansible 部署主机。
如何做…
要在 OpenStack 仪表板中启用多域支持,我们将使用 openstack-ansible 部署工具更新 local_settings.py 中的一个 Horizon 变量 OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT。首先,您需要连接到您的 openstack-ansible 部署主机。连接后,执行以下步骤:
-
编辑
/etc/openstack_deploy/user_variables.yml文件,添加以下行:horizon_keystone_multidomain_support: True -
使用
openstack-ansible命令部署 Horizon:openstack-ansible /opt/openstack-ansible/playbooks/os-horizon-install.ymlopenstack-ansible命令会生成大量输出。为简洁起见,已省略其输出。 -
启动 OpenStack 仪表盘,验证登录屏幕现在是否显示域字段:
![如何操作…]()
它是如何工作的…
在 OpenStack 中,如果你正在利用多域功能,可以通过命令行工具完全控制。然而,如果你希望能够在 OpenStack 仪表盘上使用多个域,则需要启用 Horizon 的多域支持。为此,你需要更新 Horizon 设置文件。由于我们使用的是openstack-ansible工具,我们更新了user_variables.yml文件并运行了openstack-ansible命令。此命令更新了所需的变量,并重新启动了 Horizon 容器上的apache2(HTTP 服务器)服务。
在 Keystone 中创建 OpenStack 项目
用户在没有分配项目的情况下无法创建,因此必须先创建项目。对于本节内容,我们将为我们的用户创建一个名为cookbook的项目。
准备工作
确保你已登录到配置正确的 OpenStack 客户端,并且可以作为具有管理员权限的用户访问 OpenStack 环境。
请参阅第二章,OpenStack 客户端,了解如何设置环境以使用 OpenStack 命令行客户端。
如何操作…
要在我们的 OpenStack 环境中创建项目,请执行以下步骤:
-
我们首先创建一个名为
cookbook的项目,如下所示:openstack project create --domain bookstore --description "Cookbook Project" cookbook该命令应产生类似如下的输出:
![如何操作…]()
它是如何工作的…
通过运行前面的命令,我们刚刚在bookstore域中创建了一个项目。语法如下:
openstack project create --domain <domain>
--description <description> <name>
domain参数是可选的,用于确定项目将属于哪个域。如果省略,项目将在default域中创建。description参数也是可选的,但强烈建议填写。name参数必须在该安装中唯一。
在 Keystone 中配置角色
角色是分配给项目中用户的权限。角色还可以限定在特定的域中,这样可以限制特定用户在某个域和项目中的权限。如果你使用了 Ansible 安装 OpenStack 环境,它应该已经包含一些默认角色,例如admin和_member_。在这里,我们将配置一个角色,即cloud_admin角色,允许管理我们的示例bookstore域环境,以及一个user角色,授予default域中的普通用户,该用户将使用云环境。
准备工作
确保你已登录到配置正确的 OpenStack 客户端,并且可以作为具有管理员权限的用户访问 OpenStack 环境。
请参阅第二章,OpenStack 客户端,了解如何设置环境以使用 OpenStack 命令行客户端。
如何操作…
要在我们的 OpenStack 环境中创建所需的角色,请执行以下步骤:
-
cloud_admin角色的创建如下所示:openstack role create --domain bookstore cloud_admin:![如何操作…]()
-
要为
default域配置user角色,请执行以下命令:openstack role create user![如何操作…]()
该命令创建了一个名为
user的新角色。由于我们未指定域,它是在default域下创建的。 -
查看与
bookstore域关联的角色:openstack role list --domain bookstore![如何操作…]()
-
列出与当前管理员用户关联的角色:
openstack role list![如何操作…]()
它是如何工作的…
角色的创建简单地通过 OpenStack 客户端完成,使用role create选项,语法如下:
openstack role create --domain <domain_name> <role_name>
domain_name属性是可选的,如果省略该属性,将为default域创建一个角色。
对于role_name属性,admin和_member_角色名称不能重复使用。admin角色是 OpenStack 代码中从 Pike 版本开始默认设置的,在 Pike 版本之前的版本中,它在/etc/keystone/policy.json文件中被设置为具有管理员权限:
{
"admin_required": "role:admin or is_admin:1",
}
_member_角色在通过 Web 界面创建非管理员用户时,也会在仪表盘中默认配置。
创建角色时,会返回与角色关联的 ID,我们可以在分配角色给用户时使用它。要查看我们环境中角色及其关联 ID 的列表,可以执行以下命令:
openstack role list --domain <domain_name>
注意
如果未指定domain参数,则只会看到与当前用户域关联的角色。
在 Keystone 中添加用户
向 OpenStack 身份服务中添加用户需要用户属于某个域或该域中的项目,并且需要分配一个在该域或项目中定义的角色。在本节中,我们将创建两个用户。第一个用户命名为cloud_admin,并将在cookbook项目中为其分配cloud_admin角色。第二个用户命名为reader,并将在同一cookbook项目中为其分配默认的_member_角色。
准备就绪
确保你已登录到正确配置的 OpenStack 客户端,并且可以作为具有管理员权限的用户访问 OpenStack 环境。
参见第二章,OpenStack 客户端,了解如何设置你的环境以使用 OpenStack 命令行客户端。
如何操作…
为了在 OpenStack 中创建用户并为其分配角色,我们需要执行以下列出的命令。
-
首先,获取
bookstore域 ID 或域名:![如何操作…]()
-
使用
bookstore域名,创建一个新的cloud_admin用户:openstack user create --domain bookstore --password verysecret cloud_admin![如何操作…]()
-
接下来,获取一个 cookbook 项目的 ID 或项目名:
openstack project list![如何操作…]()
-
在
bookstore域的cookbook项目中创建reader用户:openstack user create --domain bookstore --project cookbook --password verysecret reader![如何操作…]()
-
将
cloud_admin用户分配给admin角色:openstack role add --domain bookstore --user cloud_admin --role-domain bookstore admin此命令没有输出。
-
将
reader用户分配给_member_角色:openstack role add --project cookbook --user reader _member_此命令没有输出。
-
列出用户和角色分配:
openstack role assignment list输出将是角色、用户、组、项目和域 ID 的矩阵。由于包含每个角色、用户、组、项目、域的 ID 矩阵及其是否继承角色的庞大表格,我们省略了示例输出。
工作原理……
在 OpenStack 身份服务中添加用户涉及多个步骤和依赖关系。首先,需要一个域和项目,用户必须属于其中一个。用户必须始终属于一个域。如果没有创建自定义域,则将使用default域。一旦项目存在,用户可以被添加。在此时,用户没有关联的角色,因此最后一步是将角色分配给该用户,例如_member_、admin或自定义角色。
使用user create选项创建用户时,语法如下:
openstack user create --domain <domain>
--password <password> <user_name>
user_name属性是一个任意名称,但不能包含空格。必须存在password属性。在之前的示例中,这些设置为verysecret。如果未指定domain属性,则将设置为default域。
要使用role add选项将角色分配给用户,default域的语法如下:
openstack role add --project <project>
--user <user>
<role>
对于自定义域中的用户,使用以下语法分配角色:
openstack role add --domain <domain>
--user <user>
--role-domain <role_domain>
<role>
role_domain参数是角色所属的域的名称(或 ID)。
我们还需要用户、角色和项目的名称或 ID,以便将角色分配给用户。这些名称或 ID 可以通过以下命令找到:
openstack project list
openstack user list
openstack role list
--domain <domain>选项仅在使用自定义域时需要。如果要获取域列表,请发出以下命令:
openstack domain list
要获取域、项目、用户和角色分配的矩阵,请使用以下命令:
openstack
role assignment list
配置 Keystone 中的组
如果您希望按角色组织用户,可以使用 Keystone 组创建一个用户组。组属于一个域。在此示例中,我们将创建一个组reader_group,并为其设置cloud_admin角色。我们还将向其中添加两个用户reader和reader1。我们还将验证这些用户是否属于该组,并在之后移除其中一个用户。
正在准备中
确保您已登录到正确配置的 OpenStack 客户端,并且能够以具有管理员权限的用户身份访问 OpenStack 环境。
请参阅第二章,OpenStack 客户端,以获取设置环境以使用 OpenStack 命令行客户端的详细信息。
如何执行…
为了创建组并将用户分配给它们,我们将需要执行以下步骤:
-
首先创建一个组:
openstack group create --domain bookstore --description "Bookstore reader group" reader_group![如何执行...]()
-
列出现有组:
openstack group list![如何执行...]()
-
将组添加到角色:
openstack role add --group reader_group --domain bookstore --role-domain bookstore cloud_admin--domain和--role-domain参数是必需的。此命令没有输出。 -
将
reader用户添加到组中:openstack group add user --group-domain bookstore --user-domain bookstore reader_group reader这将产生类似以下的信息:
reader added to group reader_group -
将
reader1用户添加到组中:openstack group add user --group-domain bookstore --user-domain bookstore reader_group reader1这将输出以下信息:
reader1 added to group reader_group -
检查
reader是否在reader_group组中:openstack group contains user reader_group reader这将输出以下信息:
reader in group reader_group -
检查
reader1是否在reader_group组中:openstack group contains user readergroup reader1这将产生类似以下的信息:
reader1 in group readergroup -
将
reader1用户从reader_group组中移除:openstack group remove user reader_group reader1这将产生类似以下的信息:
reader1 removed from group reader_group -
再次检查
reader1是否在reader_group组中:openstack group contains user reader_group reader1这将产生类似以下的信息:
reader1 not in group reader_group
它是如何工作的…
将用户添加到身份组是一种为他们授予特定角色集合的好方法,而无需单独为每个用户分配每个角色。如果您需要管理总是获得相同角色集合的用户,可以创建一个用户组,并根据需要添加或删除用户,而不是为每个用户设置单独的角色。角色的分配方式与将角色分配给用户类似。在我们的示例中,我们首先创建了一个自定义组 reader_group。创建组的命令如下:
openstack group create --domain <domain-name>
--description <group-description>
<group-name>
由于我们在示例中使用了自定义域,因此需要 <domain-name>。但是,如果省略 <domain-name>,将使用当前用户的域。
将组添加到角色:
openstack role add --group <group>
--domain <domain>
--role-domain <role_domain>
<role>
role_domain 参数是角色所属域的名称(或 ID)。
我们还需要知道组名、角色名和项目名,以便将角色分配给用户。这些名称可以使用以下命令查找:
openstack project list
openstack group list
openstack role list
如果你使用自定义域,请将 --domain <domain> 作为选项传递给前面的命令。要获取域的列表:
openstack domain list
要将用户添加到组中,请使用以下命令:
openstack group add user --group-domain <group_domain>
--user-domain <user_domain>
<group>
<user>
要将用户从组中移除,请执行以下命令:
openstack group remove user <group> <user>
要验证用户是否属于该组,请使用此命令:
openstack group contains user <group> <user>
要获取域、项目、用户、组和角色分配的矩阵,请使用以下命令:
openstack role assignment list
你也可以在所有前面的命令中使用项目的 ID,而不是名称。
注意
组是在 Keystone v3 中引入的。
删除项目
即使项目中有用户与之关联,也可以删除项目,因此在删除项目之前,务必先删除用户和其他项目资源,否则可能会留下孤立的资源。在本示例中,我们将展示如何删除名为 oldbook 的项目。
准备就绪
确保你已登录到正确配置的 OpenStack 客户端,并且能够以具有管理员权限的用户身份访问 OpenStack 环境。
参阅第二章,OpenStack 客户端,了解如何设置环境以使用 OpenStack 命令行客户端。
如何操作…
要删除项目,请执行以下命令:
-
从当前项目列表中获取项目名称:
openstack project list![如何操作…]()
-
删除项目:
openstack project delete oldbook此命令将没有输出。
它是如何工作的…
使用 OpenStack 命令行工具删除不必要的项目非常简单。确保只删除空项目。首先使用命令获取现有的项目:
openstack project list
执行以下命令删除项目:
openstack project delete <project>
这里的 <project> 参数可以是项目 ID 或项目名称。
如果项目已分配用户,则这些用户不会被删除,但该项目将被删除。
删除用户
从 OpenStack 身份服务中删除用户是一个简单的单步过程。在本例中,我们将展示如何删除一个名为 oldreader 的用户。
准备工作
确保您已经登录到正确配置的 OpenStack 客户端,并且可以作为具有管理员权限的用户访问 OpenStack 环境。
详细信息请参见第二章,OpenStack 客户端,了解如何设置环境以使用 OpenStack 命令行客户端。
如何操作…
要删除用户,请执行以下命令:
-
从当前域中的用户中获取用户的名字:
openstack user list![如何操作…]()
-
删除
oldreader用户:openstack user delete oldreader此命令将没有输出。
它是如何工作的…
使用 OpenStack 命令行工具删除不必要的用户非常简单。首先使用命令获取现有的用户:
openstack user list
执行以下命令删除用户:
openstack user delete <user>
这里的 <user> 参数可以是用户 ID 或用户名。
删除角色
从 OpenStack 身份服务中删除角色是一个简单的单步过程。在本例中,我们将展示如何删除一个名为 oldrole 的角色。
准备工作
确保您已经登录到正确配置的 OpenStack 客户端,并且可以作为具有管理员权限的用户访问 OpenStack 环境。
详细信息请参见第二章,OpenStack 客户端,了解如何设置环境以使用 OpenStack 命令行客户端。
如何操作…
要删除角色,请执行以下命令:
-
从当前角色列表中获取角色的名字:
openstack role list![如何操作…]()
-
删除
oldrole角色:openstack role delete oldrole此命令将没有输出。
它是如何工作的…
使用 OpenStack 命令行工具删除不必要的角色非常简单。首先使用命令获取现有角色:
openstack role list
执行以下命令删除角色:
openstack role delete <role>
这里的 <role> 参数可以是角色 ID 或角色名称。
删除组
从 OpenStack 身份服务中删除用户组是一个简单的单步过程。在本例中,我们将展示如何删除一个名为 oldgroup 的组。请注意,当您删除一个组时,并不会删除分配给该组的用户。角色和组权限映射将消失,结果是,用户可能会丧失权限。
准备工作
确保您已经登录到正确配置的 OpenStack 客户端,并且可以作为具有管理员权限的用户访问 OpenStack 环境。
参见 第二章,OpenStack 客户端,了解如何配置环境以使用 OpenStack 命令行客户端。
如何操作…
要删除一个用户组,请执行以下命令:
-
从当前的组列表中获取组名称:
openstack group list![如何操作…]()
-
删除
oldgroup组:openstack group delete oldgroup此命令将没有输出。
它是如何工作的…
使用 OpenStack 命令行工具删除不必要的组非常简单。首先使用命令获取现有组:
openstack group list
执行以下命令删除组:
openstack group delete <group>
在此,<group> 参数可以是组 ID 或组名称。
删除域
如果域没有任何关联的用户,Keystone 域可以被删除。如果尝试删除时域中有用户,系统将显示错误。在此示例中,我们将展示如何删除一个不再使用的域,名为 olddomain。
准备工作
确保你已登录到正确配置的 OpenStack 客户端,并且可以作为具有管理员权限的用户访问 OpenStack 环境。
参见 第二章,OpenStack 客户端,了解如何配置环境以使用 OpenStack 命令行客户端。
如何操作…
要删除一个域,请执行以下命令:
-
从当前域列表中获取域的名称:
![如何操作…]()
-
验证我们将要删除的
olddomain域没有任何关联的用户:openstack user list --domain olddomain在继续之前,该列表应为空。如果不为空,请删除所有用户后再进行下一步。
-
禁用该域:
openstack domain set --disable olddomain此命令将没有输出。
-
删除域:
openstack domain delete olddomain如果成功,该命令将没有输出。
它是如何工作的…
删除不必要的域需要确保域没有任何关联的用户。
验证该域没有任何关联的用户:
openstack user list --domain <domain>
删除域之前需要先禁用该域。即使域中有用户,也可以禁用该域:
openstack domain set --disable <domain>
只有在禁用域并且该域没有任何关联的用户之后,才可以删除该域:
openstack domain delete <domain>
如果你需要删除用户,请参考本章前面提到的 删除用户 章节。
OpenStack 端点信息
如果你需要查看不同 OpenStack 服务的端点信息,或者查看 OpenStack 安装上运行的服务,可以使用 OpenStack 服务目录。如果你需要自动化任何 OpenStack 任务,或者将其他工具与 OpenStack 集成,服务目录也会很有用。该目录列出了每个服务的服务和端点信息。每个部署的目录可能不同。
准备工作
确保你已登录到正确配置的 OpenStack 客户端,并且可以作为具有管理员权限的用户访问 OpenStack 环境。
请参考第二章,OpenStack 客户端,了解如何设置环境以使用 OpenStack 命令行客户端。
如何操作…
要列出 OpenStack 目录信息,请执行以下命令:
openstack catalog list
如何工作…
在 OpenStack 中,可以使用 OpenStack 目录查找不同的服务 API 端点。该目录将列出它所知道的所有 OpenStack 服务及其各自的内部、管理员和公共 URL。如果你尝试自动化任何 OpenStack 任务,目录也非常方便。在命令行界面(CLI)中,通过运行以下命令列出可用的端点:
openstack catalog list

我们的 catalog 命令的输出已为本示例进行了截断。完整的目录命令将列出所有已安装的服务。
注意
每个 OpenStack 安装的服务目录将有所不同。
第四章:Neutron – OpenStack 网络
在本章中,我们将涵盖以下主题:
-
OpenStack 网络介绍
-
管理网络、子网和端口
-
创建提供商网络
-
创建租户网络
-
创建端口
-
更新网络属性
-
删除端口
-
删除网络
-
管理路由器和浮动 IP
-
将网络附加到路由器
-
创建和分配浮动 IP
-
删除路由器
-
管理安全组
-
管理负载均衡器
OpenStack 网络介绍
OpenStack 中的网络由一个名为 Neutron 的项目提供。Neutron 是一个由 API 驱动的系统,用于管理 OpenStack 云中的物理和虚拟网络资源。操作员和用户可以利用 Neutron API 来构建适合其应用需求的丰富网络架构。
Neutron 利用一个可插拔和可扩展的架构,允许开发人员编写强大的驱动程序,以实现和配置虚拟和物理网络资源,包括交换机、路由器、防火墙和负载均衡器。Neutron 由一个 API 服务器和各种代理组成,这些代理负责实现用户架构的虚拟网络。以下图示展示了 Neutron API 服务器如何与各种插件和代理交互,构建云中的网络:

图 4.1
图示展示了 Neutron API 服务、Neutron 插件和驱动程序,以及如 L2 和 L3 代理等服务之间的交互。在通过 API 或代理执行网络操作时,Neutron 会发布消息到队列,代理会消费并实现这些消息。
本章将涵盖许多常见的网络相关任务,但不会深入探讨任何特定主题的细节。有关 Neutron 网络基础的介绍,请参阅 OpenStack Networking Essentials,Packt Publishing,2016 年。要深入了解 Neutron 特性,包括交换和路由的核心功能、负载均衡、VPN 等,请参阅 Learning OpenStack Networking, Second Edition,Packt Publishing,2015 年。
管理网络、子网和端口
网络、子网和端口构成了 Neutron 逻辑网络架构的基础。一个网络描述了一个二层段,通常用于定义一个边界,如 VLAN。子网是与网络相关联的 IPv4 或 IPv6 地址块。一个网络可以与一个或多个子网关联。最后,端口表示跨越整个云的逻辑交换机上的交换机端口。一个端口对象包含与其关联的设备的信息,包括其 MAC 地址、IP 地址和设备 ID。设备可以是虚拟机实例接口、虚拟路由器接口或将连接到虚拟网络的其他设备。
OpenStack 中的网络对象有许多属性,用于描述该网络如何连接物理和虚拟基础设施。以下表格描述了其中的一些细节:
属性 |
描述 |
|---|---|
provider:physical_network |
这描述了用于此网络的物理接口。这里的标签是像 eth0 和 bond1 这样的接口的别名。这个别名被称为提供者标签,并在相应的插件和代理配置文件中进行配置。主要由 flat 和 vlan 类型的网络使用。 |
provider:segmentation_id |
这描述了段 ID,如 VLAN ID 或 VXLAN VNI。并非所有网络类型都使用此项。 |
provider:network_type |
这描述了网络类型,如 Flat、VLAN、VXLAN 和 GRE。 |
router:external |
布尔值(真或假),用于确定网络是否有资格作为浮动 IP 池使用。 |
创建网络的用户角色决定了该用户在创建网络时可以指定哪些属性。管理员用户可以在创建网络时指定诸如物理网络或分段 ID 等详细信息。普通用户必须依赖 Neutron 自动配置网络,基于 Neutron 配置文件中设置的细节,包括为每个物理网络选择分段 ID 的池。专门用于将虚拟设备连接到物理网络基础设施的网络通常被称为提供者网络,因为它们的属性是根据其所在环境或数据中心故意设置的。提供者网络通常跨项目或租户共享,并且通常为上游设备提供连接,以便在环境中进行路由。普通用户创建的网络被称为租户网络,通常仅由创建它们的项目或租户使用。在大多数情况下,租户网络必须连接到虚拟路由器,而虚拟路由器又连接到提供者网络,并可以提供租户网络的进出连接。在接下来的章节中,我们将讨论涉及这些资源的常见任务。
创建提供者网络
在 OpenStack 中创建提供者网络时,必须提供描述网络如何连接到物理基础设施的属性。这些属性包括网络类型、服务器使用的网络接口和网络的分段 ID。通常,只有具有管理员级别权限的用户才能创建和管理提供者网络。提供者网络可以是共享的,也可以是私有的,当网络的 router:external 属性被设置为 True 时,它们还可以作为浮动 IP 网络连接到 Neutron 路由器。
准备就绪
创建提供者网络时,您必须以管理员身份进行身份验证。至少需要以下信息来配置该网络:
-
网络名称
-
提供者标签
-
网络类型
-
分段 ID
对于我们的示例,将使用以下内容:
-
网络名称:
COOKBOOK_PROVIDER_NET -
提供者标签:
vlan -
网络类型:
vlan -
分段 ID:
200
至少需要以下信息来配置相应的子网:
-
子网名称
-
网络名称或 ID
-
子网范围(CIDR)
对于我们的示例,将使用以下内容:
-
子网名称:
COOKBOOK_PROVIDER_SUBNET -
网络名称或 ID:
COOKBOOK_PROVIDER_NET -
子网范围(CIDR):
192.168.200.0/24
如何操作…
在我们的系统上安装了 OpenStack 客户端后,我们可以通过以下步骤创建提供者网络:
-
创建网络:
openstack network create COOKBOOK_PROVIDER_NET \ --provider-network-type vlan \ --provider-physical-network vlan \ --provider-segment 200输出将类似于以下内容:
![如何操作…]()
-
创建子网:
openstack subnet create COOKBOOK_PROVIDER_SUBNET \ --network COOKBOOK_PROVIDER_NET \ --subnet-range 192.168.200.0/24输出将类似于以下内容:
![如何操作…]()
它是如何工作的...
提供者网络使用以下语法创建:
openstack network create NETWORK_NAME \
--provider-network-type NETWORK_TYPE \
--provider-physical-network PROVIDER_LABEL \
--provider-segment SEGMENTATION_ID \
[--external | --internal]
创建网络会创建一个逻辑的二层段,其细节用于在云中构建虚拟网络连接,这些连接将虚拟机和其他虚拟网络对象与物理基础设施连接起来。
provider-network-type 参数定义了网络的类型。选项包括 vlan、vxlan、gre、flat、geneve 和 local,这些选项必须得到配置的网络驱动程序的支持。
provider-physical-network 参数定义了用于网络的接口。在 Neutron 中,接口不是直接引用的,而是映射到 提供者标签。在 OpenStack-Ansible 部署中,默认的提供者标签是 vlan,并映射到如 bond1 或 eth1 的物理接口。
provider-segment 参数定义了网络使用的二层分段 ID。对于 vlan 网络类型,分段 ID 是 VLAN ID。对于 vxlan 网络类型,分段 ID 是 VXLAN VNI。并非所有网络类型都使用分段 ID,如果没有指定,Neutron 可能会在需要时自动分配。
当指定时,--external 选项将网络标记为路由器的网关网络。该网络将作为附加实例的浮动 IP 网络。网络默认被认为是 内部 网络。
还有其他可选的网络参数,可以通过以下 --help 标志来发现:
openstack network create --help
提示
--help 标志可以附加到 OpenStack 命令行工具的大多数命令中,在本章节中构建命令时将非常有用。
子网使用以下语法创建:
openstack subnet create SUBNET_NAME \
--network NETWORK_NAME \
--subnet-range SUBNET_RANGE
创建子网会创建一个逻辑层 3 路由域,其详细信息用于向虚拟机和其他虚拟网络对象提供 IP 服务。network 参数将子网映射到 OpenStack 中定义的层 2 网络。subnet-range 参数定义了子网使用的 L3 地址范围,并以 CIDR 表示法编写。一个网络可以关联多个子网,这通常发生在特定子网中的所有地址都已被使用时。尽管在逻辑上是分离的,网络中的多个子网仍然是同一个层 2 广播域的一部分。
当在 OpenStack 中创建网络和子网并启用 DHCP 时,会在运行 DHCP 代理的一个或多个节点上创建一个相应的网络命名空间。可以使用以下 ip netns 命令识别该命名空间:
# ip netns list
...
qdhcp-c881ce20-1649-4f03-bea7-40da536e21b2
...
DHCP 命名空间的前缀为 qdhcp-,后缀对应于网络 ID。
注意
ip netns 命令必须由 root 用户或具有 sudo 权限的用户运行。
创建租户网络
当在 OpenStack 中创建租户网络时,描述网络如何连接到物理基础设施的提供者属性会根据配置文件中硬编码的设置由 Neutron 自动确定。通常,租户网络由特定项目中的用户创建和管理,并且不会与其他项目共享。
准备就绪
至少需要以下网络信息:
- 网络名称
在我们的示例中,将使用以下网络名称:
- 网络名称:
COOKBOOK_TENANT_NET_1
至少需要以下信息来创建对应的子网:
-
子网名称
-
网络名称或 ID
-
子网范围(CIDR)
在我们的示例中,将使用以下内容:
-
子网名称:
COOKBOOK_TENANT_SUBNET_1 -
网络名称或 ID:
COOKBOOK_TENANT_NET_1 -
子网范围(CIDR):
172.16.200.0/24
如何操作…
在我们的系统上安装了 openstack 客户端后,我们可以通过以下步骤创建租户网络:
-
创建网络:
openstack network create COOKBOOK_TENANT_NET_1输出将类似于以下内容:
![如何操作…]()
注意
作为非管理员用户,某些网络属性可能不可见。
-
创建子网:
openstack subnet create COOKBOOK_TENANT_SUBNET_1 \ --network COOKBOOK_TENANT_NET_1 \ --subnet-range 172.16.200.0/24输出将类似于以下内容:
![如何操作…]()
它是如何工作的...
租户网络的创建遵循以下语法:
openstack network create NETWORK_NAME
当作为非管理员用户创建时,网络的提供者属性会根据相应网络插件配置文件中定义的设置由 Neutron 自动确定。租户网络与创建它们的项目关联,默认情况下,其他项目无法看到或使用这些网络。
提示
Neutron 基于角色的访问控制 (RBAC) 可用于在需要时与其他项目共享网络。有关在 OpenStack Pike 版本中使用 RBAC 的更多信息,请访问以下网站:
docs.openstack.org/neutron/pike/admin/config-rbac.html
创建端口
在 OpenStack 中可以使用 openstack port create 命令创建端口。OpenStack 在创建服务器时会自动创建端口,也可以在稍后创建并附加到实例上。用户还可以创建端口,以便预留 IP 地址供以后使用,或者避免 OpenStack 分配某些地址。
准备中
至少需要以下详细信息来创建端口:
-
网络名称或 ID
-
端口名称
对于我们的示例,将使用以下内容:
-
网络名称:
COOKBOOK_TENANT_NET_1 -
端口名称:
COOKBOOK_TEST_PORT_1
如何操作...
安装了 OpenStack 客户端后,我们现在可以使用以下命令创建端口:
openstack port create COOKBOOK_TEST_PORT_1 \
--network COOKBOOK_TENANT_NET_1
输出将类似于以下内容:

它是如何工作的...
当在 OpenStack 中创建端口并与实例或其他虚拟网络设备关联时,它会绑定到托管实例或设备的相应节点上的 Neutron 代理。使用端口提供的详细信息,OpenStack 服务可以在主机上构建 虚拟机接口 (vif) 或 虚拟以太网接口 (veth),供虚拟机、网络命名空间或其他应用使用。
更新网络属性
网络属性可以通过 openstack network set 和 openstack network unset 命令进行更新。
准备中
更新网络时,确保你已认证为管理员或是网络的所有者。你将需要以下详细信息:
-
网络名称或 ID
-
更新的属性
对于我们的示例,将使用以下内容:
-
网络名称:
COOKBOOK_PROVIDER_NET -
更新的属性:
router:external
如何操作...
安装了 OpenStack 客户端后,我们现在可以使用以下命令来更新网络:
openstack network set COOKBOOK_PROVIDER_NET --external
不会返回任何输出。
它是如何工作的...
网络更新的语法如下:
openstack network set NETWORK \
[--share | --no-share] \
[--description <description>] \
[--external | --internal]
openstack network unset [--tag <tag> | --all-tag] NETWORK
share 和 no-share 参数决定网络是否可以在项目之间共享,或者仅限于网络的所有者使用。
description 参数允许用户提供网络的有用描述。
当指定时,--external 选项将网络标识为路由器的网关网络。该网络将作为附加实例的浮动 IP 网络。默认情况下,网络被视为内部网络。
注意
并非所有网络插件都支持更新现有网络的某些网络属性。如果需要更改,可能需要删除并重新创建网络。
删除端口
在 OpenStack 中可以使用 openstack port delete 命令删除端口。OpenStack 会自动删除它创建的端口,例如,当创建服务器或浮动 IP 时,但可能不会删除用户创建并与实例关联的端口。
注意
删除与活动实例关联的端口可能导致实例崩溃或造成实例中的意外行为。
准备工作
删除端口时,确保你已经通过管理员身份验证或是端口的所有者。你需要以下信息:
- 端口名称或 ID
对于我们的示例,将使用以下内容:
- 端口名称:COOKBOOK_TEST_PORT_1
如何操作…
安装了 OpenStack 客户端后,我们现在可以使用以下命令删除端口:
openstack port delete COOKBOOK_TEST_PORT_1
不会返回任何输出。
删除网络
在 OpenStack 中删除网络与调用 openstack network delete 命令一样简单。Neutron 会删除与该网络相关的所有自动创建的端口,如由 DHCP 或路由器命名空间创建的端口,并将任何自动分配的分段 ID 归还到相应的池中,以供分配给其他网络。
准备工作
在 OpenStack 中删除网络时,确保所有相关的用户创建端口已被删除。这可能需要删除实例、从实例中分离并删除端口,或从路由器中分离并删除端口。删除网络时,以下信息是必需的:
- 网络名称或 ID
如何操作…
安装了 OpenStack 客户端后,我们现在可以使用以下命令删除网络:
openstack network delete COOKBOOK_TENANT_NETWORK_3
不会返回任何输出。
工作原理…
当调用 openstack network delete 命令时,它会指示 Neutron 删除指定的网络以及所有相关的子网(子网),前提是所有用户管理的端口都已被删除。在参考架构中,第二层代理负责删除在主机上配置的相应虚拟桥接和接口,所有网络记录都会从 OpenStack 数据库中清除。
注意
一旦这些对象被删除,Neutron 不再在数据库中维护网络信息。虽然 OpenStack API 的请求可能会被记录,但如果需要审计跟踪,强烈建议使用第三方工具或代理。
管理路由器和浮动 IP
在 OpenStack 中,路由器代表一个虚拟路由设备,为直接连接的网络提供路由功能。为了为虚拟机提供端到端的连接,路由器必须连接到外部提供者网络以及实例所在的租户网络。通常,路由器由单独的项目创建和管理。默认情况下,外部提供者网络是共享的,所有项目都可以使用。以下图示表示一个由 ADMIN 项目拥有并被其他三个项目使用的外部提供者网络:

图 4.2
在图 4.2中,三个项目的路由器连接到外部提供商网络。外部提供商网络不仅提供路由器及其后方网络的连接,还提供一个可以派发浮动 IP 的网络。浮动 IP 提供 1 对 1 的地址转换,允许外部客户端直接连接到实例。
创建路由器
在 OpenStack 中,路由器可以使用openstack router create命令创建。默认情况下,路由器被认为是内部的,只能在直接连接的租户网络之间进行路由。另一方面,外部路由器能够路由到外部网关,并能为连接的网络提供网络地址转换(NAT)服务。
在 OpenStack 参考架构中,可以创建三种类型的路由器:
-
独立路由器
-
高可用(HA)
-
分布式(DVR)
独立路由器不提供任何级别的容错性,而高可用路由器通过实现 VRRP 来提供冗余,以应对一个或多个 Neutron 节点故障。分布式虚拟路由器驻留在计算节点上,而不是集中式网络节点上,提供比其同类更高的性能,特别是在东西向流量或不同网络中实例间的流量时,因为这类流量是通过计算节点转发的,无需经过网络节点。
对于非管理员用户,通过openstack router create命令创建的路由器类型由 Neutron 配置文件中定义的设置自动决定。只有拥有管理员权限的用户才能在创建路由器时指定路由器类型。
准备中
至少需要以下详细信息,用于路由器:
- 路由器名称
对于我们的示例,将使用以下内容:
-
路由器名称:
COOKBOOK_ROUTER_STANDALONE -
路由器名称:
COOKBOOK_ROUTER_HA -
路由器名称:
COOKBOOK_ROUTER_DVR
至少需要以下详细信息,用于连接到路由器的网络:
-
外部提供商网络名称或 ID
-
租户子网名称或 ID
对于我们的示例,将使用以下内容:
-
外部提供商网络名称:
COOKBOOK_PROVIDER_NET -
租户子网名称:
COOKBOOK_TENANT_SUBNET
如何操作...
在系统上安装了openstack客户端后,我们现在可以按照以下步骤创建一个路由器:
-
创建独立路由器:
openstack router create COOKBOOK_ROUTER_STANDALONE输出将类似于以下内容:
![如何操作…]()
-
创建一个 HA 路由器:
openstack router create COOKBOOK_ROUTER_HA --ha输出将类似于以下内容:
![如何操作…]()
-
创建分布式路由器:
openstack router create COOKBOOK_ROUTER_DVR --distributed输出将类似于以下内容:
![如何操作…]()
它是如何工作的...
当在 OpenStack 中使用原生路由服务创建任何路由器时,会在运行neutron-l3-agent服务的一个或多个节点上创建一个相应的网络命名空间。可以使用以下ip netns命令来识别该命名空间:
# ip netns list
...
qrouter-058ea6a3-ca86-46f8-80c8-d63bbc195212
...
路由器的命名空间以qrouter-为前缀,并且后缀与路由器 ID 相对应。在配置了分布式虚拟路由器的环境中,可能还会有其他命名空间用于促进正确的网络配置,例如fip-和snat-命名空间。
默认情况下,非管理员用户无法指定正在创建的路由器类型。路由器类型由 Neutron 根据第 3 层代理配置文件自动确定。作者建议尽可能使用 HA 或分布式虚拟路由器,以限制虚拟路由器所在物理节点故障的影响。
注意
云操作员可以修改 Neutron 配置文件来更改默认行为。Neutron API 服务使用的policy.json文件可以被修改,以允许用户和角色执行通常仅限管理员的操作。有关修改policy.json文件的指南和注意事项,请参考社区文档。
将网络连接到路由器
在 OpenStack 中,路由器可以连接到单一的外部提供者网络和一个或多个租户网络,如下图所示:

图 4.3
在图 4.3中,外部提供者网络提供外部连接,而租户网络则为项目内的虚拟机和其他虚拟网络设备提供连接。路由器的任务是通过路由和有时通过浮动 IP 的 NAT 来促进端到端连接。
将网络连接到路由器所需的命令可能会根据网络和需求的不同而有所变化:
-
将路由器连接到外部网络:
openstack router set --external-gateway <network> <router> -
使用子网 ID 或名称将路由器连接到租户网络:
openstack router add subnet <router> <subnet> -
使用特定端口 ID 或名称将路由器连接到租户网络:
openstack router add port <router> <port>
准备工作
在将路由器连接到网络时,以下信息是必需的:
-
路由器名称或 ID
-
网络名称或 ID,或子网名称或 ID,或端口名称或 ID
请记住,当将路由器连接到外部提供者网络时,网络的router:external属性必须设置为External或True。
如何操作……
在 OpenStack 中将网络连接到路由器,请按以下步骤操作:
-
将路由器连接到外部提供者网络
COOKBOOK_PROVIDER_NET:openstack router set --external-gateway COOKBOOK_PROVIDER_NET COOKBOOK_ROUTER_STANDALONE没有输出提供。
-
使用子网名称将路由器连接到
COOKBOOK_TENANT_SUBNET子网:openstack router add subnet COOKBOOK_ROUTER_STANDALONE COOKBOOK_TENANT_SUBNET_1没有输出提供。
它是如何工作的……
当路由器连接到外部提供者网络时,路由器将从网络中可分配的 IP 地址池中分配一个 IP 地址。路由器还会配置一个默认网关,该网关对应于各自提供者子网的指定网关。
当路由器连接到租户网络时,路由器就成为该网络及其所有实例的网关。它会被分配一个指定为各自租户子网网关的 IP 地址。
可以使用以下命令列出连接到路由器的端口:
openstack port list --router ROUTER_NAME_OR_ID
在本例中,以下端口和相应子网已附加到路由器:

使用 ip netns exec 命令,并结合相应路由器命名空间的名称,我们可以看到路由器有两个附加的接口,分别是 qg-ed006ed1-b8 和 qr-c69005cb-aa:

注意
路由器命名空间中的接口名称与相应端口 ID 的前 10 个字符相对应。外部或网关端接口以 qg- 为前缀,而内部或路由器端接口以 qr- 为前缀。这种命名方案可以追溯到 Neutron 项目被称为 Quantum 时。
创建并分配浮动 IP
OpenStack 中的浮动 IP 是静态 IPv4 地址,它们与 Neutron 路由器后面的实例进行映射,为这些实例提供直接的入站连接。浮动 IP 的使用方式与 Amazon Web Services 中的弹性 IP 类似,用户可以在实例故障时快速重新映射 IP 地址。这个功能的核心是网络地址转换(NAT)。浮动 IP 通常被视为外部地址,映射到实例上配置的内部地址。NAT 在连接到实例网络的 Neutron 路由器上实现。浮动 IP 提供了对那些通常会被隔离在 Neutron 路由器后非路由网络上的实例的连接。
准备工作
回想一下,实例通过端口连接到反映连接网络和关联 IP 地址的端口。当创建浮动 IP 时,需要以下信息:
- 外部网络名称或 ID
分配浮动 IP 到端口时,需进行以下操作:
-
浮动 IP ID
-
内部端口名称或 ID
在本例中,创建一个新的端口,命名为 COOKBOOK_TEST_PORT_2,并放置在现有的租户网络中:
openstack port create COOKBOOK_TEST_PORT_2 \
--network COOKBOOK_TENANT_NET_1
如何操作…
要在 OpenStack 中创建浮动 IP,请执行以下命令:
openstack floating ip create --port COOKBOOK_TEST_PORT_2 COOKBOOK_PROVIDER_NET
输出将类似于以下内容:

如何操作…
浮动 IP 的创建语法如下:
openstack floating ip create EXTERNAL_NETWORK_NAME_OR_ID \
[--port PORT_NAME_OR_ID]
浮动 IP 可以通过以下语法与端口关联:
openstack floating ip associate FLOATING_IP_NAME_OR_ID \
PORT_NAME_OR_ID
当浮动 IP 与端口关联时,Neutron 使用端口信息来确定要在哪个路由器上配置 NAT。一旦 NAT 配置完成,连接到浮动 IP 的请求将被转换为内部 IP 并转发到相应实例。实例的响应将被转发到路由器,从内部 IP 转换为浮动 IP,然后路由回原始地址。
在我们的例子中,实例的端口与 COOKBOOK_TENANT_NET 网络关联,而该网络又与 COOKBOOK_ROUTER_STANDALONE 路由器连接。在各自的 qrouter 网络命名空间中,我们可以看到通过 iptables 应用的源 NAT 和目标 NAT:

删除路由器
在 OpenStack 中,可以使用 openstack router delete 命令删除路由器。在删除路由器之前,必须先断开所有连接到该路由器的子网/端口。这会导致任何连接到路由器后面的网络的实例的流量中断。可以使用 openstack router remove subnet 或 openstack router remove port 命令来断开子网。
准备工作
删除路由器时,将需要以下信息:
- 路由器名称或 ID
如何操作……
要在 OpenStack 中删除路由器,请执行以下命令:
openstack router delete COOKBOOK_ROUTER_DVR
没有输出。然而,可以使用 openstack router list 命令来验证操作:

被删除的路由器将不再出现在列表中。
它是如何工作的……
当调用 openstack router delete 命令时,将指示 Neutron 删除指定的路由器及其关联的资源。在参考架构中,第三层代理负责删除主机上配置的相应网络命名空间和虚拟接口,且所有与路由器相关的记录都会从 OpenStack 数据库中清除。
管理安全组
在 OpenStack 中,安全组描述了具有相似安全要求的端口的组合。安全组规则与安全组关联,并为该组提供入站和出站过滤能力。安全组规则可以使用 CIDR 表示法引用其他组或远程网络。实际的过滤操作发生在计算节点的“端口”级别,并且可以通过 iptables 或作为 OpenFlow 规则来实现,具体取决于在特定节点上配置的防火墙驱动程序。每个新创建的项目都包含一个名为 default 的安全组,只允许出站通信。入站通信被拒绝。
创建安全组
可以使用 openstack security group create 命令在 OpenStack 中创建安全组。安全组是项目拥有的对象,不能被其他项目共享或引用。
准备工作
创建安全组时,与该组关联的每个端口将继承应用于该组的规则。至少需要以下详细信息来创建该组:
- 安全组名称
对于我们的示例,将使用以下内容:
- 安全组名称:
COOKBOOK_SG_WEB
如何操作……
在我们的系统上安装了 OpenStack 客户端后,我们现在可以使用以下命令创建安全组:
openstack security group create COOKBOOK_SG_WEB
输出将类似于以下内容:

它是如何工作的……
安全组使用以下语法创建:
openstack security group create SECURITY_GROUP_NAME
当创建安全组时,OpenStack 会将一组默认规则应用于该组,这些规则允许端口通过 IPv4 和 IPv6 进行出站通信(egress)。默认情况下,所有入站流量会被拒绝。
创建安全组只是为实例提供过滤的第一步。接下来的步骤,即创建安全组规则并将安全组应用于端口,将在后续章节中讨论。
创建安全组规则
可以使用 openstack security group rule create 命令在 OpenStack 中创建安全组规则。安全组规则提供了在第 3 层和第 4 层的过滤信息,包括 IP 地址和目标端口。
准备工作
在创建安全组规则时,请记住,每个与该组关联的端口将继承应用于该组的规则。因此,重要的是仅限于所需的规则,以便为关联组提供所需的访问权限。至少,您需要以下详细信息来定义规则:
- 安全组名称
对于我们的示例,将使用以下内容:
-
安全组名称:
COOKBOOK_SG_WEB -
目标端口:
80 -
协议:TCP
-
方向:入口
-
来源:所有地址
如何操作……
在我们的系统上安装了 OpenStack 客户端后,现在可以通过以下命令创建安全组规则:
openstack security group rule create COOKBOOK_SG_WEB \
--dst-port 80 \
--protocol tcp \
--ingress \
--remote-ip 0.0.0.0/0
输出将类似于以下内容:

它是如何工作的……
安全组是通过以下语法创建的:
openstack security group rule create SECURITY_GROUP_NAME \
[--remote-ip <ip-address> | --remote-group <group>] \
[--dst-port <port-range>] \
[--icmp-type <icmp-type>] \
[--icmp-code <icmp-code>] \
[--protocol <protocol>] \
[--ingress | --egress] \
[--ethertype <ethertype>]
安全组规则为 OpenStack 提供了 Neutron 代理用来在计算节点上单独端口上实现流量过滤的详细信息。在我们的环境中,这些规则作为 iptables 规则实现。
如果在创建安全组规则时未提供任何额外的过滤信息,可能会导致一个规则允许来自所有源地址的入口访问。当没有指定详细信息时,OpenStack 会假设某些默认值,因此验证提供的输出非常重要,以确保已实施适当的过滤。
将安全组应用于实例
安全组通常在启动时通过 openstack server create 命令应用于实例,但也可以通过 openstack network port create 或 set 命令应用于单个端口。在启动时应用时,每个列出的安全组都会应用于与实例关联的每个端口。因此,可能会在每个接口上应用不必要的规则,这可能导致安全风险或底层 Neutron 代理性能下降,该代理负责应用规则。当应用于单个端口时,用户可以确保如果实例是多宿主的,相应端口仅具有提供对该接口访问所需的规则。
注意
多宿主(multihomed)是指通过不同接口连接到多个网络的实例。
准备工作
在启动时将安全组应用于实例时,您需要以下信息:
- 安全组名称或 ID
在将安全组应用于单个端口时,您需要以下信息:
-
端口名称或 ID
-
安全组名称或 ID
对于我们的示例,将使用以下内容:
-
端口名称:
COOKBOOK_TEST_PORT_1 -
安全组名称:
COOKBOOK_SG_WEB -
实例名称:
COOKBOOK_INSTANCE_WEB -
实例规格:
COOKBOOK_FLAVOR_TINY -
实例镜像:
COOKBOOK_IMAGE_CIRROS -
网络名称:
COOKBOOK_TENANT_NET_1
操作步骤…
在我们的系统上安装了 openstack 客户端后,我们可以按照以下步骤应用安全组:
-
创建实例并在启动时提供安全组:
openstack server create COOKBOOK_INSTANCE_WEB \ --flavor COOKBOOK_FLAVOR_TINY \ --image COOKBOOK_IMAGE_CIRROS \ --nic net-id=COOKBOOK_TENANT_NET_1 \ --security-group COOKBOOK_SG_WEB注意
使用适合你环境的规格和镜像,或使用在第五章,Nova – OpenStack 计算和第六章,Glance – OpenStack 镜像服务中创建的规格和镜像。
另外,安全组可以在端口创建时或应用于现有端口时进行配置。通过在系统上安装 OpenStack 客户端,我们可以按照以下步骤应用安全组。
-
将安全组应用到新端口:
openstack port create COOKBOOK_TEST_PORT_3 \ --network COOKBOOK_TENANT_NET_1 \ --security-group COOKBOOK_SG_WEB输出结果如下所示:
![操作步骤…]()
-
将安全组应用于现有端口:
openstack port set COOKBOOK_TEST_PORT_2 \ --security-group COOKBOOK_SG_WEB不会返回输出。不过,可以通过使用
openstack port show命令查询应用到端口的安全组来确认该更改:openstack port show COOKBOOK_TEST_PORT_2 -c security_group_ids输出结果如下所示:
![操作步骤…]()
工作原理…
安全组可以在启动时应用于实例,在创建端口时应用,或应用于现有端口。计算节点上的 Neutron 插件代理负责在主机上为端口应用相应的过滤规则。在所有场景中,可以将多个安全组应用于同一个端口。
安全组可以通过以下语法在启动时应用:
openstack server create INSTANCE_NAME \
...
--security-group SECURITY_GROUP_NAME
安全组也可以通过以下语法应用于新端口:
openstack port create PORT_NAME \
--network NETWORK_NAME \
--security-group SECURITY_GROUP_NAME
最后,安全组可以通过以下语法应用于现有端口:
openstack port set PORT_NAME \
--security-group SECURITY_GROUP_NAME
端口绑定到位于环境中主机上的 Neutron 插件代理。例如,属于实例的端口会绑定到该实例所在的计算节点上的代理。该代理负责为端口设置虚拟网络。当安全组应用于端口时,端口绑定的 Neutron 代理在主机上实施过滤规则。环境中的其他代理会收到安全组已更改的通知,并相应地更新。
管理负载均衡器
Neutron 包含一个名为 负载均衡即服务(LBaaS)的服务,允许用户创建将流量负载均衡到云中多个实例上部署的应用程序的负载均衡器。在参考架构中,Neutron 依赖一个开源负载均衡软件包 HAProxy 来提供负载均衡功能。就像 Neutron L3 代理处理虚拟路由器、DHCP 代理处理虚拟 DHCP 服务器一样,Neutron LBaaS 代理负责在请求时构建和配置虚拟负载均衡器。
注意
LBaaS 不应与另一个名为 Octavia 的负载均衡项目混淆。两者都提供类似的负载均衡功能,但这里只涵盖 LBaaS。
在 OpenStack 中,负载均衡器包含三个主要组件:
-
池成员
-
池
-
监听器
池成员 描述一个第 4 层对象,由实例上服务的 IP 地址和端口组成。例如,池成员可能是一个 Web 服务器,地址配置为 10.30.0.2,并在 TCP 端口 80 上监听。
池 是一组提供相同内容的池成员。
监听器 是一个对象,表示负载均衡器本身正在监听的 虚拟 IP(VIP)和端口。流量将根据虚拟 IP 在关联池的成员之间进行负载均衡。
其他组件,如健康检查器和 L7 策略,有助于扩展负载均衡器的实用性和功能,但不是必需的。
创建功能性负载均衡器的工作流程如下:
-
创建负载均衡器对象
-
创建并关联监听器
-
创建并关联池
-
创建并关联池成员
-
创建并关联健康检查器(可选)
创建负载均衡器
从 OpenStack 的 Pike 版本开始,负载均衡器相关的命令不再在 OpenStack 客户端中提供。相反,应使用 neutron 客户端。可以通过 neutron lbaas-loadbalancer-create 命令在 OpenStack 中创建负载均衡器。
准备就绪
至少需要以下详细信息来创建负载均衡器:
- VIP 子网
还推荐为其命名。对于我们的示例,以下内容将被使用:
-
名称:
COOKBOOK_LOADBALANCER_1 -
VIP 子网:
COOKBOOK_TENANT_SUBNET_1
如何操作…
在我们的系统上安装了 Neutron 客户端后,现在可以使用以下命令创建负载均衡器对象:
neutron lbaas-loadbalancer-create COOKBOOK_TENANT_SUBNET_1 \
--name COOKBOOK_LOADBALANCER_1
输出将类似于以下内容:

它是如何工作的…
负载均衡器通过以下语法创建:
neutron lbaas-loadbalancer-create VIP_SUBNET \
[--name NAME]
当负载均衡器创建时,OpenStack 会分配一个被称为虚拟 IP 的 IP 地址。客户端将使用 VIP 来访问负载均衡的应用程序。创建负载均衡器对象只是将流量负载均衡到实例的第一步。接下来的步骤,创建监听器、池和健康检查器,将在接下来的章节中讨论。
创建池
与负载均衡器关联的池是代表接收发送到 VIP 的流量的实例集合的对象。在 OpenStack 中,可以使用 neutron lbaas-pool-create 命令创建负载均衡池。
准备工作
至少需要以下详细信息来配置池:
-
平衡算法
-
协议
-
负载均衡器或监听器
也推荐指定一个名称。在我们的示例中,将使用以下名称:
-
名称:
COOKBOOK_POOL_1 -
平衡算法:
ROUND_ROBIN -
协议:
HTTP -
负载均衡器:
COOKBOOK_LOADBALANCER_1
负载均衡器可以与多个监听器关联,每个监听器可以与其各自的池关联。此类设置的常见场景是,一个负载均衡器上有一个监听器监听端口80,另一个监听器监听端口443,每个监听器都有其各自的后端池。
如何操作…
在系统上安装了 Neutron 客户端后,我们现在可以使用以下命令创建一个负载均衡器池:
neutron lbaas-pool-create --lb-algorithm ROUND_ROBIN \
--protocol HTTP \
--loadbalancer COOKBOOK_LOADBALANCER_1 \
--name COOKBOOK_POOL_1
输出结果如下所示:

它是如何工作的…
负载均衡池的创建语法如下:
neutron lbaas-pool-create [--name NAME] \
--lb-algorithm {ROUND_ROBIN,LEAST_CONNECTIONS,SOURCE_IP} \
[--listener LISTENER | --loadbalancer LOADBALANCER] \
--protocol {HTTP,HTTPS,TCP}
其他负载均衡对象,如成员和监控器,引用池,并且必须在创建时应用到池中。
创建成员
成员与池关联,代表一个在特定 IP 和端口上监听的后端应用程序。在 OpenStack 中,池成员可以通过 neutron lbaas-member-create 命令创建。
准备工作
至少需要以下详细信息来配置成员:
-
子网名称
-
IP 地址
-
端口
-
池名称
也推荐指定一个名称。在我们的示例中,将使用以下名称:
-
名称:
COOKBOOK_MEMBER_1 -
子网名称:
COOKBOOK_TENANT_SUBNET_1 -
IP 地址:
172.16.200.11(对应COOKBOOK_TEST_PORT_2) -
端口:
80 -
池名称:
COOKBOOK_POOL_1
一个成员只能与一个池关联。但是,相同的 IP 地址和应用端口组合可以用于多个成员。
如何操作…
在系统上安装了 Neutron 客户端后,我们可以使用以下命令创建一个池成员:
neutron lbaas-member-create --name COOKBOOK_MEMBER_1 \
--subnet COOKBOOK_TENANT_SUBNET_1 \
--address 172.16.200.11 \
--protocol-port 80 \
COOKBOOK_POOL_1
输出结果如下所示:

它是如何工作的…
池成员的创建语法如下:
neutron lbaas-member-create [--name NAME] \
--subnet SUBNET --address ADDRESS \
--protocol-port PROTOCOL_PORT \
POOL
创建监听器
监听器与负载均衡器对象关联,描述了负载均衡器 VIP 与服务监听的端口之间的关系。客户端将流量发送到监听器地址和端口,然后该流量被代理并发送到池中的一个成员。每个监听器可以配置为将流量发送到不同的池。在 OpenStack 中,监听器可以通过 neutron lbaas-listener-create 命令创建。
准备工作
至少需要以下详细信息来配置监听器:
-
负载均衡器名称
-
协议
-
端口
也推荐指定名称和默认池。在我们的示例中,将使用以下名称:
-
名称:
COOKBOOK_LISTENER_1 -
负载均衡器名称:
COOKBOOK_LOADBALANCER_1 -
协议:
HTTP -
端口:
80 -
默认池:
COOKBOOK_POOL_1
如何操作……
在我们的系统上安装了 Neutron 客户端后,现在可以使用以下命令创建一个监听器:
neutron lbaas-listener-create --name COOKBOOK_LISTENER_1 \
--loadbalancer COOKBOOK_LOADBALANCER_1 \
--protocol HTTP \
--protocol-port 80 \
--default-pool COOKBOOK_POOL_1
输出将类似于以下内容:

工作原理……
监听器是通过以下语法创建的:
neutron lbaas-listener-create [--name NAME] \
--loadbalancer LOADBALANCER \
--protocol {TCP,HTTP,HTTPS,TERMINATED_HTTPS} \
--protocol-port PORT \
[--default-pool DEFAULT_POOL]
提示
可以通过将安全组应用到负载均衡器地址的相应端口来限制对监听器的访问。使用本章前面描述的 openstack port set 命令来将安全组应用于监听器的端口。
验证连接性
一旦工作流完成并且池成员上的应用程序已启动,可以使用 Web 浏览器或从能够访问 VIP 的客户端的 curl 命令验证到负载均衡器 VIP 的连接。在本示例中,Web 服务器在前一节中配置的池成员上运行。我们将从与负载均衡器关联的 qlbaas 命名空间进行连接,但也可以从与 VIP 地址来源的网络关联的 qdhcp 命名空间进行连接。
准备就绪
至少需要以下详细信息来测试连接性
-
网络 ID 或负载均衡器 ID
-
VIP 地址和端口
对于我们的示例,将使用以下内容:
-
负载均衡器 ID:
aa599cee-b49f-44f1-a0fd-51fa69ebf6db(COOKBOOK_LOADBALANCER_1) -
VIP 地址和端口:
172.16.200.14:80
如何操作……
在 Neutron 代理容器内,可以使用 curl 在 qdhcp 或 qlbaas 命名空间内确认与 VIP 的连接:
# ip netns exec qlbaas-aa599cee
-b49f-44f1-a0fd-51fa69ebf6db \
curl http://172.16.200.14:80
输出将类似于以下内容:
Hello Cookbook Readers!
注意
你可能需要安装 curl 工具才能使命令正常工作。在 Neutron 代理容器中,可以通过运行 apt install curl 来完成此操作。池成员上 Web 服务器的配置超出了本书的范围。
若要从外部网络访问负载均衡器虚拟 IP,可能需要将浮动 IP 映射到虚拟 IP。可以参考本章前面的说明来完成该任务。
第五章:Nova – OpenStack 计算
在本章中,我们将涵盖以下主题:
-
OpenStack 计算简介
-
使用 OpenStack-Ansible 添加计算主机
-
暂停主机进行维护
-
配置 Nova 调度器以使用主机聚合
-
创建主机聚合
-
向主机聚合添加计算主机
-
从主机聚合中移除计算主机
-
向主机聚合添加元数据
-
删除主机聚合
-
创建可用区
-
将实例启动到可用区
-
删除可用区
-
创建 flavor
-
删除 flavor
-
为 flavor 设置 CPU 限制
-
为 flavor 设置 IOPS 限制
-
启动实例
-
停止实例
-
删除实例
-
实时迁移
-
快照实例
-
从快照启动实例
-
救援实例
-
搁置实例
-
查看控制台日志
OpenStack 计算简介
OpenStack 中的计算服务由名为 Nova 的项目提供。Nova 是一个基于 API 的系统,管理 OpenStack 云中的物理和虚拟计算资源,提供基础设施即服务(IaaS)。OpenStack 的操作员、管理员和用户可以利用 Nova API 来管理计算资源的生命周期。
Nova 主要负责管理两种资源类型:实例,即用户请求的正在运行的虚拟机、应用程序容器,甚至是裸金属机器;和主机,即提供实例所需硬件资源的主机。在大多数情况下,实例就是虚拟机的同义词。
理解 Nova 的两个主要功能非常重要:Nova API 服务(以及相关服务,如nova-scheduler、nova-conductor和nova-placement)运行在我们三个控制节点的集群上,而nova-compute服务则运行在我们环境中的每个计算主机上。
在本章中,我们将首先介绍物理主机和 Nova 服务的管理,接下来,本章的其余部分将采用以任务为中心的方法来处理 Nova。这意味着,关于 Nova 功能和特性的深度与细节超出了本书的范围。
使用 OpenStack-Ansible 添加计算主机
为了运行实例,OpenStack 计算需要知道在哪些物理资源上运行实例。随着 OpenStack 的成长和成熟,添加主机的过程也随之发展。OpenStack-Ansible 提供了一种非常便捷且一致的方法来添加新的计算主机,这使得你可以在需求增长时扩展你的环境。计算主机运行nova-compute服务和启动适当实例类型的虚拟化程序。
准备工作
为了使用openstack-ansible将计算主机添加到 OpenStack 集群中,您需要以下信息:
-
主机的 IP 地址
-
访问主机的 SSH
-
部署主机的 SSH 密钥
-
访问部署主机
示例中使用的值如下:
-
计算主机:
172.29.236.15 -
部署主机:
controller-01.cook.book
我们假设您的环境已经使用 OpenStack-Ansible 安装,如 第一章 中所述,使用 Ansible 安装 OpenStack。
操作方法…
使用 openstack-ansible 安装和配置额外的计算主机,请执行以下步骤:
-
从 部署主机,按以下示例将附加计算主机添加到
/etc/openstack_deploy/openstack_user_config.yml文件中:compute_hosts: compute-01: ip: 172.29.236.13 compute-02: ip: 172.29.236.14 compute-03: ip: 172.29 236.15 -
运行
setup-hosts.yml,将任务限制为仅限compute-03:cd /opt/openstack-ansible/playbooks openstack-ansible setup-hosts.yml --limit compute-03 -
让 Ansible 收集有关新主机的信息:
ansible nova_all -m setup -a 'filter=ansible_local gather_subset="!all"' -
只需运行
os-nova-install.yml在我们的新计算主机上安装和配置nova-compute:openstack-ansible os-nova-install.yml --limit compute-03提示
如果
openstack-ansible命令失败,可以使用-v标志增加详细信息以帮助进行故障排除。多次添加-v将提供额外的详细级别。 -
在任何控制器服务器上运行以下命令以确认新的虚拟化主机(因为它们运行实用程序容器):
lxc-attach --name $(lxc-ls -1 | grep utility) source openrc openstack hypervisor list这应该返回如下输出:
![操作方法…]()
工作原理…
/etc/openstack_deploy/openstack_user_config 文件提供了在我们的环境中将角色映射到主机的映射。向 compute_hosts 部分添加 compute-03.cook.book 的 IP 地址,告知 openstack-ansible 命令将包、设置等应用到新主机。它还向您的其余环境添加任何所需的配置。
提示
本书不涵盖 Openstack-Ansible playbooks 的详细讨论范围。有关 playbooks 及其操作方式的更多信息,请参阅此处的文档:docs.openstack.org/project-deploy-guide/openstack-ansible/pike/
暂停维护主机
经常需要将主机脱机以更换内存、升级操作系统或执行其他常规维护任务。为了确保运行中的实例不受不利影响,我们使用 openstack compute service set 命令。
准备工作
为了将主机置于维护模式,您将需要以下信息:
-
openstack命令行实用程序 -
nova命令行实用程序 -
带有管理员凭据的
openrc文件 -
主机的 名称
我们将置于维护模式的主机如下:
- 计算主机:
compute-03
操作方法…
要删除维护的虚拟化主机,请执行以下步骤:
-
首先,我们将列出可用的主机:
source ~/openrc openstack compute service list -c Binary -c Host -c Status -f table这将返回如下输出:
![操作方法…]()
-
接下来,我们将禁用称为
nova-compute的服务以进行计算主机的操作,因此我们将指定:openstack compute service set --disable compute-03 nova-compute提示
当成功时,此命令不会产生任何输出。
-
使用以下命令验证主机是否已禁用:
openstack compute service list -c Binary -c Host -c Status -f table这将生成如下所示的输出:
![如何操作…]()
-
一旦计算主机被禁用(意味着它将不再接受请求运行新实例),我们就可以将正在运行的实例从这个禁用的计算主机迁移到我们环境中的其他计算主机上:
nova host-evacuate-live --block-migrate compute-03这将生成如下所示的输出:
![如何操作…]()
它是如何工作的…
为了将主机下线进行维护,Nova 必须首先停止在该主机上放置新实例。可以通过使用 openstack service set --disable [host] [service] 命令禁用计算主机上的 nova-compute 服务来完成此操作。一旦主机被标记为禁用,在将其关闭进行维护之前,运行中的实例需要迁移到其他主机。nova host-evacuate-live [host] 命令尝试将所有正在运行的实例实时迁移到指定主机上。它通过要求 Nova 将实例重新调度到具有可用性的主机来实现这一点。
提示
如果实例没有使用共享存储,可以使用 --block-migrate 标志尝试迁移存储。
配置 Nova Scheduler 以使用主机聚合
OpenStack 计算提供了创建名为 主机聚合 的逻辑分组的能力,这些分组允许用户和管理员控制哪些物理计算主机可以运行请求的工作负载。通常,主机聚合用于组织具有相似属性的主机,例如 SSD、性能或已通过 HITRUST 或 PCI 安全审计的主机。一个主机可以被分配到多个聚合中。也就是说,一个主机可以同时属于 PCI 和 SSD 分组。为了在 Nova Scheduler 中启用主机聚合调度,必须首先在 nova.conf 中启用主机聚合过滤。在 openstack-ansible 中,Ansible 管理此文件,我们将使用它来推送适当的更改。
准备工作
确保你在部署主机上拥有 root 权限。在大多数情况下,这是第一个基础设施控制节点 infra01。
如何操作…
要启用主机聚合的调度,可以使用以下步骤:
-
在部署主机上,将以下行添加到
/etc/openstack_deploy/user_variables.yml文件中:nova_scheduler_default_filters: "AggregateInstanceExtraSpecsFilter,RetryFilter,AvailabilityZoneFilter,RamFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,ServerGroupAntiAffinityFilter,ServerGroupAffinityFilter,AggregateCoreFilter,AggregateDiskFilter" -
然后我们可以使用 Ansible 来部署以下命令进行更改:
cd /opt/openstack-ansible/playbooks openstack-ansible os-nova-install.yml -
登录到
nova-scheduler容器并验证更改:lxc-attach --name controller-01_nova_scheduler_container-ed0f657d grep Aggregate /etc/nova/nova.conf提示
容器的名称中有唯一的 UUID。使用以下命令查看容器的名称:
lxc-ls -f如果找到了
Aggregate这个词,以下输出将被返回,表明更改已成功:enabled_filters = AggregateInstanceExtraSpecsFilter,RetryFilter,AvailabilityZoneFilter,RamFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,ServerGroupAntiAffinityFilter,ServerGroupAffinityFilter,AggregateCoreFilter,AggregateDiskFilter
它是如何工作的…
将AggregateInstanceExtraSpecsFilter添加到enabled_filters中,告知nova-scheduler将实例的flavor 元数据与主机聚合元数据匹配。然后使用openstack-ansible命令将此更改传播到 OpenStack 云环境中的/etc/nova/nova.conf文件。
一旦启用,当请求新的实例时,Nova 调度器会检查与请求相关的 flavor 元数据,并尝试将其与主机聚合的元数据匹配。
创建主机聚合
启用 OpenStack 以允许主机聚合过滤后,我们可以继续创建主机聚合。本食谱将向您展示如何创建主机聚合。
准备工作
要创建主机聚合,您将需要以下信息:
-
openstack命令行客户端 -
包含适当凭据的
openrc文件 -
聚合的名称
对于我们的示例,主机聚合将命名为cookbook-ssd-hosts。
如何操作…
创建主机聚合,请执行以下步骤:
-
首先,我们将列出当前的主机聚合:
openstack aggregate list这将产生如下所示的输出:
![如何操作…]()
-
接下来,我们将创建聚合:
openstack aggregate create cookbook-ssd-hosts这将返回如下所示的输出:
![如何操作…]()
-
列出主机聚合:
openstack aggregate list这将产生如下所示的输出:
![如何操作…]()
它是如何工作的…
在 Nova 中,主机聚合为 OpenStack 管理员和操作员提供了一种机制,可以根据任意属性将主机分组,稍后用于控制哪些计算主机处理用户的请求。创建主机聚合是通过openstack aggregate create name命令完成的。
将计算主机添加到主机聚合
在 OpenStack 计算节点可以使用主机聚合之前,必须首先将主机添加到创建的聚合组中。
准备工作
要将主机添加到聚合中,您将需要以下信息:
-
openstack命令行客户端 -
包含适当凭据的
openrc文件 -
聚合的名称或ID
-
主机的名称或ID
对于以下示例,所需的值如下:
-
主机聚合:
cookbook-ssd-hosts -
计算主机:
compute-01
如何操作…
以下过程用于将主机添加到主机聚合中:
-
列出已经在聚合中的主机:
openstack aggregate show cookbook-ssd-hosts这将返回如下所示的输出:
![如何操作…]()
-
现在按如下方式将指定的计算主机添加到该聚合中:
openstack aggregate add host cookbook-ssd-hosts compute-01这将返回如下所示的输出:
![如何操作…]()
它是如何工作的…
openstack aggregate host add命令将主机与 Nova 数据库中的主机聚合关联。然后,Nova 调度器将根据此信息做出决策,决定将实例放置在哪个主机上。如果主机聚合的元数据与 flavor 或用户所在项目的元数据匹配,则实例可以调度到该聚合内的主机上。
从主机聚合中移除计算主机
如果主机的属性发生变化,或者聚合的需求发生变化,主机可以从主机聚合中移除。
准备工作
要从主机聚合中移除主机,你需要以下信息:
-
openstack命令行客户端 -
包含适当凭证的
openrc文件 -
聚合的名称或ID
-
主机的名称或ID
如何操作……
-
使用以下命令列出已在聚合中的主机:
openstack aggregate show cookbook-ssd-hosts这将返回如下输出。请注意,
hosts字段显示的是当前与主机聚合相关联的计算主机:![如何操作…]()
-
要从此主机聚合中移除计算主机,请发出以下命令:
openstack aggregate remove host cookbook-ssd-hosts compute-01这将返回以下内容。请注意,在
hosts字段中,compute-01现在已缺失:![如何操作…]()
它是如何工作的……
从主机聚合中移除主机会告知 OpenStack Compute,该额外的元数据过滤器不再适用,且该主机可以正常调度。
提示
当前,正在运行的实例不受此操作影响。主机聚合的操作仅影响新的实例请求。
向主机聚合添加元数据
主机聚合的强大之处在于能够基于主机的属性将其逻辑分组。这可以用于,例如,启用负载均衡、强制物理隔离,或者防止不安全的实例被调度到受保护的环境中。我们将通过将主机聚合的元数据与实例规格相匹配来展示这一点。
准备工作
要向主机聚合添加元数据,你需要以下信息:
-
openstack命令行客户端 -
包含适当凭证的
openrc文件 -
聚合的名称或ID
-
要添加的元数据属性
在我们的示例中,这些值将如下所示:
-
主机聚合:
cookbook-ssd-hosts -
元数据:
ssd=true
如何操作……
要向主机聚合添加元数据,请按照以下过程操作:
-
显示与聚合相关联的现有元数据:
openstack aggregate show cookbook-ssd-hosts这将返回如下输出。请注意,如果尚未关联任何元数据,
properties字段将是空白的:![如何操作…]()
-
使用以下命令添加元数据:
openstack aggregate set --property ssd=true cookbook-ssd-hosts提示
这个命令在成功时不会显示任何输出。
-
现在再次使用以下命令确认元数据的添加:
openstack aggregate show cookbook-ssd-hosts你将看到
properties字段已更新,包含以下信息:![如何操作…]()
-
现在我们已经设置了主机聚合的元数据,我们可以将其与配置关联,这样当用户在启动过程中指定该配置时,Nova 将根据该属性仅匹配主机聚合组中的主机。例如,我们可能有一个名为
cookbook.ssd的配置,它设定了预期,当用户选择时,该主机将提供 SSD。这就是主机聚合的强大之处。在此示例中,compute-02主机提供 SSD,因为我们在名为cookbook-ssd-hosts的主机聚合中指定了这一点。为了利用这一点,让我们创建一个新的配置,名为cookbook.ssd,并设置ssd=true属性:openstack flavor create --vcpus 1 --ram 512 --disk 5 --public cookbook.ssd提示
创建配置的详细说明请参见创建配置示例。
-
现在我们需要设置配置的额外规格,以便在选择配置时它与相关的主机聚合关联。为此,我们使用
nova命令:nova flavor-key cookbook.ssd set ssd=true提示
您可能需要使用配置的 UUID,而不是名称。如果是这样,请使用以下命令列出配置,并使用
cookbook.ssd配置的 UUID:openstack flavor list -
现在,当用户选择
cookbook.ssd配置时,他们可能并不知道,该实例将仅限于具有此键值对的主机聚合组中的主机。
它是如何工作的…
元数据以键/值对的形式指定,然后与 Nova 数据库中的主机聚合关联。这些键/值对是任意的,可以定义以适应特定环境。一个主机聚合可以存储任意数量的键/值对;然而,这可能会对实例调度产生不利影响,因为可能存在冲突或混淆的键/值对。
删除主机聚合
当主机聚合在给定环境中不再适用时,可以删除它。删除主机聚合之前,必须先移除所有主机。
准备工作
要删除主机聚合,您需要以下信息:
-
openstack命令行客户端 -
包含适当凭证的
openrc文件 -
聚合的名称或ID
在以下示例中,我们将删除cookbook-threadripper-hosts聚合。
如何操作…
以下命令用于删除主机聚合:
-
首先,列出现有的聚合:
openstack aggregate list这将返回以下输出:
![如何操作…]()
-
确认聚合中没有主机(如有必要,请参考从主机聚合中移除计算主机的示例):
openstack aggregate show cookbook-threadripper-hosts这将返回以下输出:
![如何操作…]()
-
现在我们可以使用以下命令删除聚合:
openstack aggregate delete cookbook-threadripper-hosts提示
此命令在成功时不会产生输出。
-
使用以下命令确认更改:
openstack aggregate list这将返回以下输出,其中主机聚合已被删除:
![如何操作…]()
它是如何工作的…
删除主机聚合会将其及其所有元数据从 Nova 数据库中移除,并且它将不再用于实例调度。
创建可用区
可用区(AZ)是主机聚合的特殊情况。在这里,主机聚合由 Nova 用于进行调度决策;通常它们只对 OpenStack 云的操作员和管理员可见。AZ 则是终端用户可见的组件。AZ 可以像主机聚合一样进行配置,以代表硬件的特性。
AZ 通常用于定义故障域,例如机柜、数据中心,甚至地理位置。在配置 AZ 时,需要注意的是,每个主机一次只能属于一个 AZ。
注意
由于 AZ 是主机聚合的特殊用例,很多操作(如添加和删除主机)与聚合相同。因此,这些操作不再重复说明。
创建 AZ 是一个两步过程。首先,我们使用--zone参数创建一个聚合,或者将其添加到现有的聚合中。其次,在实例可以调度到该区之前,必须将主机添加到聚合中。
准备就绪
创建 AZ 时,您需要以下信息:
-
openstack命令行客户端 -
包含适当凭证的
openrc文件 -
聚合的名称或ID
-
AZ 的期望名称
-
要添加到 AZ 的主机或主机
对于我们的示例,以下是这些值:
-
聚合名称:
cookbook-az -
可用区名称:
cookbook-az -
计算主机:
compute-01
操作方法…
创建 AZ 时需要执行以下步骤:
-
首先,我们将使用以下命令列出当前的 AZ:
openstack availability zone list这将返回如下输出:
![操作方法…]()
-
使用
--zone参数创建新的聚合:openstack aggregate create --zone cookbook-az cookbook-az这将返回如下输出:
![操作方法…]()
-
现在使用以下命令将主机添加到聚合中:
openstack aggregate add host cookbook-az compute-01成功时,返回如下输出:
![操作方法…]()
-
现在列出我们可用的 AZ:
openstack availability zone list这将显示以下内容:
![操作方法…]()
提示
列出所有可用的可用区(AZ),不论其中是否存在主机。要验证某个 AZ 中的主机,可以执行以下命令:
openstack availability zone show nameofAZ这将返回如步骤 3 所示的输出。
工作原理…
第一个命令openstack availability zone list列出了所有 AZ。接下来,在创建新聚合时,传递特殊的--zone cookbook-az参数,告诉 OpenStack Nova 这个聚合也是一个 AZ,并指定其名称。最后,像将主机添加到聚合一样将主机添加到 AZ。
启动实例到可用区
可以通过在创建过程中传递--availability-zone参数,将实例创建到指定的 AZ。此外,AZ 也可以在 OpenStack Horizon 中的实例创建向导中选择。
准备就绪
启动实例到 AZ 时需要以下信息:
-
openstack命令行客户端 -
包含适当凭证的
openrc文件 -
AZ 的名称或ID
-
启动实例所需的附加信息
提示
创建实例的详细步骤在启动实例的示例中有详细说明。因此,这个示例跳过了一些细节,专注于如何在特定的 AZ 中创建实例。
如何操作…
要将实例引导到特定的 AZ,需在运行openstack server create命令时指定--availability-zone参数:
openstack server create --flavor openstack.cookbook
--image 08b822ba-be44-4639-b577-45e8dd37c06d
--nic net-id=6cb5a4ce-1ea5-4817-9c34-a2212a66f394
--security-group bd7d5e0f-538a-4d93-b123-98cc3207b3d2
--key-name cookbook_key
--availability-zone cookbook-az
cookbook.test-03
这将带回如下输出,显示实例所在的 AZ(OS-EXT-AZ:availability-zone字段):

工作原理…
如果指定了--availability-zone参数,Nova 调度程序会检查指定的 AZ,看看是否可以满足请求。
移除可用性区域
移除 AZ 是一个多步骤的过程,并且有一些注意事项。要移除 AZ,必须先从主机聚合中移除主机。
准备工作
删除 AZ 所需的以下信息:
-
openstack命令行客户端 -
包含适当凭据的
openrc文件 -
AZ 的名称或ID
如何操作…
以下步骤可用于移除一个 AZ:
-
首先,使用以下命令列出可用的 AZ:
openstack availability zone list这将带回如下输出:
![操作步骤…]()
-
现在列出我们要删除的 AZ 中的主机:
openstack aggregate show cookbook-az这将带回如下输出:
![操作步骤…]()
-
现在使用以下命令移除主机(根据需要重复每个主机的操作):
openstack aggregate remove host cookbook-az compute-01这将带回以下输出:
![操作步骤…]()
-
使用
aggregate delete命令移除 AZ:openstack aggregate delete cookbook-az提示
如果成功,该命令将不产生任何输出。
-
使用以下命令确认 AZ 的移除:
openstack availability zone list这将带回如下输出,显示我们的 AZ 已被移除:
![操作步骤…]()
工作原理…
要移除 AZ,首先必须确保没有活动主机。因为 AZ 是主机聚合的特例,用于识别和移除主机的命令相同。一旦移除了主机,使用openstack aggregate delete [name]命令完成 AZ 的移除。
创建一个 flavor
在 Nova 可以启动实例之前,首先需要知道应分配给这些实例的资源。Nova 处理资源分配的方式是定义flavors。一个 flavor 指定了分配给实例的 vCPU 数、RAM 和磁盘大小。
准备工作
要创建一个新的 flavor,您需要以下内容:
-
openstack命令行客户端 -
包含适当凭据的
openrc文件 -
新 flavor 的名称、vCPU、RAM和磁盘值
在本示例中我们将创建的 flavor 将具有以下属性:
-
Flavor 名称:
openstack.cookbook -
vCPU:1
-
RAM:512 MB
-
磁盘:5 GB
-
可见性:公共
如何操作…
以下命令用于创建新的 flavor:
-
首先,使用以下命令列出我们环境中已配置的可用 flavor:
openstack flavor list这将返回如下所示的输出:
![如何操作…]()
-
使用我们提供的属性创建 flavor:
openstack flavor create --vcpus 1 --ram 512 --disk 5 --public openstack.cookbook这将返回如下所示的输出:
![如何操作…]()
-
再次列出 flavor,以查看新 flavor:
openstack flavor list这将输出如下所示的内容:
![如何操作…]()
如何操作…
openstack flavor create --vcpus [vcpu_count] --ram [ram_MB] --disk [disk_GB] --public [name]命令用于定义 flavor。--public选项用于指定该 flavor 是否应对所有 OpenStack 环境中的用户可用,或者是否应仅限于用户所属项目的范围和可见性。
删除 flavor
由于需求的变化,可能会有对更多性能的要求,或者业务需求发生变化。无论原因如何,现有的 flavor 可能无法满足使用云资源的需求。当某个 flavor 不再适用时,它需要被删除。
提示
与正在运行的实例相关联的 flavor 无法删除。
准备就绪
要更改 Nova 的 flavor 属性,您需要以下内容:
-
openstack命令行客户端 -
包含适当凭证的
openrc文件 -
要删除 flavor 的名称
如何操作…
以下命令用于删除 flavor:
-
首先,列出可用的 flavor:
openstack flavor list这将返回如下所示的 flavor 列表:
![如何操作…]()
-
要删除 flavor,请执行以下命令:
openstack flavor delete openstack.cookbook提示
该命令执行成功时不会显示任何输出。
-
再次列出 flavor,以查看更新后的属性:
openstack flavor list再次列出当前可用的 flavor:
![如何操作…]()
如何操作…
删除 flavor 时使用openstack flavor delete [name]命令。如果需要删除多个 flavor,可以指定多个名称或 ID,每个名称或 ID 之间用空格分隔。
为 flavor 设置 CPU 限制
除了定义分配给实例的 vCPU 数量外,还可以进一步限制这些 CPU 周期的使用。Nova 依赖于底层的虚拟化管理程序来实现 CPU 限制,因此可用的值可能会有所不同。我们的示例基于 QEMU/KVM。
CPU 限制是您可能会遇到的 flavor 属性的特殊情况。
准备就绪
要为 flavor 添加 CPU 限制,您需要以下内容:
-
openstack命令行客户端 -
包含适当凭证的
openrc文件 -
要更改 flavor 的名称
-
您希望设置的 CPU 限制值(分配的 CPU 每个周期可消耗的时间份额,以毫秒为单位)
我们示例中的这些值如下:
-
cpu_quota= 5000 ms -
cpu_period= 2500 ms
如何操作…
以下命令用于为 flavor 添加 CPU 限制。
提示
CPU 限制不是实时应用的,而是在实例启动时应用。
在撰写本文时,openstack 命令行客户端是查看和更改此设置的唯一方式。默认情况下,查看实例属性时也不会显示此设置。
-
首先,查看我们正在更改的 flavor 的当前属性,注意我们没有设置
properties:openstack flavor show openstack.cookbook这将给出如下输出:
![How to do it…]()
-
添加 CPU 限制:
openstack flavor set --property quota:cpu_quota=5000 --property quota:cpu_period=2500 openstack.cookbook提示
此命令成功时不会显示任何输出
-
通过再次查询 flavor 来查看 CPU 限制,注意
properties字段:openstack flavor show openstack.cookbook这将给出类似以下的输出:
![How to do it…]()
它是如何工作的…
为了帮助缓解 吵闹邻居 问题,或者进一步定义服务等级,OpenStack 支持 CPU 限制。在 OpenStack 中,这被称为 实例资源配额。CPU 限制是 flavor 定义的一部分。也就是说,给定 flavor 的所有实例都会有相同的 CPU 限制。
强加 CPU 限制是特定于虚拟化管理程序的。对于 KVM/libvirt 环境,CPU 限制是通过 cgroups 强制实施的,结合使用以下三个值:
-
cpu_shares -
cpu_quota -
cpu_period
对于这些值及其交互的完整讨论超出了本书的范围。不过,你可以在 OpenStack wiki 上找到详细的解释,网址如下:
wiki.openstack.org/wiki/InstanceResourceQuota
为 flavor 设置 IOPS 限制
与 CPU 限制一样,IOPS 限制也可以被施加,以防止某个实例类型占用系统上所有可用的 IO。此处的 IOPS 指的是存储和网络 IO。同时,像 CPU 限制一样,IOPS 限制是 flavor 属性的一个特殊案例,你可能会经常遇到。
提示
在撰写本文时,openstack 命令行客户端是查看和更改此设置的唯一方式。默认情况下,查看实例属性时也不会显示此设置。
准备就绪
要向 flavor 添加 IOPS 限制,你需要以下内容:
-
openstack命令行客户端 -
包含适当凭据的
openrc文件 -
要更改的 flavor 的 名称
-
你希望设置的 IOPS 限制值。
-
在我们的示例中,这些值如下:
-
disk_read_iops= 100 IOPS -
disk_write_iops= 100 IOPS
如何操作…
以下命令用于向 flavor 添加 IOPS 限制:
提示
与更改 flavor 属性一样,IOPS 限制不会应用于正在运行的实例。相反,它们是在实例启动时应用的。
-
首先,查看正在更改的 flavor 的属性,注意
properties字段为空:openstack flavor show openstack.cookbook这将给出类似以下的输出:
![How to do it…]()
-
现在我们可以使用以下命令添加 IOPS 限制:
openstack flavor set --property quota:disk_read_iops=100 --property quota:disk_write_iops=100 openstack.cookbook提示
此命令成功时不会显示任何输出。
-
我们可以通过查看 flavor 属性来验证 IOPS 限制:
openstack flavor show openstack.cookbook这将返回类似以下的输出,注意我们现在已经设置属性以反映施加的 IOPS:
![操作方法…]()
它是如何工作的……
与 CPU 限制一样,IO 限制也在 flavor 级别定义。然而,与 CPU 限制不同,IO 限制可以由虚拟机监控程序、存储层或两者的组合来应用。
要为给定的 flavor 设置 IOPS 限制值,请使用以下openstack命令:
openstack flavor set
--property quota:disk_read_iops=[read_iops]
--property quota:disk_write_iops=[write_iops]
[name]
虽然为了完整性显示了读写 IOPS,但你不需要同时指定两者。
启动实例
使用实例可以执行的最基本任务是生命周期任务。在本示例中,我们将向你展示如何启动或引导实例。
准备就绪
要启动一个实例,你将需要以下内容:
-
openstack命令行客户端 -
包含适当凭据的
openrc文件 -
实例的名称
-
用于实例的镜像
-
用于创建实例的flavor名称
-
要将实例附加到的网络的名称
-
用于允许访问实例的密钥对名称
-
与实例关联的任何安全组名称
它是如何工作的……
我们将启动的实例将具有以下属性:
-
实例名称:
cookbook.test -
Flavor 类型:
openstack.cookbook -
镜像名称:
Ubuntu 16.04 amd64(UUID) -
网络:
public(UUID) -
密钥对名称:
cookbook_key -
安全组:
ssh
要启动一个实例,使用以下步骤:
-
要列出当前正在运行的实例,我们执行以下命令:
openstack server list提示
如果没有实例,这个命令将不会产生任何输出。
-
列出可用的镜像:
openstack image list这将返回一个可用镜像的列表:
![操作方法…]()
-
列出可用的网络:
openstack network list这将列出我们可以将实例附加到的网络:
![操作方法…]()
-
创建一个密钥对(如果你还没有创建并可供使用):
ssh-keygen -q -N ""还可以使用以下命令上传:
openstack keypair create --public-key ~/.ssh/id_rsa.pub cookbook_key这将返回一个输出,显示您的密钥指纹:
![操作方法…]()
-
现在我们可以使用以下命令启动实例:
openstack server create --flavor openstack.cookbook --image 08b822ba-be44-4639-b577-45e8dd37c06d --nic net-id=6cb5a4ce-1ea5-4817-9c34-a2212a66f394 --security-group ssh --key-name cookbook_key cookbook.test这将产生一个输出表,显示实例正在引导(为了简洁起见,此处不显示)。
-
要查看已启动实例的更多信息,请执行以下命令:
openstack server show cookbook.test这将输出如下内容:
![操作方法…]()
它是如何工作的……
在记录下需要输入的一些必需值后,例如我们要启动的镜像的 UUID 和要将实例附加到的网络的 UUID,我们然后调用了 OpenStack 客户端中的一个工具来启动我们的实例。该命令行的一部分指向要使用的密钥对。然后我们通过生成的密钥对中的私钥连接到实例。
云实例如何知道使用哪个密钥?作为该镜像启动脚本的一部分,它会回调到元服务器,这是 nova-api 和 nova-api-metadata 服务的一个功能。元服务器充当我们实例和外部世界之间的桥梁,云-init 启动过程可以调用它,在这种情况下,它下载一个脚本,将我们的私钥注入到 Ubuntu 用户的 .ssh/authorized_keys 文件中。
当云实例启动时,它会生成一些关于该实例的有用指标和详细信息。这些通过 openstack server list 和 openstack server show 命令呈现。openstack server list 命令显示一个简洁的版本,列出实例的 ID、名称、状态和 IP 地址。
停止实例
有时,实例需要停止,可能是出于多种原因,例如维护和离线迁移,但作为 OpenStack 管理员,您可能不想完全销毁实例及其相关数据。因此,您可能只想停止实例。
准备就绪
要停止实例,您需要以下内容:
-
openstack命令行客户端 -
包含适当凭证的
openrc文件 -
实例的 名称
如何操作…
在此示例中,我们将停止在 启动实例 方案中创建的 cookbook.test 实例。要停止实例,请按照以下步骤操作:
-
首先,我们列出正在运行的实例:
openstack server list这将返回一个正在运行的实例列表。考虑以下示例:
![如何操作…]()
-
要停止实例,只需执行以下命令:
openstack server stop cookbook.test提示
该命令完成需要一些时间,如果成功,将不会显示输出。
-
现在列出实例以确认实例的状态。在这里,我们正在寻找
cookbook.test实例的SHUTOFF状态:openstack server list这将输出以下内容:
![如何操作…]()
它是如何工作的…
要停止实例,我们使用 openstack 客户端的 server stop 命令:openstack server stop [名称或 ID]。这会告诉 Nova 关闭实例的电源。这相当于按住笔记本电脑的电源按钮或拔掉服务器的电源线。
删除实例
要完成实例的生命周期,您需要删除它。Nova 提供了这个功能,通过 openstack 命令行工具来实现。
准备就绪
要删除一个实例,您需要以下内容:
-
openstack命令行客户端 -
包含适当凭证的
openrc文件 -
实例的 名称
如何操作…
在这个示例中,我们将删除在 启动实例 方案中创建的 cookbook.test 实例。要删除实例,请按照以下步骤操作:
-
首先,列出正在运行的实例:
openstack server list![如何操作…]()
-
要删除名为
cookbook.test的实例,请执行以下命令:openstack server delete cookbook.test提示
如果命令成功执行,将不会有输出。
-
现在再次列出实例以确认删除:
openstack server list这将返回一个输出,显示我们删除的实例现在已不在:
![如何操作…]()
它是如何工作的…
openstack server delete命令不同于暂停或挂起实例,它会删除实例及其中的所有数据。
实时迁移
云计算的一个关键理念是将硬件抽象化。然而,硬件确实需要定期维护,或者主机需要进行软件升级。无论是什么原因,主机可能需要下线进行维护,理想情况下,实例的停机时间应该尽可能少。为了适应这一需求,Nova 提供了两种实时迁移实例的方法:当环境中没有共享存储时使用块迁移,当实例从共享存储启动时使用实时迁移标志(在每个计算主机都能看到每个实例的启动卷时,实例将从共享存储启动)。
准备就绪
要进行实例的实时迁移,您需要以下信息:
-
openstack命令行客户端 -
包含适当管理员凭证的
openrc文件 -
实例的名称
-
目标虚拟化管理程序的名称
提示
如果你的环境配置为实例从共享存储(例如 Ceph 提供的 RBD)启动,那么实时迁移几乎是瞬时完成的(这取决于实例的忙碌程度)。一个叫做块迁移的特性要慢得多。块迁移用于没有为实例提供共享存储的环境中。
迁移只能由具有管理员角色权限的用户执行。
如何操作…
-
首先,我们列出可用的虚拟化管理程序。我们需要记录可以将正在运行的实例迁移到的地方:
openstack hypervisor list这将返回如下所示的输出:
![如何操作…]()
-
接下来,查看实例属性以识别源主机:
openstack server show cookbook.test -c name -c OS-EXT-SRV-ATTR:hypervisor_hostname这将返回我们感兴趣的字段(也称为列名,使用
-c标志标识)。请注意,在这个例子中,名为cookbook.test的实例正在名为compute-01.cook.book的虚拟化管理程序上运行:![如何操作…]()
-
要执行没有共享存储可用的实例实时迁移,请发出以下命令:
openstack server migrate --block-migration cookbook.test提示
我们不使用
--block-migration方法指定目标计算主机,而是让 Nova 调度器决定下一个可用的虚拟化管理程序。当成功时,此命令不会显示任何输出。
要实时迁移实例,使用共享存储(如 Ceph),请发出以下命令:
openstack server migrate cookbook.test --live compute-02.cook.book提示
我们通过
--live标志指定目标虚拟化管理程序。当成功时,此命令不会显示任何输出。
-
检查迁移状态:
openstack server show -c name -c OS-EXT-STS:task_state cookbook.test由于块迁移通常需要更长的时间,您可能会看到状态为
resize_migrating,这表示迁移任务仍在进行中:![如何操作…]()
-
使用以下命令验证迁移,确保实例现在运行在不同的虚拟化管理程序上:
openstack server show cookbook.test -c name -c OS-EXT-SRV-ATTR:hypervisor_hostname这将返回如下所示的输出:
![如何操作…]()
提示
任何类型的迁移通常最好在实例未被大量使用时进行。
它是如何工作的…
实时迁移是一个关键特性,使 OpenStack 操作员和管理员能够在不影响云服务消费者的情况下,对底层云基础设施进行维护。此外,OpenStack 管理员可以使用来自资源监控服务(如 Ceilometer)的遥测数据,并做出实时迁移决策,以平衡 OpenStack 云中的工作负载。
OpenStack 中的实时迁移由 libvirt 驱动程序处理。具体来说,当您发出openstack server migrate命令时,OpenStack Compute 会从一个计算主机上的 libvirtd 建立到远程主机上同一进程的连接。一旦建立了此连接,根据您指定的参数,实例的内存状态会同步,并且控制权会转移。在前面的示例中,我们首先指定了额外的--block-migrate参数,它在没有共享存储的情况下处理实例磁盘文件的移动,然后我们展示了如何在实例从共享存储启动时使用--live标志。
提示
记住:迁移只能由具有admin角色的用户执行。
对实例进行快照
对实例进行快照将创建实例在拍摄快照时的 Glance 镜像。然后,您可以使用该镜像部署给定应用程序的额外实例,或作为实例的可启动备份。
准备工作
为了创建实例的快照,您需要以下信息:
-
openstack命令行客户端 -
包含适当凭证的
openrc文件 -
实例的名称
如何操作…
以下命令用于创建实例快照:
-
首先,我们使用以下命令列出现有镜像:
openstack image list -c Name -c Status这将返回如下所示的镜像列表:
![如何操作…]()
-
现在,使用以下命令列出正在运行的实例:
openstack server list -c Name -c Status这将输出如下所示的内容:
![如何操作…]()
-
要创建快照,请执行以下命令(请注意我们使用的可选 shell 扩展命令,它会为快照名称添加时间戳):
openstack server image create --name cookbook.test_snapshot-$(date +"%FT%H%M%S") cookbook.test这将输出如下所示的内容:
![如何操作…]()
-
我们可以使用以下命令验证快照是否已创建。请注意,我们将屏幕截图限制为仅显示我们的快照镜像:
openstack image list这将输出显示我们的快照镜像:
![如何操作…]()
它是如何工作的…
实例快照会创建正在运行实例的 Glance 镜像。该快照可以用于备份、重新分发或作为持续部署管道中的构建工件。使用openstack server image create --name [snapshot_name] [instance]创建的镜像是可启动的。您可以灵活地使用这些镜像。
还有更多…
实例快照非常强大。虽然本书无法详细探讨其所有可能性,但以下示例展示了使用此功能可以实现的目标:一种轻松备份所有运行实例的方式。
要快照每个实例,请使用以下命令:
for instance in $(openstack server list -f value -c ID); do {
openstack server image create \
--name "${instance}"-$(date +"%FT%H%M%S") ${instance}
}; done
小贴士
警告:不推荐在较大的环境中对每个实例进行快照。除了耗时之外,它还可能消耗 Glance 使用的相当大一部分存储空间,因为快照不像您可能使用的原始 QCOW2 镜像那样稀疏创建
从快照启动实例
现在我们已经创建了一个实例快照,假设我们需要回滚并恢复文件,或将应用程序恢复到快照创建时的状态。由于快照作为 OpenStack 镜像存储,您可以直接从快照启动,因此启动实例所需的所有细节也适用于启动快照。
准备就绪
要从快照启动实例,您将需要以下内容:
-
openstack命令行客户端 -
包含适当凭证的
openrc文件 -
实例的名称
-
用于实例的快照
-
用于创建实例的规格名称(此规格必须与原始实例使用的规格大小相等或更大)
-
要附加到实例的网络或网络名称
-
允许访问实例的密钥对名称
-
任何安全组的名称,用于与实例关联
如何操作…
我们将启动的实例将具有以下属性:
-
镜像名称:
cookbook.test_snapshot-2017-09-08T163619 -
实例名称:
cookbook.test_restore -
规格类型:
openstack.cookbook -
网络:
public(UUID) -
密钥对名称:
cookbook_key -
安全组:
ssh
要从实例快照启动,我们使用与启动实例相同的过程。以下命令是重复的:
-
首先,我们可以使用以下命令列出现有的运行实例:
openstack server list -c Name -c Status这将返回一个
ACTIVE运行实例的列表:![如何操作…]()
-
然后我们可以使用以下命令启动实例快照:
openstack server create --flavor openstack.cookbook --image cookbook.test_snapshot-2017-09-08T163619 --nic net-id=6cb5a4ce-1ea5-4817-9c34-a2212a66f394 --security-group bd7d5e0f-538a-4d93-b123-98cc3207b3d2 --key-name cookbook_key cookbook.test_restore这将返回熟悉的启动实例的输出,已在此省略。
-
现在我们可以再次列出运行中的实例,以显示我们的
cookbook.test_restore实例是ACTIVE的:openstack server list -c Name -c Status这显示我们的实例现在正在运行:
![如何操作…]()
它是如何工作的…
由于实例快照存储为 OpenStack 镜像,从快照启动的过程与从现有镜像启动的过程相同。然而,存在一些注意事项。由于快照是在镜像运行时创建的,从它们启动的过程类似于在断电后启动服务器。您还必须确保使用的 flavor 与原始实例相同或更大。例如,如果一个实例最初创建为 m1.large,则必须使用 m1.large 或更大的 flavor 来启动快照。此外,如果实例是附加到 Active Directory 域的 Windows 镜像,可能会导致两个相同的实例同时运行时出现问题。为缓解此问题,请考虑将实例启动到单独的恢复网络上。
提示
有一些工具可用于暂停实例内的文件系统,并提供一个更一致的镜像,这超出了本书的范围。然而,作为指导,建议在拍摄快照之前,确保运行实例内的文件系统同步(以刷新任何磁盘写入)。
救援一个实例
OpenStack Compute 提供了一个方便的故障排除工具——救援模式。如果用户丢失了 SSH 密钥,或者无法启动并访问实例,例如,出现错误的 iptables 设置或失败的网络配置,救援模式会启动一个最小化实例并附加来自故障实例的磁盘以帮助恢复。这个过程适用于 Windows 和 Linux 实例,因为它本质上允许将故障实例的引导卷作为二级磁盘附加到救援实例上。
准备工作
要将实例置于救援模式,您需要以下信息:
-
openstack命令行客户端 -
包含适当凭证的
openrc文件 -
实例的名称或ID
本示例中使用的实例是cookbook.test。
如何操作…
要将实例置于救援模式,请按照以下步骤操作:
-
首先,我们将按以下方式将实例置于救援模式:
openstack server rescue cookbook.test这将向我们展示一个临时密码,我们可以使用它来访问救援实例:
![如何操作…]()
-
要验证实例是否处于救援模式,请使用以下命令:
openstack server show cookbook.test -c name -c status这将显示
status值为RESCUE:![如何操作…]()
-
此时,我们可以使用
root用户名和我们获得的临时密码访问该实例,并在挂载的文件系统上执行操作系统救援命令(即原始故障实例的引导卷文件系统)。提示
在救援模式下,实例的磁盘将作为二级磁盘附加。为了访问磁盘上的数据,您需要将其挂载。由于操作系统和部署方式之间的文件系统差异,本书不涉及挂载过程。
-
要退出救援模式,请使用以下命令:
openstack server unrescue cookbook.test提示
如果命令成功执行,将不会产生任何输出。
它是如何工作的……
openstack server rescue命令提供一个救援环境,并将你的实例磁盘附加到该环境中。首先,它关闭指定的实例,然后启动救援环境并附加原始实例的磁盘。最后,它为你提供救援实例的登录凭证。
通过 SSH 访问救援实例。一旦登录到救援实例,你可以使用命令 mount <path to disk> /mnt 挂载磁盘。
一旦完成故障排除或恢复,unrescue命令会逆转此过程:首先停止救援环境并分离磁盘,然后按原样启动实例。
将实例置于架空状态
OpenStack Nova 中有一个稍微独特的功能,那就是能够将实例置于架空状态。实例架空允许你停止实例而不消耗资源。一个架空的实例将被保留为一个可启动的实例,并保留它所分配的资源(如 IP 地址),该实例将保持一定时间后被删除。这在实例生命周期过程中或节省资源时非常有用。
提示
停止与架空有什么区别?
停止实例并不会释放作为配额一部分仍然可用的资源,因为假设你将在短时间内重新启动该实例。如果你没有剩余的 CPU 或 RAM 配额,便无法启动已停止的实例。已停止实例的资源仍然被视为 OpenStack 计算调度程序的已使用资源。
然而,将实例置于架空状态可以释放这些资源,但仍然允许你在稍后的时间访问已架空的实例。解除架空时,配额规则和限制仍然适用,但将实例置于架空状态可以让你在保持实例数据的同时,在分配的资源配额内工作。
准备工作
要将实例置于架空状态,需提供以下信息:
-
openstack命令行客户端 -
包含适当凭证的
openrc文件 -
实例的名称或ID
操作方法…
要将实例置于架空状态,使用以下命令:
-
首先,我们检查实例的状态:
openstack server show cookbook.test -c name -c status确保你的实例的
status为ACTIVE:![操作方法…]()
-
要将实例置于架空状态,执行以下命令:
openstack server shelve cookbook.test提示
该命令执行成功时不会产生任何输出。将实例置于架空状态可能需要一些时间,具体取决于你的环境。
-
要检查实例的状态,执行以下命令,注意新的状态:
openstack server show cookbook.test -c name -c addresses -c statusstatus值已更改为SHELVED_OFFLOADED:![操作方法…]()
提示
一个架空的实例将保留它已分配的地址。
-
要解除架空实例并将其恢复为
ACTIVE状态,只需执行以下命令:openstack server unshelve cookbook.test提示
该命令执行成功时不会产生任何输出。与架空操作一样,实例可能需要几分钟才能变为活动状态,这取决于你的环境。
-
我们可以通过检查状态来验证该状态:
openstack server show cookbook.test -c name -c addresses -c statusstatus值已返回ACTIVE:![如何操作...]()
它是如何工作的...
当被要求架空实例时,OpenStack Compute 会先停止该实例。然后,它会创建一个实例快照以保留该实例的状态。运行时的细节,例如 vCPU 数量、内存和 IP 地址,会被保留,以便可以在稍后的时间将实例恢复并重新调度。
这与关闭实例不同,因为关闭实例的资源仍然保留在其所在的主机上,以便可以快速重新启动。然而,已架空的实例仍会出现在openstack server list中,分配的资源将保持可用。此外,由于已架空的实例需要从镜像恢复,OpenStack Compute 将执行放置操作,就像该实例是全新的一样,启动时将需要一些时间。
审查控制台日志
控制台日志对于排查实例启动过程中的问题至关重要。这些日志在启动时生成,在控制台可用之前。通常,在使用云托管实例时,访问这些日志可能比较困难。OpenStack Compute 提供了一种访问控制台日志的机制。
准备工作
要访问实例的控制台日志,需要以下信息:
-
openstack命令行客户端 -
包含适当凭据的
openrc文件 -
实例的名称或ID
在此示例中,我们将查看cookbook.test实例的最后五行。
如何操作...
要显示实例的控制台日志,请使用以下命令:
openstack console log show --lines 5 cookbook.test
这将连接到实例的串行控制台输出,模拟如同监视器直接连接到物理服务器的信息:
[[0;32m OK [0m] Started udev Coldplug all Devices.
[[0;32m OK [0m] Started Dispatch Password Requests to Console Directory Watch.
[[0;32m OK [0m] Started Set console font and keymap.
[[0;32m OK [0m] Created slice system-getty.slice.
[[0;32m OK [0m] Found device /dev/ttyS0.
它是如何工作的...
openstack console log show命令收集控制台日志,就像你通过串行端口连接到服务器或在启动时坐在键盘和显示器后面一样。默认情况下,该命令将返回所有生成的日志。要限制输出量,可以使用--lines参数返回日志末尾的特定行数。
第六章:Glance – OpenStack 镜像服务
在本章中,我们将涵盖以下主题:
-
OpenStack 镜像服务介绍
-
管理镜像
-
使用镜像快照
-
使用镜像元数据
-
保护镜像
-
禁用镜像
-
创建自定义镜像
OpenStack 镜像服务介绍
OpenStack 镜像服务,也称为 Glance,是一个允许用户注册、发现和获取虚拟机镜像,以便在 OpenStack 云中使用的服务。通过 OpenStack 镜像服务提供的镜像可以存储在多种格式和后端位置中,从本地文件系统存储到分布式文件系统,如 OpenStack 对象存储(Swift)和 Ceph。
OpenStack 镜像服务由两个主要组件组成:glance-api服务和glance-registry服务。用户在使用 OpenStack 客户端执行创建、列出、删除或管理镜像等命令时,间接与glance-api服务进行交互。glance-registry服务负责连接后端数据库,并存储或检索镜像。
管理镜像
在 OpenStack 环境中,可以使用openstack命令行工具、Horizon 仪表板或通过 Glance 基于 REST 的 API 直接进行镜像管理。镜像可以直接从互联网获取,或者使用virsh、virt-manager、growpart、cloud-init等工具创建和操作。自定义镜像创建将在本章后面进行介绍。
上传镜像
在 OpenStack 中创建镜像时,必须提供描述镜像的属性。这些属性包括镜像名称、磁盘格式和容器格式。镜像可以是公共的、私有的,或者在多个项目之间共享。
准备工作
以下示例所需的镜像可以从以下位置下载:
-
Ubuntu:
cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-disk1.img -
CirrOS:
download.cirros-cloud.net/0.3.5/cirros-0.3.5-i386-disk.img
注意
随着时间的推移,网络上的镜像位置可能会发生变化,本书中的 URL 可能不可用。您可以自由地将这些示例中的任何 URL 替换为已知且有效的 URL。
上传镜像时,确保您已经正确获取凭证或已通过其他方式正确认证。
上传镜像时,您至少需要以下信息:
-
镜像名称
-
磁盘格式
-
镜像位置
对于我们的第一个示例,将使用以下内容:
-
镜像名称:
COOKBOOK_CIRROS_IMAGE -
磁盘格式:
qcow2 -
镜像位置:
/tmp/cirros-0.3.5-i386-disk.img
对于我们的第二个示例,将使用以下内容:
-
镜像名称:
COOKBOOK_UBUNTU_IMAGE -
磁盘格式:
qcow2 -
镜像位置:
/tmp/xenial-server-cloudimg-amd64-disk1.img
如何操作……
在系统上安装 OpenStack 客户端后,我们现在可以通过以下步骤上传镜像:
-
将 CirrOS 镜像下载到
/tmp目录:wget https://download.cirros-cloud.net/0.3.5/cirros-0.3.5-i386-disk.img -O /tmp/cirros-0.3.5-i386-disk.img -
上传 CirrOS 镜像:
openstack image create COOKBOOK_CIRROS_IMAGE \ --disk-format qcow2 \ --file /tmp/cirros-0.3.5-i386-disk.img输出将类似于以下内容:
![如何操作...]()
对 Ubuntu 镜像重复执行上述步骤:
-
将 Ubuntu 镜像下载到
/tmp目录:wget https://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-disk1.img -O /tmp/xenial-server-cloudimg-amd64-disk1.img -
上传 Ubuntu 镜像:
openstack image create COOKBOOK_UBUNTU_IMAGE \ --disk-format qcow2 \ --file /tmp/xenial-server-cloudimg-amd64-disk1.img
它是如何工作的...
创建镜像的语法如下:
openstack image create IMAGE_NAME \
--disk-format DISK_FORMAT \
--file FILE_LOCATION \
[--public | --private | --shared | --community]
使用 OpenStack 客户端创建镜像时,指定的文件将被上传到 OpenStack 镜像库。镜像库可以是 Glance 配置文件中指定的本地目录或卷,也可以是由 Swift、Ceph、Rackspace Cloud Files 等提供的对象存储。
disk-format 参数定义了镜像使用的虚拟磁盘格式。可选项包括 ami、ari、aki、vhd、vmdk、raw、qcow2、vhdx、vdi、iso 和 ploop。qcow2 格式在基于 OpenStack 的云环境中广泛使用,特别是在运行 QEMU/KVM 虚拟化的环境中,它支持较小的镜像文件大小、写时复制(copy-on-write)支持以及各种压缩和加密技术。默认格式为 raw。
当将镜像上传到由 Ceph 支持的 Glance 存储时,镜像必须为 raw 格式,否则无法正常工作。可以使用 qemu-img 命令识别镜像的格式,同时该命令也可以用来将镜像从一种格式转换为另一种格式。
下面是一个将 qcow2 格式的镜像转换为 raw 格式的示例:
qemu-img convert -f qcow2 -O raw image.qcow2 image.raw
提示
更多使用 qemu-img 命令的示例可以在 OpenStack 文档中找到:
docs.openstack.org/image-guide/convert-images.html
file 参数定义了镜像文件相对于运行 OpenStack 客户端的位置。OpenStack 客户端将镜像上传到 OpenStack 镜像库,并根据 Glance 中的设置进行存储。
当指定时,--public 选项将镜像标记为所有云中的项目都可以访问。或者,--private 选项将镜像标记为仅创建它的项目可以访问。默认情况下,所有创建的镜像都标记为 shared,并且可以与另一个项目共享。然而,在创建时,镜像只能由创建它的项目看到。--shared 和 --community 选项将在本章后续的 共享镜像 章节中讨论。
列出镜像
要列出 OpenStack 镜像服务库中的镜像,请使用以下 OpenStack 客户端命令:
openstack image list
输出将类似于以下内容:

查看镜像详情
可以使用以下 OpenStack 客户端命令查询单个镜像的详细信息:
openstack image show IMAGE_NAME_OR_ID
输出将类似于以下内容:

删除镜像
图像可以随时从 OpenStack 图像仓库中删除。但请记住,根据安装的 OpenStack 版本,删除图像可能会对迁移实例的能力产生不利影响。
注意
新版本的 OpenStack(Kilo 之后)不应受到此问题的影响。
准备工作
删除图像时,需要以下信息:
- 图像名称或 ID
如何操作……
要在 OpenStack 中删除图像,请执行以下命令:
openstack image delete COOKBOOK_CIRROS_IMAGE
如果操作成功,则不会返回任何输出。要验证图像是否已不再可用,可以使用openstack image list或openstack image show命令。
下载图像
存在于 OpenStack 图像仓库中的图像可以在以后下载并传输到其他系统。
准备工作
要从 OpenStack 图像仓库下载图像,您必须拥有访问该图像的权限。下载图像时,至少需要以下详细信息:
-
图像名称或 ID
-
下载文件的目标位置
对于我们的示例,将使用以下内容:
-
图像名称:
COOKBOOK_UBUNTU_IMAGE -
下载位置:
/tmp/my_downloaded_ubuntu_image.qcow2
如何操作……
在我们的系统上安装了 OpenStack 客户端后,我们现在可以使用以下命令从仓库中下载图像:
openstack image save COOKBOOK_UBUNTU_IMAGE \
--file /tmp/my_downloaded_ubuntu_image.qcow2
如果操作成功,则不会返回任何输出。使用ls命令列出已下载的文件:

分享图像
当图像为私有时,仅对创建或上传该图像的项目可用。另一方面,当图像为公共时,它对所有项目可用。OpenStack 图像服务提供了一种机制,允许这些私有图像在一部分项目之间共享。这使得在不向所有项目公开的情况下,更好地控制需要存在于不同项目中的图像。
在项目之间共享图像需要以下工作流程:
-
租户 A 更新图像的共享能力
-
租户 A 与租户 B 分享图像
-
租户 B 接受或拒绝共享请求
准备工作
共享图像时,请确保您已通过身份验证为管理员,或是该图像的所有者。共享图像至少需要以下详细信息:
-
图像名称或 ID
-
项目名称或 ID
对于我们的示例,ADMIN 项目将与 FINANCE 项目共享图像。将使用以下内容:
-
图像名称:
COOKBOOK_UBUNTU_IMAGE -
项目名称:
FINANCE
注意
有关如何在 OpenStack 中创建项目的说明,请参见本书的第三章,Keystone – OpenStack 身份服务。
如何操作……
在我们的系统上安装了 OpenStack 客户端后,我们现在可以通过以下步骤共享图像:
-
使用
FINANCE项目中用户的凭证配置环境:source finance_openrc -
作为
FINANCE项目中的用户,查看所有可用的图片:openstack image list如果没有可用的图片,输出将类似于以下内容:
![如何操作...]()
注意
在此环境中,
FINANCE项目没有可用的图片。 -
现在,使用 ADMIN 项目中用户的凭证配置环境:
source openrc -
更新 Ubuntu 镜像并使其可共享:
openstack image set COOKBOOK_UBUNTU_IMAGE --shared不会返回任何输出。
-
与 FINANCE 项目共享 Ubuntu 镜像:
openstack image add project COOKBOOK_UBUNTU_IMAGE FINANCE输出将类似于以下内容:
![如何操作...]()
注意
此时,用户应通知
FINANCE项目共享尝试并提供图片 ID。在此示例中,图片 ID 为d120a923-5246-4dca-8f52-51a951bffce5。 -
使用
FINANCE项目中用户的凭证重新配置环境:source finance_openrc -
接受共享尝试:
openstack image set d120a923-5246-4dca-8f52-51a951bffce5 --accept不会返回任何输出。
-
查看所有可用的图片:
openstack image list输出将类似于以下内容:
![如何操作...]()
它是如何工作的...
共享图片需要生产者使用openstack image add project命令,消费者使用openstack image set命令。此过程涉及生产者与消费者之间的沟通,超出了 OpenStack API,因为图片 ID 必须在它们之间共享。
生产者使用以下命令启动共享过程:
openstack image add project <image> <project>
一旦共享,消费者可以使用以下方式接受或拒绝该尝试:
openstack image set <image> [--accept | --reject | --pending]
注意
将图片标记为pending使该图片在消费项目中不可用,但仍然保留稍后使其可用的可能性。
生产者可以使用以下命令撤销图片的共享:
openstack image remove project <image> <project>
标记图片为共享的替代方法是将其可见性标记为community,使用--community选项。这允许用户将图片共享给所有项目,但仍然需要消费项目在图片出现在图片列表之前接受该图片。这减少了共享图片用户的管理负担,同时不会无谓地使所有项目的图片列表变得凌乱。
有关共享图片的更多信息,请访问docs.openstack.org/image-guide/share-images.html。
使用图片快照
在 OpenStack 中,快照是反映实例在某个时间点状态的图片。快照通常用于备份实例或将实例从一个云迁移到另一个云,并且可以像普通图片一样与其他项目共享。
创建快照
可以使用openstack server image create命令在 OpenStack 中创建快照。
准备就绪
创建快照时,请确保您已作为管理员进行身份验证或是实例的所有者。您将需要以下详细信息:
-
实例名称或 ID
-
图片名称
对于我们的示例,将使用以下内容:
-
实例名称:
COOKBOOK_TEST_INSTANCE -
图片:
COOKBOOK_TEST_SNAPSHOT_20170824
如何操作…
安装 OpenStack 客户端后,我们现在可以使用以下命令创建快照:
openstack server image create \
--name COOKBOOK_TEST_SNAPSHOT_20171016 \
COOKBOOK_TEST_INSTANCE
输出结果将类似于以下内容:

它是如何工作的…
图片快照使用以下语法创建:
openstack server image create [--name <image-name>] \
[--wait] \
<server>
快照的创建会导致系统将实例的磁盘写入计算节点上的临时文件,并将其上传到 OpenStack 镜像服务作为新的图片。当实例的磁盘位于 Ceph 后端时,快照发生在后端本身,计算节点文件系统不参与其中。生成的快照/图片随后可以用于在同一云中启动新的实例,或者可以下载并复制到离线存储系统或其他云中。
name参数定义了图片存储在镜像库中的名称。
<server>参数定义了从中拍摄快照的实例的名称或 ID。
如果指定了--wait选项,它会强制 OpenStack 在前台执行快照操作,这意味着在任务完成之前,CLI 将无法使用。
使用图片元数据
图片具有被称为元数据的属性,这些属性有助于描述图片及其与其他 OpenStack 组件的关系。应用于图片的元数据可以用于启用其他 OpenStack 服务中的特定功能,或根据 CPU 架构或特性等确定将实例调度到主机的方式,等等。
设置图片元数据
OpenStack 中的图片元数据可以通过openstack image set命令进行操作。--property参数可以用来通过key=value对设置其他属性。
准备工作
在设置图片元数据时,请确保您已认证为管理员或是该图片的所有者。至少需要以下信息:
-
图片名称或 ID
-
属性名称和值
在我们的示例中,将使用以下内容:
-
图片名称:
COOKBOOK_UBUNTU_IMAGE -
属性名称和值:
architecture=m68k, os_distro=ubuntu
如何操作…
安装 OpenStack 客户端后,我们现在可以使用以下命令设置图片元数据:
openstack image set COOKBOOK_UBUNTU_IMAGE \
--property architecture=m68k \
--property os_distro=ubuntu
如果操作成功,则不会返回任何输出。然而,使用openstack image show将显示属性已被设置:

它是如何工作的...
在 OpenStack 中设置图片元数据时,属性会影响系统如何处理使用该图片的实例。属性如hypervisor_type和architecture影响实例如何调度到主机,而其他属性如hw_disk_bus和hw_cdrom_bus则影响虚拟设备如何连接到实例。
注意
要根据镜像元数据调度实例,请确保在/etc/nova/nova.conf中的enabled_filters列表中包含'ImagePropertiesFilter'过滤器。这是大多数 OpenStack 安装的默认设置,包括本书中构建的环境。
在这种环境中,使用要求架构为m68k(Motorola 68000)的修改后镜像引导实例应导致以下错误:
NoValidHost: No valid host was found. There are not enough hosts available.
修改镜像以要求x86_64或完全删除该属性应允许根据其他定义的元数据或环境默认值来安排实例的调度。
在撰写本文时,可以在以下位置找到当前的镜像元数据属性列表:
docs.openstack.org/python-glanceclient/latest/cli/property-keys.html
删除图像元数据
在 OpenStack 中,可以使用openstack image unset命令来删除图像元数据。--property参数可用于取消单个属性的设置。
准备工作
在删除图像元数据时,请确保您已经作为管理员进行了身份验证,或者是镜像的所有者。至少需要以下详细信息:
-
镜像名称或 ID
-
属性名称
对于我们的示例,将使用以下内容:
-
镜像名称:
COOKBOOK_UBUNTU_IMAGE -
属性名称:
architecture
如何操作…
在我们的系统上安装了 OpenStack 客户端后,现在可以使用以下命令取消设置图像元数据:
openstack image unset COOKBOOK_UBUNTU_IMAGE \
--property architecture
如果操作成功,则不返回任何输出。要验证已删除属性,请使用openstack image show命令。
保护图像
与其他 OpenStack 对象类似,图像和快照容易被用户意外删除。默认情况下,图像是不受保护的,这意味着可以随时由项目中的用户删除。以下各节将解释如何保护图像以确保其存活。
保护图像
可以使用openstack image set命令并带有--protected参数来保护图像。
准备工作
在保护镜像时,请确保您已经作为管理员进行了身份验证,或者是镜像的所有者。至少需要以下详细信息:
- 镜像名称或 ID
对于我们的示例,将使用以下内容:
- 镜像名称:
COOKBOOK_UBUNTU_IMAGE
如何操作…
在我们的系统上安装了 OpenStack 客户端后,现在可以使用以下命令保护图像:
openstack image set COOKBOOK_UBUNTU_IMAGE --protected
如果操作成功,则不返回任何输出。使用openstack image show命令来查看镜像的状态:

工作原理…
当在 OpenStack 中保护图像时,用户无法删除该图像。尝试删除受保护的图像将导致类似以下的错误:
Failed to delete image with name or ID 'COOKBOOK_UBUNTU_IMAGE': 403 Forbidden: Image d120a923-5246-4dca-8f52-51a951bffce5 is protected and cannot be deleted. (HTTP 403)
Failed to delete 1 of 1 images.
保护图像是确保由许多用户和项目共享的云中快照和其他特殊图像保持完好的有用步骤。
解除图像保护
可以使用 openstack image set 命令与 --unprotected 参数解除镜像的保护。
准备工作
当解除保护镜像时,确保你已认证为管理员或是镜像的所有者。你至少需要以下信息:
- 镜像名称或 ID
在我们的示例中,将使用以下内容:
- 镜像名称:
COOKBOOK_UBUNTU_IMAGE
如何操作…
在我们的系统上安装了 OpenStack 客户端后,我们现在可以使用以下命令解除镜像保护:
openstack image set COOKBOOK_UBUNTU_IMAGE --unprotected
如果操作成功,将不返回任何输出。使用 openstack image show 命令查看镜像的状态。
停用镜像
默认情况下,镜像在上传过程完成后即可使用。有时,可能需要停用镜像,以防止用户使用该镜像启动实例,尤其是当镜像可能过时但必须保留用于归档时。
停用镜像
可以使用 openstack image set 命令与 --deactivate 参数停用镜像。
准备工作
停用镜像时,确保你已认证为管理员或是镜像的所有者。你至少需要以下信息:
- 镜像名称或 ID
在我们的示例中,将使用以下内容:
- 镜像名称:
COOKBOOK_UBUNTU_IMAGE
如何操作…
在我们的系统上安装了 OpenStack 客户端后,我们现在可以使用以下命令停用镜像:
openstack image set COOKBOOK_UBUNTU_IMAGE --deactivate
如果操作成功,将不返回任何输出。使用 openstack image show 命令查看镜像的状态:

工作原理...
当镜像在 OpenStack 中被停用时,用户无法使用该镜像启动实例。尝试使用停用镜像启动实例时,将出现类似以下的错误:
Image d120a923-5246-4dca-8f52-51a951bffce5 is not active. (HTTP 400) (Request-ID: req-fb43f34c-982b-4eeb-abb1-76c93ebc2b5f)
停用镜像是确保镜像被保留但无法使用的一个有用步骤。现有的使用该镜像的实例不会受到影响。
激活镜像
停用的镜像可以通过 openstack image set 命令与 --activate 参数重新激活。
准备工作
激活镜像时,确保你已认证为管理员或是镜像的所有者。你至少需要以下信息:
- 镜像名称或 ID
在我们的示例中,将使用以下内容:
- 镜像名称:
COOKBOOK_UBUNTU_IMAGE
如何操作…
在我们的系统上安装了 OpenStack 客户端后,我们现在可以使用以下命令激活镜像:
openstack image set COOKBOOK_UBUNTU_IMAGE --activate
如果操作成功,将不返回任何输出。使用 openstack image show 命令查看镜像的状态。
创建自定义镜像
用户可以创建各种操作系统的自定义镜像,这些镜像可以在 OpenStack 环境中使用。诸如 cloud-init 之类的工具可以安装在镜像中,以提供一种在实例部署后进行引导的方法。
注意
cloud-init的使用超出了本书的范围。更多信息请参见cloud-init.io。
准备就绪
首先,确保你使用的操作系统不是本书中所用的 OpenStack 环境。创建镜像所需的软件包和库可能与当前已安装的软件发生冲突,导致环境损坏。在本示例中,我们将使用配置为 Ubuntu 16.04 LTS 的虚拟机来创建自定义的 CentOS 7 镜像。
注意
配置 Ubuntu 16.04 LTS 操作系统的虚拟机超出了本书的范围。如果需要,也可以使用物理服务器代替虚拟机。
以下软件包是构建镜像所需的主机前置条件:
-
qemu-kvm -
libvirt-bin -
virt-manager
使用apt,通过以下命令安装软件包:
sudo apt update
sudo apt install qemu-kvm libvirt-bin virt-manager
如何操作…
在虚拟机内执行以下步骤以创建自定义镜像:
-
切换到你的主目录,并创建一个名为
ks.cfg的 kickstart 文件,内容如下:cd ~/ install text url --url http://mirror.rackspace.com/CentOS/7/os/x86_64/ lang en_US.UTF-8 keyboard us network --onboot yes --bootproto dhcp --noipv6 timezone --utc America/Chicago zerombr clearpart --all --initlabel bootloader --location=mbr --append="crashkernel=auto" part / --fstype=ext4 --size=1024 --grow authconfig --enableshadow --passalgo=sha512 rootpw openstack firewall --disable selinux --disabled skipx shutdown %packages @core openssh-server openssh-clients wget curl git man vim ntp %end %post %end -
创建一个空的 10GB 虚拟磁盘供 CentOS 虚拟机使用:
sudo qemu-img create -f qcow2 \ /var/lib/libvirt/images/centos-7.qcow2 10G -
执行以下命令以启动 CentOS 操作系统的无人值守安装:
sudo virt-install --virt-type qemu \ --name centos-7 \ --ram 2048 \ --location="http://mirror.rackspace.com/CentOS/7/os/x86_64/" \ --disk /var/lib/libvirt/images/centos-7.qcow2,format=qcow2 \ --network network=default \ --graphics vnc,listen=0.0.0.0 \ --noautoconsole \ --os-type=linux \ --os-variant=centos7.0 \ --initrd-inject ks.cfg \ --rng /dev/random \ --extra-args="inst.ks=file:/ks.cfg console=ttyS0,115200"注意
如果安装是在启用嵌套虚拟化的虚拟机内进行的,可能需要将
virt-type从kvm更改为qemu,以便虚拟机正确启动。如果没有嵌套虚拟化,使用kvm能获得更好的性能。返回的输出应类似于以下内容:
Starting install... Retrieving file vmlinuz... | 5.1 MB 00:00:01 Retrieving file initrd.img... | 41 MB 00:00:07 Allocating 'centos-7.0-vm.img' | 5.0 GB 00:00:00 Creating domain... | 0 B 00:00:00 Domain installation still in progress. You can reconnect to the console to complete the installation process.从主机登录到新创建的 CentOS 虚拟机,并使用
openstack密码作为root用户登录。要退出控制台会话,请按Ctrl + ]:virsh console centos-7要刷新控制台,请按Enter键。输出将类似于以下内容:
![如何操作…]()
客户机应正在启动,并且将显示实时控制台日志。安装过程是自动化的,可能会根据主机提供的资源而需要一段时间。
安装完成时,输出将类似于以下内容:
[ OK ] Reached target Shutdown. dracut Warning: Killing all remaining processes Powering off. [ 3388.611074] Power down.控制台会话应结束,你将返回到主机的提示符。
-
使用以下命令启动虚拟机:
sudo virsh start centos-7从主机登录到 CentOS 虚拟机,并使用
openstack密码作为root用户登录。要退出控制台会话,请按Ctrl + ]:virsh console centos-7要刷新控制台,请按Enter键。输出将类似于以下内容:
Connected to domain centos-7 Escape character is ^] CentOS Linux 7 (Core) Kernel 3.10.0-693.el7.x86_64 on an x86_64 localhost login: root Password: Last login: Wed Aug 30 09:02:14 on tty1 [root@localhost ~]# -
在来宾中,通过以下命令安装
epel-release和cloud-init软件包:yum -y install epel-release yum -y install cloud-init cloud-utils cloud-utils-growpart -
使用文本编辑器,将来宾的
cloud.cfg文件(位于/etc/cloud/cloud.cfg)替换为以下内容:users: - default disable_root: 1 ssh_pwauth: 0 locale_configfile: /etc/sysconfig/i18n mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2'] resize_rootfs_tmp: /dev ssh_deletekeys: 0 ssh_genkeytypes: ~ syslog_fix_perms: ~ cloud_init_modules: - bootcmd - write-files - resizefs - set_hostname - update_hostname - update_etc_hosts - rsyslog - users-groups - ssh cloud_config_modules: - mounts - locale - set-passwords - timezone - puppet - chef - salt-minion - mcollective - disable-ec2-metadata - runcmd cloud_final_modules: - rightscale_userdata - scripts-per-once - scripts-per-boot - scripts-per-instance - scripts-user - ssh-authkey-fingerprints - keys-to-console - phone-home - final-message system_info: distro: rhel default_user: name: centos lock_passwd: True shell: /bin/bash sudo: ["ALL=(ALL) NOPASSWD: ALL"] paths: cloud_dir: /var/lib/cloud templates_dir: /etc/cloud/templates ssh_svcname: sshd注意
cloud.cfg的内容是以 YAML 格式构建的,在启动时由cloud-init进行解析。在这个示例中,访问实例的默认用户名是centos,并且没有设置密码。相反,必须使用 SSH 密钥,并将其通过 OpenStack 元数据服务推送到实例。更多信息请参见 第五章, Nova – OpenStack 计算。 -
确保虚拟机能够通过以下命令与元数据服务进行通信:
echo "NOZEROCONF=yes" >> /etc/sysconfig/network -
使用以下命令删除持久化规则:
rm -rf /etc/udev/rules.d/70-persistent-net.rules -
删除特定机器的 MAC 地址和 UUID。编辑
/etc/sysconfig/network-scripts/ifcfg-eth0文件并删除以HWADDR和UUID开头的行:sed -i '/HWADDR/d' /etc/sysconfig/network-scripts/ifcfg-eth0 sed -i '/UUID/d' /etc/sysconfig/network-scripts/ifcfg-eth0 -
做出更改后,确保接口配置文件类似于以下内容:
NAME="eth0" ONBOOT="yes" NETBOOT="yes" IPV6INIT="no" BOOTPROTO="dhcp" TYPE="Ethernet" DEFROUTE="yes" PEERDNS="yes" PEERROUTES="yes" IPV4_FAILURE_FATAL="no"注意
如果您需要支持 IPv6,请相应地修改接口文件,确保使用该镜像的实例能够通过 DHCPv6 或 SLAAC 获取其 IPv6 地址。
-
使用以下命令清理各种文件和目录:
yum clean all rm -rf /var/log/* rm -rf /tmp/* history -c -
在虚拟机内部,使用以下命令干净地关闭虚拟机:
shutdown -h now一旦虚拟机关闭,控制台会话应该结束,您将返回到主机上的提示符。在主机上将位于
/var/lib/libvirt/images/centos-7.qcow2的磁盘文件传输到您的主目录,在那里它可以被传输出主机并转移到安装了 OpenStack 命令行工具的客户端。使用 OpenStack 客户端,将镜像上传到 OpenStack 镜像库:openstack image create MY_CENTOS_IMAGE \ --disk-format qcow2 \ --file ~/centos-7.qcow2输出应类似于以下内容:
![如何操作…]()
欲了解有关构建自定义镜像的更多信息,请访问
docs.openstack.org/image-guide/create-images-manually.html。
第七章:Cinder – OpenStack 块存储
在本章中,我们将涵盖以下主题:
-
配置 Cinder 卷服务
-
创建卷
-
将卷附加到实例
-
从实例中分离卷
-
删除卷
-
使用卷快照
-
配置卷类型
-
启用卷加密
-
配置卷的服务质量(QoS)
-
重置卷状态
介绍
当一个基础计算实例被启动时,该实例的数据会存储在计算主机的磁盘上,直到实例运行结束,写入的数据在实例终止后并不持久——这意味着用户请求销毁该实例时,保存在磁盘上的任何数据都会丢失。OpenStack 提供了解决方案。卷是持久存储,可以附加到你正在运行的 OpenStack 计算实例上;最好的类比是你可以将 USB 驱动器连接到实例。像 USB 驱动器一样,你一次只能将实例附加到一台计算机上。
提示
目前有一个实验性功能,可以将一个卷附加到多个实例。我们在此不予涉及,也不建议目前使用该功能。
OpenStack 块存储项目的代号 Cinder 提供了接口和自动化功能,允许将存储卷连接到 OpenStack 计算实例。OpenStack 块存储与 Amazon 弹性块存储 (EBS) 非常相似——主要区别在于如何将卷呈现给正在运行的实例。在 OpenStack 计算中,一种方法是专门为此目的分配一台服务器,使得可以通过 iSCSI 暴露 LVM 卷组,特别命名为 cinder-volumes。然后通过一个名为 cinder-volume 的 OpenStack 服务,通过 iSCSI 将其呈现给实例。OpenStack 用户通过 Cinder API 与此服务交互。在我们的环境中,Cinder API 服务运行在三个控制节点上,通常这些服务会暴露在负载均衡器后面。本章中的配方使用了这种方法,通过 LVM 和 iSCSI 提供 Cinder 卷。然而,Cinder 支持由商业供应商和开源软件 (OSS) 社区提供的各种第三方存储提供商——例如,Cinder 的一个非常流行的后端提供商(而不是单独一台服务器运行 cinder-volume 服务)是 Ceph。
提示
在本章中,“OpenStack 块存储”和“Cinder”这两个术语将交替使用。
配置 Cinder 卷服务
在本配方中,我们将使用 Openstack-Ansible 部署 Cinder 服务。我们假设你的环境已经按照第一章,使用 Ansible 安装 OpenStack中描述的配方进行部署。
准备工作
要使用 LVM 和 iSCSI 的 Cinder 卷,您需要一台(或多台)运行 Ubuntu 16.04 的主机。此外,您还需要确保卷主机可以由您的 Openstack-Ansible 部署主机进行管理。
以下是所需的:
-
一个具有适当凭据的
openrc文件 -
访问
openstack-ansible部署主机 -
一个专用服务器,用于向实例提供 Cinder 卷:
-
一个名为
cinder-volumes的 LVM 卷组 -
一个从部署主机可以访问的 IP 地址
-
如果您使用的是本书附带的实验环境,cinder-volume已部署到具有以下详细信息的主机:
-
cinder-volumeAPI 服务主机 IP:172.29.236.10 -
cinder-volume服务主机 IP:OpenStack 管理调用通过172.29.236.100,存储流量通过172.29.244.100
如何做...
要部署cinder-volume服务,首先我们将创建一个 YAML 文件来描述如何部署 Cinder。然后我们将使用openstack-ansible来部署适当的服务。
要配置运行cinder-volume服务的 Cinder LVM 主机,请在部署主机上执行以下步骤:
-
首先,编辑
/etc/openstack_deploy/openstack_user_config.yml文件,添加以下行,注意我们同时使用了 API 和存储网络的地址:--- storage-infra_hosts: controller-01: ip: 172.29.236.10 storage_hosts: cinder-volume: ip: 172.29.236.100 container_vars: cinder_backends: limit_container_types: cinder_volume lvm: volume_group: cinder-volumes volume_driver: cinder.volume.drivers.lvm.LVMVolumeDriver volume_backend_name: LVM_iSCSI iscsi_ip_address: "172.29.244.100"提示
可以向
storage-infra_hosts部分添加更多节点以匹配您的环境。请注意,我们引用了来自容器网络(172.29.236)的storage_hosts和storage-infra_hostsIP,并且我们将在存储网络(172.29.244)上将实际的 iSCSI 卷呈现给实例。 -
现在编辑
/etc/openstack_deploy/user_variables.yml文件,添加以下行。此处显示的是 OpenStack-Ansible 部署的默认值;如有必要,请根据您的环境进行编辑:## Cinder iscsi cinder_iscsi_helper: tgtadm cinder_iscsi_iotype: fileio cinder_iscsi_num_targets: 100 cinder_iscsi_port: 3260 -
使用 LVM 时,如我们所做的那样,我们必须告诉 OpenStack-Ansible不要将服务部署到容器中(通过设置
is_metal: true)。确保/etc/openstack_deploy/env.d/cinder.yml文件包含以下内容:--- container_skel: cinder_volumes_container: properties: is_metal: true -
由于我们在本示例中专门选择使用
LVMVolumeDriver服务安装 Cinder,因此我们必须确保设置为运行cinder-volume服务的主机(或主机)在部署 Cinder 之前已创建了一个名为cinder-volumes的卷组。执行以下步骤以创建此重要的卷组。以下示例假设有一个额外的磁盘,在/dev/sdb,我们将用作此目的:pvcreate /dev/sdb vgcreate cinder-volumes /dev/sdb这将返回如下所示的输出:
Physical volume "/dev/sdb1" successfully created Volume group "cinder-volumes" successfully created提示
提示:创建
cinder-volumes逻辑卷组(VG)仅在我们选择volume_driver类型为cinder.volume.drivers.lvm.LVMVolumeDriver时才需要创建。Cinder 还提供其他后端,这些后端不需要执行此步骤。 -
我们现在可以使用
openstack-ansible命令部署 Cinder 服务:cd /opt/openstack-ansible/playbooks openstack-ansible os-cinder-install.yml请注意,Ansible 的输出在此已被省略。如果成功,Ansible 会报告安装成功,或者向您提供有关失败步骤的信息。
提示
您是否使用了多个
storage-infra_hosts?这些是 Cinder API 服务器。由于这些服务器位于负载均衡器后面,请确保您已将负载均衡器的 VIP 更新为这些新节点的 IP 地址。Cinder 服务运行在端口8776。如果您使用的是通过 OpenStack-Ansible 安装的 HAProxy,您还必须运行以下命令:openstack-ansible haproxy-install.yml -
通过以下检查从 OpenStack 客户端或控制节点上的任何一个实用容器中验证 Cinder 服务是否正在运行,如下所示:
lxc-attach --name $(lxc-ls -1 | grep util) source openrc cinder service-list这将返回如下的输出:
![如何操作...]()
它是如何工作的...
为了使用某个主机作为cinder-volume服务器,我们首先需要确保已创建名为cinder-volumes的逻辑卷组(LVM VG)。
提示
提示:您可以将卷组重命名为除cinder-volumes之外的其他名称;然而,重命名的理由非常少。如果确实需要这么做,请确保/etc/openstack_deploy/openstack_user_config.yml中的volume_group:参数与您创建的 LVM 卷组名称匹配。
完成此步骤后,我们将配置我们的 OpenStack-Ansible 部署,指定我们的cinder-volume服务器(如storage_hosts部分所示)以及运行 API 服务的服务器(如storage-infra_hosts部分所示)。然后,我们将使用openstack-ansible将软件包部署到控制节点和我们指定的 Cinder 卷服务器上。
请注意,如果您使用多个网络或 VLAN 段,请相应地配置您的 OpenStack-Ansible 部署。本书中介绍的存储网络应当用于 iSCSI 流量(也就是说,当一个卷附加到一个实例时),并且它与专用于 API 流量和服务间流量的容器网络是分开的。
在我们的示例中,cinder-volume使用 iSCSI 作为将卷附加到实例的机制;然后,openstack-ansible会安装运行 iSCSI 目标所需的软件包。
OpenStack-Ansible 提供了部署任何支持 Cinder 所需的更改的额外好处。这包括在 Keystone 中创建该服务并配置 Nova 以支持卷后端。
创建卷
现在我们已经创建了 Cinder 卷服务,我们可以为我们的实例创建卷。我们将在客户端环境中使用 Python-OpenStack 客户端和python-cinderclient库来执行此操作;因此,我们正在为我们的项目(租户)创建特定的卷。
提示
请参考第二章,OpenStack 客户端,了解更多关于安装和配置 OpenStack 客户端的信息。
准备工作
创建卷需要以下内容:
-
openstack命令行客户端 -
一个包含适当凭证的
openrc文件,适用于当前环境 -
期望的卷名称
-
期望的卷大小,以 GiB 为单位
对于我们的示例,以下是这些信息:
-
卷名称:
cookbook.volume -
大小:10 GiB
如何操作...
执行以下步骤以创建卷:
我们只需使用以下命令创建卷,然后将其附加到我们的实例:
openstack volume create
--size 10
--description "Cookbook Volume"
cookbook.volume
完成后,命令会返回以下输出:

它是如何工作的...
创建卷非常简单。使用 openstack 客户端,我们提供 volume 上下文和 create 操作,语法如下:
openstack volume create
--size size_GiB
--description "meaningful description"
volume_name
在这里,volume_name 可以是任何不包含空格的任意名称。
由于我们使用的服务器运行 cinder-volume 服务,我们可以使用常规的 LVM 工具查看 cinder-volumes 上的实际 LVM 卷,如下所示(确保你以 root 用户身份登录到我们指定的存储主机服务器):
lvdisplay cinder-volumes
--- Logical volume ---
LV Path /dev/cinder-volumes/volume-bb7a7d2c-8069-4924-a18e-8fb398584a5d
LV Name volume-bb7a7d2c-8069-4924-a18e-8fb398584a5d
VG Name cinder-volumes
LV UUID XqZY27-Ei32-EEdC-3UtE-MR6e-2EKw-XCvIGt
LV Write Access read/write
LV Creation host, time cinder-volume, 2017-09-22 20:25:17 +0000
LV Status available
# open 0
LV Size 10.00 GiB
Current LE 2560
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device
252:2
还有更多...
默认情况下,Cinder 卷像物理磁盘一样工作,即它们一次只能附加到一个实例。然而,对于需要磁盘在多个实例之间共享的工作负载,您可以在创建卷时传递 --multi-attach 标志,使得该卷可以附加到多个实例:
openstack volume create
--multi-attach
--description "description"
--size size_GiB
volume_name
提示
提醒
该功能相当新,并被视为生产环境中的实验性功能,它并不替代像 NFS 这样的共享存储服务。NFS 支持锁定,允许多个客户端读取和写入同一个挂载点。而多重附加块存储不支持锁定。因此,一个有效的使用场景可能是一个主/从服务的场景,其中数据应仅由一个实例在同一时间写入,但在故障转移时能立即访问数据是有益的。
将卷附加到实例
现在我们有了一个可用的磁盘卷,可以将其附加到任何实例。我们将使用 openstack server volume add 命令来执行此操作。
准备就绪
要将卷附加到实例,您将需要以下内容:
-
openstack命令行客户端 -
一个包含适当凭证的
openrc文件,适用于当前环境 -
要附加的卷的 名称 或 ID
-
要附加卷的实例的 名称 或 ID
对于我们的示例,这些值如下:
-
卷:
cookbook.volume -
实例:
cookbook.test
如何操作...
执行以下步骤,将卷附加到实例上,使用 openstack 客户端:
-
首先,列出正在运行的实例,以获取我们实例的 ID:
openstack server list -c Name -c ID -f table下面是一个示例,展示了我们正在运行的实例
cookbook.test:![如何操作...]()
-
现在列出可用卷,以获取我们卷的 ID:
openstack volume list这展示了我们需要的卷信息:
![如何操作...]()
-
使用实例和卷的名称或 ID,我们将按照以下方式将卷附加到实例:
openstack server add volume cookbook.test cookbook.volume --device /dev/vdc当命令成功执行时,不会输出任何内容。
请注意,
--device选项并非始终有效,具体取决于操作系统和镜像类型。执行任何操作之前,始终检查目标实例操作系统为新卷分配了哪个设备。提示
提示:在 OpenStack 中,卷或服务器名称不需要唯一;如果卷和服务器名称不唯一,请使用分配的 ID 代替名称。在前面的示例中,这样也能实现相同的目标:
openstack server add volume 90654098-477f-417f-b102-453c0f1f9119 daeddd6c-908a-4ea8-8632-d93d198c2621 --device /dev/vdb -
现在我们将在运行中的实例内执行操作。登录到实例并验证卷是否已附加:
lsblk这将列出可供我们实例使用的块设备。在这里,我们可以看到我们的卷作为
/dev/vdb已附加,但尚未挂载:NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sr0 11:0 1 558K 0 rom vda 253:0 0 2.2G 0 disk `-vda1 253:1 0 2.2G 0 part / vdb 253:16 0 10G 0 disk -
我们应该看到
10G的空间可供运行中的实例使用。由于这是一个新的卷,就像为系统添加一个全新的磁盘。我们需要先格式化它以供使用,然后将其挂载到文件系统中:sudo mkfs.ext4 /dev/vdb sudo mkdir /mnt1 sudo mount /dev/vdb /mnt1提示
提示:使用 Cinder 创建的卷是持久存储卷;格式化卷(磁盘)只需要执行一次。如果将来需要将此数据卷重新附加到另一个实例,请不要重新格式化该磁盘!
-
我们现在应该看到新附加的磁盘可用在
/mnt1:df -h这将显示类似以下的输出:
Filesystem Size Used Avail Use% Mounted on udev 238M 0 238M 0% /dev tmpfs 49M 1.8M 48M 4% /run /dev/vda1 2.1G 843M 1.3G 41% / tmpfs 245M 0 245M 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 245M 0 245M 0% /sys/fs/cgroup tmpfs 49M 0 49M 0% /run/user/1000 /dev/vdb 9.8G 23M 9.2G 1% /mnt1
它是如何工作的...
附加一个新的 Cinder 卷就像将一个未格式化的 USB 闪存盘插入计算机。当它第一次需要使用时,必须先格式化才能使用。
提示
在后续使用此磁盘(将来连接到其他实例时),您无需执行此格式化步骤。
在openstack客户端中,server add volume选项的语法如下:
openstack server add volume
instance_ID
volume_ID
--device /dev/device_ID
instance_ID 是通过openstack server list返回的,我们希望将卷附加到的实例 ID。
volume_ID 是通过openstack volume list返回的卷 ID。
device_ID 是在实例上创建的设备,用于挂载卷。请记住,这个参数有时可以忽略;因此,可以将其视为仅供传递给正在运行的实例的提示。
从实例中卸载卷
通常,Cinder 卷一次只能附加到一个实例。因此,您需要先从一个实例卸载卷,再将其附加到另一个实例。要卸载卷,我们将使用另一个 OpenStack 客户端命令,叫做openstack server remove volume。
准备工作
要从实例中卸载卷,您需要以下内容:
-
openstack命令行客户端 -
带有适当凭据的
openrc文件 -
要卸载的卷的名称或 ID
-
要从实例中卸载卷,需要指定实例的名称或 ID
对于我们的示例,值如下:
-
卷:
cookbook.volume -
实例:
cookbook.test -
挂载点:
/mnt1
如何操作...
执行以下步骤以使用 openstack 客户端将卷从实例中分离:
-
列出正在运行的实例,以获取我们实例的 ID:
![如何操作...]()
-
列出我们环境中可用的和
in-use的卷:openstack volume list这将返回类似以下的输出。请注意,提供的信息显示了卷是否正在使用以及它附加到哪个实例:
![如何操作...]()
-
现在我们需要在运行中的实例内部执行操作。连接到此实例并验证该卷是否已挂载:
df -h这将显示类似以下的输出:
Filesystem Size Used Avail Use% Mounted on udev 238M 0 238M 0% /dev tmpfs 49M 1.8M 48M 4% /run /dev/vda1 2.1G 843M 1.3G 41% / tmpfs 245M 0 245M 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 245M 0 245M 0% /sys/fs/cgroup tmpfs 49M 0 49M 0% /run/user/1000 /dev/vdb 9.8G 23M 9.2G 1% /mnt1 -
现在卸载
/mnt1卷:sudo umount /mnt1(通过再次运行
df -h来验证是否已卸载)。 -
退出访客系统后,在 OpenStack 客户端中,使用以下命令将卷从实例中分离:
openstack server remove volume cookbook.test c ookbook.volume -
此命令在成功时不会产生任何输出,因此请再次查看卷列表以验证该卷已从
cookbook.test实例中分离:openstack volume list这表明该卷可用且未附加到任何实例:
![如何操作...]()
它是如何工作的…
从实例中分离 Cinder 卷的步骤类似于从计算机中拔出 USB 硬盘的步骤。首先,我们需要将其从实例中卸载,以便操作系统不会因存储的意外移除而报错。接下来,在openstack客户端中,server remove volume选项使用以下语法:
openstack server remove volume instance_name_or_id volume_name_or_id
删除卷
在某个时刻,您将不再需要您已创建的卷。为了永久将它们从系统中删除,使它们不再可用,我们只需从 OpenStack 客户端中调用另一个工具——volume delete选项。
准备工作
删除一个卷,您需要以下内容:
-
openstack命令行客户端 -
一个包含适当凭据的
openrc文件,用于该环境 -
要删除的卷的名称或 ID
对于我们的示例,以下是这些值:
- 卷:
cookbook.volume
提示
警告:这将删除卷及其上存储的所有数据,请确保这是您希望执行的正确操作,然后再继续。
只能删除未附加到任何实例的卷。
它是如何工作的…
使用 OpenStack 客户端删除一个卷,请执行以下步骤:
-
首先,我们列出可用的卷,以便识别要删除的卷,使用以下命令:
openstack volume list这表明该卷可用且未附加到任何实例:
![如何操作…]()
-
我们现在将使用卷的名称或 ID 删除该卷,使用以下命令:
openstack volume delete cookbook.volume提示
此命令在成功时不会产生输出。
与附加和分离卷类似,可以使用 ID 或名称。最佳实践是使用 ID 以避免出现差异并删除错误的卷。
它是如何工作的…
实际删除卷的方式在很大程度上取决于 Cinder 卷驱动程序。在本章的 配置 Cinder 卷服务 配方中,我们使用了 cinder.volume.drivers.lvm.LVMVolumeDriver。在这种情况下,删除镜像会将 LVM 卷从我们的系统中移除。
还有更多…
OpenStack Cinder 卷可以拍摄快照,在这种情况下,openstack volume delete 命令会产生如下错误消息:
Invalid volume: Volume status must be available or error or error_restoring or error_extending or error_managing and must not be migrating, attached, belong to a group, have snapshots or be disassociated from snapshots after volume transfer. (HTTP 400) (Request-ID: req-2b82e7fc-0cb4-403f-8dd8-35d99a0f6c6c)
要删除一个卷及其所有快照,请在 openstack volume delete 命令中传递 --purge 标志。
提示
小心操作。这是一个单向操作,并且 openstack volume delete 命令不会要求确认。此外,命令成功时不会产生任何输出。
使用卷快照
Cinder 卷 快照 提供了一种非破坏性地复制卷的方法;允许进行原位卷备份。它还启用了更高级的备份功能,并提供了从指定快照或某个时间点启动实例的能力。
在本节中,我们将展示如何创建快照、基于快照挂载卷、刷新快照以及删除指定的快照。
准备工作
使用 Cinder 卷快照时,你将需要以下内容:
-
openstack命令行客户端 -
一个带有适当凭据的
openrc文件,用于当前环境 -
要删除的 卷 的名称或 ID
如何操作…
要创建快照,卷必须首先从实例中分离:
-
首先,列出你当前的卷:
![如何操作…]()
提示
如果你希望拍摄快照的卷状态为
in-use,你需要使用本章前面 从实例中分离卷 的配方中的说明将其分离。 -
由于我们的卷处于正确的
available状态,我们将继续使用openstack volume snapshot create命令创建卷的快照:openstack volume snapshot create --volume cookbook.volume cookbook.snapshot这将产生类似如下的输出,显示
creating状态:![如何操作…]()
-
快照完成后,你可以使用本章中的 将卷附加到实例 配方重新附加原始卷并继续操作。
-
如果你将快照作为持续测试/验证过程的一部分,或作为备份方案的一部分,你可能希望使用最新数据更新快照。为此,我们使用
cinder snapshot-reset-state,如果成功,命令不会产生任何输出:openstack volume snapshot list -c ID -c Name -c Status -f table cinder snapshot-reset-state cookbook.snapshot提示
请注意使用
cinder命令行工具,而不是openstack。 -
你不能直接使用快照;要将快照作为卷挂载到实例上,首先需要基于该快照创建一个新的卷。为此,执行以下操作:
openstack volume create --snapshot cookbook.snapshot newcookbook.volume这将产生如下输出。请注意所使用的
snapshot_id和我们未指定大小这一事实:![如何操作…]()
-
我们可以通过再次查看卷列表来确认基于快照创建的新的食谱卷现在可用:
openstack volume list –c Name –c ID –c Status –f table这将生成我们卷及其状态的列表:
![如何操作…]()
-
最后,你希望在某个时候删除快照。为此,请使用
openstack volume snapshot delete命令,如下所示:openstack volume snapshot delete cookbook.snapshot使用
openstack volume snapshot list确认剩余的可用快照列表。
它是如何工作的…
Cinder 卷快照提供了一种灵活的方式来克隆卷进行快照类型备份、附加到其他实例等。我们在这里使用的 cinder snapshot 命令,具体包括 openstack volume snapshot create、openstack volume snapshot list、cinder snapshot-reset-state 和 openstack volume snapshot delete,指示 cinder 与存储驱动程序一起执行特定的快照操作——创建、列出、更新和删除。快照的具体实现取决于底层驱动程序。
还要注意,你不能直接将快照与实例一起使用。你必须先根据选择的快照创建一个新卷。其语法如下:
openstack volume create
--snapshot snapshot_name_or_id
new_volume_name
配置卷类型
Cinder 中的卷类型是一个标签或标识符,在创建卷时选择。通常,卷类型对应卷的某些属性,例如 SSD、High IOPS 和 Encrypted。我们将使用这个与下一个配方一起定义我们 Cinder 服务的更多功能。
准备工作
要创建一个卷类型,你需要以下内容:
-
一个具有适当凭证的
openrc文件(你必须是管理员) -
openstack命令行客户端 -
要创建的卷类型名称。在我们的示例中,我们将创建
"High IOPS"卷类型,作为一个虚构的示例类型,指的是专用于高 IOPS 的块存储设备。
如何操作…
我们将使用 openstack volume type 命令来操作 Cinder 卷类型。要创建一个卷类型,请按照以下步骤操作:
-
首先,列出现有的卷类型:
openstack volume type list这将返回类似如下的输出。这里我们有安装 LVM 服务时设置的默认值:
![如何操作…]()
-
创建新的卷类型:
openstack volume type create --description "The High IOPS volume type is QOS applied to 500 IOPS" "High IOPS"这将返回类似如下的输出:
![如何操作…]()
-
通过显示卷类型列表,确认新卷类型是否可用:
openstack volume type list这现在将返回我们额外的卷类型:
![如何操作…]()
-
在创建卷时使用这个新类型,我们将使用
--type标志,如下所示:openstack volume create --size 10 --type "High IOPS" --description "High IOPS Volume" highiops.volume -
我们将在输出中验证类型:
![如何操作…]()
它是如何工作的…
openstack volume type create 命令只有一个必填参数,name。name 参数允许用户定义不同的卷类型或标识符。虽然通常基于存储的某些属性,如部门、存储后端或 QOS 水平,但由于这些只是标签,只要它们易于理解,名称可以是任意的。
此外,--description 标志可以用来提供有关卷类型的更多细节。--private 标志允许你限制公共访问。--project 标志允许选择性地与其他命名项目共享私有卷类型。
然后,我们将利用这些类型(通过进一步配置 Cinder 来指定与特定卷类型相关联的存储类型),通过在 volume create 命令中使用 --type 标志来实现:
openstack volume create
--size size_GiB
--description "meaningful description"
--type "Type"
volume_name
启用卷加密
Cinder 可以管理卷的 加密,并且加密对客户机是透明的。加密在 卷类型 级别启用。
准备工作
加密可以在创建新的卷类型时启用,也可以添加到没有卷正在使用的现有卷类型中。要启用卷加密,你将需要以下内容:
-
一个包含适当凭证的
openrc文件 -
openstack命令行客户端 -
卷类型 的名称
-
加密提供者 的名称
-
加密控制位置
-
加密密钥大小
-
加密算法
对于我们的示例,以下内容将是:
-
名称:
Cookbook Encrypted Volumes -
加密提供者:
nova.volume.encryptors.luks.LuksEncryptor -
加密控制位置:
front-end -
加密密钥大小:
256 -
加密算法:
aes-xts-plain64
注意
你选择的加密特定值将基于你所在环境中可用的内容。本书不讨论这些值的详细内容。
如何操作…
要启用卷加密作为新的卷类型,使用以下命令:
openstack volume type create
--description "LUKS Encrypted volumes"
--encryption-provider nova.volume.encryptors.luks.LuksEncryptor
--encryption-control-location front-end
--encryption-key-size 256
--encryption-cipher aes-xts-plain64
"Encrypted"
然后,我们将在创建卷时使用这个 "Encrypted" 卷类型,具体如下:
openstack volume create
--size 1
--type "Encrypted"
--description "An encrypted volume"
encrypted.volume
它是如何工作的…
卷通过卷类型进行配置,因此,额外的参数会传递给 openstack volume type create:
-
--encryption-provider标志告诉 Cinder 哪个提供者将执行加密。与存储后端类似,提供者有多种可选项。请参阅 OpenStack 文档获取当前的提供者列表。 -
--encryption-control-location参数告诉 Cinder 加密将在哪里处理。在我们的例子中,front-end表示 Nova 将处理加密。 -
接下来,
--encryption-key-size参数指定所用密钥的大小。为了避免影响实验性能,示例中选择了256。你选择的加密提供者和密码算法将提供具体的建议。 -
最后,
--encryption-cipher指定使用哪个加密算法。你可以使用cryptsetup benchmark来获取可用选项的列表,并了解它们的性能。
配置卷的服务质量 (QoS)
Cinder 提供的另一个功能是能够为卷定义和管理服务类别。与卷加密类似,Cinder 中的 服务质量 (QoS) 是通过卷类型进行配置的。默认情况下,你可以定义最小、最大和突发 IOPS 值。
准备工作
要配置卷的 QoS,您需要以下信息:
-
一个包含适当凭据的
openrc文件(您需要是管理员) -
openstack命令行客户端 -
卷类型的名称或 ID
-
QoS 策略的 消费者
-
以下值:
-
最小 IOPS
-
最大 IOPS
-
突发 IOPS
注意
要定义一个最小的 QoS 策略,只需提供三项中的一个(最小、最大和突发)。
-
对于我们的示例,值如下所示:
-
名称:
High IOPS -
消费者:
both -
最大 IOPS:
500
如何操作…
为了使 Cinder 卷使用 QoS,管理员需要执行两个步骤:首先定义规范,其次将规范与卷类型关联。
要创建并分配 QoS 规范,请使用以下步骤:
-
首先,列出现有的 QoS 规范:
openstack volume qos list --print-empty目前我们没有定义任何 QoS:
![如何操作…]()
-
定义一个新的 QoS 规范,内容如下:
openstack volume qos create --consumer both --property maxIOPS=500 "High IOPS"这将返回以下输出:
![如何操作…]()
-
通过列出可用的 QoS 来确认我们创建的 QoS 规范:
openstack volume qos list -c Name -c Consumer -c Properties -f table这将返回以下输出:
![如何操作…]()
-
我们现在将策略与卷类型关联,如下所示:
openstack volume qos associate "High IOPS" "High IOPS"注意
成功时,此命令不会产生任何输出。
它是如何工作的…
QoS 规范在 Cinder 中使用 openstack volume qos 一组命令进行定义。创建 QoS 规范时,可以指定 QoS 应用的位置以及设置的值。目前,您可以指定一组静态的最小、最大和突发 IOPS,以及一个可伸缩的 IOPS 集合。
静态值分解如下:
-
最小 IOPS:这是保证分配给卷的 IOPS 数量
-
最大值:这是卷的 IOPS 上限
-
突发 IOPS:这是短时间内的最大 IOPS
伸缩 IOPS 时,定义每增加一个千兆字节的卷大小,静态值的变化量。
重置卷状态
在 OpenStack 云的持续运行过程中,您偶尔会遇到 Cinder 卷卡在某个奇怪状态的问题。在写这章内容时,作者遇到了多个卷在实例从它们启动失败后卡在 attaching 状态的情况。以下是该情况的表现:
openstack volume list -c Name -c Status -f table

注意
这次错误是因为在创建从卷启动部分时,手误造成的!
准备就绪
要重置 Cinder 卷的状态,您需要以下内容:
-
一个包含适当凭据的
openrc文件 -
openstack命令行客户端 -
cinder命令行客户端 -
卷的 名称 或 ID
对于以下示例,我们将重置以下卷为可用状态:
-
cookbook.boot.volume -
cookbook.volume.boot.test
如何操作…
重置 Cinder 卷的状态是通过cinder命令完成的。这里的openstack命令集覆盖了大多数您常用的操作,而cinder命令则提供了额外的管理员功能,如reset-state。
提示
由于reset-state命令仅操作数据库,不考虑实际状态,因此在使用时应谨慎。
要重置 Cinder 卷的状态,请执行以下步骤:
-
首先,列出你的 Cinder 卷及其状态
openstack volume list -c Name -c Status -f table这将列出 OpenStack 所知道的卷:
![如何操作…]()
-
使用
cinder客户端重置卷的状态:cinder reset-state 23e1e006-a753-403c -ad8f-27e98444f71e --state available cinder reset-state e934c45f-6e2f-431f-8457-7e84f6cee876 --state available注意
当成功时,此命令不会产生任何输出。
-
确认新的状态:
openstack volume list -c Name -c Status -f table这将显示状态已重置为
available:![如何操作…]()
它是如何工作的…
cinder reset-state命令直接操作cinder数据库,而不考虑卷的实际状态。我们使用的--state标志允许我们更改可能卡在特定状态中的卷的状态。还有两个附加标志,分别允许您更改附件状态和迁移状态:
cinder help reset-state
usage: cinder reset-state
[--type ]
[--state ]
[--attach-status ]
[--reset-migration-status]
[ ...]
该工具显式地更新cinder数据库中的实体状态。由于它仅涉及数据库更改,因此不会影响实体的真实状态,可能与实际状态不符。在更改为available状态时,这可能导致实体无法使用。
第八章. Swift – OpenStack 对象存储
本章我们将覆盖以下主题:
-
介绍 – OpenStack 对象存储
-
创建对象容器
-
删除对象容器
-
上传对象
-
上传大对象
-
下载对象
-
删除对象
-
容器 ACL
介绍 – OpenStack 对象存储
OpenStack 对象存储,也称为 Swift,是一个允许在商品硬件上进行大规模可扩展和高度冗余存储的服务。该服务由 Rackspace 实现,名为 Cloud Files,也类似于 Amazon 的 S3 存储服务,并在 OpenStack 下以类似方式进行管理。通过 OpenStack 对象存储,我们可以存储许多几乎无限大小的对象—仅受限于可用硬件—并根据需要扩展环境以适应我们的存储需求。OpenStack 对象存储的高度冗余特性非常适合用于归档数据(例如日志和备份归档),同时也为 OpenStack Compute 提供了一个存储系统,可用于虚拟机实例镜像。
OpenStack 对象存储的架构是直接而简单的。API 服务运行在控制节点上。然后是 Swift 代理服务,这些服务可以部署到控制节点上,也可以根据需求分布到独立的服务器上,之后是实际存储数据的存储节点。这些存储节点是为随着存储需求增长而进行扩展而设计的服务器。
注意
扩展 Swift 的特性和设计超出了本书的范围。
这里展示了一个典型的简化架构视图:

本质上,上传或下载对象等请求是通过负载均衡池发送到 API 的,然后数据通过 Swift-Proxy 服务传送到物理存储节点。Swift-Proxy 服务会从终端用户那里获取数据,并将其存储进出。
正如名称所示,OpenStack 对象存储基于所谓的对象操作。对象可以是任何东西,从文件到一个名为完整文件夹和文件名的对象——对 OpenStack 对象存储来说,不管是什么文件名,所有它看到的内容都只是一个单一的对象。对象被存储在 容器 中。一个很好的类比是桶。在桶里,你可以存放任何适合其中的东西,从沙粒到你放在棚子里的工具!
创建对象容器
要开始使用 OpenStack 对象存储,我们必须首先创建一个容器。在这里,容器类似于 Windows 或 Linux 文件目录中的文件夹。然而,容器不能嵌套,尽管在上传存储在这些容器中的对象时,我们可以通过容器和对象名称(伪文件夹)的组合方式创建类似嵌套文件夹结构的深层结构。我们分配给容器和对象的名称类似于标签,允许我们通过在这些标签中使用/字符来将其解释为文件夹结构。
准备就绪
请确保您已登录到正确配置的 OpenStack 客户端,如第二章,OpenStack 客户端,中所述,并且可以作为具有swiftoperator权限的用户访问 OpenStack 环境。
我们将使用在第二章,OpenStack 客户端中创建的developer用户,并使用cookbook4密码;我们还授予此用户swiftoperator权限。
提示
参考第二章,OpenStack 客户端,获取有关设置环境以使用 OpenStack 命令行客户端的详细信息。
如何操作…
要在我们的环境中创建一个 Swift 容器,请按照以下步骤操作:
-
要创建一个容器,请执行以下命令:
openstack container create books -
创建容器后,您将看到以下输出:
![如何操作…]()
-
要查看所有可用的容器,请输入以下命令:
openstack container list这将返回类似以下的输出:
![如何操作…]()
-
一旦容器创建完成,我们可以通过执行以下命令设置附加的详细信息或元数据:
openstack container set books --property title=cookbooks -
要查看容器详细信息,请输入以下命令:
openstack container show books这将返回以下输出:
![如何操作…]()
-
如引言中所述,我们分配给容器和对象的名称很像标签;因此,要在容器中创建一个伪文件夹,请在容器名称中使用
/分隔符:openstack container create books/chapter1这将返回类似以下的输出:
![如何操作…]()
-
要查看伪文件夹的详细信息,请通过包含完整的伪文件夹名称执行
container show命令:openstack container show books/chapter1这将提供类似以下的信息:
![如何操作…]()
它是如何工作的…
在 OpenStack 对象存储中,具有admin或swiftoperator权限的用户可以使用对象存储服务。为此,我们首先必须创建容器,其中将存储对象。容器不能嵌套,但我们可以使用/分隔符在容器名称中创建伪文件夹。要创建容器,请遵循以下命令行语法:
openstack container create container_name
要列出可用容器,请使用以下命令:
openstack container list
我们还可以在每个容器上设置元数据。使用以下命令为容器设置附加信息:
openstack container set container_name
--property key=value
可以在每个容器上设置多对元数据。
要查看容器详细信息,请执行以下命令:
openstack container show <container_name>
删除对象容器
删除 OpenStack 对象存储容器非常简单。只要它们为空,任何容器都可以被删除。
注意
在此情况下,OpenStack CLI 与 Swift CLI 工具的行为不同。Swift CLI 将删除包括所有内容在内的容器,而 OpenStack CLI 则不会。在本示例中,我们使用的是 OpenStack CLI。
准备就绪
确保您以正确配置的 OpenStack 客户端登录,并作为具有 swiftoperator 特权的用户访问 OpenStack 环境。我们将使用在 第二章 的 Common OpenStack identity tasks 配方中创建的 developer 用户,密码为 cookbook4。我们还为该用户授予了 swiftoperator 特权。
详细设置环境以使用 OpenStack 命令行客户端,请参阅 第二章 的 OpenStack 客户端。
如何操作…
要在我们的环境中删除 Swift 容器,请执行以下步骤:
-
首先,列出可用容器:
openstack container list这将显示如下输出:
![如何操作…]()
-
查看容器详细信息,确保它为空:
openstack container show books这将显示如下输出:
![如何操作…]()
-
现在使用以下命令删除容器:
openstack container delete books注意
此命令不会输出任何内容。
工作原理…
在 OpenStack 对象存储中,用户可以删除空容器。首先,我们必须确保容器为空,方法是查看其详细信息:
openstack container show container_name
然后,使用以下命令删除容器:
openstack container delete container_name
验证容器是否已删除,方法是列出可用容器:
openstack container list
上传对象
一旦我们创建了一个或多个容器,就可以开始向其中上传对象。虽然 OpenStack 对象存储不支持嵌套容器,但我们可以通过对象名称模拟文件夹或文件目录。这与我们在容器名称中使用伪文件夹的类似结构,并且都能实现用户期望的对象存储使用树形结构的最终目标。
准备就绪
确保你已登录到配置正确的 OpenStack 客户端,并且作为具有 swiftoperator 权限的用户可以访问 OpenStack 环境。我们将使用在第二章,OpenStack 客户端,中创建的 developer 用户,密码为 cookbook4;我们也已经授予该用户 swiftoperator 权限。
请参阅第二章,OpenStack 客户端,了解如何设置环境以使用 OpenStack 命令行客户端。
如何操作…
要将对象上传到 OpenStack 对象存储容器,请按照以下步骤操作:
-
我们将把
intro.txt文件上传到books容器中:openstack object create books intro.txt这将产生以下输出:
![如何操作…]()
-
通过提供容器名称来列出容器中的对象:
openstack object list books这将产生如下输出:
![如何操作…]()
注意
这里的
chapter1是我们在 创建对象容器 章节中创建的伪文件夹,它显示为一个对象。 -
我们可以通过以下方式将对象上传到名为
books/chapter1的伪文件夹中:openstack object create books/chapter1 swift.txt这将产生如下输出:
![如何操作…]()
-
要列出容器中的对象,请对容器名称执行以下操作:
openstack object list books这将列出该容器下可用的对象:
![如何操作…]()
-
要列出伪文件夹容器中的所有对象,请使用
prefix标志:openstack object list books --prefix chapter1/![如何操作…]()
提示
你可以使用
--prefix来列出以指定前缀字母开头的任何对象。 -
要列出容器中的所有顶级对象,请使用分隔符标志。在此示例中,分隔符为
/:openstack object list books --delimiter /![如何操作…]()
-
要显示有关对象的信息,请执行以下命令:
openstack object show books chapter1/swift.txt这将显示该对象的信息:
![如何操作…]()
它是如何工作的…
为了将文件存储到 OpenStack 对象存储中,对象必须上传到一个容器中。容器不能嵌套;然而,可以使用 / 分隔符创建伪文件夹或伪目录。一旦容器创建完成,你可以使用以下命令上传文件:
openstack object create container_name object_1 [object_2 …]
提示
可以通过一条命令上传多个对象。
要列出上传到容器中的对象,请执行以下命令:
openstack object list container_name
列出容器中的对象时,启用 --prefix 和 --delimiter 标志进行过滤。
注意
默认情况下,将列出最多 10,000 个对象。使用分页或 --all 标志查看超过默认数量的对象。
要查看单个对象的详细信息,请使用以下命令:
openstack object show container_name object_name
注意
在 Swift 中,常规对象的大小有限制。默认情况下,只有 5 GB 或更小的对象可以通过 openstack object create 命令上传。有关如何上传大型对象的详细信息,请参考上传大型对象配方。
上传大型对象
每个 OpenStack 对象存储集群都有一个上传对象大小的限制。通常,该限制为 5 GB,尽管每个集群可以有自己的限制。然而,这并不意味着你只能上传 5 GB 或更小的对象到 OpenStack 对象存储。Swift 通过已经配置和部署的中间件提供大对象支持,通过将大对象拆分成较小的部分来实现。有两种类型的大对象支持:动态和静态。
准备就绪
确保你已经登录到正确配置的 OpenStack 客户端,并且可以作为具有 swiftoperator 权限的用户访问 OpenStack 环境。我们将使用在公共 OpenStack 身份任务配方中创建的 developer 用户,该用户的密码为 cookbook4,同时我们也授予该用户 swiftoperator 权限。
由于 OpenStack CLI 没有通过单独的 OpenStack 项目客户端提供所有必要的功能,我们需要使用 Swift CLI 来完成本配方。请确保你已安装 Swift 命令行客户端。如果没有,请安装:
pip install python-swiftclient
如何操作..
要将大型对象上传到 OpenStack 对象存储容器,请按照以下步骤操作:
-
首先,我们可以使用以下命令列出可用的容器:
swift list这会给出我们拥有的容器列表:
books -
要上传一个大型文件,我们将使用
–S标志指定对象的分段大小,单位为字节:swift upload -S 25000 books nova.txt这将显示对象被拆分为分段的输出:
nova.txt segment 1 nova.txt segment 0 nova.txt segment 5 nova.txt segment 2 nova.txt segment 3 nova.txt segment 4 nova.txt在这个例子中,分段大小为 25000 字节,我们的 128 K
nova.txt文件在上传到 Swift 集群之前被拆分成了 6 个分段。 -
通过列出容器中可用的对象,验证文件是否已上传:
swift list books这显示了我们可用的
nova.txt文件:nova.txt尽管文件被拆分成 6 个部分进行上传,但它在 Swift 的
books容器中显示为一个文件。这些分段会在一个新的容器中单独列出。 -
要查看可用的容器,请执行以下命令:
swift list这会为我们提供容器,并自动创建一个新的容器:
books books_segments你会注意到一个新的
books_segments容器已经自动创建。 -
列出
books_segments容器中的对象,以查看单个对象:swift list books_segments这显示了我们分段的文件对象:
nova.txt/1512361523.073429/131024/25000/00000000 nova.txt/1512361523.073429/131024/25000/00000001 nova.txt/1512361523.073429/131024/25000/00000002 nova.txt/1512361523.073429/131024/25000/00000003 nova.txt/1512361523.073429/131024/25000/00000004 nova.txt/1512361523.073429/131024/25000/00000005注意
请勿单独修改或删除这些对象。
-
使用
stat命令查看books容器中已上传对象的详细信息:swift stat books nova.txt这提供了有关
books容器中nova.txt文件的详细信息:Account: AUTH_402e8fe274c143ea91fe905a1b8c7614 Container: books Object: nova.txt Content Type: text/plain Content Length: 131024 Last Modified: Sun, 17 Dec 2017 06:36:32 GMT ETag: "cd0ef1b80a6261f0b6b7db9efa739938" Manifest: books_segments/nova.txt/1512361523.073429/131024/25000/Meta Mtime: 1512361523.073429 Accept-Ranges: bytes X-Timestamp: 1513492591.13264 X-Trans-Id: tx4fa6e7a4e53a459a86430-005a3611ad X-Openstack-Request-Id: tx4fa6e7a4e53a459a86430-005a3611ad查看提供的信息中的
manifest字段。manifest字段将包括为各个段创建的container详细信息、原始文件大小以及段的大小。
它是如何工作的
由于 OpenStack CLI 在编写本食谱时不支持大文件上传,我们将使用 Swift 命令行客户端。为了将大文件存储到 OpenStack 对象存储中,必须先将对象拆分或分段,然后再上传到容器中。这一分段过程通过在 swift upload 命令中指定 -S 标志来完成:
swift upload -S size_in_bytes container large_object
在上传大文件时,Swift 会自动为上传对象的各个段创建一个新的容器和伪文件夹。各个段可以像常规对象一样列出;但是,请勿直接操作它们。
下载对象
一旦对象上传到容器中,你可能还想下载它们。在本食谱中,我们将向你展示如何将对象下载到本地磁盘。
准备工作
确保你已经登录到正确配置的 OpenStack 客户端,并且能够以具有 swiftoperator 权限的用户身份访问 OpenStack 环境。我们将使用在第二章 OpenStack 客户端 任务中创建的 developer 用户,并使用 cookbook4 密码。我们还为该用户授予了 swiftoperator 权限。
参见第二章 OpenStack 客户端,了解如何设置你的环境以使用 OpenStack 命令行客户端。
如何操作…
要从 Swift 集群下载对象,请执行以下步骤:
-
列出容器中的可用对象:
openstack object list books这将列出我们在
books容器中的对象:![如何操作…]()
-
要下载所需的文件,例如
intro.txt,请执行以下命令:openstack object save books intro.txt注意
此命令没有输出。文件将保存到当前目录。
-
我们还可以下载文件并指定目标文件:
openstack object save books nova.txt --file /tmp/nov a.txt
它是如何工作的…
为了从 OpenStack 对象存储中下载文件,请执行以下命令:
openstack object save container object --file file_name
--file 标志是可选的。如果未指定,将把对象保存到当前目录。
注意
下载大对象时不需要特别处理;同样的命令可以用于大对象和小对象。
删除对象
从 OpenStack 对象存储删除对象相当简单,无论是小文件还是大文件。
准备工作
确保你已经登录到正确配置的 OpenStack 客户端,并且能够以具有 swiftoperator 权限的用户身份访问 OpenStack 环境。我们将使用在第二章,The OpenStack Client 中的 Common OpenStack identity tasks 配方中创建的 developer 用户,密码为 cookbook4。我们也已授予该用户 swiftoperator 权限。
请参考第二章,The OpenStack Client,了解如何设置环境以使用 OpenStack 命令行客户端。
如何操作…
要从 Swift 集群中删除对象,请执行以下步骤:
-
列出容器中可用的对象:
openstack object list books这将列出我们
books容器中的对象:![如何操作…]()
-
从容器中删除对象:
openstack object delete books intro.txt注意
此命令不会输出任何内容。
-
删除对象后的
books容器中的对象列表:openstack object list books容器列表将显示
intro.txt不再存在:![如何操作…]()
-
要删除 所有对象 并 随后删除容器,请执行以下命令:
openstack container delete -r books注意
此命令不会输出任何内容。
工作原理
为了从 OpenStack 对象存储集群中删除文件,请使用以下命令指定应删除的容器和对象:
openstack object delete container object
使用 -r 标志来删除容器及其所有内容。
容器 ACL
OpenStack 对象存储容器通常由创建它们的用户拥有。然而,通过 Swift 的 ACLs(访问控制列表),可以使容器对不同的 OpenStack 用户可访问,或者完全公开。容器的拥有者可以设置特定的读写规则。这些读写规则必须单独设置,并且必须在每个容器上明确启用。容器的拥有者可以将容器设置为完全公开,或根据项目、用户或规则集设置规则。
准备工作
确保你已经登录到正确配置的 OpenStack 客户端,并且能够以具有 swiftoperator 权限和 admin 权限的用户身份访问 OpenStack 环境。我们将使用在第二章,The OpenStack Client 中的 Common OpenStack identity tasks 配方中创建的 developer 用户,密码为 cookbook4。我们也已授予该用户 swiftoperator 权限。
由于 OpenStack CLI 并未提供所有通过各个 OpenStack 项目客户端可用的功能,因此我们需要使用 Swift CLI 来执行此配方。确保你已经安装了 Swift 命令行客户端。如果没有,请安装:
pip install python-swiftclient
如何操作…
要查看和修改容器上的 ACL,请按照以下步骤操作:
-
首先,查看容器上的现有 ACL(如果有的话):
swift stat books这将提供关于我们名为
books的容器的信息:Account: AUTH_402e8fe274c143ea91fe905a1b8c7614 Container: books Objects: 3 Bytes: 32764 Read ACL: Write ACL: Sync To: Sync Key: Accept-Ranges: bytes X-Storage-Policy: default Last-Modified: Mon, 18 Dec 2017 06:09:45 GMT X-Timestamp: 1512278405.11522 X-Trans-Id: tx484e741deb754fdb86f7a-005a375e4c Content-Type: text/plain; charset=utf-8 X-Openstack-Request-Id: tx484e741deb754fdb86f7a-005a375e4c -
在我们的示例中,还没有设置读或写的 ACL。让我们设置一个
readACL 使books容器 公开:swift post books --read-acl ".r:*,.rlistings"注意
此命令没有输出。
-
要使
books容器对所有人 可写,请执行以下操作:swift post books --write-acl "*:*"注意
此命令没有输出。
-
现在再次使用 stat 命令检查
books容器的详细信息:swift stat books我们可以看到
Read ACL和Write ACL字段已经被填充:Account: AUTH_402e8fe274c143ea91fe905a1b8c7614 Container: books Objects: 3 Bytes: 32764 Read ACL: .r:*,.rlistings Write ACL: *:* Sync To: Sync Key: Accept-Ranges: bytes X-Trans-Id: txc0d0d64ed54e48989f3f6-005a3760ba X-Storage-Policy: default Last-Modified: Mon, 18 Dec 2017 06:22:56 GMT X-Timestamp: 1512278405.11522 Content-Type: text/plain; charset=utf-8 X-Openstack-Request-Id: txc0d0d64ed54e48989f3f6-005a3760ba -
由于操作 世界可写 和 可读 容器并不是一个很好的安全做法,我们可以从容器中删除 ACL。要删除 读 ACL,可以执行以下命令:
swift post -r "" books -
要删除 写 ACL,请使用此命令:
swift post -w "" books -
如果你需要与 OpenStack 环境中的其他用户共享容器,可以基于 项目 和 用户 设置权限。在我们的示例中,我们将设置
books容器的访问权限,使admin项目中的所有人都可以读取:swift post -r "admin:*" books:后面的星号(*)表示admin项目中的所有用户都可以访问books容器。 -
现在检查
books容器的详细信息:swift stat -v books这将产生如下输出:
URL: http://172.29.236.100:8080/v1/AUTH_402e8fe/books Auth Token: gAAAAABaODQ8R93x7kW46CW_u9ZS3 Account: AUTH_402e8fe274c143ea91fe905a1b8c7614 Container: books Objects: 3 Bytes: 32764 Read ACL: admin:* Write ACL: Sync To: Sync Key: Accept-Ranges: bytes X-Trans-Id: tx20b0d0d8394b4b0a81cba-005a38343c X-Storage-Policy: default Last-Modified: Mon, 18 Dec 2017 21:24:27 GMT X-Timestamp: 1512278405.11522 Content-Type: text/plain; charset=utf-8 X-Openstack-Request-Id: tx20b0d0d8394b4b0a81cba-005a38343c注意容器详细信息中的
URL。任何希望访问此容器的人都需要将URL字段作为参数传递。 -
作为
admin用户,测试访问books容器:swift --os-storage-url http://172.29.236.100:8080/v1/AUTH_402e8fe/books list这将提供来自我们共享容器的对象,指定 URL 如下:
chapter1 chapter1/swift.txt intro.txt在我们的示例中,
admin用户属于admin项目,因此可以通过--os-storage-url标志访问books容器。
它是如何工作的…
可以通过设置 读 和 写 ACL 来与其他用户共享容器。目前,OpenStack 客户端不支持 ACL 功能,因此我们在示例中使用了 Swift CLI。
容器可以设置两种类型的 ACL,读 和 写,并且它们需要单独设置。
使用以下命令设置读 ACL:
swift post -r "project:user" container
按如下方式设置写 ACL:
swift post -w "project:user" container
在这里,项目和用户都可以用通配符(*)来替代。
要使容器完全公开,可以使用以下命令:
swift post --read-acl ".r:*,.rlistings" container
swift post --write-acl "*:*" container
设置 .r:* 和 .rlistings 元素后,books 容器将公开可访问。.r* 元素允许访问容器中的对象,.rlistings 允许列出容器的内容。
注意
设置写 ACL 为 "*:*" 后,容器可以被任何人更新,因此请小心使用。
-r 和 --read-acl 命令,以及 -w 和 --write-acl 是相同标志的短形式和长形式。也就是说,-r 和 --read-acl 可以互换,-w 和 --write-acl 也可以互换。
一旦启用了其他用户对容器的访问,可以使用以下命令查找容器的 URL:
swift stat -v container | grep URL
启用访问后,要访问其他用户的容器,请使用此命令:
swift --os-storage-url URL list
提示
如果你始终访问相同的存储 URL,可以将其设置为 OS_STORAGE_URL 环境变量。
第九章:使用 Heat 和 Ansible 进行 OpenStack 编排
本章将涵盖以下主题:
-
介绍 – 使用 OpenStack 进行编排
-
使用 Heat 创建您的第一个堆栈
-
使用 Heat 启动您的堆栈
-
查看通过 Heat 创建的堆栈的资源和输出
-
删除 Heat 堆栈
-
更新 Heat 堆栈
-
安装和配置 Ansible 以用于 OpenStack
-
使用 Ansible 启动实例
-
使用 Ansible 编排软件安装
-
使用 Ansible 在多个实例之间编排软件安装
-
使用 Ansible 完全编排 Web 服务器和负载均衡器堆栈的创建
介绍 – 使用 OpenStack 进行编排
OpenStack 被选择作为平台有很多原因,但其中一个经常排在首位的是编排。如果您的 OpenStack 环境没有编排元素,那么您就拥有了一辆强大的涡轮增压赛车,却仅仅用于接送孩子上学。与任何云环境一样,帮助编排工作负载的工具有很多,但 OpenStack 自带 Heat——编排引擎。
使用 Heat,您可以在模板中定义丰富的环境,例如多层 Web 应用程序,这使得用户在启动这些相对复杂的部署时保持一致性。我将 Heat 编排模板(称为 HOT(Heat Orchestration Template)——明白了吗?)看作是用 YAML(Yet Another Markup Language)编写的食谱。您定义构成环境的配料。在烹饪食谱中,这将列出制作蛋糕所需的巧克力、面粉和糖的数量。在 HOT 文件中,这就是参数部分。您定义实例的规格、使用的镜像以及实例应该在哪些网络上启动。
像任何好的食谱一样,您可以覆盖这些默认值——所以如果您想尝试用果酱代替巧克力酱,或者调整所需糖分的量——您可以进行调整。此外,在 Heat 中,您是在环境文件中执行此操作。此文件的布局就像您正在为参数分配值。例如,HOT 文件中的输入参数可能是 image_name,而在环境文件中,您将 image_name=ubuntu-image 进行分配。
HOT 文件中的下一部分是最大的也是最复杂的,因为它是配方的“方法”部分——即“所有配料如何创造一个蛋糕”的部分。在 Heat 中,这是资源部分的开始。资源部分描述了实例之间如何相互作用。例如,在 Heat 运行期间,可能会创建一个包含三个 Web 服务器的负载均衡器。负载均衡器资源将有一个方法,将这三个未知的 Web 服务器附加到负载均衡池中,以便该资源完成。
最后一部分是输出部分。在烹饪食谱中,你会把蛋糕从烤箱中取出。在 OpenStack 中,这将是最终结果——你的多层 Web 应用程序。然而,由于 OpenStack 以及启动多个实例到可能尚未创建网络的环境中的特性,很难知道已经使用了哪些 IP 地址,而这些信息可能是访问已部署堆栈所需要的。因此,为此,我们有了输出部分,OpenStack 的用户可以查询堆栈并获得有用的信息,以便已启动的堆栈可用。
然而,在实例和应用程序生命周期管理方面,我们不仅限于使用 OpenStack 内的 Heat 编排引擎。如第一章 《使用 Ansible 安装 OpenStack》 中介绍的,Ansible 是一个平台无关的工具,我们可以利用它来帮助编排任务。通过使用特定于目标环境(如 OpenStack)的 Ansible 模块,我们可以以结构化的方式启动实例并执行软件安装,这种方式适用于 OpenStack 用户和其他云环境的用户。
Ansible 的基本结构非常简单。最基本的形式中,它包括剧本(playbooks)、剧本任务(plays)和任务(tasks)。如果你研究第一章 《使用 Ansible 安装 OpenStack》 中描述的 OpenStack-Ansible 剧本,你将获得一些本章未涉及的高级功能的见解,这些功能可以帮助你将基于 OpenStack 的云环境扩展为完全编排的杰作!
创建你的第一个堆栈
使用 Heat,我们可以创建各种各样的模板,从启动基本实例,到为应用程序创建完整的环境。在这一部分,我们将通过启动一个实例并将其附加到现有的 Neutron 网络,并为其分配浮动 IP,来展示 Heat 的基础知识。Heat 模板描述了所使用的资源、实例的类型和大小、实例将附加的网络,以及运行该环境所需的其他信息。
在这一部分,我们将展示如何使用 HOT 文件启动两个运行 Apache 的 Web 服务器,并将其连接到第三个运行 HAProxy 的实例上,后者充当负载均衡器。
准备工作
确保你已登录到正确配置的 OpenStack 客户端,并能够访问 OpenStack 环境。有关如何设置环境以使用 Heat 的详细信息,请参考第二章 《OpenStack 客户端》。
如何实现…
在这一部分,我们将下载一个名为 cookbook.yaml 的 HOT 文件,该文件将描述我们的实例及其要连接的网络:
-
首先,我们从 Cookbook GitHub 仓库下载 HOT 文件:
wget -O cookbook.yaml https://raw.githubusercontent.com/OpenStackCookbook/OpenStackCookbook/master/cookbook.yaml -
Heat 从命令行或环境文件中获取输入参数,这些参数会传递给模板。这些参数出现在 HOT 文件的顶部,如下所示:
parameters: key_name: type: string description: Name of keypair to assign to servers image: type: string description: Name of image to use for servers flavor: type: string description: Flavor to use for servers public_net_id: type: string description: > ID of public network for which floating IP addresses will be allocated private_net_id: type: string description: ID of private network into which servers get deployed private_subnet_id: type: string description: ID of private sub network into which servers get deployed -
如图所示,我们在启动这个模板时预计会传入多个参数。通过运行以下命令,确保我们拥有这些详细信息:
openstack keypair list openstack image list openstack flavor list openstack network listopenstack network list的输出可能如下所示:![How to do it...]()
-
有了手头的信息后,我们创建一个环境文件,用于存储将在启动堆栈时传递给 HOT 文件的参数。根据之前命令的输出,在与
cookbook.yaml相同的目录下创建cookbook-env.yaml文件(根据你的环境进行调整):parameters: key_name: demokey image: xenial-image flavor: m1.tiny public_net_id: 2da8979e-dcf8-4eb8-b207-f33bfce4a15a private_net_id: 78a5a119-c27a-41c4-8310-5c04d3a6bc31 private_subnet_id: 3cee2bb9-5673-4a6e-bb1e-8cb66be066b2
它是如何工作的…
Heat Orchestration Templates (HOT) 是描述我们的环境的 YAML 文件,环境也称为“堆栈”(Stacks)。基本模板通常具有以下结构:
-
description: -
parameters: -
resources: -
outputs:
description: 部分包含了一些词语,帮助用户理解使用模板时预期会发生什么。
parameters: 部分定义了输入变量,例如,要使用的镜像类型、要将实例附加到的网络、以及与实例关联的密钥对名称。参数是任意的,可以包含执行模板所需的任何信息。parameters: 部分与附带的环境文件中的信息直接配合(如 --environment 参数所指定)。每个参数必须要么有默认值,要么在环境文件中指定,以便堆栈能够成功启动。
resources: 部分通常是最大的一部分,因为它描述了环境。它可以描述将要使用的实例、实例的命名、需要附加的网络,以及所有元素如何相互关联以及环境是如何协调的。如何编写这些资源的最佳方法超出了本书的范围。
outputs: 部分指的是运行堆栈时的“返回”值。例如,用户需要知道如何访问刚刚创建的某个堆栈。随机的 IP 和主机名可以像正常运行堆栈一样被分配,因此,能够查询正确的信息以访问环境是必须的。
使用 Heat 启动堆栈
要启动一个 Heat 堆栈,我们需要三样东西:堆栈的 名称,描述部署的 模板(HOT),以及最后,填补输入参数空白的 环境文件。
准备就绪
确保您已登录到正确配置的 OpenStack 客户端,并且能够访问 OpenStack 环境。有关如何设置环境以使用 OpenStack 的详细信息,请参考第二章,OpenStack 客户端。
提示
如果收到openstack: 'stack' 不是一个 openstack命令,请参考openstack --help。
确保已安装python-heatclient包:
sudo -H pip install python-heatclient
还要确保您已下载示例cookbook.yaml Heat 模板,并根据前面的步骤创建了环境文件。
如何操作...
在本节中,我们将下载一个名为cookbook.yaml的 HOT 文件,该文件将描述我们的实例及其要连接的网络:
-
我们将使用以下命令启动堆栈:
openstack stack create myStack --template cookbook.yaml --environment cookbook-env.yaml提示
提示:您可以使用
-t标志代替--template,使用-e代替--environment。这将生成如下输出:
![如何操作...]()
-
要查看堆栈列表,请执行以下命令:
openstack stack list这将返回当前运行的堆栈列表:
![如何操作...]()
注意堆栈状态。成功启动时,状态会标记为CREATE_COMPLETE。
它是如何工作的...
启动堆栈很简单。我们将使用--template参数指定 HOT 文件,然后使用--environment参数指定一个文件,该文件中描述了模板中的输入。
语法如下:
openstack stack create nameOfStack
--template template.yaml
--environment template-env.yaml
注意
请注意,堆栈名称在您的项目中必须是唯一的。
查看使用 Heat 创建的堆栈的资源和输出
堆栈是一个编排的服务集,启动堆栈的用户不需要过多关心分配了哪些 IP 地址。然而,应用堆栈的启动是为了某个目的,因此了解如何访问它非常有用!要访问该环境,用户需要查询堆栈的“输出”,这些输出是模板的一部分。在本示例中,我们关心的是如何访问在 HAProxy 服务器后面运行的网站。HAProxy 服务器已从 GATEWAY_NET 网络分配了一个浮动 IP 地址,假设这是访问该应用程序的方式。
准备工作
确保您已登录到正确配置的 OpenStack 客户端,并且能够访问 OpenStack 环境。有关如何设置环境以使用 Heat 的详细信息,请参考第二章,OpenStack 客户端。
如何操作...
要查看应用堆栈并获取有关如何访问它的信息,请执行以下步骤:
-
您可以使用以下命令查看堆栈的更多详细信息:
openstack stack show myStack这将返回关于创建的堆栈的多个详细信息:
![如何操作...]()
-
模板中的一部分引用了输出。输出使得用户可以查询这些值,从而访问正在运行的堆栈。如果没有这个功能,用户就需要深入研究运行中的系统,才能找出分配给堆栈组成实例的 IP 地址。要查看与我们正在运行的堆栈相关联的输出列表,请执行以下命令:
openstack stack output list myStack这将返回以下输出:
![如何操作...]()
-
要查看特定的值,比如分配给 HAProxy 实例的公共 IP(浮动 IP),我们可以访问通过负载均衡器后面的私有地址运行的站点。要做到这一点,请执行以下命令:
openstack stack output show myStack haproxy_public_ip这将返回我们用于访问该特定服务的 IP 地址,该服务设置为一个堆栈:
![如何操作...]()
-
在这个示例应用堆栈中,我们可以使用
http://192.168.100.108/地址,它会将请求发送到任意正在运行的 Web 服务器,这些服务器是作为 HAProxy 负载均衡器演示的一部分进行配置的。
它是如何工作的…
一个堆栈被设计为接受多个输入,执行一些操作,并生成多个运行应用的实例,准备提供服务。然而,这种免操作的方式意味着许多决策都是由 OpenStack 自动决定的——主要是因为这些实例是从启用 DHCP 的子网中提供的。为了了解堆栈的状态以及如何访问堆栈的信息,用户需要查询模板中描述的输出。在示例模板中,输出部分如下所示:
outputs:
webserver1_private_ip:
description: IP address of webserver1 in private network
value: { get_attr: [ webserver1, first_address ] }
webserver2_private_ip:
description: IP address of webserver2 in private network
value: { get_attr: [ webserver2, first_address ] }
haproxy_public_ip:
description: Floating IP address of haproxy in public network
value: { get_attr: [ haproxy_floating_ip, floating_ip_address ] }
包含更多信息的输出标注如下:
-
webserver1_private_ip -
webserver2_private_ip -
haproxy_public_ip
在这个教程中,我们特别针对haproxy_public_ip进行了设置,因为这是我们访问所创建的 Web 服务的方式。我们执行了以下命令来实现这一点:
openstack stack output show myStack haproxy_public_ip
删除 Heat 堆栈
要删除一个运行中的 Heat 堆栈,我们将按照此教程中的方式发出一个简单的调用。
准备就绪
确保您已经登录到正确配置的 OpenStack 客户端,并能够访问 OpenStack 环境。有关如何设置环境以使用 OpenStack,请参阅第二章,OpenStack 客户端,其中详细介绍了如何设置您的环境。
如何操作...
在本节中,我们将展示如何删除堆栈。
-
要删除名为
myStack的运行堆栈,请执行以下命令:openstack stack delete myStack -
系统会提示您确认是否删除,正如下面所示。输入
y以继续销毁堆栈:![如何操作...]()
-
您可以通过列出已创建的堆栈来检查删除状态:
openstack stack list如果没有堆栈可显示,或者在删除期间出现以下情况,它将返回一个空列表:
![如何操作...]()
它是如何工作的...
就像我们可以轻松启动堆栈一样,删除堆栈只需指定我们要销毁的堆栈,并使用stack delete命令即可。
如果您希望在不确认的情况下销毁堆栈,请使用以下语法:
openstack stack delete nameOfStack -y
更新 Heat 堆栈
我们的运行堆栈是基于模板的,这允许我们通过更改输入来修改应用程序堆栈。如果我们想更改 flavor 的大小或使用的密钥,可以通过更改输入并发出stack update命令来触发堆栈中实例的重建。
准备工作
确保您已登录到配置正确的 OpenStack 客户端,并能够访问 OpenStack 环境。有关设置环境以使用 OpenStack 的详细信息,请参阅第二章,OpenStack 客户端。
如何操作...
在本节中,我们将修改环境文件,将 flavor 从m1.tiny更改为m1.large。(在继续之前,请确保您有一个有效的 flavor 名称!)
-
我们首先编辑名为
cookbook-env.yaml的环境文件,展示我们希望对正在运行的堆栈进行的更改:parameters: key_name: demokey image: xenial-image flavor: m1.large public_net_id: 2da8979e-dcf8-4eb8-b207-f33bfce4a15a private_net_id: 78a5a119-c27a-41c4-8310-5c04d3a6bc31 private_subnet_id: 3cee2bb9-5673-4a6e-bb1e-8cb66be066b2 -
通过查看资源,确保堆栈正在正常运行:
openstack stack show myStack这将返回类似以下的输出:
![如何操作...]()
-
现在,我们将使用更新后的环境文件来修改正在运行的堆栈:
openstack stack update myStack --existing提示
提示:我们使用
--existing参数,以避免再次指定模板和环境文件。这将返回类似以下的输出,显示更新已经开始:
![如何操作...]()
-
完成此操作后,我们还可以查看堆栈的状态,以显示反映的更改:
openstack stack show myStack这将返回类似以下的输出(注意 flavor 已从
m1.tiny更改为m1.large)。还请注意,IP 地址没有改变:![如何操作...]()
它是如何工作的...
OpenStack Orchestration 服务 Heat 旨在遵循模板为最终用户提供运行中的服务。从头到尾,所有操作都是自动化的。这个关键功能允许我们更新正在运行的堆栈,实际上是通过更新重新部署堆栈,运行完全自动化的流程来恢复服务,使用相同的 IP 地址,但做出所需的更改。
更新堆栈的语法如下:
openstack stack update nameOfStack
--environment updatedEnvironmentFile.yaml
--template originalStackTemplate.yml
在我们的示例中,我们省略了--environment和--template参数,因为我们直接在最初使用的环境文件中对堆栈进行了所需的更改。这使得语法更简单:
openstack stack update nameOfStack --existing
安装和配置 Ansible 以用于 OpenStack
Ansible 对大多数 Linux 和 macOS 系统的先决条件要求较少。然而,在我们能使用 Ansible 来管理 OpenStack 环境之前,仍有一些步骤需要遵循。
准备工作
确保您已登录到正确配置的 OpenStack 客户端,并且可以访问 OpenStack 环境。有关如何设置环境以使用 OpenStack 的详细信息,请参见第二章,OpenStack 客户端。
Ansible 2.x 版本需要 Python 2.6 或 2.7。大多数现代 Linux 发行版和 macOS/OS X 都已经安装了这些。如果您能成功执行第二章中描述的openstack命令,OpenStack 客户端,那么您就可以继续进行。
您可能需要安装 Shade。Shade 是一个与 OpenStack 云交互的简单客户端库。Red Hat 和 CentOS 环境默认未安装此库。可以通过以下命令进行安装:
sudo pip install shade
注意
请注意,Shade 可能会引入其他依赖项,这些依赖项可能会破坏您的环境。建议您使用虚拟环境(venv)来避免此问题。
如何做...
由于我们在客户端计算机上执行此操作,请确保您拥有安装软件的必要权限。准备好后,根据您选择的操作系统执行以下步骤。
Ubuntu
对于 Ubuntu,我们可以按以下方式使用 Ansible PPA:
-
首先,确保我们可以通过安装以下工具来添加PPA(个人软件包档案):
sudo apt-get install software-properties-common -
接下来,我们将添加 PPA:
sudo apt-add-repository ppa:ansible/ansible -
最后,我们将运行安装:
sudo apt-get update sudo apt-get install ansible
macOS/OS X(以及那些想使用 pip 的人)
对于 macOS,我们可以按照以下方式使用 pip:
-
确保
pip可用:sudo easy_install pip -
接下来,使用
pip安装 Ansible:sudo pip install ansible
验证安装
要验证安装,请发出以下命令:
ansible --version
这应该会产生如下输出:

它是如何工作的...
为了能够使用 Ansible 管理我们的 OpenStack 环境,我们必须确保已经正确设置了 Ansible。前面的步骤仅帮助我们使用该操作系统提供的工具将 Ansible 安装到我们的客户端上。
使用 Ansible 启动实例
使用 Ansible 启动实例是一种方便的平台无关方法。虽然我们需要为 OpenStack 指定如何执行此操作作为特定任务,但 Ansible playbook 可以扩展,使用户能够使用相同的 Ansible 命令在任何云上启动实例。本教程是将 Ansible 与 OpenStack 一起使用的一个非常基础的介绍。
准备就绪
确保您已登录到正确配置的 OpenStack 客户端,并且可以访问已安装 Ansible 的 OpenStack 环境。
如何做...
Ansible 通过称为 playbook 的任务执行文件来执行任务。在本例中,我们将创建一个简单的任务来启动名为cookbook1的特定实例:
-
第一步是为我们的任务创建 Ansible playbook,该任务将启动我们的实例。在你的客户端创建一个名为
launch-instance.yml的文件,放在你选择的目录中:- name: Launch instance on OpenStack hosts: localhost gather_facts: false tasks: - name: Deploy an instance os_server: state: present name: cookbook1 image: xenial-image key_name: demokey timeout: 200 flavor: m1.tiny network: private-net verify: false -
一旦描述了这些,我们只需使用
ansible-playbook命令运行该特定任务,如下所示:source openrc ansible-playbook launch-instance.yml这将恢复熟悉的 Ansible 输出,如下所示:
![How to do it...]()
注意
这是一个
localhost任务,因此可以忽略警告。 -
我们可以通过查看服务器列表来验证是否在 OpenStack 中启动了实例,如下所示:
openstack server list这将恢复如下所示的输出:
![How to do it...]()
请注意,任务自动从GATEWAY_NET网络分配了一个公共浮动 IP 地址。这是一个重要细节,因为 Ansible 能做的不仅仅是启动实例。如果我们希望能够安装和配置实例,Ansible 必须能够从客户端通过 SSH 连接到正在运行的实例。私有租户网络通常无法访问;因此,Ansible 将使用公共路由网络来访问实例,就像你通过 SSH 连接到它一样。
工作原理...
使用 Ansible 启动实例使用的是os_server Ansible 模块。该模块从 Ansible 2.0 版本开始可用。os_server模块接受许多参数,这些参数描述了使用命令行启动实例时通常会遇到的参数。
请注意,我们在任务中没有指定任何认证细节。这是因为该模块会解释我们的 shell 环境变量,就像我们使用 OpenStack 客户端工具时一样。
你会注意到,任务中的一个条目标明了如下内容:
os_server:
state: present
这在 Ansible 中有特定的意图,因为 Ansible 旨在确保任务的状态一致性,无论该任务执行多少次。这个简单的语句基本上表示该实例必须存在。如果不存在,它将启动该实例。一旦实例启动,它将满足该条件。在 Ansible 输出中,你会看到整体运行状态为ok=1 changed=1。这意味着它改变了这个环境的状态。换句话说,它启动了实例(这是一种状态变化)。
然而,如果我们再次运行该任务,输出中会出现以下微妙的变化,表明任务不需要执行,因为实例已经“存在”(即,正在运行):

请注意,任务执行成功,但由于changed=0输出的原因,PLAY RECAP行中没有需要更改的内容。
另请参见
-
访问
docs.ansible.com/ansible/latest/os_server_module.html获取更多信息 -
对于那些不想通过
source openrc方法将环境变量导入到 playbook 中的用户,可以访问docs.openstack.org/shade/latest/来设置clouds.yaml云环境文件
使用 Ansible 来协调软件安装
使用 Ansible 启动实例并不会为用户提供太多,除了提供一致性,因为 playbook 描述了环境的最终状态:每次用户运行任务时,要么需要启动该特定实例以确保它存在,要么跳过该任务,因为该实例已经在运行。然而,我们可以通过 Ansible 实现更多的功能,而不仅仅是启动虚拟机。在这个食谱中,我们将启动另一个实例,该实例将安装并启动 Apache。
准备工作
确保你已经登录到正确配置的 OpenStack 客户端,并且可以访问安装了 Ansible 的 OpenStack 环境。
如何操作...
Ansible 执行任务的 playbook。在此示例中,我们将扩展启动特定实例的任务,允许 Ansible 连接到该实例并安装 Apache:
-
我们通过扩展前面食谱中介绍的 Ansible playbook 来开始,增加了创建安全组规则(这是为了确保 Ansible 可以通过端口
22访问实例,并且最终能够通过端口80访问运行的 Web 服务器)。创建一个名为orchestrate-instance.yml的文件,内容如下:- name: Launch instances on OpenStack hosts: localhost gather_facts: false tasks: - name: Create ansible security group os_security_group: state: present name: ansible verify: false - name: Create a rule to allow SSH connections os_security_group_rule: security_group: ansible protocol: tcp port_range_min: 22 port_range_max: 22 remote_ip_prefix: 0.0.0.0/0 verify: false - name: Create webserver security group os_security_group: state: present name: webserver verify: false - name: Create rule to allow http connections os_security_group_rule: security_group: webserver protocol: tcp port_range_min: 80 port_range_max: 80 remote_ip_prefix: 0.0.0.0/0 verify: false -
一旦我们配置了安全组,我们就可以确保这些安全组规则包含在任务中,该任务用于启动实例。我们还确保包括一个新的条目,名为
register。这使我们能够设置与该实例关联的变量,然后可以在其他任务中引用该变量。继续编辑此文件并加入以下任务:- name: Deploy an instance os_server: state: present name: cookbook1 image: xenial-image key_name: demokey timeout: 200 flavor: m1.tiny network: private-net security_groups: default,ansible,webserver verify: false register: nova_cookbook -
接下来,我们将添加一个任务,将该特定实例添加到一个内部的内存库存中,我们可以在 playbook 后续部分访问该库存。作为这个库存的一部分,我们告诉 Ansible,当访问该库存项时,当 Ansible 想连接到它(通过
ssh)时,它将使用特定的 IP 地址(在我们的案例中是公共浮动 IP)。继续编辑文件并添加下一个条目,格式如下所示。由于我们使用的是 YAML,确保每个元素的缩进一致。例如,这个额外的- name: Add instance to Inventory块必须与前一个- name: Deploy an instance块在同一列对齐,因为它是同一个 play 的一部分:- name: Add instance to Inventory add_host: name=cookbook1 groups=webservers ansible_ssh_host={{ nova_cookbook.server.accessIPv4 }} -
接下来,我们将添加一个新的任务,告诉 Ansible 等待该实例完成启动过程。由于 Ansible 使用 SSH 执行任务,因此合理的做法是仅在 SSH 守护进程运行并接受连接时继续。确保运行 Ansible 任务的私钥与
key_name:中描述的公钥部分匹配。提示
请注意,这是一个新的剧本和任务,因此确保这一条目从行的起始列(列 0)开始。
- name: Wait for port 22 to be ready hosts: webservers gather_facts: False tasks: - local_action: wait_for port=22 host="{{ ansible_ssh_host }}" search_regex=OpenSSH delay=10 -
这最后一组任务在运行中的实例内执行步骤;下一任务将在该运行中的实例上安装 Apache。Ansible 知道操作这个实例,因为这组任务是对
webservers主机组执行的。我们在步骤 2 的任务中,在内存中的库存中注册了这个新组。注意
pre_tasks:部分是可选的,在所有情况下可能不需要。本书中的示例是使用 Ubuntu 16.04 镜像创建的。Ubuntu 16.04 默认不安装 Python 2,然而这个特定的 Ansibleapt模块,最终将安装 Apache,需要执行 Python 2 代码才能正常工作。因此,我们执行一个初始的raw命令,这个命令不执行任何 Python,而是运行一些 shell 脚本来为我们设置一些东西。如果你正在使用随附的 Vagrant 环境,这个示例也会更加复杂,因为实例没有直接访问互联网的权限。所以,作为pre_tasks:部分的一部分,我们还配置了一个 APT 代理服务器。- hosts: webservers remote_user: ubuntu become: yes gather_facts: no pre_tasks: - name: Set APT proxy raw: echo "Acquire::http::Proxy \"http://192.168.1.20:3128\";" > /etc/apt/apt.conf - name: 'install python2' raw: sudo apt-get -y install python-simplejson tasks: - name: Ensure Apache is installed apt: name=apache2 state=latest - name: Ensure that Apache is started service: name=apache2 state=started提示
提示:这个剧本也可以在
raw.githubusercontent.com/OpenStackCookbook/vagrant-openstack/master/orchestrate-instance.yml找到。
创建此文件后,保存并退出。然后运行以下命令,这将启动一个实例并安装 Apache:
source openrc
ansible-playbook orchestrate-instance.yml
这将返回类似下面的熟悉的 Ansible 输出:

它是如何工作的...
我们在这里做的是扩展原本简单的剧本,该剧本启动了一个单一实例,并在实例完成启动过程后,添加了后续的任务,使我们能够在该实例上安装一些软件。如何实现这一点的关键细节在这里描述。
在第一个剧本中,名为 Launch instance on OpenStack,我们首先配置一些任务来设置我们的安全组规则。默认情况下,不允许任何传入连接,而 Ansible 使用 SSH 来执行任务,因此我们至少需要确保 TCP 端口 22 是开放的。我们还配置了适合我们正在安装的服务的规则。在这种情况下,我们运行 Apache,所以我们打开 TCP 端口 80。安全组配置好之后,我们有一个名为 Deploy an instance 的任务。我们确保这个实例启动时使用我们刚刚配置的安全组,并且我们还将该实例注册到名为 nova_cookbook 的变量中。
Ansible 使用inventory数据来允许后续的 play 和 task 访问 Ansible 在环境中执行过的详细信息,因此下一个名为Add instance to Inventory的task会将一个名为cookbook1的host放入一个名为webservers的host group中。对于这个特定的host(名为cookbook1,属于webservers组),我们设置了 Ansible 访问该实例时使用的变量,即分配的浮动 IP 地址:(ansible_ssh_host={{ nova_cookbook.server.accessIPv4 }}。如你所见,我们使用了已注册的变量nova_cookbook来访问 Ansible 存储的该实例的信息。使用浮动 IP 地址非常重要,因为私有租户网络无法从我们的客户端路由,因此 Ansible 无法连接以执行 Apache 安装。
下一个名为Wait for port 22 to be ready的play基本上是一个等待 SSH 启动的task。这表示实例已准备好使用,因此我们可以通过 SSH 进入该实例并执行进一步的 Ansible 命令。
最后一个play包含执行 Apache 安装的tasks。如前所述,我们在此部分加入了一组可选的pre_tasks,以解决 Ubuntu 16.04 没有提供 Ansible 运行所需的 Python 依赖包的问题。我们还在这里设置了一个可选的 APT 代理,因此可以根据所使用的镜像和环境自由删除和调整此部分。
这个play中的最后一组tasks基本上确保 Apache 已经安装并运行。在这里,你可以进一步添加tasks从 GitHub 拉取 Apache 配置数据,或者安装其他软件包,从而通过单个 Ansible 命令完成该实例的设置。
使用 Ansible 在多个实例上协调软件安装。
到目前为止,我们创建的 playbook 首先启动了一个实例,然后在前一个配方中扩展了该过程,接着在运行中的实例上安装了 Apache。本配方描述了一个 playbook,它可以启动任意数量的实例,并在每个实例上安装 Apache。
准备工作
确保你已登录到一个正确配置的 OpenStack 客户端,并能够访问安装了 Ansible 的 OpenStack 环境。
如何操作...
我们将扩展前一个配方中的 playbook,以增加灵活性,支持包括可变数量的实例。
-
基本结构在前面的配方中已经提供,因此我们唯一需要调整的是第一个启动实例的play,名为
Launch instances on OpenStack。这个完整的play如下所示,其中我们引入了一个名为count的变量,已设置为2,并且我们还引入了with_sequence部分,形成一个循环,该循环会执行指定次数的task。请注意,我们还将 count 值作为实例名称的一部分:- name: Launch instances on OpenStack hosts: localhost gather_facts: false vars: count: 2 tasks: - name: Create ansible security group os_security_group: state: present name: ansible verify: false - name: Create a rule to allow SSH connections os_security_group_rule: security_group: ansible protocol: tcp port_range_min: 22 port_range_max: 22 remote_ip_prefix: 0.0.0.0/0 verify: false - name: Create webserver security group os_security_group: state: present name: webserver verify: false - name: Create a rule to allow http connections os_security_group_rule: security_group: webserver protocol: tcp port_range_min: 80 port_range_max: 80 remote_ip_prefix: 0.0.0.0/0 verify: false - name: Deploy an instance os_server: state: present name: cookbook{{ item }} image: xenial-image key_name: demokey timeout: 200 flavor: m1.tiny network: private-net verify: false register: nova_cookbook with_sequence: count={{ count }} - name: Add instance to Inventory add_host: name="{{ item.server.name }}" groups=webservers ansible_ssh_host="{{ item.server.accessIPv4 }}" with_items: "{{ nova_cookbook.results }}" -
下一组任务与前面的食谱中描述的内容相同,例如等待实例的 SSH 可用并随后安装 Apache,这里列出是为了完整性:
- name: Wait for port 22 to be ready hosts: webservers gather_facts: False tasks: - local_action: wait_for port=22 host="{{ ansible_ssh_host }}" search_regex=OpenSSH delay=10 - hosts: webservers remote_user: ubuntu become: yes gather_facts: no注意
pre_tasks:部分是可选的。您的使用方式将根据您所使用的镜像或环境所施加的任何隐性限制而有所不同。有关如何使用它的说明,请参见前面一篇食谱中的描述:pre_tasks: - name: Set APT proxy raw: echo "Acquire::http::Proxy \"http://192.168.1.20:3128\";" > /etc/apt/apt.conf - name: 'install python2' raw: sudo apt-get -y install python-simplejson tasks: - name: Ensure Apache is installed apt: name=apache2 state=latest - name: Ensure that Apache is started service: name=apache2 state=started -
假设您创建的文件名为
multi-orchestrate-instances.yml,您可以使用以下命令执行它:source openrc ansible-playbook multi-orchestrate-instances.yml这将返回如下输出。这产生的输出比到目前为止的其他任务要多,因此这里只显示了最后一部分:
![如何操作...]()
它是如何工作的...
我们在这个剧本中添加了一些额外的内容,扩展了前一个用于将 Apache 安装到新启动实例的剧本。这里对这些内容进行了描述:
vars:
count: 2
我们引入了一个名为 count 的变量,给它赋值为 2。这个变量的作用范围仅限于当前特定的任务(名为 Launch instances on OpenStack)。这个变量用于形成一个循环,正如下面这个分配给 os_server 调用的属性所示:
with_sequence:
count={{ count }}
这基本上表示:当 count = 1 时运行 os_server 模块任务,count = 2 时也运行。在这个顺序中,我们可以访问 count 的值,并存储在一个名为 item 的变量中。我们利用这个值来追加到实例的 name 变量中,从而最终生成 cookbook1 和 cookbook2,其语法如下:
name: cookbook{{ item }}
使用 Ansible 完全编排创建 Web 服务器和负载均衡器堆栈
前面的食谱将实例启动到一个现有环境中,包括现有的网络、镜像和密钥等。例如,使用 Ansible 编排 OpenStack 环境提供了完整的模块集,可以用于操作不仅仅是 Nova。例如,我们可以使用 Ansible 来控制 Glance、Neutron、Cinder 等。
在这个食谱中,我们仅假设用户能够对一个项目进行身份验证。我们不假设任何网络存在,甚至假设没有镜像存在。我们可以获取 Ansible 的世界视图,以确保镜像和网络存在,如果不存在——就创建它们。
请注意,这个食谱旨在带您进入 Ansible 的美妙世界。这个示例展示了从头到尾创建堆栈的过程。优化 Ansible 剧本超出了本书的范围。
准备工作
确保您已登录到正确配置的 OpenStack 客户端,并且可以访问已安装 Ansible 的 OpenStack 环境。
如何操作...
执行以下步骤以启动一个环境,确保镜像可用,设置正确的安全组,创建新的网络和路由器,最后在两台 Web 服务器上安装 Apache:
-
我们可以假设一个空白的 OpenStack 项目,但我们要确保有适当运行的实例和服务。我们首先将任务包含在
Create OpenStack Cloud Environment的剧本中,该剧本首先下载 Ubuntu 16.04 镜像,并将其加载到 OpenStack 中。首先创建full-stack.yml文件,并添加以下内容:- name: Create OpenStack Cloud Environment hosts: localhost gather_facts: false vars: webserver_count: 2 tasks: - name: Download Ubuntu 16.04 Xenial get_url: url: http://releases.ubuntu.com/16.04/ubuntu-16.04.3-server-amd64.img dest: /tmp/ubuntu-16.04.img - name: Ensure Ubuntu 16.04 Xenial Image Exists os_image: name: xenial-image container_format: bare disk_format: qcow2 state: present filename: /tmp/ubuntu-16.04.img verify: false -
接下来,我们将创建 私有租户网络和路由器。我们假设已经存在一个共享的提供者网络。在此实例中,我们假设这个提供者网络(提供浮动 IP 地址)被称为
GATEWAY_NET。继续编辑文件,将以下 任务 添加到相同的Create OpenStack Cloud Environment剧本中:- name: Create the cookbook network os_network: state: present name: cookbook_network external: false shared: false verify: false register: cookbook_network - name: Create the test subnet os_subnet: state: present network_name: "{{ cookbook_network.id }}" name: cookbook_subnet ip_version: 4 cidr: 192.168.0.0/24 gateway_ip: 192.168.0.1 enable_dhcp: yes dns_nameservers: - 192.168.1.20 verify: false register: cookbook_subnet - name: Create the test router os_router: state: present name: cookbook_router network: GATEWAY_NET external_fixed_ips: - subnet: GATEWAY_SUBNET interfaces: - cookbook_subnet verify: false注意
可选(如果使用 Vagrant 环境)。当前,
os_router模块无法向路由器中插入静态路由,因此,如果您需要在 Ansible 控制的剧本中使用静态路由,可以通过执行openstack命令来实现,如下所示。如果您使用的是本书附带的 Vagrant 实验环境,您可能需要为路由器提供静态路由,以便流量从物理主机流向 VirtualBox/VMware 环境。如果需要此功能,请添加以下 任务(根据您的环境进行修改)。在此示例中,运行 Vagrant 环境的物理主机 IP 地址为 192.168.100.1,并允许流量从物理主机流向通过192.168.100.0/24提供商网络的实例,这里的提供商网络即为示例中的GATEWAY_NET:- name: Insert routes into router command: openstack router set --route destination=192.168.1.0/24,gateway=192.168.100.1 cookbook_router register: cookbook_router_route -
接下来,我们配置安全组。记住,Ansible 使用 SSH 连接到服务器,而默认情况下,云镜像会阻止任何传入连接。因此,其中一条规则应该是允许传入的 SSH 连接。我们还需要配置安全组规则,以支持将在实例上运行的服务。在这种情况下,我们将在 TCP 端口 80 上运行 Apache 和 HAProxy,因此这里也需要进行配置:
- name: Create ansible security group os_security_group: state: present name: ansible verify: false - name: Create rule to allow SSH connections os_security_group_rule: security_group: ansible protocol: tcp port_range_min: 22 port_range_max: 22 remote_ip_prefix: 0.0.0.0/0 verify: false - name: Create webserver security group os_security_group: state: present name: webserver verify: false - name: Create rule to allow http connections os_security_group_rule: security_group: webserver protocol: tcp port_range_min: 80 port_range_max: 80 remote_ip_prefix: 0.0.0.0/0 verify: false注意
由于我们是从一个特定的主机上运行 Ansible,因此可以通过限制来自单个 IP 地址的访问,而不是 0.0.0.0/0 的通用范围,进一步增强 Ansible SSH 安全组规则:
-
我们现在可以启动实例。继续编辑此文件,以添加启动多个网页服务器和一个单独 HAProxy 实例的任务,如下所示。请注意,选择的网络、镜像和安全组应与前面任务中创建的设置相匹配:
- name: Deploy Webserver Instances os_server: state: present name: webserver{{ item }} image: xenial-image key_name: demokey timeout: 200 flavor: m1.tiny network: cookbook_network security_groups: default,ansible,webserver verify: false register: nova_webservers with_sequence: count={{ webserver_count }} - name: Add webservers to Inventory add_host: name="{{ item.server.name }}" groups=webservers ansible_ssh_host="{{ item.server.accessIPv4 }}" with_items: "{{ nova_webservers.results }}" - name: Deploy HAProxy Instance os_server: state: present name: haproxy image: xenial-image key_name: demokey timeout: 200 flavor: m1.tiny network: cookbook_network security_groups: default,ansible,webserver verify: false register: nova_haproxy with_sequence: count=1 - name: Add HAProxy to Inventory add_host: name="{{ item.server.name }}" groups=haproxy ansible_ssh_host="{{ item.server.accessIPv4 }}" with_items: "{{ nova_haproxy.results }}" -
正如我们所看到的,我们需要等到 SSH 可用后,Ansible 才能继续,因此我们添加一个 wait,直到满足此条件。请注意,我们将此剧本应用于
webservers和haproxyhosts 组:- name: Wait for port 22 to be ready hosts: webservers:haproxy gather_facts: False tasks: - local_action: wait_for port=22 host="{{ ansible_ssh_host }}" search_regex=OpenSSH delay=10 -
一旦实例启动并运行,最后的任务是安装和配置在实例上运行的服务。我们将首先在我们的网页服务器上安装 Apache。这个剧本应用于我们的
webservers主机,因此这些任务将在每台主机上运行:- name: Configure Web Servers hosts: webservers remote_user: ubuntu become: yes gather_facts: False pre_tasks: - name: Set APT proxy raw: echo "Acquire::http::Proxy \"http://192.168.1.20:3128\";" > /etc/apt/apt.conf - name: 'install python2' raw: sudo apt-get -y install python-simplejson tasks: - name: Ensure Apache is installed apt: name=apache2 state=latest - name: Ensure that Apache is started service: name=apache2 state=started -
由于我们的 Plays 将
gather_facts设置为False(因为我们使用的镜像没有预期的 Python 库来运行 Ansible,默认情况下 Ansible 任务会立即失败,这意味着我们将在新的 Play 中启动一个单独的任务来填充 Ansible 的事实清单,我们在前面的 Play 中安装了先决条件 Python 2 库)。我们需要这些信息以后来填充 HAProxy 配置文件:- name: Gathering facts about webservers hosts: webservers remote_user: ubuntu become: yes tasks: - name: Gathering facts setup: -
现在我们可以安装和配置 HAProxy。这将应用于我们haproxy主机组(只有一个名为haproxy的服务器)。作为这个 Play 的一部分,我们将引用一个 HAProxy 配置文件模板。我们将在下一步中创建这个模板。
注意
Ansible 提供了预定义且经过广泛测试的角色,可用于软件安装。以下指南仅供示例目的。实际上,您将利用来自
galaxy.ansible.com/的角色。继续构建此
full-stack.ymlplaybook 文件,其中包含以下内容:- name: Configure HAProxy hosts: haproxy remote_user: ubuntu become: yes gather_facts: False pre_tasks: - name: Set APT proxy raw: echo "Acquire::http::Proxy \"http://192.168.1.20:3128\";" > /etc/apt/apt.conf - name: 'install python2' raw: sudo apt-get -y install python-simplejson tasks: - name: Update apt cache apt: update_cache=yes cache_valid_time=3600 - name: Install haproxy apt: name=haproxy state=present - name: Enable init script replace: dest='/etc/default/haproxy' regexp='ENABLED=0' replace='ENABLED=1' - name: Update HAProxy config template: src=templates/haproxy.cfg.j2 dest=/etc/haproxy/haproxy.cfg notify: - restart haproxy handlers: - name: restart haproxy service: name=haproxy state=restarted -
在我们继续执行 playbook 之前,我们需要根据前面步骤中指定的内容创建 HAProxy 配置模板文件。配置指向一个名为
haproxy.cfg.j2的模板文件,位于templates目录中。在您正在编辑full-stack.yml文件的当前工作目录中创建此目录:mkdir templates/ vi templates/haproxy.cfg.j2 -
将
haproxy.cfg.j2文件填充如下内容:global log 127.0.0.1 local0 notice maxconn 2000 user haproxy group haproxy daemon defaults log global mode http option httplog option dontlognull retries 3 option redispatch timeout connect 5000 timeout client 10000 timeout server 10000 listen {{haproxy_app_name}} bind *:80 mode {{haproxy_mode}} stats {{haproxy_enable_stats}} {% if haproxy_enable_stats == 'enable' %} stats uri /haproxy?stats stats realm Strictly\ Private {% endif %} balance {{haproxy_algorithm}} option httpclose option forwardfor {% for host in groups['webservers'] %} server {{ hostvars[host].inventory_hostname }} {{ hostvars[host]['ansible_all_ipv4_addresses'][0] }} check {% endfor %}注意
server {{ hostvars[host]...check行都在一行上。 -
templates/haproxy.cfg.j2文件还涉及到一些我们尚未向 Ansible 声明的变量,例如haproxy_app_name和haproxy_algorithm。这些变量位于特定于我们haproxy组的group_var文件中。要创建此组变量文件,我们需要创建一个名为group_vars/haproxy的目录,并在其中创建一个名为main.yml的文件。从与我们的full-stack.yml文件相同的目录中执行以下步骤:mkdir -p group_vars/haproxy vi group_vars/haproxy/main.yml -
将
group_vars/haproxy/main.yml文件填充如下内容:--- haproxy_app_name: myapp haproxy_mode: http haproxy_enable_stats: enable haproxy_algorithm: roundrobin -
现在我们可以准备运行我们的
full-stack.ymlplaybook,以创建类似于 Heat 示例描述的环境。执行以下命令:source openrc ansible-playbook full-stack.yml这将产生类似于以下内容的输出。由于这是一个较长的 playbook,只显示最后部分:
![如何做...]()
我们还可以通过查看
openstack server list的输出来验证这些实例正在运行并分配的地址:![如何做...]()
-
最后,我们可以通过访问 HAProxy 服务器的浮动 IP 地址来测试我们的设置,如下所示。在这里,我们可以查看 HAProxy 统计信息:
![如何做...]()
工作原理是这样的...
我们在这里做的是系统地构建一个名为full-stack.yml的 playbook,它执行以下步骤:
-
如有必要,请下载并安装 Ubuntu 16.04 镜像
-
创建我们的 Web 服务器和 Ansible SSH 安全组
-
创建一个私有租户网络、路由器并配置路由器
-
启动两个 Web 服务器实例和一个 HAProxy 实例
-
为每个 Web 服务器安装 Apache
-
对于 HAProxy 服务器,安装 HAProxy 并配置配置文件,自动填充 Ansible 从启动 Web 服务器中获取的信息(例如分配给每个 Web 服务器的 IP 地址)。
在这个示例中,我们介绍了几个显著的项:Ansible 事实、Jinja2配置模板文件(haproxy.cfg.j2文件)和group_vars。
Ansible 的事实和 HAProxy 的group_var变量被用来填充 HAProxy 配置文件templates/haproxy.cfg.j2。这个文件大部分看起来像普通的haproxy.cfg文件,但包含适用于 Jinja2 的元素,Ansible 会解析这些元素。特别值得注意的是haproxy.cfg文件,它包含负载均衡池成员行,通常看起来像以下基本结构:
server webserver1 192.168.0.6 check
server webserver2 192.168.0.3 check
当我们将实例启动到 OpenStack 时,我们不知道它们会被分配什么 IP 地址,但 Ansible 通过其事实收集做到了这一点。如果我们看看模板中的同一行,我们得到以下内容:
{% for host in groups['webservers'] %}
server {{ hostvars[host].inventory_hostname }} {{ hostvars[host]['ansible_all_ipv4_addresses'][0] }} check
{% endfor %}
这一行在开头和结尾有一些静态文本,用server和check表示。它们是相同的server和check文本,正如我们在最终输出中看到的。
模板和 Ansible 的魔力在于我们可以通过循环来做的事情,这个循环包围了这一行和我们可以访问的hostvars。循环说明:
对于webservers 组中的每个hosts(回顾一下,我们将 Web 服务器实例注册到这个特定的清单组中),获取hostvars[host].inventory_hostname和hostvars[host]['ansible_all_ipv4_addresses'][0](来自收集的事实)的值。这个最后的变量取ansible_all_ipv4_addresses字典中的第一个条目,它是我们实例的内部 IP。
结果是上一页显示的输出,列出了 HAProxy 可以访问的负载均衡池中的 Web 服务器。
我们并不局限于 Ansible 收集到的变量。我们指定了一个group_var变量文件,内容如下:
---
haproxy_app_name: myapp
haproxy_mode: http
haproxy_enable_stats: enable
haproxy_algorithm: roundrobin
这在模板文件中的以下位置直接引用。这允许我们添加一些可配置的静态元素,同时保持灵活的、环境无关的 Playbook 集合。
listen {{haproxy_app_name}}
bind *:80
mode {{haproxy_mode}}
stats {{haproxy_enable_stats}}
{% if haproxy_enable_stats == 'enable' %}
stats uri /haproxy?stats
stats realm Strictly\ Private
{% endif %}
balance {{haproxy_algorithm}}
第十章:使用 OpenStack Dashboard
本章将涵盖以下主题:
-
介绍 – OpenStack Dashboard
-
使用 OpenStack Dashboard 进行密钥管理
-
使用 OpenStack Dashboard 管理 Neutron 网络和路由器
-
使用 OpenStack Dashboard 管理安全组
-
使用 OpenStack Dashboard 启动实例
-
使用 OpenStack Dashboard 删除实例
-
使用 OpenStack Dashboard 添加新项目
-
使用 OpenStack Dashboard 进行用户管理
-
使用 OpenStack Dashboard 配合 LBaaS
-
使用 OpenStack Dashboard 与 OpenStack Orchestration 配合使用
介绍 – OpenStack Dashboard
通过命令行接口管理我们的 OpenStack 环境使我们能够完全控制云环境,但提供一个基于 Web 的界面,供操作员和管理员用来管理他们的环境和实例,则使这个过程更加便捷。OpenStack Dashboard,称为 Horizon,提供了一个图形化的 Web 用户界面。Horizon 是一个 Web 服务,运行在 Apache 安装下,使用 Python 的 Web Service Gateway Interface (WSGI) 和 Django,一个快速开发的 Web 框架。
安装 OpenStack Dashboard 后,我们可以管理 OpenStack 环境的所有核心组件。如果你使用 OpenStack Ansible playbook,Horizon 会通过 os-horizon-install.yml playbook 安装。
使用 OpenStack Dashboard 进行密钥管理
SSH 密钥对允许用户在不需要密码的情况下连接到他们的 Linux 实例,它几乎是所有你将在 OpenStack 中使用的 Linux 镜像的默认访问机制。用户可以通过 OpenStack Dashboard 管理自己的密钥对。通常,这是新用户在获得访问 OpenStack 环境权限后要做的第一项任务。
准备工作
打开一个 Web 浏览器,访问我们的 OpenStack Dashboard 地址 http://192.168.100.117/,并以 default 域中的用户身份登录,例如在 第二章 OpenStack 客户端 配方中创建的 developer 用户,使用密码 cookbook4。我们的 Dashboard URL 与 第一章 使用 Ansible 安装 OpenStack 中讨论的公共负载均衡器 IP 相同。如果你需要查找 Horizon 的 URL,可以根据 第三章 Keystone – OpenStack 身份服务 中描述的方式,使用 OpenStack 目录列表中的公共 IP 地址。
如何操作…
登录用户的密钥对管理通过以下章节中讨论的步骤来实现:
添加密钥对
密钥对可以通过以下步骤添加:
-
可以通过点击项目 | 计算部分中的密钥对选项卡,将新密钥对添加到我们的系统:
![添加密钥对]()
-
我们现在会看到一个屏幕,允许密钥对管理。在屏幕的右上角有一个创建密钥对按钮。点击该按钮来创建新的密钥对:
![添加密钥对]()
-
在创建密钥对屏幕上,输入一个有意义的名称(例如
developer),确保名称中没有空格,然后点击创建密钥对按钮:![添加密钥对]()
-
新密钥对创建后,密钥对的私钥部分将自动下载。如果没有,请点击重新生成并下载密钥对 "developer"按钮:
![添加密钥对]()
注意
私有 SSH 密钥无法重新创建,因此请妥善保管,并确保将其安全地存储在文件系统中。
-
点击密钥对链接,返回到我们的密钥对列表。此时我们会看到新创建的密钥对已列出。在启动实例时,我们可以选择这个新密钥对,并仅使用我们本地存储的私钥访问它:
![添加密钥对]()
删除密钥对
可以通过执行以下步骤删除密钥对:
-
当不再需要密钥对时,我们可以将其从 OpenStack 环境中删除。为此,请点击屏幕左侧的密钥对选项卡。
-
然后我们将看到一个屏幕,允许访问密钥对管理。在密钥对下,会列出我们可以用来访问实例的密钥对。要从系统中删除一个密钥对,点击我们想要删除的密钥对旁边的删除密钥对按钮:
![删除密钥对]()
-
我们将看到一个确认对话框:
![删除密钥对]()
一旦点击删除密钥对按钮,密钥对将被删除。
导入密钥对
如果你有用于访问其他系统的密钥对,这些密钥对可以导入到我们的 OpenStack 环境中,从而继续用于访问我们 OpenStack 计算环境中的实例。要导入密钥对,请执行以下步骤:
-
我们可以将传统 Linux 环境中创建的密钥对导入到 OpenStack 设置中。如果你还没有密钥对,可以在 Linux 或其他 Unix 主机上运行以下命令:
ssh-keygen -t rsa -f cookbook.key -
这将在我们的客户端上生成以下两个文件:
cookbook.keycookbook.key.pub -
cookbook.key文件是我们的私钥,必须保护它,因为它是唯一与cookbook.key.pub密钥对的公钥部分匹配的密钥。 -
我们可以导入这个公钥到 OpenStack 环境中,这样当实例启动时,公钥会被插入到正在运行的实例中。要导入公钥,确保你在访问与安全屏幕,然后在密钥对下,点击导入密钥对按钮:
![导入密钥对]()
-
我们看到一个屏幕,要求我们命名密钥对并粘贴我们的公钥内容。所以请命名密钥对,然后将公钥的内容复制并粘贴到空白处——例如,
cookbook.key.pub的内容。一旦输入完毕,点击导入密钥对按钮:![导入密钥对]()
完成后,我们会看到该用户可用的密钥对列表,包括我们导入的密钥对:

工作原理…
密钥对管理很重要,因为它为访问我们的运行实例提供了一种一致且安全的方式。允许用户在其项目中创建、删除和导入密钥对,可以帮助他们创建更安全的系统。
OpenStack 仪表盘允许用户轻松创建密钥对。不过,用户必须确保下载的私钥保持安全。
虽然删除密钥对很简单,但用户必须记住,删除与正在运行的实例关联的私钥会导致无法访问正在运行的系统。从仪表盘删除密钥对不会删除已经运行的实例中的密钥。每个创建的密钥对都是唯一的,不管其名称是什么。名称只是标签,密钥的唯一指纹是必需的,且无法重新创建。
导入密钥对的优势在于,我们可以在 OpenStack 内部使用我们已经在外部使用的现有安全密钥对。这为在不同环境之间迁移提供了一致的用户体验。
使用 OpenStack 仪表盘管理 Neutron 网络和路由器
OpenStack 仪表盘具有查看、创建和编辑 Neutron 网络的功能,这使得管理复杂的软定义网络变得更加容易。某些功能,如创建共享网络和提供商路由器,要求用户以管理员权限登录 OpenStack 仪表盘,但任何用户都可以创建私有网络。为了帮助管理复杂的软定义网络,OpenStack 仪表盘提供了图形化查看和更新网络拓扑的功能。
准备工作
打开一个网页浏览器,访问我们的 OpenStack Dashboard 地址 http://192.168.100.117/,并以 default 域中的用户身份登录,例如在第二章 OpenStack 客户端 中创建的 developer 用户,密码为 cookbook4。我们的 Dashboard URL 与第一章 使用 Ansible 安装 OpenStack 中讨论的公共负载均衡器 IP 地址相同。如果你需要找出 Horizon 的 URL,请使用 OpenStack 目录列表中的公共 IP,方法如在第三章 Keystone – OpenStack 身份服务 中所述。
如何操作
本食谱将指导你通过 OpenStack Dashboard 创建和删除网络:
创建网络
要为已登录用户创建私有网络,请执行以下步骤:
-
要管理 OpenStack Dashboard 中的网络,选择网络标签,如下图所示:
![创建网络]()
-
选择该选项后,我们将看到一个可以分配给实例的网络列表:
![创建网络]()
-
要创建一个新网络,点击创建网络按钮。
-
我们将看到一个对话框,首先要求我们为网络命名:
![创建网络]()
-
选择名称后,保持管理状态设置为启用(这意味着我们的网络将处于开启状态,并且实例可以连接到该网络),然后选择子网标签或点击下一步按钮为其分配一个子网:
![创建网络]()
-
填写子网的详细信息后,选择子网详情标签,允许我们配置例如 DHCP 范围、DNS 和用户选择该网络时希望设置的任何其他路由:
![创建网络]()
-
填写完所有详细信息后,点击创建按钮,这将使该网络对我们项目的用户可用,并将我们带回可用网络列表:
![创建网络]()
创建路由器
一旦添加了私有网络,它可能需要连接到外部网络。如果你有公共网络,只需在私有网络和公共网络之间创建一个路由器即可。
要管理路由器,请执行以下步骤:
-
选择路由器标签,如下图所示:
![创建路由器]()
这将显示已登录用户可用的路由器:
![创建路由器]()
-
点击创建路由器按钮以添加新路由器:
![创建路由器]()
-
输入路由器名称并选择外部网络。在我们的例子中,我们将选择 公共 网络。点击 创建路由器 按钮。将显示可用路由器的列表,包括新创建的路由器:
![创建路由器]()
-
点击新创建的路由器名称查看详细信息:
![创建路由器]()
-
此路由器仍然缺少一个接口。要将私有网络作为可用接口添加,请选择 接口 标签:
![创建路由器]()
-
点击 添加接口 按钮以添加缺失的接口:
![创建路由器]()
-
选择需要通过路由器连接到公共网络的子网,并点击 提交 按钮。现在我们的路由器有了一个额外的接口:
![创建路由器]()
查看网络
OpenStack 控制面板为用户和管理员提供查看环境拓扑的能力。要查看网络拓扑,请执行以下步骤:
-
要在我们的 OpenStack 控制面板中管理网络,请选择 网络拓扑 标签,如下图所示:
![查看网络]()
-
点击 网络拓扑 标签会显示一个丰富的界面,概览我们网络及附加在其上的实例,如下所示:
![查看网络]()
-
在这个界面中,我们可以点击该界面的各个部分,如网络(带我们进入管理网络界面)、实例(带我们进入实例界面),以及创建新网络、路由器和启动新实例。
删除路由器
要删除登录用户的私有路由器,请执行以下步骤:
-
要在我们的 OpenStack 控制面板中管理路由器,请选择 路由器 标签,如下图所示:
![删除路由器]()
-
选择此选项后,我们将看到所有登录用户的可用路由器:
![删除路由器]()
-
要删除路由器,请点击 清除网关 按钮旁边的下拉操作菜单项,然后点击 删除路由器 选项:
![删除路由器]()
-
一旦路由器被删除,您将看到可用剩余路由器的列表:
![删除路由器]()
删除网络
要删除登录用户的私有网络,请执行以下步骤:
-
要在我们的 OpenStack 控制面板中管理网络,请选择 网络 标签,如下图所示:
![删除网络]()
-
选择此选项后,我们将看到一个可以分配给实例的网络列表:
![删除网络]()
-
要删除网络,请选中我们想要删除的网络名称旁的复选框,然后点击 删除网络 按钮:
![删除网络]()
-
我们将看到一个对话框,要求我们确认删除操作:
![删除网络]()
-
点击 删除网络 按钮将删除该网络,并返回到可用网络的列表中。
注意
你只能删除没有实例附加的网络。如果该网络上仍然有实例,系统会警告你无法删除。
它是如何工作的…
查看和编辑 Neutron 网络的功能是 OpenStack 较早版本引入的一个便捷特性。管理 Neutron 网络和路由器可能相当复杂,但借助 OpenStack Dashboard 提供的可视化帮助,操作变得更加轻松。
作为管理员(具有管理员角色的用户),你可以创建共享网络。前面的配方中的相同过程也适用,但你会看到一个额外的选项,允许所有创建的网络被所有项目看到。
使用 OpenStack Dashboard 进行安全组管理
安全组是网络规则,允许一个项目中的实例与另一个项目中的实例相隔离。在 OpenStack Dashboard 中,管理安全组规则变得非常简单。
准备好
打开一个网页浏览器,访问我们的 OpenStack Dashboard 地址 http://192.168.100.117/,并以 default 域中的用户身份登录,例如在第二章 OpenStack 客户端 的 常见 OpenStack 身份任务 配方中创建的 developer 用户,使用 cookbook4 密码。我们的 Dashboard URL 与第一章 使用 Ansible 安装 OpenStack 中讨论的公共负载均衡器 IP 地址相同。如果你需要查找 Horizon 的 URL,请使用 OpenStack 目录列表中的公共 IP,如第三章 Keystone – OpenStack 身份服务 中所述。
操作步骤…
要在 OpenStack Dashboard 中管理安全组,请按照以下章节中的步骤进行操作:
创建安全组
创建安全组,请执行以下步骤:
-
通过 网络 部分的 安全组 标签,我们可以将新的安全组添加到系统中,因此请点击它:
![创建安全组]()
-
接下来,我们将看到一个屏幕,允许访问安全设置并管理密钥对。在 安全组 中,将列出我们启动实例时可以使用的安全组。要创建一个新的安全组,请点击 创建安全组 按钮:
![创建安全组]()
-
我们需要为安全组命名并提供描述。名称不能包含空格:
![创建安全组]()
-
创建新安全组后,屏幕上将显示可用安全组的列表。在这里,我们可以向新的安全组添加新的网络安全规则:
![创建安全组]()
编辑安全组以添加和删除规则
要添加和删除规则,可以通过执行以下步骤编辑安全组:
-
当我们创建了一个新的安全组,或者希望修改现有安全组的规则时,可以点击该安全组的管理规则按钮:
![编辑安全组以添加和删除规则]()
-
在点击管理规则按钮后,我们将进入一个列出所有现有规则的界面,允许我们向该安全组添加新规则:
![编辑安全组以添加和删除规则]()
要向新的安全组添加规则,我们点击添加规则按钮。这将允许我们根据不同的协议类型创建规则:ICMP、TCP和UDP。还提供了常用服务的规则模板列表。举个例子,我们将添加一条允许来自任何地方的HTTPS访问的安全组规则。为此,我们选择以下选项:
![编辑安全组以添加和删除规则]()
-
我们从下拉菜单中选择HTTPS选项。这会将我们带回到添加规则菜单,在这里我们可以指定网络流量的来源:
![编辑安全组以添加和删除规则]()
-
当我们点击添加按钮时,我们会被重定向到与我们的安全组相关联的规则列表。重复前一步骤,直到配置完成与安全组相关的所有规则:
![编辑安全组以添加和删除规则]()
-
我们还可以为没有内置规则模板的服务添加自定义安全规则。在点击添加规则按钮后,我们将从规则下拉列表中选择自定义 TCP 规则选项。然后,我们将从开放端口下拉列表中选择端口范围选项,这将展示起始端口和结束端口字段。我们输入端口范围后,点击添加按钮:
![编辑安全组以添加和删除规则]()
-
请注意,我们也可以在这里删除规则。只需选择我们不再需要的规则,并点击删除规则按钮。系统将要求我们确认删除操作。
删除安全组
删除安全组的步骤如下:
-
删除安全组的操作是选择我们要删除的安全组,并点击删除安全组按钮:
![删除安全组]()
-
您将被要求确认此操作。点击删除安全组将删除安全组及其关联的访问规则:
![删除安全组]()
注意
如果有实例正在使用该安全组,您将无法删除该安全组。
它是如何工作的…
安全组对我们的 OpenStack 环境至关重要,因为它们为访问运行中的实例提供了一种一致且安全的方式。允许用户创建、删除和修改安全组以供其项目使用,使他们能够创建安全的环境。安全组中的规则是“默认拒绝”,意味着如果没有为特定协议定义规则,则该协议的流量无法访问分配给该安全组的运行实例。
安全组在创建时与实例关联;然而,它们也可以稍后添加到正在运行的实例中。例如,假设某个实例仅使用default安全组启动。我们设置的default安全组仅允许访问 TCP 端口22,并且能够 ping 实例。如果我们需要访问 TCP 端口80,则必须将此规则添加到default安全组中,或者将一个新的安全组添加到正在运行的实例中。
提示
对安全组的修改会立即生效,任何分配了该安全组的实例都将应用这些新规则。
使用 OpenStack Dashboard 启动实例
使用 OpenStack Dashboard 启动实例非常简单。我们只需选择所需的镜像,选择实例的大小,然后启动它。
准备工作
打开一个网页浏览器,访问我们的 OpenStack Dashboard 地址http://192.168.100.117/,并以default域中的用户(如在第二章的Common OpenStack 身份任务配方中创建的developer用户)身份登录,密码为cookbook4。我们的仪表板 URL 与在第一章的使用 Ansible 安装 OpenStack中讨论的公共负载均衡器 IP 相同。如果需要查找你的 Horizon 的 URL,请使用 OpenStack 目录列表中的公共 IP,方法请参考第三章的Keystone – OpenStack 身份服务。
如何操作…
要通过 OpenStack Dashboard 界面启动实例,请执行以下步骤:
-
转到计算部分的实例标签页:
![如何操作…]()
-
到达此页面后,您将看到所有正在运行的实例:
![如何操作…]()
-
在实例屏幕上,点击启动实例按钮。这将显示实例创建的第一个标签页:
![如何操作…]()
输入实例名称,选择可用区和实例数量。然后,点击下一步按钮。
-
选择实例启动时应使用的源。我们在示例中使用的是预加载的
ubuntu-xenial镜像。如果需要 Cinder 卷,也可以在此标签中指定。设置好实例源信息后,点击下一步按钮:![如何操作…]()
-
选择你的虚拟机(VM)规格。规格决定了虚拟机的大小。点击下一步按钮继续:
![如何操作…]()
-
选择在启动时应该附加到实例的网络。可以指定多个网络。选择网络后,点击左侧的安全组标签:
![如何操作…]()
-
选择应该附加到实例的安全组。安全组决定了新创建的虚拟机的网络访问权限。点击下一步按钮继续:
![如何操作…]()
-
在此屏幕上,我们需要选择一个密钥对,用于实例启动后访问该实例。选择密钥对后,你可以点击启动实例按钮,或者查看其余屏幕以获取可能会添加到实例中的额外信息:
![如何操作…]()
-
虚拟机启动后,将显示现有实例列表。如果新创建的虚拟机出现问题,它将在状态列中显示:
![如何操作…]()
它是如何工作的……
从 Horizon——OpenStack 仪表板——启动实例是通过几个步骤完成的,所有这些都通过引导式的启动实例界面。以下是启动实例所需的属性:
-
来源:这可以是镜像、快照、卷或卷快照
-
规格或大小:这决定了实例的计算、内存和存储容量
-
网络:必须选择至少一个网络接口以启动实例
-
安全组:这些不是启动实例所必需的,但它们用于控制实例的网络访问
-
密钥对:这是可选的,但建议用于登录到实例
实例标签显示了我们开发项目中正在运行的实例。
提示
你还可以通过点击概览标签,查看我们环境中正在运行的概况。
使用 OpenStack 仪表板删除实例
使用 OpenStack 仪表板终止实例非常简单。
准备工作
打开一个网页浏览器,访问我们的 OpenStack Dashboard 地址 http://192.168.100.117/,并以 default 域中的用户身份登录,例如在 第二章 OpenStack 客户端 中创建的 developer 用户,密码为 cookbook4。我们 Dashboard 的 URL 与 第一章 使用 Ansible 安装 OpenStack 讨论的公共负载均衡器 IP 相同。如果你需要查找 Horizon 的 URL,可以使用 OpenStack 目录列表中的公共 IP,如 第三章 Keystone – OpenStack 身份服务 中所述。
如何操作……
使用 OpenStack Dashboard 删除实例,请执行以下步骤:
-
选择 实例 标签页,勾选要终止的实例旁边的复选框,然后点击红色的 删除实例 按钮:
![如何操作]()
-
我们将看到一个确认屏幕。点击 删除实例 按钮以终止选定的实例:
![如何操作]()
-
现在我们会看到 实例 屏幕,并确认实例已成功删除。
它是如何工作的……
使用 OpenStack Dashboard 删除实例很简单。我们只需选择正在运行的实例,并点击 删除实例 按钮,该按钮在选择实例时会被高亮显示。点击 删除实例 按钮后,我们需要确认此操作,以最大程度地减少意外终止实例的风险。
使用 OpenStack Dashboard 添加新项目
OpenStack Dashboard 不仅仅是管理我们实例的界面。它还允许管理员配置环境、用户和项目。在 OpenStack Dashboard 中,添加用户可以加入的新项目非常简单。
准备就绪
打开一个 web 浏览器,指向我们的 OpenStack Dashboard 地址 http://192.168.100.117/,并以 default 域中的用户(例如在第二章中的Common OpenStack identity tasks食谱创建的 developer 用户)身份登录,使用 cookbook4 密码。我们的仪表盘网址与第一章中讨论的公共负载均衡器 IP 相同。如果你需要查找 Horizon 的 URL,可以使用 OpenStack 目录列表中的公共 IP,正如在第三章中描述的那样,Keystone – OpenStack 身份服务。
如何操作…
要将一个新项目添加到我们的 OpenStack 环境,执行以下步骤:
-
在我们以具有管理员权限的用户身份登录后,我们将看到更多的菜单选项出现在身份选项卡下。其中一个选项是项目,如下图所示:
![如何操作…]()
-
要管理项目,我们点击身份选项卡下列出的项目选项。这将列出我们环境中可用的项目,如下图所示:
![如何操作…]()
-
要创建一个新项目,点击创建项目按钮。
-
接下来,我们将看到一个表单,要求输入项目名称和描述。将
horizon作为我们的项目名称,并输入描述:![如何操作…]()
-
我们通过选择启用复选框来启用该项目,然后点击创建项目按钮。
-
我们将看到一个当前可用的项目列表,并显示一条消息,说明
horizon项目已成功创建。
它是如何工作的…
OpenStack Dashboard 是一个功能丰富的界面,补充了在管理 OpenStack 环境时可用的命令行选项。这意味着我们可以简单地创建一个项目,用户可以加入到该项目中,使用 OpenStack Dashboard。创建新项目时,我们需要以具有管理员权限的用户身份登录,以便访问完整的项目管理界面。
使用 OpenStack Dashboard 进行用户管理
OpenStack Dashboard 使我们能够通过 Web 界面管理用户。这允许管理员轻松地在 OpenStack 环境中创建和编辑用户。要管理用户,你必须使用管理员角色成员的帐户登录。
准备工作
打开一个网页浏览器,将其指向我们 OpenStack Dashboard 的地址 http://192.168.100.117/,并以 default 域中的用户身份登录,例如在第二章的常见 OpenStack 身份任务食谱中创建的 developer 用户,密码为 cookbook4。我们的仪表板的 URL 与第一章的使用 Ansible 安装 OpenStack中讨论的公共负载均衡器 IP 相同。如果你需要查找 Horizon 的 URL,请使用 OpenStack 目录列表中的公共 IP,如第三章的Keystone – OpenStack 身份服务中所述。
如何操作……
在 OpenStack Dashboard 中的用户管理通过执行以下章节讨论的步骤来实现。
添加用户
要添加用户,请执行以下步骤:
-
在身份面板中,点击用户选项以显示系统上配置的用户列表:
![添加用户]()
此截图为了清晰和节省空间,截断了可用的用户列表。
-
要创建一个新用户,点击创建用户按钮。
-
我们将看到一个表单,要求填写用户名的详细信息。请输入用户名、电子邮件和该用户的密码。在下面的截图示例中,我们创建了一个名为
test的用户,设置了密码,并将该用户分配给horizon项目,角色为管理员。点击创建用户按钮以创建一个包含所有指定详细信息的新用户:![添加用户]()
-
我们将返回到列出我们 OpenStack 环境中的用户的屏幕,并显示一条消息,表示我们的用户创建成功。
删除用户
要删除用户,请执行以下步骤:
-
在身份面板中,点击用户选项以显示系统上的用户列表。
-
我们将看到我们 OpenStack 环境中的用户列表。要删除一个用户,点击编辑按钮,弹出一个下拉列表,其中包含删除用户选项:
![删除用户]()
-
点击删除用户选项会弹出确认对话框。点击删除用户按钮确认,删除该用户:
![删除用户]()
更新用户的详细信息和密码
要更新用户的详细信息和密码,请执行以下步骤:
-
在身份面板中,点击用户选项以显示系统上的用户列表。
-
要更改用户的密码、电子邮件地址或主要项目,点击该用户的编辑按钮。
-
这将弹出一个对话框,要求提供相关信息。当信息设置完成后,点击更新用户按钮:
![更新用户详情和密码]()
将用户添加到项目中
要将用户添加到项目中,请执行以下步骤:
-
在身份面板中,点击项目选项以显示系统中的项目列表:
![将用户添加到项目]()
-
点击管理成员选项以显示与项目关联的用户列表以及我们可以将其添加到项目中的用户列表:
![将用户添加到项目]()
-
要将新用户添加到列表中,只需点击该用户旁边的+(加号)按钮。
-
要更改该项目中用户的角色,请选择用户名旁边的下拉菜单并选择新的角色(或多个角色):
![将用户添加到项目]()
在我们的示例中,我们已将
developer用户添加到demo项目,并为user分配了admin和_member_角色。 -
在点击对话框底部的保存按钮后,我们将看到一条消息,表示我们的项目已更新。此用户现在可以在不同的项目中启动实例。
从项目中移除用户
要从项目中移除用户,请执行以下步骤:
-
在身份面板中,点击项目选项以显示系统中的项目列表。
-
例如,要从
demo项目中移除用户,请点击管理成员按钮:![从项目中移除用户]()
-
点击管理成员按钮后,您将看到一个弹出窗口,显示所有用户以及项目成员的列表,我们可以将其从项目中移除:
![从项目中移除用户]()
-
要从此项目中移除用户,请点击项目成员下该特定用户旁边的-(减号)按钮。
-
在点击对话框底部的保存按钮后,我们将看到一条消息,表示我们的项目已更新。
工作原理……
OpenStack 仪表板使得创建用户、修改其在项目中的成员身份、更新密码以及将其从系统中删除变得更加简便。
使用 OpenStack 仪表板与 LBaaS
OpenStack 仪表板具有查看、创建和编辑负载均衡器、添加虚拟 IP(VIPs)以及将节点添加到负载均衡器后的功能。仪表板还提供了创建 HA Proxy 服务器负载均衡服务的接口。我们首先通过创建负载均衡池来做,然后将正在运行的实例添加到这些池中。
在本节中,我们将使用两个运行 Apache 的实例。我们将创建一个 HTTP 负载均衡池,创建一个虚拟 IP(VIP),并将实例配置为池的一部分。结果是能够使用 HTTP 负载均衡池地址将流量发送到两个运行 Apache 的实例。
准备工作
打开一个网页浏览器,访问我们的 OpenStack 仪表盘地址 http://192.168.100.117/,并以 default 域中的用户登录,例如在第二章的常见 OpenStack 身份任务食谱中创建的 developer 用户,使用 cookbook4 密码登录。我们的仪表盘 URL 与在第一章的使用 Ansible 安装 OpenStack中讨论的公共负载均衡器 IP 相同。如果您需要查找 Horizon 的 URL,可以使用在第三章的Keystone – OpenStack 身份服务中描述的 OpenStack 目录列表中的公共 IP。
如何操作…
本食谱将指导您如何使用 OpenStack 仪表盘创建和删除负载均衡器:
创建负载均衡器
要为已登录用户创建负载均衡器池,请执行以下步骤:
-
要在我们的 OpenStack 仪表盘中管理负载均衡器,请选择负载均衡器选项卡,如下图所示:
![创建负载均衡器]()
-
这将显示可用的负载均衡池。由于我们当前没有任何已创建的负载均衡池,请点击右上角的创建负载均衡器按钮以添加负载均衡器。
-
点击创建负载均衡器按钮后,我们将看到一个弹出窗口。填写详细信息以添加新的负载均衡器:
![创建负载均衡器]()
-
IP 地址不是必需的;如果未提供,系统将选择所选子网中的下一个可用 IP。
-
通过点击下拉菜单选择池的子网。我们的所有实例都连接到私有网络,因此我们选择private-subnet。
-
点击下一步按钮后,提供负载均衡器监听器的详细信息:
![创建负载均衡器]()
-
HTTP和TCP协议可供我们选择,因此我们将使用HTTP。TERMINATED_HTTPS仅在配置了密钥管理服务时可用。 -
选择前端监听的端口。一个负载均衡器可以配置多个监听器,但每个监听器必须具有唯一的端口。
-
点击下一步按钮后,提供池的详细信息。我们将使用
ROUND_ROBIN负载均衡方法。其他算法包括LEAST_CONNECTIONS和SOURCE_IP:![创建负载均衡器]()
-
点击下一步按钮进入池成员页面。通过点击可用实例旁边的添加按钮,将成员添加到池中:
![创建负载均衡器]()
提示
如果实例未列在可用实例中,请点击添加外部成员按钮。
-
点击下一步按钮后,我们将进入监控器详情页面。在这里,我们为池成员配置健康检查。我们将使用
PING作为监控器类型。其他可选类型包括HTTP和TCP。 -
设置健康检查间隔时间(以秒为单位),然后设置重试次数和健康检查超时的时间:
![创建负载均衡器]()
注意
每个池只能关联一个健康监控器。
-
点击创建负载均衡器按钮,使用所有输入的详情创建负载均衡器。您将在所有可用负载均衡器的列表中看到新创建的负载均衡器。
![创建负载均衡器]()
删除负载均衡器
要删除负载均衡器,我们首先需要删除附加的健康监控器、监听器和池。在我们的示例中,我们将展示如何删除其中一个,但如果有多个池,您需要在删除负载均衡器之前删除所有池、监听器和健康监控器。
-
从负载均衡器页面开始,点击您希望删除的负载均衡器名称。在我们的示例中,名称是
web-loadbalancer:![删除负载均衡器]()
-
从负载均衡器详情页面,点击监听器名称。在我们的示例中,监听器名为
test-lb:![删除负载均衡器]()
-
在监听器详情页面,点击默认池 ID:
![删除负载均衡器]()
默认池 ID 位于管理员状态下方,它是显示的三个 ID 中的第一个:
![删除负载均衡器]()
-
点击池 ID 会将我们带到池详情页面。点击添加/移除池成员按钮删除所有池成员:
![删除负载均衡器]()
-
这将显示一个新的页面,用于移除池成员。通过点击每个成员旁边的移除按钮,删除所有池成员:
![删除负载均衡器]()
-
点击添加/移除池成员按钮以保存更改:
![删除负载均衡器]()
-
删除池成员后,我们将返回到池详情页面。我们需要删除所有健康监控器,才能删除池:
![删除负载均衡器]()
-
点击健康监控器 ID以访问健康监控器详情:
![删除负载均衡器]()
-
从健康监控器详情页面,点击编辑按钮旁边的下拉箭头,选择删除健康监控器选项。点击删除健康监控器选项以删除健康监控器:
![删除负载均衡器]()
-
这将显示一个确认页面。点击删除健康监控器按钮进行确认:
![删除负载均衡器]()
-
删除健康监控后,我们会回到池的页面。点击编辑池按钮旁边的操作箭头,展开删除池选项。点击删除池选项:
![删除负载均衡器]()
-
系统会显示确认页面。点击删除池按钮以确认删除池:
![删除负载均衡器]()
-
删除池后,我们会回到监听器详情页面。点击编辑按钮旁边的操作箭头,展开删除监听器选项。点击删除监听器选项以删除监听器:
![删除负载均衡器]()
-
系统会显示确认页面;点击删除监听器按钮以确认删除监听器:
![删除负载均衡器]()
-
删除监听器后,我们会回到负载均衡器详情页面。点击编辑按钮旁边的操作箭头,展开删除负载均衡器选项。点击删除负载均衡器选项以删除负载均衡器:
![删除负载均衡器]()
-
系统会显示确认页面。点击删除负载均衡器按钮以删除负载均衡器:
![删除负载均衡器]()
工作原理……
我们创建了一个带有健康监控的负载均衡池,并向其中添加了两个实例。为此,我们执行了以下步骤:
-
从负载均衡器页面创建负载均衡器。
-
创建监听器时,选择所有节点所连接的子网。
-
向监听器添加成员。
-
添加健康监控。
创建负载均衡器后,所有负载均衡器的详细信息都可以编辑。删除负载均衡器时需要删除所有已创建的资源:池、监听器和健康监控。
使用 OpenStack 仪表盘与 OpenStack 编排
Heat 是 OpenStack 编排引擎,允许用户通过模板快速启动整个环境。Heat 模板,称为HOT(Heat 编排模板),是基于YAML(另一种标记语言)的文件。这些文件描述了所使用的资源、实例的类型和大小,以及实例将连接的网络等信息,这是运行该环境所需的其他信息。
在第九章中,使用 Heat 和 Ansible 进行 OpenStack 编排,我们向你展示了如何使用 Heat 命令行客户端。在本节中,我们将展示如何在 OpenStack 仪表盘中使用现有的 Heat 模板文件启动两个运行 Apache 的 Web 服务器,并将其连接到一个运行 HA Proxy 的第三个实例。
正在准备
打开一个网页浏览器,访问我们的 OpenStack 仪表板地址http://192.168.100.117/,并以default域中的用户身份登录,例如在第二章的常见 OpenStack 身份任务食谱中创建的developer用户,使用密码cookbook4。我们仪表板的 URL 与第一章的使用 Ansible 安装 OpenStack中讨论的公共负载均衡器 IP 相同。如果需要找出 Horizon 的 URL,请使用 OpenStack 目录列表中的公共 IP,如第三章的Keystone – OpenStack 身份服务中所述。
如何操作…
本教程将引导您使用 OpenStack 仪表板启动和删除编排堆栈。
启动堆栈
要为已登录用户启动 Heat 堆栈,请执行以下步骤:
-
要查看我们 OpenStack 仪表板中可用的 Heat 堆栈,请从编排菜单中选择堆栈选项卡,如下所示:
![启动堆栈]()
-
单击堆栈选项卡后,您将看到环境中所有运行的堆栈。在我们的例子中,列表是空的,如下所示:
![启动堆栈]()
-
单击启动堆栈按钮以创建一个新的堆栈。您将看到以下窗口:
![启动堆栈]()
-
有几种方式可以指定要在堆栈中使用的模板源:文件、直接输入或URL。选择对您来说最方便的选项。在我们的示例中,您可以直接使用 URL,也可以上传文件。模板文件可以从这里下载:
raw.githubusercontent.com/OpenStackCookbook/OpenStackCookbook/master/cookbook.yaml。我们将使用URL选项,直接在模板中使用链接。 -
就像可以上传模板源文件一样,我们也可以上传环境源文件。在这种情况下,我们不一定非要使用环境源文件,但它使得过程更加便捷。环境文件存储了我们需要手动输入到浏览器中的值,而是会在启动堆栈屏幕上加载这些值,如第 8 步所示。在我们的示例中,我们使用的环境文件可以从这里下载:
raw.githubusercontent.com/OpenStackCookbook/OpenStackCookbook/master/cookbook-env.yaml。请更新public_net_id、private_net_id和private_subnet_id字段,以匹配您的环境。提示
如果您不确定在哪里找到网络信息,请参考使用 OpenStack Dashboard 管理 Neutron 网络和路由器一文。
-
选择模板源和环境源文件后,点击下一步:
![启动堆栈]()
-
我们的示例环境文件包含以下内容:
parameters: key_name: web image: ubuntu-xenial flavor: small public_net_id: eacdcb30-9c41-4be5-8954-d8dfff793512 private_net_id: 9db0448b-eb48-4cd0-ac01-676266c3463e private_subnet_id: 4485b7ba-d895-487a-83c7-a319e90549ba -
点击下一步将显示一个启动堆栈窗口,包含所有输入项:
![启动堆栈]()
-
请注意,我们模板中的大部分输入项现在已经填写。如果您在前一步中没有指定环境源文件,您需要填写
key_name、image、flavor、public_net_id、private_net_id和private_subnet_id字段。注意
这些字段是特定于每个模板的。您的模板可能有不同的字段。
-
输入堆栈名称和您的用户密码。如果您以 admin 或 demo 身份登录,密码为
openstack。 -
点击启动开始堆栈创建。如果所有输入项都正确,您应该会看到堆栈正在创建,类似以下示例:
![启动堆栈]()
-
在堆栈创建完成后,如果没有出现错误,您将看到堆栈的状态更新为创建完成:
![启动堆栈]()
查看堆栈详情
启动堆栈后,会有很多与每个堆栈相关的信息,包括输入、输出以及在出现错误时,堆栈创建失败的原因信息。
-
要查看堆栈的详细信息,请点击堆栈列表中的堆栈名称。第一个可用视图是拓扑:
![查看堆栈详情]()
点击节点可以浏览拓扑。如果图形不完全适合,或者您希望看到不同的视角,可以拖动图形到窗口中的其他位置。
-
下一个标签页是概览,它将提供用于创建堆栈的所有信息:
![查看堆栈详情]()
概览标签页中提供的堆栈信息如下:
-
信息
-
状态
-
输出
-
堆栈参数
-
启动参数
-
-
资源标签页将显示在堆栈启动过程中创建的所有 HEAT 资源:
![查看堆栈详情]()
如果在堆栈启动过程中出现错误,请查看此页面,了解哪个组件的创建失败。
-
事件标签页显示堆栈创建过程中发生的所有事件。此页面在排查 Heat 模板问题时也非常有帮助。
![查看堆栈详情]()
-
模板标签页将显示用于创建堆栈的模板。
-
在您的 Heat 堆栈运行时,您还可以在计算标签页的实例选项中查看它创建了多少实例。这是我们在实例页面上看到的实例:
![查看堆栈详情]()
删除堆栈
堆栈删除很简单,但请注意,在删除时,它会删除堆栈启动过程中创建的所有资源。
-
要删除堆栈,首先在堆栈页面查看可用的堆栈:
![删除堆栈]()
-
选择要删除的堆栈,然后点击 删除堆栈 按钮删除堆栈。系统会要求你确认删除:
![删除堆栈]()
-
确认删除后,所有与堆栈相关的资源将被删除。
它是如何工作的……
我们使用 OpenStack 仪表板来启动、查看和删除编排堆栈。我们首先需要从 GitHub 下载一个示例 HAProxy Heat 编排模板(HOT)。由于我们使用了环境文件,我们还需要修改适当的输入。你自己的模板可能有不同的输入。
在启动 HAProxy 堆栈后,我们探索了其拓扑、资源和事件。在堆栈启动过程中创建的资源也会反映在环境的其他部分。如果你正在启动新的实例,所有实例也会在 实例 页面上显示。仅通过 OpenStack 仪表板的编排部分或命令行删除和修改在堆栈启动过程中创建的资源。通过仪表板删除堆栈将删除所有相关资源。
你可能喜欢的另一本书
如果你喜欢这本书,可能会对 Packt 的另一本书感兴趣:

OpenStack 架构师指南
Michael Solberg, Ben Silverman
ISBN: 978-1-78439-510-0
-
熟悉 OpenStack 的各个组件
-
构建一个日益复杂的 OpenStack 实验室部署
-
为你组织内的架构团队编写有说服力的文档
-
应用敏捷配置管理技术部署 OpenStack
-
将 OpenStack 与你组织的身份管理、供应和计费系统集成
-
为用户配置一个稳健的虚拟环境以进行互动
-
使用企业安全指南进行 OpenStack 部署
-
创建一个能够迅速为平台用户提供功能的产品路线图
留下评论——让其他读者知道你的想法
请通过在购买书籍的网站上留下评论与他人分享你对这本书的看法。如果你是通过亚马逊购买的书籍,请在本书的亚马逊页面上留下诚实的评论。这对其他潜在读者非常重要,他们可以通过你的公正意见做出购买决策,我们也可以了解客户对我们产品的看法,作者们则能看到你对他们与 Packt 合作创作的书籍的反馈。只需要几分钟时间,但对其他潜在客户、我们的作者和 Packt 都非常有价值。谢谢!

































































































































































































































































浙公网安备 33010602011771号