如何在 Glance 中上传 OpenStack 磁盘镜像

让镜像在您的私有云中可用,以及更多。
157 位读者喜欢这篇文章。
Your image here

Opensource.com

Glance 是一种镜像服务,允许您发现、提供、注册甚至删除磁盘和/或服务器镜像。它是管理 OpenStackTripleO(代表“OpenStack-On-OpenStack”)上镜像的基本组成部分。

如果您使用过最新版本的 OpenStack 平台,您可能已经使用 TripleO 启动了您的第一个 Overcloud,因为当您在 Undercloud 的 OpenStack 内部上传 Overcloud 磁盘镜像时(即,您云内部的节点,用于安装 Overcloud、添加/删除节点以及执行其他方便的操作),您会与 Glance 交互。

在本文中,我将解释如何将镜像上传到 Glance。将镜像上传到该服务使其可用于您的私有云中的实例。此外,当您部署 Overcloud 时,它可以使镜像可用,以便可以使用它们来部署裸机节点。

在 Undercloud 中,执行以下命令

$ openstack overcloud image upload --image-path /home/stack/images/

这将以下 Overcloud 镜像上传到 Glance

  1. overcloud-full
  2. overcloud-full-initrd
  3. overcloud-full-vmlinuz

几秒钟后,镜像将成功上传。通过运行以下命令检查结果

(undercloud) [stack@undercloud ~]$ openstack image list
+--------------------------------------+------------------------+--------+
| ID                                   | Name                   | Status |
+--------------------------------------+------------------------+--------+
| 09ca88ea-2771-459d-94a2-9f87c9c393f0 | overcloud-full         | active |
| 806b6c35-2dd5-478d-a384-217173a6e032 | overcloud-full-initrd  | active |
| b2c96922-161a-4171-829f-be73482549d5 | overcloud-full-vmlinuz | active |
+--------------------------------------+------------------------+--------+

这是部署 Overcloud 过程中的一个强制性且简单的步骤,它会在几秒钟内发生,因此很难看到幕后发生了什么。但是,如果您想知道发生了什么呢?

需要记住的一件事:Glance 使用通过 REST API 进行的客户端-服务器通信。因此,您可以使用 tcpdump 捕获一些 TCP 数据包来了解正在发生的事情。

另一件重要的事情:所有 OpenStack 平台组件之间共享一个数据库(总是有一个数据库,对吧?),它包含 Glance(和其他组件)运行所需的所有信息。(在我的例子中,MariaDB 是后端。)我不会深入研究如何访问 SQL 数据库,因为我不建议随意使用它,但我将展示上传过程中数据库的样子。(这是一个完全用于测试的 OpenStack 安装,因此无需在本例中使用该数据库。)

数据库

此示例练习的基本流程是

镜像已创建 -> 镜像已排队 -> 镜像已保存 -> 镜像已激活

您需要权限才能完成此流程,因此首先,您必须向 OpenStack 的身份服务 Keystone 请求授权。我的 Keystone 目录条目如下所示;由于我在 Undercloud 中,因此我将访问公共端点

| keystone  | identity       | regionOne                           |
|           |                |   public: https://172.16.0.20:13000 |
|           |                | regionOne                           |
|           |                |   internal: http://172.16.0.19:5000 |
|           |                | regionOne                           |
|           |                |   admin: http://172.16.0.19:35357   |

对于 Glance

| glance    | image    | regionOne                              |
|           |          |   public: https://172.16.0.20:13292    |
|           |          | regionOne                              |
|           |          |   internal: http://172.16.0.19:9292    |
|           |          | regionOne                              |
|           |          |   admin: http://172.16.0.19:9292       |

我将访问捕获中的这些端口和 TCP 端口 3306;后者是为了我可以捕获 SQL 数据库中发生的事情。要捕获数据包,请使用 tcpdump 命令

$ tcpdump -nvs0 -i ens3 host 172.16.0.20 and port 13000 or port 3306 or port 13292

幕后,看起来像这样

身份验证

初始请求(API 版本信息发现)

https://172.16.0.20:13000 "GET / HTTP/1.1"

响应

Content-Length: 268 Content-Type: application/json Date: Tue, 18 Feb 2020 04:49:55 GMT Location: https://172.16.0.20:13000/v3/ Server: Apache Vary: X-Auth-Token x-openstack-request-id: req-6edc6642-3945-4fd0-a0f7-125744fb23ec

