[ English | 日本語 | Deutsch | Indonesia ]
面向用户的操作¶
本指南适用于 OpenStack 运维人员,并非旨在作为用户详尽的参考手册,但作为运维人员,您应该对如何使用云设施有基本的了解。本章从基本用户视角审视 OpenStack,这有助于您了解用户的需求,并在收到故障工单时判断是用户问题还是服务问题。主要概念包括镜像、规格、安全组、块存储、共享文件系统存储和实例。
镜像¶
OpenStack 镜像通常可以被认为是“虚拟机模板”。镜像也可以是标准安装介质,如 ISO 镜像。本质上,它们包含用于启动实例的可启动文件系统。
添加镜像¶
存在一些预制镜像,可以轻松导入到镜像服务中。常见的要添加的镜像是 CirrOS 镜像,它非常小,用于测试目的。要添加此镜像,只需执行
$ wget http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img
$ openstack image create --file cirros-0.3.5-x86_64-disk.img \
--public --container-format bare \
--disk-format qcow2 "cirros image"
openstack image create 命令提供了大量用于处理镜像的选项。例如,--min-disk 选项对于需要特定大小的根磁盘的镜像(例如,大型 Windows 镜像)很有用。要查看这些选项,请运行
$ openstack help image create
运行以下命令查看现有镜像的属性
$ openstack image show IMAGE_NAME_OR_UUID
添加签名镜像¶
为了提供从最终用户到镜像服务,以及从镜像服务到计算服务的信任链,最终用户可以导入签名镜像,这些镜像可以在镜像服务中进行初步验证,随后在计算服务中进行验证。需要设置适当的镜像服务属性以启用此签名功能。
注意
在执行以下步骤之前,必须生成非对称密钥对和证书。在此示例中,它们分别被称为 private_key.pem 和 new_cert.crt,并且都位于当前目录中。另请注意,此示例中的镜像是 cirros-0.3.5-x86_64-disk.img,但可以使用任何镜像。
以下是创建用于签名镜像的签名所需的步骤
检索用于上传的镜像
$ wget http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img
使用私钥创建镜像签名
注意
此示例中用于创建签名的隐式值如下
签名哈希方法 = SHA-256
签名密钥类型 = RSA-PSS
注意
目前支持以下选项
签名哈希方法:SHA-224、SHA-256、SHA-384 和 SHA-512
签名密钥类型:DSA、ECC_SECT571K1、ECC_SECT409K1、ECC_SECT571R1、ECC_SECT409R1、ECC_SECP521R1、ECC_SECP384R1 和 RSA-PSS
生成镜像签名并将其转换为 base64 表示
$ openssl dgst -sha256 -sign private_key.pem -sigopt rsa_padding_mode:pss \ -out image-file.signature cirros-0.3.5-x86_64-disk.img $ base64 -w 0 image-file.signature > signature_64 $ cat signature_64 'c4br5f3FYQV6Nu20cRUSnx75R/VcW3diQdsUN2nhPw+UcQRDoGx92hwMgRxzFYeUyydRTWCcUS2ZLudPR9X7rM THFInA54Zj1TwEIbJTkHwlqbWBMU4+k5IUIjXxHO6RuH3Z5f/SlSt7ajsNVXaIclWqIw5YvEkgXTIEuDPE+C4='
注意
使用 Image API v1 需要上述‘-w 0’,因为不支持多行镜像属性。
Image API v2 支持多行属性,因此 v2 不需要此选项,但仍可使用。
创建上下文
$ python >>> from keystoneclient.v3 import client >>> keystone_client = client.Client(username='demo', user_domain_name='Default', password='password', project_name='demo', auth_url='https://:5000/v3') >>> from oslo_context import context >>> context = context.RequestContext(auth_token=keystone_client.auth_token, tenant=keystone_client.project_id)
以 DER 格式编码证书
>>> from cryptography import x509 as cryptography_x509 >>> from cryptography.hazmat import backends >>> from cryptography.hazmat.primitives import serialization >>> with open("new_cert.crt", "rb") as cert_file: >>> cert = cryptography_x509.load_pem_x509_certificate( cert_file.read(), backend=backends.default_backend() ) >>> certificate_der = cert.public_bytes(encoding=serialization.Encoding.DER)
以 DER 格式将证书上传到 Castellan
>>> from castellan.common.objects import x_509 >>> from castellan import key_manager >>> castellan_cert = x_509.X509(certificate_der) >>> key_API = key_manager.API() >>> cert_uuid = key_API.store(context, castellan_cert) >>> cert_uuid u'62a33f41-f061-44ba-9a69-4fc247d3bfce'
将镜像和签名元数据上传到镜像服务
注意
使用以下签名属性
img_signature 使用名为 signature_64 的签名
img_signature_certificate_uuid 使用上面第 5 节中 cert_uuid 的值
img_signature_hash_method 匹配上面第 2 节中的 'SHA-256'
img_signature_key_type 匹配上面第 2 节中的 'RSA-PSS'
$ . openrc demo $ export OS_IMAGE_API_VERSION=2 $ openstack image create --property name=cirrosSignedImage_goodSignature \ --property is-public=true --container-format bare --disk-format qcow2 \ --property img_signature='c4br5f3FYQV6Nu20cRUSnx75R/VcW3diQdsUN2nhPw+UcQRDoGx92hwMgRxzFYeUyydRTWCcUS2ZLudPR9X7rMTHFInA54Zj1TwEIbJTkHwlqbWBMU4+k5IUIjXxHO6RuH3Z5fSlSt7ajsNVXaIclWqIw5YvEkgXTIEuDPE+C4=' \ --property img_signature_certificate_uuid='62a33f41-f061-44ba-9a69-4fc247d3bfce' \ --property img_signature_hash_method='SHA-256' \ --property img_signature_key_type='RSA-PSS' < ~/cirros-0.3.5-x86_64-disk.img
注意
镜像签名的最大字符限制为 255。
验证 Keystone URL
注意
默认的 Keystone 配置假定 Keystone 位于本地主机,并使用
https://:5000/v3作为端点 URL,该 URL 在glance-api.conf和nova-api.conf文件中指定[barbican] auth_endpoint = https://:5000/v3
注意
如果 Keystone 位于远程,则编辑
glance-api.conf和nova.conf文件。在[barbican]部分,配置auth_endpoint选项[barbican] auth_endpoint = https://192.168.245.9:5000/v3
当计算服务启动签名镜像时,将进行签名验证。
注意
nova-compute 服务器首先需要通过以下步骤进行更新
确保安装了 cryptsetup,并确保安装了
pythin-barbicanclientPython 包通过编辑 /etc/nova/nova.conf 并添加以下代码块中的条目来设置密钥管理器服务
标志 verify_glance_signatures 允许计算服务在启动前自动验证已签名的实例。当该值设置为 TRUE 时,将启用此验证功能。
[key_manager] api_class = castellan.key_manager.barbican_key_manager.BarbicanKeyManager [glance] verify_glance_signatures = TRUE
注意
api_class [keymgr] 从 Newton 版本开始已弃用,因此在此版本或更高版本中不应包含。
删除镜像¶
要删除镜像,只需执行
$ openstack image delete IMAGE_NAME_OR_UUID
警告
通常,删除镜像不会影响基于该镜像的实例或快照。但是,某些驱动程序可能要求存在原始镜像才能执行迁移。例如,如果镜像被删除,XenAPI 实时迁移将正常工作,但 libvirt 将失败。
其他 CLI 选项¶
可以使用以下命令找到全套选项
$ glance help
或 命令行界面参考。
镜像服务和数据库¶
镜像服务不存储在数据库中的唯一内容是镜像本身。镜像服务数据库有两个主要表
imagesimage_properties
直接使用数据库和 SQL 查询可以为您提供自定义的镜像列表和报告。从技术上讲,您可以通过数据库更新镜像的属性,尽管通常不建议这样做。
镜像服务数据库查询示例¶
一个有趣的例子是修改镜像表和该镜像的所有者。如果您简单地显示所有者的唯一 ID,这可以很容易地完成。此示例更进一步,显示了所有者的可读名称。
mysql> select glance.images.id,
glance.images.name, keystone.tenant.name, is_public from
glance.images inner join keystone.tenant on
glance.images.owner=keystone.tenant.id;
另一个例子是显示某个镜像的所有属性
mysql> select name, value from
image_properties where id = <image_id>
规格¶
虚拟硬件模板在 OpenStack 中称为“规格”,定义了 RAM、磁盘、核心数等大小。默认安装提供了五种规格。
这些可以由管理员用户配置(通过在 nova-api 服务器上的 /etc/nova/policy.json 中重新定义 compute_extension:flavormanage 的访问控制,权限也可以委托给其他用户)。要获取系统上可用规格的列表,请运行
$ openstack flavor list
+----+-----------+-------+------+-----------+-------+-----------+
| ID | Name | RAM | Disk | Ephemeral | VCPUs | Is Public |
+----+-----------+-------+------+-----------+-------+-----------+
| 1 | m1.tiny | 512 | 1 | 0 | 1 | True |
| 2 | m1.small | 2048 | 20 | 0 | 1 | True |
| 3 | m1.medium | 4096 | 40 | 0 | 2 | True |
| 4 | m1.large | 8192 | 80 | 0 | 4 | True |
| 5 | m1.xlarge | 16384 | 160 | 0 | 8 | True |
+----+-----------+-------+------+-----------+-------+-----------+
openstack flavor create 命令允许授权用户创建新规格。可以通过以下命令显示其他规格操作命令
$ openstack help | grep flavor
规格定义了许多参数,使用户可以选择运行哪种类型的虚拟机,就像他们购买物理服务器时一样。表. 规格参数 列出了可以设置的元素。特别注意 extra_specs,它可以用于定义自由形式的特性,提供了比 RAM、CPU 和磁盘大小更大的灵活性。
列 |
描述 |
|---|---|
ID |
规格的唯一 ID(整数或 UUID)。 |
名称 |
描述性名称,例如 xx.size_name,是惯例但不是必需的,尽管某些第三方工具可能依赖它。 |
Memory_MB |
虚拟内存(以兆字节为单位)。 |
磁盘 |
虚拟根磁盘大小(以千兆字节为单位)。这是一个临时磁盘,基本镜像将复制到其中。当您从持久卷启动时,您不使用它。“0”大小是一种特殊情况,它使用原生基本镜像大小作为临时根卷的大小。 |
临时 |
指定辅助临时数据盘的大小。这是一个空的、未格式化的磁盘,仅在实例的生命周期内存在。 |
Swap |
为实例分配的可选交换空间。 |
VCPUs |
呈现给实例的虚拟 CPU 数量。 |
RXTX_Factor |
可选属性,允许创建的服务器具有与所连接网络中定义的带宽限制不同的带宽限制。此因子乘以网络的 rxtx_base 属性。默认值为 1.0(即与所连接网络相同)。 |
Is_Public |
布尔值,指示该规格是可供所有用户使用还是私有。私有规格不会分配给当前租户。默认为 |
extra_specs |
对规格可以在哪些计算节点上运行的其他可选限制。这以键值对的形式实现,必须与计算节点上的相应键值对匹配。可用于实现特殊资源(例如,只能在具有 GPU 硬件的计算节点上运行的规格)。 |
私有规格¶
用户可能需要一个为她正在处理的项目独特调整的自定义规格。例如,用户可能需要 128 GB 内存。如果您按照上述说明创建一个新规格,该用户将可以访问该自定义规格,但您的云中的所有其他租户也将可以访问。有时这种共享是不可取的。在这种情况下,允许所有用户访问具有 128 GB 内存的规格可能会导致您的云很快达到满负荷。为防止这种情况,您可以使用 nova flavor-access-add 命令限制对自定义规格的访问
$ nova flavor-access-add FLAVOR_ID PROJECT_ID
要查看规格的访问列表,请执行以下操作
$ nova flavor-access-list [--flavor FLAVOR_ID]
提示
一旦对规格的访问受到限制,除了被授予明确访问权限的项目之外,其他项目都无法看到该规格。这包括管理员项目。请务必除了原始项目之外,还要添加管理员项目。
为自定义和私有规格分配特定的数字范围也很有帮助。在基于 UNIX 的系统中,非系统账户通常从 500 开始的 UID。自定义规格也可以采用类似的方法。这有助于您轻松识别整个云中哪些规格是自定义的、私有的和公共的。
如何修改现有规格?¶
OpenStack 控制台通过删除现有规格并创建同名新规格来模拟修改规格的能力。
安全组¶
OpenStack 中常见的新用户问题是在启动实例时未能设置适当的安全组。结果是,用户无法在网络上联系到实例。
安全组是应用于实例网络的 IP 过滤规则集。它们是项目特定的,项目成员可以编辑其组的默认规则并添加新的规则集。所有项目都有一个“默认”安全组,它应用于未定义其他安全组的实例。除非更改,否则此安全组会拒绝所有传入流量。
提示
如前一章所述,每个安全组的规则数量由 quota_security_group_rules 控制,每个项目允许的安全组数量由 quota_security_groups 配额控制。
安全组的最终用户配置¶
当前项目的安全组可以在 OpenStack 控制台的 访问与安全 下找到。要查看现有组的详细信息,请选择该安全组的 编辑安全组 操作。显然,修改现有组可以从此编辑界面完成。主 访问与安全 页面上有一个 创建安全组 按钮,用于创建新组。当我们解释命令行等效项时,我们将讨论这些字段中使用的术语。
使用 openstack 命令设置
如果您的环境正在使用 Neutron,您可以使用 openstack 命令配置安全组设置。使用以下命令获取您正在操作的项目的安全组列表
$ openstack security group list
+------------------------+---------+------------------------+-------------------------+
| ID | Name | Description | Project |
+------------------------+---------+------------------------+-------------------------+
| 3bef30ed-442d-4cf1 | default | Default security group | 35e3820f7490493ca9e3a5e |
| -b84d-2ba50a395599 | | | 685393298 |
| aaf1d0b7-98a0-41a3-ae1 | default | Default security group | 32e9707393c34364923edf8 |
| 6-a58b94503289 | | | f5029cbfe |
+------------------------+---------+------------------------+-------------------------+
要查看安全组的详细信息
$ openstack security group show 3bef30ed-442d-4cf1-b84d-2ba50a395599
+-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| created_at | 2016-11-08T21:55:19Z |
| description | Default security group |
| id | 3bef30ed-442d-4cf1-b84d-2ba50a395599 |
| name | default |
| project_id | 35e3820f7490493ca9e3a5e685393298 |
| project_id | 35e3820f7490493ca9e3a5e685393298 |
| revision_number | 1 |
| rules | created_at='2016-11-08T21:55:19Z', direction='egress', ethertype='IPv6', id='1dca4cac-d4f2-46f5-b757-d53c01a87bdf', project_id='35e3820f7490493ca9e3a5e685393298', |
| | revision_number='1', updated_at='2016-11-08T21:55:19Z' |
| | created_at='2016-11-08T21:55:19Z', direction='egress', ethertype='IPv4', id='2d83d6f2-424e-4b7c-b9c4-1ede89c00aab', project_id='35e3820f7490493ca9e3a5e685393298', |
| | revision_number='1', updated_at='2016-11-08T21:55:19Z' |
| | created_at='2016-11-08T21:55:19Z', direction='ingress', ethertype='IPv4', id='62b7d1eb-b98d-4707-a29f-6df379afdbaa', project_id='35e3820f7490493ca9e3a5e685393298', remote_group_id |
| | ='3bef30ed-442d-4cf1-b84d-2ba50a395599', revision_number='1', updated_at='2016-11-08T21:55:19Z' |
| | created_at='2016-11-08T21:55:19Z', direction='ingress', ethertype='IPv6', id='f0d4b8d6-32d4-4f93-813d-3ede9d698fbb', project_id='35e3820f7490493ca9e3a5e685393298', remote_group_id |
| | ='3bef30ed-442d-4cf1-b84d-2ba50a395599', revision_number='1', updated_at='2016-11-08T21:55:19Z' |
| updated_at | 2016-11-08T21:55:19Z |
+-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
这些规则都是“允许”类型的规则,因为默认是拒绝。此示例显示了允许来自所有 IP 的所有协议的完整端口范围。本节描述了最常见的安全组规则参数
- 方向
应用安全组规则的方向。有效值为
ingress或egress。- remote_ip_prefix
此属性值将指定的 IP 前缀匹配为 IP 数据包的源 IP 地址。
- 协议
安全组规则匹配的协议。有效值为
null、tcp、udp、icmp和icmpv6。- port_range_min
安全组规则匹配的范围内的最小端口号。如果协议是 TCP 或 UDP,此值必须小于或等于
port_range_max属性值。如果协议是 ICMP 或 ICMPv6,此值必须分别是 ICMP 或 ICMPv6 类型。- port_range_max
安全组规则匹配的范围内的最大端口号。
port_range_min属性约束port_range_max属性。如果协议是 ICMP 或 ICMPv6,此值必须分别是 ICMP 或 ICMPv6 类型。- ethertype
必须是
IPv4或IPv6,并且 CIDR 中表示的地址必须与入站或出站规则匹配。
添加新安全组时,应选择一个描述性但简短的名称。此名称会出现在使用它的实例的简短描述中,而较长的描述字段通常不会出现。看到实例正在使用安全组 http 比 bobs_group 或 secgrp1 更容易理解。
此示例创建了一个安全组,允许 Internet 上的任何位置的 Web 流量。我们将此组称为 global_http,它清晰且合理简洁,概括了允许的内容和来源。在命令行中,执行
$ openstack security group create global_http --description "allow web traffic from the Internet"
Created a new security_group:
+-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| created_at | 2016-11-10T16:09:18Z |
| description | allow web traffic from the Internet |
| headers | |
| id | 70675447-1b92-4102-a7ea-6a3ca99d2290 |
| name | global_http |
| project_id | 32e9707393c34364923edf8f5029cbfe |
| project_id | 32e9707393c34364923edf8f5029cbfe |
| revision_number | 1 |
| rules | created_at='2016-11-10T16:09:18Z', direction='egress', ethertype='IPv4', id='e440b13a-e74f-4700-a36f-9ecc0de76612', project_id='32e9707393c34364923edf8f5029cbfe', |
| | revision_number='1', updated_at='2016-11-10T16:09:18Z' |
| | created_at='2016-11-10T16:09:18Z', direction='egress', ethertype='IPv6', id='0debf8cb-9f1d-45e5-98db-ee169c0715fe', project_id='32e9707393c34364923edf8f5029cbfe', |
| | revision_number='1', updated_at='2016-11-10T16:09:18Z' |
| updated_at | 2016-11-10T16:09:18Z |
+-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
创建后,安全组只包含一个允许出站规则。为了使其达到我们想要的效果,我们需要添加一些规则
$ openstack security group rule create --help
usage: openstack security group rule create [-h]
[-f {json,shell,table,value,yaml}]
[-c COLUMN]
[--max-width <integer>]
[--noindent] [--prefix PREFIX]
[--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>]
[--project <project>]
[--project-domain <project-domain>]
<group>
$ openstack security group rule create --ingress --ethertype IPv4 \
--protocol tcp --remote-ip 0.0.0.0/0 global_http
Created a new security group rule:
+-------------------+--------------------------------------+
| Field | Value |
+-------------------+--------------------------------------+
| created_at | 2016-11-10T16:12:27Z |
| description | |
| direction | ingress |
| ethertype | IPv4 |
| headers | |
| id | 694d30b1-1c4d-4bb8-acbe-7f1b3de2b20f |
| port_range_max | None |
| port_range_min | None |
| project_id | 32e9707393c34364923edf8f5029cbfe |
| project_id | 32e9707393c34364923edf8f5029cbfe |
| protocol | tcp |
| remote_group_id | None |
| remote_ip_prefix | 0.0.0.0/0 |
| revision_number | 1 |
| security_group_id | 70675447-1b92-4102-a7ea-6a3ca99d2290 |
| updated_at | 2016-11-10T16:12:27Z |
+-------------------+--------------------------------------+
尽管只输出新添加的规则,但此操作是累加的
$ openstack security group show global_http
+-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| created_at | 2016-11-10T16:09:18Z |
| description | allow web traffic from the Internet |
| id | 70675447-1b92-4102-a7ea-6a3ca99d2290 |
| name | global_http |
| project_id | 32e9707393c34364923edf8f5029cbfe |
| project_id | 32e9707393c34364923edf8f5029cbfe |
| revision_number | 2 |
| rules | created_at='2016-11-10T16:09:18Z', direction='egress', ethertype='IPv6', id='0debf8cb-9f1d-45e5-98db-ee169c0715fe', project_id='32e9707393c34364923edf8f5029cbfe', |
| | revision_number='1', updated_at='2016-11-10T16:09:18Z' |
| | created_at='2016-11-10T16:12:27Z', direction='ingress', ethertype='IPv4', id='694d30b1-1c4d-4bb8-acbe-7f1b3de2b20f', project_id='32e9707393c34364923edf8f5029cbfe', protocol='tcp', |
| | remote_ip_prefix='0.0.0.0/0', revision_number='1', updated_at='2016-11-10T16:12:27Z' |
| | created_at='2016-11-10T16:09:18Z', direction='egress', ethertype='IPv4', id='e440b13a-e74f-4700-a36f-9ecc0de76612', project_id='32e9707393c34364923edf8f5029cbfe', |
| | revision_number='1', updated_at='2016-11-10T16:09:18Z' |
| updated_at | 2016-11-10T16:12:27Z |
+-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
反向操作称为 openstack security group rule delete,指定 security-group-rule ID。整个安全组可以通过 openstack security group delete 删除。
要为实例集群创建安全组规则,请使用 RemoteGroups。
RemoteGroups 是定义允许源的 CIDR 的动态方式。用户指定一个 RemoteGroup(安全组名称),然后动态选择所有使用指定 RemoteGroup 的其他用户实例。这种动态选择避免了为集群的每个新成员单独设置规则的需要。
代码与上面 openstack security group rule create 的示例相似。要使用 RemoteGroup,请指定 --remote-group 而不是 --remote-ip。例如
$ openstack security group rule create --ingress \
--ethertype IPv4 --protocol tcp \
--remote-group global_http cluster
“cluster”规则允许来自使用 global-http 组的任何其他实例的 SSH 访问。
块存储¶
OpenStack 卷是持久的块存储设备,可以从实例附加和分离,但一次只能附加到一个实例。与外部硬盘类似,它们不提供网络文件系统或对象存储那样的共享存储。由实例中的操作系统决定是否在块设备上放置文件系统并挂载它。
与其他可移动磁盘技术一样,重要的是操作系统在移除磁盘之前不要试图使用它。在 Linux 实例上,这通常涉及卸载从卷挂载的任何文件系统。OpenStack 卷服务无法判断从实例中移除卷是否安全,因此它会按照指示操作。如果用户告诉卷服务在写入时从实例中分离卷,则可以预期一定程度的文件系统损坏以及实例内使用该设备的任何进程的故障。
从实例操作系统内部访问块设备、首次使用时可能对其进行格式化以及移除时要谨慎,这些方面没有什么 OpenStack 特有的。特有的是如何创建新卷以及如何从实例附加和分离它们。这些操作都可以通过控制台的 卷 页面或使用 openstack 命令行客户端来完成。
要添加新卷,您只需要一个以千兆字节为单位的卷大小。您可以将其输入 创建卷 Web 表单,或使用命令行
$ openstack volume create volume1 --size 10
这将创建一个 10 GB 的卷。要列出现有卷及其连接的实例(如果有)
$ openstack volume list
+--------------------------------------+--------------+--------+------+-------------+
| ID | Display Name | Status | Size | Attached to |
+--------------------------------------+--------------+--------+------+-------------+
| 6cf4114a-56b2-476b-acf7-7359d8334aa2 | volume1 | error | 10 | |
+--------------------------------------+--------------+--------+------+-------------+
OpenStack 块存储还允许创建卷快照。请记住,这是一个崩溃一致的块级快照,因此最好在拍摄快照时卷未连接到实例,其次是如果卷未在其连接的实例上使用。如果卷正在大量使用,快照可能具有不一致的文件系统。事实上,默认情况下,卷服务不会为连接到镜像的卷拍摄快照,尽管可以强制执行。要拍摄卷快照,请在控制台 卷 页面上卷名称旁边的操作列中选择 创建快照,或从命令行运行此命令
$ openstack help snapshot create
usage: openstack snapshot create [-h] [-f {json,shell,table,value,yaml}]
[-c COLUMN] [--max-width <integer>]
[--noindent] [--prefix PREFIX]
[--name <name>] [--description <description>]
[--force] [--property <key=value>]
<volume>
Create new snapshot
positional arguments:
<volume> Volume to snapshot (name or ID)
optional arguments:
-h, --help show this help message and exit
--name <name> Name of the snapshot
--description <description>
Description of the snapshot
--force Create a snapshot attached to an instance. Default is
False
--property <key=value>
Set a property to this snapshot (repeat option to set
multiple properties)
output formatters:
output formatter options
-f {json,shell,table,value,yaml}, --format {json,shell,table,value,yaml}
the output format, defaults to table
-c COLUMN, --column COLUMN
specify the column(s) to include, can be repeated
table formatter:
--max-width <integer>
Maximum display width, <1 to disable. You can also use
the CLIFF_MAX_TERM_WIDTH environment variable, but the
parameter takes precedence.
json formatter:
--noindent whether to disable indenting the JSON
shell formatter:
a format a UNIX shell can parse (variable="value")
--prefix PREFIX add a prefix to all variable names
注意
有关更新块存储卷(例如,调整大小或传输)的更多信息,请参阅 OpenStack 最终用户指南。
块存储创建失败¶
如果用户尝试创建卷并且卷立即进入错误状态,最好的故障排除方法是使用卷的 UUID 搜索 cinder 日志文件。首先尝试云控制器上的日志文件,然后尝试尝试创建卷的存储节点
# grep 903b85d0-bacc-4855-a261-10843fc2d65b /var/log/cinder/*.log
实例¶
实例是 OpenStack 云中运行的虚拟机。本节讨论如何使用它们及其底层镜像、网络属性以及它们在数据库中的表示方式。
启动实例¶
要启动一个实例,您需要选择一个镜像、一个规格和一个名称。名称不必是唯一的,但如果它是唯一的,您的生活会更简单,因为许多工具会在名称是唯一的情况下使用名称代替 UUID。您可以从控制台的 实例 页面上的 启动实例 按钮启动一个实例,或者通过在 镜像 页面上选择镜像或快照旁边的 启动 操作。
在命令行中,执行此操作
$ openstack server create --flavor FLAVOR --image IMAGE_NAME_OR_ID
可以指定许多可选项目。在尝试启动实例之前,您应该阅读本节的其余部分,但这是基本命令,后续的细节都建立在此基础上。
要从仪表板删除实例,请在 实例 页面上选择实例旁边的 删除实例 操作。
注意
在 Mitaka 之前的版本中,选择等效的 终止实例 操作。
从命令行中,执行此操作
$ openstack server delete INSTANCE_ID
重要的是要注意,关闭实例并不意味着在 OpenStack 意义上终止它。
实例启动失败¶
如果实例启动失败并立即进入错误状态,有几种不同的方法可以查明哪里出了问题。其中一些可以通过普通用户访问完成,而另一些则需要访问您的日志服务器或计算节点。
节点启动失败最简单的原因可能是配额违规或调度器无法找到合适的计算节点来运行实例。在这些情况下,当您对故障实例运行 openstack server show 时,错误是显而易见的
$ openstack server show test-instance
+--------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+--------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+
| OS-DCF:diskConfig | AUTO |
| OS-EXT-AZ:availability_zone | nova |
| OS-EXT-SRV-ATTR:host | None |
| OS-EXT-SRV-ATTR:hypervisor_hostname | None |
| OS-EXT-SRV-ATTR:instance_name | instance-0000000a |
| OS-EXT-STS:power_state | NOSTATE |
| OS-EXT-STS:task_state | None |
| OS-EXT-STS:vm_state | error |
| OS-SRV-USG:launched_at | None |
| OS-SRV-USG:terminated_at | None |
| accessIPv4 | |
| accessIPv6 | |
| addresses | |
| config_drive | |
| created | 2016-11-23T07:51:53Z |
| fault | {u'message': u'Build of instance 6ec42311-a121-4887-aece-48fb93a4a098 aborted: Failed to allocate the network(s), not rescheduling.', |
| | u'code': 500, u'details': u' File "/usr/lib/python2.7/site-packages/nova/compute/manager.py", line 1779, in |
| | _do_build_and_run_instance\n filter_properties)\n File "/usr/lib/python2.7/site-packages/nova/compute/manager.py", line 1960, in |
| | _build_and_run_instance\n reason=msg)\n', u'created': u'2016-11-23T07:57:04Z'} |
| flavor | m1.tiny (1) |
| hostId | |
| id | 6ec42311-a121-4887-aece-48fb93a4a098 |
| image | cirros (9fef3b2d-c35d-4b61-bea8-09cc6dc41829) |
| key_name | None |
| name | test-instance |
| os-extended-volumes:volumes_attached | [] |
| project_id | 5669caad86a04256994cdf755df4d3c1 |
| properties | |
| status | ERROR |
| updated | 2016-11-23T07:57:04Z |
| user_id | c36cec73b0e44876a4478b1e6cd749bb |
+--------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+
在这种情况下,查看 fault 消息显示 NoValidHost,表明调度器无法匹配实例要求。
如果 openstack server show 不足以解释故障,那么在实例被调度的计算节点上的 nova-compute.log 或您的调度器主机上的 nova-scheduler.log 中搜索实例 UUID 是查找更深层次问题的好起点。
以管理员用户身份使用 openstack server show 将显示实例被调度的计算节点为 hostId。如果实例在调度过程中失败,则此字段为空。
使用实例特定数据¶
实例特定数据主要有两种类型:元数据和用户数据。
实例元数据¶
对于计算服务,实例元数据是与实例相关联的键值对集合。当最终用户使用计算 API 时,计算服务在实例生命周期内的任何时候,从实例内部和外部,读取和写入这些键值对。但是,您无法使用与 Amazon EC2 元数据服务兼容的元数据服务查询与实例相关联的键值对。
例如,用户可以使用 openstack keypair create 命令生成和注册 SSH 密钥
$ openstack keypair create mykey > mykey.pem
这将创建一个名为 mykey 的密钥,您可以将其与实例关联。mykey.pem 文件是私钥,应将其保存到安全位置,因为它允许对与 mykey 密钥关联的实例进行 root 访问。
使用此命令向 OpenStack 注册现有密钥
$ openstack keypair create --public-key mykey.pub mykey
注意
您必须拥有匹配的私钥才能访问与此密钥关联的实例。
要在启动时将密钥与实例关联,请在命令行中添加 --key-name mykey。例如
$ openstack server create --image ubuntu-cloudimage --flavor 2 \
--key-name mykey myimage
启动服务器时,您还可以添加任意元数据,以便更容易地在其他运行实例中识别它。使用带有键值对的 --property 选项,您可以在其中为键和值创建字符串。例如,您可以添加描述以及服务器的创建者
$ openstack server create --image=test-image --flavor=1 \
--property description='Small test image' smallimage
查看服务器信息时,您可以在元数据行中看到包含的元数据
$ openstack server show smallimage
+--------------------------------------+----------------------------------------------------------+
| Field | Value |
+--------------------------------------+----------------------------------------------------------+
| OS-DCF:diskConfig | MANUAL |
| OS-EXT-AZ:availability_zone | nova |
| OS-EXT-SRV-ATTR:host | rdo-newton.novalocal |
| OS-EXT-SRV-ATTR:hypervisor_hostname | rdo-newton.novalocal |
| OS-EXT-SRV-ATTR:instance_name | instance-00000002 |
| OS-EXT-STS:power_state | Running |
| OS-EXT-STS:task_state | None |
| OS-EXT-STS:vm_state | active |
| OS-SRV-USG:launched_at | 2016-12-07T11:20:08.000000 |
| OS-SRV-USG:terminated_at | None |
| accessIPv4 | |
| accessIPv6 | |
| addresses | public=172.24.4.227 |
| config_drive | |
| created | 2016-12-07T11:17:44Z |
| flavor | m1.tiny (1) |
| hostId | aca973d5b7981faaf8c713a0130713bbc1e64151be65c8dfb53039f7 |
| id | 4f7c6b2c-f27e-4ccd-a606-6bfc9d7c0d91 |
| image | cirros (01bcb649-45d7-4e3d-8a58-1fcc87816907) |
| key_name | None |
| name | smallimage |
| os-extended-volumes:volumes_attached | [] |
| progress | 0 |
| project_id | 2daf82a578e9437cab396c888ff0ca57 |
| properties | description='Small test image' |
| security_groups | [{u'name': u'default'}] |
| status | ACTIVE |
| updated | 2016-12-07T11:20:08Z |
| user_id | 8cbea24666ae49bbb8c1641f9b12d2d2 |
+--------------------------------------+----------------------------------------------------------+
实例用户数据¶
user-data 键是元数据服务中的一个特殊键,它保存着一个文件,客户机实例中支持云的应用程序可以访问该文件。例如,cloudinit 是 Ubuntu 提供的一个开源软件包,但在大多数发行版中都可用,它处理云实例的早期初始化,并利用此用户数据。
此用户数据可以放在本地系统的文件中,然后通过 --user-data <user-data-file> 标志在实例创建时传入。
例如
$ openstack server create --image ubuntu-cloudimage --flavor 1 \
--user-data mydata.file mydatainstance
要理解用户数据和元数据之间的区别,请注意用户数据是在实例启动之前创建的。用户数据在实例运行时可从实例内部访问。用户数据可用于存储配置、脚本或租户想要的任何内容。
文件注入¶
在创建时,也可以通过使用 --file <dst-path=src-path> 选项将任意本地文件放置到实例文件系统中。您最多可以存储五个文件。
例如,假设您有一个名为 special_authorized_keysfile 的特殊 authorized_keys 文件,由于某种原因,您想将其放入实例中,而不是使用常规的 SSH 密钥注入。在这种情况下,您可以使用以下命令
$ openstack server create --image ubuntu-cloudimage --flavor 1 \
--file /root/.ssh/authorized_keys=special_authorized_keysfile \
authkeyinstance
关联安全组¶
安全组,如前所述,通常需要允许网络流量进入实例,除非项目的默认安全组已修改为更宽松。
添加安全组通常在实例启动时完成。从仪表板启动时,您在 启动实例 对话框的 访问与安全 选项卡上执行此操作。
在实例运行时也可以添加和删除安全组。目前这只能通过命令行工具实现。下面是一个例子
$ openstack server add security group SERVER SECURITY_GROUP_NAME_OR_ID
$ openstack server remove security group SERVER SECURITY_GROUP_NAME_OR_ID
浮动 IP¶
在部署中配置了浮动 IP 的情况下,每个项目将拥有由配额控制的有限数量的浮动 IP。然而,这些 IP 需要在使用前从中央池分配给项目——通常由项目管理员完成。要将浮动 IP 分配给项目,请使用仪表板 访问与安全 页面 浮动 IP 选项卡上的 将 IP 分配给项目 按钮。也可以使用命令行
$ openstack floating ip create NETWORK_NAME_OR_ID
一旦分配,浮动 IP 可以从控制台分配给正在运行的实例,方法是在 访问和安全 页面的 浮动 IP 选项卡上,在 IP 旁边的操作下拉菜单中选择 关联,或者在 实例 页面上,在您要关联的实例旁边进行此选择。反向操作“解除浮动 IP 关联”可在 访问和安全 页面的 浮动 IP 选项卡和 实例 页面上找到。
要从命令行将浮动 IP 与服务器关联或取消关联,请使用以下命令
$ openstack server add floating ip SERVER IP_ADDRESS
$ openstack server remove floating ip SERVER IP_ADDRESS
附加块存储¶
您可以从控制台的 卷 页面将块存储附加到实例。单击要附加的卷旁边的 管理附件 操作。
要从命令行执行此操作,请运行以下命令
$ openstack server add volume SERVER VOLUME_NAME_OR_ID --device DEVICE
您还可以在实例启动时通过 nova 命令行客户端设置此选项来指定块设备映射。
--block-device-mapping <dev-name=mapping>
块设备映射格式为 <dev-name>=<id>:<type>:<size(GB)>:<delete-on-terminate>,其中
- 设备名称
卷在系统
/dev/dev_name处附加的设备名称。- id
要从中启动的卷的 ID,如 openstack volume list 的输出所示。
- type
要么是
snap,这意味着该卷是从快照创建的,要么是除snap之外的任何内容(空字符串有效)。在前面的示例中,该卷不是从快照创建的,因此我们在下面的示例中将此字段留空。- 大小 (GB)
卷的大小(以千兆字节为单位)。将其留空并让计算服务推断大小是安全的。
- 终止时删除
一个布尔值,指示实例终止时是否应删除卷。True 可以指定为
True或1。False 可以指定为False或0。
以下命令将启动一个新实例并同时附加一个卷。ID 为 13 的卷将作为 /dev/vdc 附加。它不是快照,未指定大小,并且在实例终止时不会被删除。
$ openstack server create --image 4042220e-4f5e-4398-9054-39fbd75a5dd7 \
--flavor 2 --key-name mykey --block-device-mapping vdc=13:::0 \
boot-with-vol-test
如果您之前已经使用可启动文件系统镜像准备了块存储,甚至可以从持久块存储启动。以下命令从指定的卷启动镜像。它与上一个命令类似,但省略了镜像,并且卷现在作为 /dev/vda 附加。
$ openstack server create --flavor 2 --key-name mykey \
--block-device-mapping vda=13:::0 boot-from-vol-test
请参阅 OpenStack 最终用户指南,了解从可启动卷启动实例的更详细说明。
要正常从镜像启动并附加块存储,请映射到 vda 以外的设备。您可以在 OpenStack 最终用户指南 中找到启动实例并将卷附加到实例以及将镜像复制到附加卷的说明。
拍摄快照¶
OpenStack 快照机制允许您从正在运行的实例创建新镜像。这对于升级基本镜像或获取已发布的镜像并将其自定义以供本地使用非常方便。要使用 CLI 将正在运行的实例快照为镜像,请执行此操作
$ openstack image create IMAGE_NAME --volume VOLUME_NAME_OR_ID
仪表板快照界面可能会让人困惑,因为快照和镜像都显示在 镜像 页面。然而,实例快照 *是* 一个镜像。直接上传到镜像服务中的镜像与通过快照创建的镜像之间的唯一区别在于,通过快照创建的镜像在 glance 数据库中具有额外的属性。这些属性在 image_properties 表中找到,包括
名称 |
值 |
|---|---|
|
snapshot |
|
<被快照的实例的 UUID> |
|
<被快照的实例的原始镜像的 UUID> |
|
snapshot |
实时快照¶
实时快照是一项允许用户在不暂停正在运行的虚拟机的情况下进行快照的功能。这些快照只是纯磁盘快照。现在可以在不中断运行的情况下执行实例快照(假设使用 QEMU 1.3+ 和 libvirt 1.0+)。
注意
如果您使用 libvirt 版本 1.2.2,您可能会遇到实时快照创建的间歇性问题。
为了有效禁用 libvirt 实时快照,直到问题解决,请将以下设置添加到 nova.conf。
[workarounds]
disable_libvirt_livesnapshot = True
确保 Linux 客户机快照的一致性
以下部分摘自 Sébastien Han 的 OpenStack: 执行一致性快照博客文章。
快照捕获文件系统状态,但不捕获内存状态。因此,为确保您的快照包含您想要的数据,在快照之前,您需要确保
运行程序已将其内容写入磁盘
文件系统没有任何“脏”缓冲区:程序已发出写入磁盘的命令,但操作系统尚未执行写入操作
为确保重要服务(如数据库)已将其内容写入磁盘,我们建议您阅读这些应用程序的文档,以确定要发出哪些命令以使其内容同步到磁盘。如果您不确定如何执行此操作,最安全的方法是正常停止这些正在运行的服务。
为了处理“脏”缓冲区问题,我们建议在快照之前使用 sync 命令。
# sync
运行 sync 会将脏缓冲区(已修改但尚未写入磁盘块的缓冲块)写入磁盘。
仅仅运行 sync 不足以确保文件系统的一致性。我们建议您使用 fsfreeze 工具,该工具会暂停对文件系统的新访问,并在磁盘上创建一个适合快照的稳定镜像。fsfreeze 工具支持多种文件系统,包括 ext3、ext4 和 XFS。如果您的虚拟机实例运行在 Ubuntu 上,请安装 util-linux 软件包以获取 fsfreeze。
注意
在底层快照通过 LVM 完成的非常常见的情况下,文件系统冻结由 LVM 自动处理。
# apt-get install util-linux
如果您的操作系统没有可用的 fsfreeze 版本,您可以改用 xfs_freeze,它在 Ubuntu 的 xfsprogs 软件包中提供。尽管名称中有“xfs”,但如果您的 Linux 内核版本是 2.6.29 或更高版本,xfs_freeze 也适用于 ext3 和 ext4,因为它从 2.6.29 开始在虚拟文件系统 (VFS) 级别工作。xfs_freeze 版本支持与 fsfreeze 相同的命令行参数。
考虑一个示例,您想对一个持久块存储卷进行快照,该卷被客户操作系统检测为 /dev/vdb 并挂载在 /mnt 上。fsfreeze 命令接受两个参数
- -f
冻结系统
- -u
解冻系统
要在准备快照时冻结卷,您需要在实例内部以 root 身份执行以下操作
# fsfreeze -f /mnt
您 *必须挂载文件系统* 才能运行 fsfreeze 命令。
发出 fsfreeze -f 命令后,允许文件系统中所有正在进行的事务完成,新的写入系统调用被暂停,以及修改文件系统的其他调用也被暂停。最重要的是,所有脏数据、元数据和日志信息都写入磁盘。
一旦卷被冻结,请勿尝试读取或写入卷,因为这些操作将挂起。操作系统会停止所有 I/O 操作,任何 I/O 尝试都会延迟,直到文件系统被解冻。
一旦您发出了 fsfreeze 命令,就可以安全地执行快照。例如,如果您的实例卷名为 mon-volume,并且您想将其快照到名为 mon-snapshot 的镜像,您现在可以运行以下命令
$ openstack image create mon-snapshot --volume mon-volume
快照完成后,您可以在实例内部以 root 身份使用以下命令解冻文件系统
# fsfreeze -u /mnt
如果您想备份根文件系统,您不能简单地运行前面的命令,因为它会冻结提示符。相反,您可以在实例内部以 root 身份运行以下单行命令
# fsfreeze -f / && read x; fsfreeze -u /
在此命令之后,通常的做法是从您的工作站调用 openstack image create,完成后在您的实例 shell 中按 Enter 键以解冻它。显然您可以自动化此过程,但至少它可以让您正确同步。
确保 Windows 客户机快照的一致性
获取 Windows VM 的一致性快照在概念上与获取 Linux VM 的一致性快照相似,尽管它需要额外的实用程序来与专为方便一致性备份而设计的仅 Windows 子系统进行协调。
Windows XP 及更高版本包含卷影复制服务 (VSS),它提供了一个框架,以便兼容的应用程序可以在活动文件系统上进行一致备份。要使用此框架,会运行一个 VSS 请求者,它向 VSS 服务发出信号,表明需要一致性备份。VSS 服务会通知兼容的应用程序(称为 VSS 编写器)暂停其数据活动。然后 VSS 服务会告诉复制提供程序创建快照。一旦快照完成,VSS 服务会解冻 VSS 编写器并恢复正常的 I/O 活动。
QEMU 提供了一个可以在 KVM 虚拟机管理程序上运行的客户机代理。此客户机代理在 Windows VM 上与 Windows VSS 服务协调,以促进确保一致快照的工作流程。此功能至少需要 QEMU 1.7。相关的客户机代理命令是
- guest-file-flush
将“脏”缓冲区写入磁盘,类似于 Linux
sync操作。- guest-fsfreeze
暂停对磁盘的 I/O,类似于 Linux
fsfreeze -f操作。- guest-fsfreeze-thaw
恢复对磁盘的 I/O,类似于 Linux
fsfreeze -u操作。
要获取 Windows VM 的快照,这些命令可以按顺序编写脚本:刷新文件系统、冻结文件系统、快照文件系统,然后解冻文件系统。与针对 Linux VM 编写类似的工作流脚本一样,在编写此类脚本时必须小心,以确保错误处理彻底,并且文件系统不会处于冻结状态。
数据库中的实例¶
虽然实例信息存储在许多数据库表中,但您最可能需要查看与用户实例相关的表是实例表。
实例表包含与运行中和已删除实例相关的大部分信息。它具有令人眼花缭乱的字段数组;要获取详尽列表,请查看数据库。以下是运维人员在制定查询时最有用的字段
如果实例已删除,
deleted字段设置为1,如果未删除,则设置为NULL。此字段对于从查询中排除已删除实例非常重要。uuid字段是实例的 UUID,在数据库中的其他表中用作外键。此 ID 也在日志、仪表板和命令行工具中报告,以唯一标识一个实例。可用的外键集合用于查找与实例的关系。其中最有用的是
user_id和project_id,它们是启动实例的用户和启动实例的项目。host字段指示哪个计算节点正在托管实例。hostname字段保存实例启动时的名称。显示名称最初与主机名相同,但可以使用 nova rename 命令重置。
许多与时间相关的字段对于跟踪实例状态何时发生变化非常有用。
created_atupdated_atdeleted_atscheduled_atlaunched_atterminated_at
祝好运!¶
本节旨在简要介绍一些最有用的 OpenStack 命令。有关详尽列表,请参阅 OpenStack 管理员指南。我们希望您的用户保持愉快并认可您的辛勤工作!(要了解更多辛勤工作,请翻到下一章,我们将讨论面向系统的操作:维护、故障和调试。)