{
   "versions":{
      "values":[
         {
            "id":"v3.13",
            "status":"stable",
            "updated":"2019-07-19T00:00:00Z",
            "links":[
               {
                  "rel":"self",
                  "href":"https://172.16.0.20:13000/v3/"
               }
            ],
            "media-types":[
               {
                  "base":"application/json",
                  "type":"application/vnd.openstack.identity-v3+json"
               }
            ]
         }
      ]
   }
}

身份验证请求

https://172.16.0.20:13000 "POST /v3/auth/tokens HTTP/1.1" 

在此步骤之后,将为管理员用户分配一个令牌以使用服务。(出于安全原因,无法显示令牌。)该令牌告诉其他服务类似:“我已经使用正确的凭据针对 Keystone 登录;请让我直接进入该服务,不要再问我是谁。”

此时,命令

$ openstack overcloud image upload --image-path /home/stack/images/

执行,并且它被授权将镜像上传到 Glance 服务。

当前状态为

镜像已创建 -> 镜像已排队 -> 镜像已保存 -> 镜像已激活

该服务检查此镜像是否已存在

https://172.16.0.20:13292 "GET /v2/images/overcloud-full-vmlinuz HTTP/1.1"

从客户端的角度来看,该请求如下所示

curl -g -i -X GET -H 'b'Content-Type': b'application/octet-stream'' -H 'b'X-Auth-Token': b'gAAAAABeS2zzWzAZBqF-whE7SmJt_Atx7tiLZhcL8mf6wJPrO3RBdv4SdnWImxbeSQSqEQdZJnwBT79SWhrtt7QDn-2o6dsAtpUb1Rb7w6xe7Qg_AHQfD5P1rU7tXXtKu2DyYFhtPg2TRQS5viV128FyItyt49Yn_ho3lWfIXaR3TuZzyIz38NU'' -H 'User-Agent: python-glanceclient' -H 'Accept-Encoding: gzip, deflate' -H 'Accept: */*' -H 'Connection: keep-alive'  --cacert /etc/pki/ca-trust/source/anchors/cm-local-ca.pem  --cert None --key None https://172.16.0.20:13292/v2/images/overcloud-full-vmlinuz

在这里,您可以看到 fernet 令牌、指示 Glance 正在通信的用户代理以及 TLS 证书;这就是您在 tcpdump 中看不到任何内容的原因。

由于该镜像不存在,因此对此请求收到 404 错误是可以的。

接下来,查询当前镜像

https://172.16.0.20:13292 "GET /v2/images?limit=20 HTTP/1.1" 200 78

并从服务中检索

HTTP/1.1 200 OK
Content-Length: 78
Content-Type: application/json
X-Openstack-Request-Id: req-0f117984-f427-4d35-bec3-956432865dd1
Date: Tue, 18 Feb 2020 04:49:55 GMT



{
   "images":[

   ],
   "first":"/v2/images?limit=20",
   "schema":"/v2/schemas/images"
}

是的,它仍然是空的。

同时,数据库也进行了相同的检查,其中触发了一个巨大的查询,结果相同。(为了同步时间戳,我在连接和查询完成后检查了 tcpdump,然后将它们与 API 调用的时间戳进行了比较。)

为了识别 Glance-DB 调用开始的位置,我在 tcpdump 文件中使用单词“glance”进行了全数据包搜索。与搜索所有其他数据库调用相比,这节省了大量时间,因此这是我检查每个数据库调用的起点。

Searching "glance" inside tcpdump

第一个查询在字段中不返回任何内容,因为该镜像仍然不存在

SELECT images.created_at AS images_created_at, images.updated_at AS images_updated_at, images.deleted_at AS images_deleted_at, images.deleted AS images_deleted, images.id AS images_id, images.name AS images_name, images.disk_format AS images_disk_format, images.container_format AS images_container_format, images.size AS images_size, images.virtual_size AS images_virtual_size, images.status AS images_status, images.visibility AS images_visibility, images.checksum AS images_checksum, images.os_hash_algo AS images_os_hash_algo, images.os_hash_value AS images_os_hash_value, images.min_disk AS images_min_disk, images.min_ram AS images_min_ram, images.owner AS images_owner, images.protected AS images_protected, images.os_hidden AS images_os_hidden, image_properties_1.created_at AS image_properties_1_created_at, image_properties_1.updated_at AS image_properties_1_updated_at, image_properties_1.deleted_at AS image_properties_1_deleted_at, image_properties_1.deleted AS image_properties_1_deleted, image_properties_1.id AS image_properties_1_id, image_properties_1.image_id AS image_properties_1_image_id, image_properties_1.name AS image_properties_1_name, image_properties_1.value AS image_properties_1_value, image_locations_1.created_at AS image_locations_1_created_at, image_locations_1.updated_at AS image_locations_1_updated_at, image_locations_1.deleted_at AS image_locations_1_deleted_at, image_locations_1.deleted AS image_locations_1_deleted, image_locations_1.id AS image_locations_1_id, image_locations_1.image_id AS image_locations_1_image_id, image_locations_1.value AS image_locations_1_value, image_locations_1.meta_data AS image_locations_1_meta_data, image_locations_1.status AS image_locations_1_status 
FROM images LEFT OUTER JOIN image_properties AS image_properties_1 ON images.id = image_properties_1.image_id LEFT OUTER JOIN image_locations AS image_locations_1 ON images.id = image_locations_1.image_id 
WHERE images.id = 'overcloud-full-vmlinuz'

接下来,镜像将开始上传,因此预期会有一个 API 调用和一个数据库写入。

在 API 端,通过在以下位置查询服务来检索镜像方案

https://172.16.0.20:13292 "GET /v2/schemas/image HTTP/1.1"

然后,使用镜像信息填充一些字段。这就是方案的样子

{
   "name":"image",
   "properties":{
      "id":{
         "type":"string",
         "description":"An identifier for the image",
         "pattern":"^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$"
      },
      "name":{
         "type":[
            "null",
            "string"
         ],
         "description":"Descriptive name for the image",
         "maxLength":255
      },
      "status":{
         "type":"string",
         "readOnly":true,
         "description":"Status of the image",
         "enum":[
            "queued",
            "saving",
            "active",
            "killed",
            "deleted",
            "uploading",
            "importing",
            "pending_delete",
            "deactivated"
         ]
      },
      "visibility":{
         "type":"string",
         "description":"Scope of image accessibility",
         "enum":[
            "community",
            "public",
            "private",
            "shared"
         ]
      },
      "protected":{
         "type":"boolean",
         "description":"If true, image will not be deletable."
      },
      "os_hidden":{
         "type":"boolean",
         "description":"If true, image will not appear in default image list response."
      },
      "checksum":{
         "type":[
            "null",
            "string"
         ],
         "readOnly":true,
         "description":"md5 hash of image contents.",
         "maxLength":32
      },
      "os_hash_algo":{
         "type":[
            "null",
            "string"
         ],
         "readOnly":true,
         "description":"Algorithm to calculate the os_hash_value",
         "maxLength":64
      },
      "os_hash_value":{
         "type":[
            "null",
            "string"
         ],
         "readOnly":true,
         "description":"Hexdigest of the image contents using the algorithm specified by the os_hash_algo",
         "maxLength":128
      },
      "owner":{
         "type":[
            "null",
            "string"
         ],
         "description":"Owner of the image",
         "maxLength":255
      },
      "size":{
         "type":[
            "null",
            "integer"
         ],
         "readOnly":true,
         "description":"Size of image file in bytes"
      },
      "virtual_size":{
         "type":[
            "null",
            "integer"
         ],
         "readOnly":true,
         "description":"Virtual size of image in bytes"
      },
      "container_format":{
         "type":[
            "null",
            "string"
         ],
         "description":"Format of the container",
         "enum":[
            null,
            "ami",
            "ari",
            "aki",
            "bare",
            "ovf",
            "ova",
            "docker",
            "compressed"
         ]
      },
      "disk_format":{
         "type":[
            "null",
            "string"
         ],
         "description":"Format of the disk",
         "enum":[
            null,
            "ami",
            "ari",
            "aki",
            "vhd",
            "vhdx",
            "vmdk",
            "raw",
            "qcow2",
            "vdi",
            "iso",
            "ploop"
         ]
      },
      "created_at":{
         "type":"string",
         "readOnly":true,
         "description":"Date and time of image registration"
      },
      "updated_at":{
         "type":"string",
         "readOnly":true,
         "description":"Date and time of the last image modification"
      },
      "tags":{
         "type":"array",
         "description":"List of strings related to the image",
         "items":{
            "type":"string",
            "maxLength":255
         }
      },
      "direct_url":{
         "type":"string",
         "readOnly":true,
         "description":"URL to access the image file kept in external store"
      },
      "min_ram":{
         "type":"integer",
         "description":"Amount of ram (in MB) required to boot image."
      },
      "min_disk":{
         "type":"integer",
         "description":"Amount of disk space (in GB) required to boot image."
      },
      "self":{
         "type":"string",
         "readOnly":true,
         "description":"An image self url"
      },
      "file":{
         "type":"string",
         "readOnly":true,
         "description":"An image file url"
      },
      "stores":{
         "type":"string",
         "readOnly":true,
         "description":"Store in which image data resides.  Only present when the operator has enabled multiple stores.  May be a comma-separated list of store identifiers."
      },
      "schema":{
         "type":"string",
         "readOnly":true,
         "description":"An image schema url"
      },
      "locations":{
         "type":"array",
         "items":{
            "type":"object",
            "properties":{
               "url":{
                  "type":"string",
                  "maxLength":255
               },
               "metadata":{
                  "type":"object"
               },
               "validation_data":{
                  "description":"Values to be used to populate the corresponding image properties. If the image status is not 'queued', values must exactly match those already contained in the image properties.",
                  "type":"object",
                  "writeOnly":true,
                  "additionalProperties":false,
                  "properties":{
                     "checksum":{
                        "type":"string",
                        "minLength":32,
                        "maxLength":32
                     },
                     "os_hash_algo":{
                        "type":"string",
                        "maxLength":64
                     },
                     "os_hash_value":{
                        "type":"string",
                        "maxLength":128
                     }
                  },
                  "required":[
                     "os_hash_algo",
                     "os_hash_value"
                  ]
               }
            },
            "required":[
               "url",
               "metadata"
            ]
         },
         "description":"A set of URLs to access the image file kept in external store"
      },
      "kernel_id":{
         "type":[
            "null",
            "string"
         ],
         "pattern":"^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$",
         "description":"ID of image stored in Glance that should be used as the kernel when booting an AMI-style image.",
         "is_base":false
      },
      "ramdisk_id":{
         "type":[
            "null",
            "string"
         ],
         "pattern":"^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$",
         "description":"ID of image stored in Glance that should be used as the ramdisk when booting an AMI-style image.",
         "is_base":false
      },
      "instance_uuid":{
         "type":"string",
         "description":"Metadata which can be used to record which instance this image is associated with. (Informational only, does not create an instance snapshot.)",
         "is_base":false
      },
      "architecture":{
         "description":"Operating system architecture as specified in https://docs.openstack.org/python-glanceclient/latest/cli/property-keys.html",
         "type":"string",
         "is_base":false
      },
      "os_distro":{
         "description":"Common name of operating system distribution as specified in https://docs.openstack.org/python-glanceclient/latest/cli/property-keys.html",
         "type":"string",
         "is_base":false
      },
      "os_version":{
         "description":"Operating system version as specified by the distributor.",
         "type":"string",
         "is_base":false
      },
      "description":{
         "description":"A human-readable string describing this image.",
         "type":"string",
         "is_base":false
      },
      "cinder_encryption_key_id":{
         "description":"Identifier in the OpenStack Key Management Service for the encryption key for the Block Storage Service to use when mounting a volume created from this image",
         "type":"string",
         "is_base":false
      },
      "cinder_encryption_key_deletion_policy":{
         "description":"States the condition under which the Image Service will delete the object associated with the 'cinder_encryption_key_id' image property.  If this property is missing, the Image Service will take no action",
         "type":"string",
         "enum":[
            "on_image_deletion",
            "do_not_delete"
         ],
         "is_base":false
      }
   },
   "additionalProperties":{
      "type":"string"
   },
   "links":[
      {
         "rel":"self",
         "href":"{self}"
      },
      {
         "rel":"enclosure",
         "href":"{file}"
      },
      {
         "rel":"describedby",
         "href":"{schema}"
      }
   ]
}

这是一个很长的方案!

这是启动上传镜像信息的 API 调用,它现在将移动到“排队”状态

curl -g -i -X POST -H 'b'Content-Type': b'application/json'' -H 'b'X-Auth-Token': b'gAAAAABeS2zzWzAZBqF-whE7SmJt_Atx7tiLZhcL8mf6wJPrO3RBdv4SdnWImxbeSQSqEQdZJnwBT79SWhrtt7QDn-2o6dsAtpUb1Rb7w6xe7Qg_AHQfD5P1rU7tXXtKu2DyYFhtPg2TRQS5viV128FyItyt49Yn_ho3lWfIXaR3TuZzyIz38NU'' -H 'User-Agent: python-glanceclient' -H 'Accept-Encoding: gzip, deflate' -H 'Accept: */*' -H 'Connection: keep-alive'  --cacert /etc/pki/ca-trust/source/anchors/cm-local-ca.pem  --cert None --key None -d '{"name": "overcloud-full-vmlinuz", "disk_format": "aki", "visibility": "public", "container_format": "bare"}' https://172.16.0.20:13292/v2/images

这是 API 响应

HTTP/1.1 201 Created
Content-Length: 629
Content-Type: application/json
Location: https://172.16.0.20:13292/v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c
Openstack-Image-Import-Methods: web-download
X-Openstack-Request-Id: req-bd5194f0-b1c2-40d3-a646-8a24ed0a1b1b
Date: Tue, 18 Feb 2020 04:49:56 GMT

{
   "name":"overcloud-full-vmlinuz",
   "disk_format":"aki",
   "container_format":"bare",
   "visibility":"public",
   "size":null,
   "virtual_size":null,
   "status":"queued",
   "checksum":null,
   "protected":false,
   "min_ram":0,
   "min_disk":0,
   "owner":"c0a46a106d3341649a25b10f2770aff8",
   "os_hidden":false,
   "os_hash_algo":null,
   "os_hash_value":null,
   "id":"13892850-6add-4c28-87cd-6da62e6f8a3c",
   "created_at":"2020-02-18T04:49:55Z",
   "updated_at":"2020-02-18T04:49:55Z",
   "tags":[

   ],
   "self":"/v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c",
   "file":"/v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c/file",
   "schema":"/v2/schemas/image"
}

以及将信息存储在 Glance-DB 中的 SQL 调用

INSERT INTO images (created_at, updated_at, deleted_at, deleted, id, name, disk_format, container_format, size, virtual_size, status, visibility, checksum, os_hash_algo, os_hash_value, min_disk, min_ram, owner, protected, os_hidden) VALUES ('2020-02-18 04:49:55.993652', '2020-02-18 04:49:55.993652', NULL, 0, '13892850-6add-4c28-87cd-6da62e6f8a3c', 'overcloud-full-vmlinuz', 'aki', 'bare', NULL, NULL, 'queued', 'public', NULL, NULL, NULL, 0, 0, 'c0a46a106d3341649a25b10f2770aff8', 0, 0)

当前状态

镜像已创建 -> 镜像已排队 -> 镜像已保存 -> 镜像已激活

在 Glance 架构中,镜像“物理”存储在指定的后端(在本例中为 Swift)中,因此流量也会访问端口 8080 上的 Swift 端点。捕获此流量将使 .pcap 文件与上传的镜像一样大(在我的例子中为 2GB)。*  

Glance architecture
SELECT image_properties.created_at AS image_properties_created_at, image_properties.updated_at AS image_properties_updated_at, image_properties.deleted_at AS image_properties_deleted_at, image_properties.deleted AS image_properties_deleted, image_properties.id AS image_properties_id, image_properties.image_id AS image_properties_image_id, image_properties.name AS image_properties_name, image_properties.value AS image_properties_value 
FROM image_properties 
WHERE '13892850-6add-4c28-87cd-6da62e6f8a3c' = image_properties.image_id

您可以看到数据库中发生了一些验证。此时,流程状态为“已排队”(如上所示),您可以在此处进行检查

Checking the Glance image status

您还可以使用以下查询进行检查,其中 updated_at 字段和流程状态会相应修改(即,排队到正在保存)

当前状态

镜像已创建 -> 镜像已排队 -> 镜像已保存 -> 镜像已激活

SELECT images.id AS images_id 
FROM images 
WHERE images.id = '13892850-6add-4c28-87cd-6da62e6f8a3c' AND images.status = 'queued'
UPDATE images SET updated_at='2020-02-18 04:49:56.046542', id='13892850-6add-4c28-87cd-6da62e6f8a3c', name='overcloud-full-vmlinuz', disk_format='aki', container_format='bare', size=NULL, virtual_size=NULL, status='saving', visibility='public', checksum=NULL, os_hash_algo=NULL, os_hash_value=NULL, min_disk=0, min_ram=0, owner='c0a46a106d3341649a25b10f2770aff8', protected=0, os_hidden=0 WHERE images.id = '13892850-6add-4c28-87cd-6da62e6f8a3c' AND images.status = 'queued'

在此过程中使用以下查询进行验证

SELECT images.created_at AS images_created_at, images.updated_at AS images_updated_at, images.deleted_at AS images_deleted_at, images.deleted AS images_deleted, images.id AS images_id, images.name AS images_name, images.disk_format AS images_disk_format, images.container_format AS images_container_format, images.size AS images_size, images.virtual_size AS images_virtual_size, images.status AS images_status, images.visibility AS images_visibility, images.checksum AS images_checksum, images.os_hash_algo AS images_os_hash_algo, images.os_hash_value AS images_os_hash_value, images.min_disk AS images_min_disk, images.min_ram AS images_min_ram, images.owner AS images_owner, images.protected AS images_protected, images.os_hidden AS images_os_hidden, image_properties_1.created_at AS image_properties_1_created_at, image_properties_1.updated_at AS image_properties_1_updated_at, image_properties_1.deleted_at AS image_properties_1_deleted_at, image_properties_1.deleted AS image_properties_1_deleted, image_properties_1.id AS image_properties_1_id, image_properties_1.image_id AS image_properties_1_image_id, image_properties_1.name AS image_properties_1_name, image_properties_1.value AS image_properties_1_value, image_locations_1.created_at AS image_locations_1_created_at, image_locations_1.updated_at AS image_locations_1_updated_at, image_locations_1.deleted_at AS image_locations_1_deleted_at, image_locations_1.deleted AS image_locations_1_deleted, image_locations_1.id AS image_locations_1_id, image_locations_1.image_id AS image_locations_1_image_id, image_locations_1.value AS image_locations_1_value, image_locations_1.meta_data AS image_locations_1_meta_data, image_locations_1.status AS image_locations_1_status 
FROM images LEFT OUTER JOIN image_properties AS image_properties_1 ON images.id = image_properties_1.image_id LEFT OUTER JOIN image_locations AS image_locations_1 ON images.id = image_locations_1.image_id 
WHERE images.id = '13892850-6add-4c28-87cd-6da62e6f8a3c'

您可以在 Wireshark 捕获中看到其响应

Wireshark capture

镜像完全上传后,其状态将更改为“已激活”,这意味着该镜像在服务中可用且可以使用。

https://172.16.0.20:13292 "GET /v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c HTTP/1.1" 200 

{
   "name":"overcloud-full-vmlinuz",
   "disk_format":"aki",
   "container_format":"bare",
   "visibility":"public",
   "size":8106848,
   "virtual_size":null,
   "status":"active",
   "checksum":"5d31ee013d06b83d02c106ea07f20265",
   "protected":false,
   "min_ram":0,
   "min_disk":0,
   "owner":"c0a46a106d3341649a25b10f2770aff8",
   "os_hidden":false,
   "os_hash_algo":"sha512",
   "os_hash_value":"9f59d36dec7b30f69b696003e7e3726bbbb27a36211a0b31278318c2af0b969ffb279b0991474c18c9faef8b9e96cf372ce4087ca13f5f05338a36f57c281499",
   "id":"13892850-6add-4c28-87cd-6da62e6f8a3c",
   "created_at":"2020-02-18T04:49:55Z",
   "updated_at":"2020-02-18T04:49:56Z",
   "direct_url":"swift+config://ref1/glance/13892850-6add-4c28-87cd-6da62e6f8a3c",
   "tags":[

   ],
   "self":"/v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c",
   "file":"/v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c/file",
   "schema":"/v2/schemas/image"
}

您还可以看到更新当前状态的数据库调用

UPDATE images SET updated_at='2020-02-18 04:49:56.571879', id='13892850-6add-4c28-87cd-6da62e6f8a3c', name='overcloud-full-vmlinuz', disk_format='aki', container_format='bare', size=8106848, virtual_size=NULL, status='active', visibility='public', checksum='5d31ee013d06b83d02c106ea07f20265', os_hash_algo='sha512', os_hash_value='9f59d36dec7b30f69b696003e7e3726bbbb27a36211a0b31278318c2af0b969ffb279b0991474c18c9faef8b9e96cf372ce4087ca13f5f05338a36f57c281499', min_disk=0, min_ram=0, owner='c0a46a106d3341649a25b10f2770aff8', protected=0, os_hidden=0 WHERE images.id = '13892850-6add-4c28-87cd-6da62e6f8a3c' AND images.status = 'saving'

当前状态

镜像已创建 -> 镜像已排队 -> 镜像已保存 -> 镜像已激活

有趣的一件事是,在使用 PATCH 上传镜像后,会添加镜像中的一个属性。此属性是 hw_architecture 并且设置为 x86_64

https://172.16.0.20:13292 "PATCH /v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c HTTP/1.1" 

curl -g -i -X PATCH -H 'b'Content-Type': b'application/openstack-images-v2.1-json-patch'' -H 'b'X-Auth-Token': b'gAAAAABeS2zzWzAZBqF-whE7SmJt_Atx7tiLZhcL8mf6wJPrO3RBdv4SdnWImxbeSQSqEQdZJnwBT79SWhrtt7QDn-2o6dsAtpUb1Rb7w6xe7Qg_AHQfD5P1rU7tXXtKu2DyYFhtPg2TRQS5viV128FyItyt49Yn_ho3lWfIXaR3TuZzyIz38NU'' -H 'User-Agent: python-glanceclient' -H 'Accept-Encoding: gzip, deflate' -H 'Accept: */*' -H 'Connection: keep-alive'  --cacert /etc/pki/ca-trust/source/anchors/cm-local-ca.pem  --cert None --key None -d '[{"op": "add", "path": "/hw_architecture", "value": "x86_64"}]' https://172.16.0.20:13292/v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c

Response:

{
   "hw_architecture":"x86_64",
   "name":"overcloud-full-vmlinuz",
   "disk_format":"aki",
   "container_format":"bare",
   "visibility":"public",
   "size":8106848,
   "virtual_size":null,
   "status":"active",
   "checksum":"5d31ee013d06b83d02c106ea07f20265",
   "protected":false,
   "min_ram":0,
   "min_disk":0,
   "owner":"c0a46a106d3341649a25b10f2770aff8",
   "os_hidden":false,
   "os_hash_algo":"sha512",
   "os_hash_value":"9f59d36dec7b30f69b696003e7e3726bbbb27a36211a0b31278318c2af0b969ffb279b0991474c18c9faef8b9e96cf372ce4087ca13f5f05338a36f57c281499",
   "id":"13892850-6add-4c28-87cd-6da62e6f8a3c",
   "created_at":"2020-02-18T04:49:55Z",
   "updated_at":"2020-02-18T04:49:56Z",
   "direct_url":"swift+config://ref1/glance/13892850-6add-4c28-87cd-6da62e6f8a3c",
   "tags":[

   ],
   "self":"/v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c",
   "file":"/v2/images/13892850-6add-4c28-87cd-6da62e6f8a3c/file",
   "schema":"/v2/schemas/image"
}

这也在 MySQL 数据库中更新

INSERT INTO image_properties (created_at, updated_at, deleted_at, deleted, image_id, name, value) VALUES ('2020-02-18 04:49:56.655780', '2020-02-18 04:49:56.655783', NULL, 0, '13892850-6add-4c28-87cd-6da62e6f8a3c', 'hw_architecture', 'x86_64')

这几乎就是将镜像上传到 Glance 时发生的情况。如果您在数据库中进行检查,则如下所示

MariaDB [glance]> SELECT images.created_at AS images_created_at, images.updated_at AS images_updated_at, images.deleted_at AS images_deleted_at, images.deleted AS images_deleted, images.id AS images_id, images.name AS images_name, images.disk_format AS images_disk_format, images.container_format AS images_container_format, images.size AS images_size, images.virtual_size AS images_virtual_size, images.status AS images_status, images.visibility AS images_visibility, images.checksum AS images_checksum, images.os_hash_algo AS images_os_hash_algo, images.os_hash_value AS images_os_hash_value, images.min_disk AS images_min_disk, images.min_ram AS images_min_ram, images.owner AS images_owner, images.protected AS images_protected, images.os_hidden AS images_os_hidden, image_properties_1.created_at AS image_properties_1_created_at, image_properties_1.updated_at AS image_properties_1_updated_at, image_properties_1.deleted_at AS image_properties_1_deleted_at, image_properties_1.deleted AS image_properties_1_deleted, image_properties_1.id AS image_properties_1_id, image_properties_1.image_id AS image_properties_1_image_id, image_properties_1.name AS image_properties_1_name, image_properties_1.value AS image_properties_1_value, image_locations_1.created_at AS image_locations_1_created_at, image_locations_1.updated_at AS image_locations_1_updated_at, image_locations_1.deleted_at AS image_locations_1_deleted_at, image_locations_1.deleted AS image_locations_1_deleted, image_locations_1.id AS image_locations_1_id, image_locations_1.image_id AS image_locations_1_image_id, image_locations_1.value AS image_locations_1_value, image_locations_1.meta_data AS image_locations_1_meta_data, image_locations_1.status AS image_locations_1_status  FROM images LEFT OUTER JOIN image_properties AS image_properties_1 ON images.id = image_properties_1.image_id LEFT OUTER JOIN image_locations AS image_locations_1 ON images.id = image_locations_1.image_id  WHERE images.id = '13892850-6add-4c28-87cd-6da62e6f8a3c'\G;
*************************** 1. row ***************************
            images_created_at: 2020-02-18 04:49:55
            images_updated_at: 2020-02-18 04:49:56
            images_deleted_at: NULL
               images_deleted: 0
                    images_id: 13892850-6add-4c28-87cd-6da62e6f8a3c
                  images_name: overcloud-full-vmlinuz
           images_disk_format: aki
      images_container_format: bare
                  images_size: 8106848
          images_virtual_size: NULL
                images_status: active
            images_visibility: public
              images_checksum: 5d31ee013d06b83d02c106ea07f20265
          images_os_hash_algo: sha512
         images_os_hash_value: 9f59d36dec7b30f69b696003e7e3726bbbb27a36211a0b31278318c2af0b969ffb279b0991474c18c9faef8b9e96cf372ce4087ca13f5f05338a36f57c281499
              images_min_disk: 0
               images_min_ram: 0
                 images_owner: c0a46a106d3341649a25b10f2770aff8
             images_protected: 0
             images_os_hidden: 0
image_properties_1_created_at: 2020-02-18 04:49:56
image_properties_1_updated_at: 2020-02-18 04:49:56
image_properties_1_deleted_at: NULL
   image_properties_1_deleted: 0
        image_properties_1_id: 11
  image_properties_1_image_id: 13892850-6add-4c28-87cd-6da62e6f8a3c
      image_properties_1_name: hw_architecture
     image_properties_1_value: x86_64
 image_locations_1_created_at: 2020-02-18 04:49:56
 image_locations_1_updated_at: 2020-02-18 04:49:56
 image_locations_1_deleted_at: NULL
    image_locations_1_deleted: 0
         image_locations_1_id: 7
   image_locations_1_image_id: 13892850-6add-4c28-87cd-6da62e6f8a3c
      image_locations_1_value: swift+config://ref1/glance/13892850-6add-4c28-87cd-6da62e6f8a3c
  image_locations_1_meta_data: {}
     image_locations_1_status: active
1 row in set (0.00 sec)

最终结果是

(undercloud) [stack@undercloud ~]$ openstack image list
+--------------------------------------+------------------------+--------+
| ID                                   | Name                   | Status |
+--------------------------------------+------------------------+--------+
| 9a26b9da-3783-4223-bdd7-c553aa194e30 | overcloud-full         | active |
| a2914297-c70f-4021-bc3e-8ec2123f6ea6 | overcloud-full-initrd  | active |
| 13892850-6add-4c28-87cd-6da62e6f8a3c | overcloud-full-vmlinuz | active |
+--------------------------------------+------------------------+--------+
(undercloud) [stack@undercloud ~]$ 

在此过程中还会发生其他一些小事情,但总的来说,就是这样。

结论

了解 OpenStack 平台中最常见操作的流程将使您能够在工作中遇到一些问题时提高故障排除技能。您可以检查 Glance 中镜像的状态;了解镜像是否处于“已排队”、“正在保存”或“已激活”状态;并在您的环境中进行一些捕获,以通过检查您需要检查的端点来了解发生了什么。

我喜欢调试。我认为这是任何角色的重要技能,无论您是在支持、咨询、开发(当然!)还是架构师角色中工作。我希望本文为您提供了一些开始调试事情的基本指南。


* 如果您想知道如何毫无问题地打开 2GB 的 .pcap 文件,这是一种方法

$ editcap -c 5000 image-upload.pcap upload-overcloud-image.pcap

这会将您的大型捕获分成每个 5,000 个数据包的较小捕获。


本文 最初发布 在 LinkedIn 上,经许可转载。

标签
User profile image.
我的名字是 Jair,来自委内瑞拉的 Puerto Ordaz,目前在墨西哥城生活了近 10 年。我在 Red Hat 工作了 11 年以上,版本不同,但总是在电信行业。

1 条评论

好文章,感谢分享!!

Creative Commons License本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
© . All rights reserved.