OpenStack-Pike版Ironic安装指导分析-(下)

基于OpenStack官网指导,结合实际应用,予以总结。

整体结构:


五,构建裸金属服务驱动


(一)启用drivers和硬件类型
1,介绍
  裸金属服务将实际的硬件管理委派给drivers来实现。从Ocata版本开始,支持两种类型的驱动程序:经典驱动程序(例如pxe ipmitool、agent ilo等)和较新的硬件类型(例如,通用redfish和ipmi或特定于供应商的ilo和irmc)。
驱动程序依次由hardware interfaces组成:以特定于供应商的方式处理裸金属供应的某些方面的功能集。传统的驱动程序(Classic drivers)有所有hardware interfaces的硬编码,而硬件类型(hardware types)只声明它们兼容的硬件接口(hardware interfaces)。
  从API用户的角度来看,经典驱动程序(classic drivers)和硬件类型(hardware types)都可以分配给节点的驱动(driver)字段。但是,它们的配置方式不同。

2,启用硬件类型
  可以在ironic-conductor服务的配置文件中,通过设置 enabled_hardware_types配置选项,启用Hardware types。例如:
[DEFAULT]
enabled_hardware_types = ipmi,redfish
由于驱动程序的动态特性,它们还需要配置启用的硬件接口。
注意:
 setup.cfg 列出了所有可用的硬件类型和接口的源码树结构。

启用硬件接口
有多种硬件接口:
boot
console
deploy
inspect
management
network
power
raid
storage
vendor
在多conductor环境中,硬件接口的使用
多个conductor可以分别配置各自的硬件接口类型(可以相同/可以不同/可以配置多个)
配置接口默认值:
当没有提供明确的接口类型是,可以使用默认值,
[DEFAULT]
default_deploy_interface = direct
default_network_interface = neutron
3,启用传统drivers
传统驱动的启动,是在 ironic-conductor服务的配置文件中设置配置项 enabled_drivers ,例如:
[DEFAULT]
enabled_drivers = pxe_ipmitool,pxe_ilo,pxe_drac
这些以逗号分隔的列表中的名字,是drivers的入口名,它们需要在 conductor 服务运行起来之前就可用,而且所有依赖必须在本地安装,例如:
从pxe开始的驱动程序和一些从代理开始的驱动程序需要:  Configuring PXE and iPXE,
以pxe开头的驱动程序,或者在名称中有iscsi:  Configuring iSCSI-based drivers,
以ipmitool结束的驱动程序,需要: Configuring IPMI support.

 Enabling drivers 可以看到所有支持的drivers配置。

(二)配置PXE和iPXE
1,PXE设置
如果您将使用PXE,它需要在ironic-conductor运行的裸金属服务节点上设置。
1),确保tftp根目录存在,并且可以由运行ironic-conductor的用户(ironic)执行写入操作。例如:
sudo mkdir -p /tftpboot
sudo chown -R ironic /tftpboot
2),安装tftp服务和syslinux包
Fedora 21/RHEL7/CentOS7:
sudo yum install tftp-server syslinux-tftpboot xinetd
3),使用xinetd提供tftp服务,创建/编辑/etc/xinetd.d/tftp,如下:
service tftp{
  protocol        = udp
  port            = 69
  socket_type     = dgram
  wait            = yes
  user            = root
  server          = /usr/sbin/in.tftpd
  server_args     = -v -v -v -v -v --map-file /tftpboot/map-file /tftpboot
  disable         = no
  # This is a workaround for Fedora, where TFTP will listen only on
  # IPv6 endpoint, if IPv4 flag is not used.
  flags           = IPv4}
然后重启xinetd服务,

Fedora/RHEL7/CentOS7/SUSE:

sudo systemctl restart xinetd
4),复制PXE到/tftpboot,

RHEL7/CentOS7/SUSE:

sudo cp /usr/share/syslinux/pxelinux.0 /tftpboot
5),如果whole磁盘镜像需要通过PXE-netboot进行部署,则需要复制 chain.c32到/tftpboot

RHEL7/CentOS7/SUSE:

sudo cp /usr/share/syslinux/chain.c32 /tftpboot/
6),如果syslinux 版本大于4,还需要确保复制库模块文件到/tftpboot
sudo cp /usr/lib/syslinux/modules/*/ldlinux.* /tftpboot
7),在tftp的boot目录/tftpboot,创建一个map文件
echo 're ^(/tftpboot/) /tftpboot/\2' > /tftpboot/map-file
echo 're ^/tftpboot/ /tftpboot/' >> /tftpboot/map-file
echo 're ^(^/) /tftpboot/\1' >> /tftpboot/map-file
echo 're ^([^/]) /tftpboot/\1' >> /tftpboot/map-file

2,PXE UEFI设置
如果想要部署支持UEFI的裸金属,在ironic conductor节点上执行这些附加步骤,以配置PXE UEFI环境。
1),安装Grub2和shim包
Fedora 21/RHEL7/CentOS7:
sudo yum install grub2-efi shim
2),复制grub和shim引导加载器镜像到/tftpboot目录

RHEL7/CentOS7:

sudo cp /boot/efi/EFI/centos/shim.efi /tftpboot/bootx64.efisudo cp /boot/efi/EFI/centos/grubx64.efi /tftpboot/grubx64.efi
3),创建 grub.cfg:

RHEL7/CentOS7: Create grub.cfg under /tftpboot/EFI/centos directory:

GRUB_DIR=/tftpboot/EFI/centos
这个文件用于将grub重定向到baremetal节点指定的配置文件。基于分配给baremetal节点的DHCP IP,将其重定向到特定的grub配置文件。

set default=master
set timeout=5
set hidden_timeout_quiet=false

menuentry "master"  {
configfile /tftpboot/$net_default_ip.conf
}

修改 grub.cfg权限:

sudo chmod 644 $GRUB_DIR/grub.cfg
4),使用节点属性中的boot_mode字段更新裸金属节点
ironic node-update <node-uuid> add properties/capabilities='boot_mode:uefi'
5),确保裸金属节点配置的启动模式为UEFI下启动,引导设备需要设置为网络pxe

pxe_ilo 驱动支持在裸金属节点上自动设置UEFI引导启动、自动配置引导方式,因此这一步在pxe_ilo 驱动 下是不需要的。


3,iPXE设置
4,PXE多架构设置
可以由一个conductor部署不同架构的服务器。要使用这个特性,需要在裸金属服务配置文件 (/etc/ironic/ironic.conf)中,分别使用 [pxe]pxe_bootfile_name_by_arch and [pxe]pxe_config_template_by_arch 来配置特定系统结构引导方法和模板文件,

这两个选项是字典值(数据结构);key是架构,value是引导(或配置模板)文件。
节点的 cpu_arch属性被用作获取合适的引导文件和模板文件的key值,如果 cpu_arch不在字典中,配置文件选项将会使用 pxe_bootfile_namepxe_config_templateuefi_pxe_bootfile_name 和 uefi_pxe_config_template替代(在[pxe]配置段中)。

[pxe]

# Bootfile DHCP parameter. (string value)
pxe_bootfile_name=pxelinux.0

# On ironic-conductor node, template file for PXE
# configuration. (string value)
pxe_config_template = $pybasedir/drivers/modules/pxe_config.template

# Bootfile DHCP parameter for UEFI boot mode. (string value)
uefi_pxe_bootfile_name=bootx64.efi

# On ironic-conductor node, template file for PXE
# configuration for UEFI boot loader. (string value)
uefi_pxe_config_template=$pybasedir/drivers/modules/pxe_grub_config.template

# Bootfile DHCP parameter per node architecture. (dict value)
pxe_bootfile_name_by_arch=aarch64:grubaa64.efi,ppc64:bootppc64

# On ironic-conductor node, template file for PXE
# configuration per node architecture. For example:
# aarch64:/opt/share/grubaa64_pxe_config.template (dict value)
pxe_config_template_by_arch=aarch64:pxe_grubaa64_config.template,ppc64:pxe_ppc64_config.template


(三)配置IPMI支持
1,安装pmitool
为了开启使用IPMI协议的driver程序进行电源和管理操作的功能(例如: ipmipxe_ipmitool 和 agent_ipmitool),ipmitool 命令必须可以在ironic-conductor运行的服务节点上执行
查看基于ipmitool drivers的更详细信息IPMITool driver

2,验证IPMI,以及异常问题定位
检查是否可以通过运行ipmitool,连接到您的裸金属服务器上的IPMI控制器,并进行身份验证:
ipmitool -I lanplus -H <ip-address> -U <username> -P <password> chassis power status
<ip-address> 是要访问的IPMI controller的ip地址,不是裸金属节点的地址,IPMI controller需要有自己独立的ip地址。
如果上述命令没有返回裸金属服务器的电源状态,请检查:
  • ipmitool已安装并可通过$PATH环境变量使用。
  • 裸金属服务器上的IPMI控制器被打开(dell服务器默认是关闭的,其它多数服务器IPMI默认是打开的)。
  • 在命令中传递的IPMI控制器凭证和IP地址是正确的。
  • conductor节点有通向IPMI控制器的路由。这可以通过在conductor节点执行ping操作IPMI控制器IP来检查。
3,IPMI配置
如果在环境中存在缓慢或无响应的BMCs,则可能需要提高[ipmi]部分中的min命令间隔配置选项。因为设置这个超时时间过低会导致较旧的BMCs崩溃,并且需要进行硬重置,因此默认值的配置是相当的保守。

4,收集传感器数据
裸金属服务支持使用某些drivers发送IPMI传感器信息到 Telemetry (即ceilometer服务),例如 ipmitoolilo 和irmc
默认情况下,发送IPMI传感器信息到 Telemetry的功能是关闭的。如果要开启,需要在ironic.conf中修改配置:
[DEFAULT]
notification_driver = messaging
[conductor]
send_sensor_data = true
如果要自定义发送给 Telemetry的传感器类型,则需要更改 send_sensor_data_types配置项,例如,想要发送温度、蜂鸣器、电压信息:
send_sensor_data_types=Temperature,Fan,Voltage
如果设置为 All ,则支持所有传感器类型。

(四)配置基于iSCSI的drivers
确保 qemu-img 和 iscsiadm 工具安装在 ironic-conductor 主机上。


扩展:Redfish

  Redfish红鱼标准:2014年科技产业厂商戴尔(DELL)、艾默生网络能源、惠普(HP)及英特尔(Intel)宣布建立Redfish“红鱼”标准,该标准应用于数据中心发展及系统管理,可传递全面的功能性、可测性和安全性资讯。这是自智能平台管理界面(IPMI)于1998年创立以来最为全面性的标准,实际上也可以理解为Redfish是IPMI的后续替代产品。主要区别于IPMI之处是,针对大规模服务器管理时,具有更丰富的命令,更简单的管理架构等。
  事实上各个服务器制造商都有自己的硬件系统管理工具,比如:戴尔的远程访问控制器(Dell Remote Access Controller,iDRAC),HPE的Integrated Lights-Out(Integrated Lights-Out,iLo),思科的集成管理控制器(Integrated Management Controller),以及超微电脑公司的Rack Scale Design产品,但是目前几乎所有主要的服务器供应商都宣传自己的管理工具与Redfish服务器开放标准参数的兼容性, 特别是他们新发布的服务器——HPE的Gen10产品、戴尔EMC的14G产品以及思科的UCSM5等厂商产品。
  Redfish最初来自于三年前的DMTF(Distributed Management Task Force,分布式管理任务组织)项目,它的目的是取代智能平台管理界面IPMI(Intelligent Platform Management Interface),Redfish专为那些寻求更安全地管理大型分布式数据中心的IT专业人士而设计。Redfish能够发现服务器、重新启动并重新设置服务器,盘点服务器中的所有硬件和固件,监控服务器及其子组件的运行状况,并生成事件日志等许多其他功能。

六,Enrollment 注册

  在所有的服务都正确配置之后,应该使用裸金属服务来注册服务器硬件,并确保可用硬件资源对Compute服务可见。一旦节点处于available供应状态,这些节点就会在Compute服务中显示出来。

注意:
  在用裸金属服务注册节点之后,计算服务将不会立即接收到新资源的通知。计算服务的资源跟踪器会周期性地同步,因此任何直接对裸金属服务资源的更改,都将在计算服务的下一个周期任务执行之后才能在计算服务中可见。

  对于任何在计算服务中可见的任何裸金属节点,如果电源和部署的接口都通过了有效性检查,那么(随时都)可能有一个工作负载来调度它。如果你希望将一个节点排除在计算服务的调度程序之外,当你需要对节点进行维护时,可以将节点设置为维护模式(maintenance mode)。更多信息查看维护模式章节  Maintenance mode

(一) 选择一个driver


在注册一个节点时,最重要的信息是驱动程序。这可以是一个经典的驱动程序,也可以是硬件类型——参考启用驱动程序和硬件类型。driver-list命令可用于列出所有主机上启用的所有驱动程序(两种类型):
ironic driver-list
+---------------------+-----------------------+
| Supported driver(s) | Active host(s)        |
+---------------------+-----------------------+
| ipmi                | localhost.localdomain |
| pxe_ipmitool        | localhost.localdomain |
+---------------------+-----------------------+
API从1.31开始,可以只列出classic driver或者只列出动态driver:
ironic --ironic-api-version 1.31 driver-list -t dynamic
+---------------------+-----------------------+
| Supported driver(s) | Active host(s)        |
+---------------------+-----------------------+
| ipmi                | localhost.localdomain |
+---------------------+-----------------------+
应该根据实际的硬件功能和预期特性来选择使用的特定驱动程序。请参阅启用驱动程序以获得更多的提示。

每个驱动程序都有一个驱动属性列表,这些属性需要通过节点的驱动程序信息字段来指定,以便驱动程序在节点上操作。这个列表包含驱动程序使用的硬件接口的属性。这些驱动属性可以使用driver-properties命令查看:
$ ironic driver-properties pxe_ipmitool
+----------------------+-------------------------------------------------------------------------------------------------------------+
| Property             | Description                                                                                                 |
+----------------------+-------------------------------------------------------------------------------------------------------------+
| ipmi_address         | IP address or hostname of the node. Required.                                                               |
| ipmi_password        | password. Optional.                                                                                         |
| ipmi_username        | username; default is NULL user. Optional.                                                                   |
| ...                  | ...                                                                                                         |
| deploy_kernel        | UUID (from Glance) of the deployment kernel. Required.                                                      |
| deploy_ramdisk       | UUID (from Glance) of the ramdisk that is mounted at boot time. Required.                                   |
+----------------------+-------------------------------------------------------------------------------------------------------------+
所标记的属性必须在节点创建期间或不久之后提供。有些属性可能只用于某些特性。

(二) 注意API版本

从API版本1.1.11开始,裸金属服务为其状态机添加了新的初始供应状态enroll,当这个或后来的API版本使用时,新的节点会得到enroll这个状态而不是available。
使用低于1.1.11的API版本的现有自动化工具不会受到影响,因为初始供应状态仍然是available。
然而,就节点创建而言,使用API版本1.11或更高版本可能会破坏现有的自动化工具。
python-ironicclient使用的默认API版本是1.9,但它可能在将来发生变化,不应该依赖于此。

下面例子中,我们将使用裸金属1.11API版本,有几个优势:
(1)在离开enroll状态之前,显式的电源凭证验证;
(2)进入available 状态之前,运行节点清理操作;
(3)不会将未配置的节点暴露给调度程序

可以通过设置环境变量IRONIC_API_VERSION来设置API版本,对于OpenStackClient 裸金属插件,可以设置OS_BAREMETAL_API_VERSION,如下:

$ export IRONIC_API_VERSION=1.11
$ export OS_BAREMETAL_API_VERSION=1.11

(三) 注册程序Enroll 

3.1 创建一个节点
本节描述注册一个节点的主要步骤,并使其供应available。为了便于说明,有些步骤是分开显示的,如果需要,可以合并。

1,用node-create命令在裸金属服务中创建一个节点。至少必须指定一个驱动程序名称(pxe_ipmitool, agent_ipmitool or ipmi).
此命令返回除了 node UUID以及其它node相关信息,node的预备供应状态将会变为enroll。
$ export IRONIC_API_VERSION=1.11
$ ironic node-create -d pxe_ipmitool
+--------------+--------------------------------------+
| Property     | Value                                |
+--------------+--------------------------------------+
| uuid         | dfc6189f-ad83-4261-9bda-b27258eb1987 |
| driver_info  | {}                                   |
| extra        | {}                                   |
| driver       | pxe_ipmitool                         |
| chassis_uuid |                                      |
| properties   | {}                                   |
| name         | None                                 |
+--------------+--------------------------------------+

$ ironic node-show dfc6189f-ad83-4261-9bda-b27258eb1987
+------------------------+--------------------------------------+
|Property               | Value                                |
+------------------------+--------------------------------------+
| target_power_state     | None                                 |
| extra                  | {}                                   |
| last_error             | None                                 |
| maintenance_reason     | None                                 |
| provision_state        | enroll                               |
| uuid                   | dfc6189f-ad83-4261-9bda-b27258eb1987 |
| console_enabled        | False                                |
| target_provision_state | None                                 |
| provision_updated_at   | None                                 |
| maintenance            | False                                |
| power_state            | None                                 |
| driver                 | pxe_ipmitool                         |
| properties             | {}                                   |
| instance_uuid          | None                                 |
| name                   | None                                 |
| driver_info            | {}                                   |
| ...                    | ...                                  |
+------------------------+--------------------------------------+
像uuid一样,节点也可能配置逻辑name。可以在node-create执行命令时,添加-n选项指定name,或者使用node-update命令修改name。

2,从API版本1.31(和python-ironicclient 1.13)开始,可以选择使用硬件类型的节点使用哪个硬件接口。每个接口都由一个名为<IFACE>_interface的节点字段来表示,<IFACE>是接口类型,例如boot。
接口可以在已存在节点上可以分别修改:
$ ironic --ironic-api-version 1.31 node-update $NODE_UUID replace \
    deploy_interface=direct \
    raid_interface=agent
也可以在节点创建时指定:
$ ironic --ironic-api-version 1.31 node-create -d ipmi \
    --deploy-interface direct \
    --raid-interface agent
若尝试用一个classic driver改变这个字段,并将节点的驱动程序设置为classic driver,这会是一个错误设置,导致这些字段被自动设置为None。

3,使用所需的driver属性更新节点的driver_info信息,这样裸金属服务就可以管理节点。
$ ironic node-update $NODE_UUID add \
    driver_info/ipmi_username=$USER \
    driver_info/ipmi_password=$PASS \
    driver_info/ipmi_address=$ADDRESS
如果IPMI没有运行在623端口(默认端口),就需要添加driver_info信息,指定ipmi_port的值,例如:
$ ironic node-update $NODE_UUID add driver_info/ipmi_port=$PORT_NUMBER
你也可以在节点创建时,多次使用-i选项,指定所有的driver_info
$ ironic node-create -d pxe_ipmitool \
    -i ipmi_username=$USER \
    -i ipmi_password=$PASS \
    -i ipmi_address=$ADDRESS
4,指定一个与节点驱动程序兼容的部署kernel和ramdisk,例如:
$ ironic node-update $NODE_UUID add \
    driver_info/deploy_kernel=$DEPLOY_VMLINUZ_UUID \
    driver_info/deploy_ramdisk=$DEPLOY_INITRD_UUID
5,你还必须通过使用节点的每个NIC网卡MAC地址创建的port,作为裸金属服务的网络接口。这些MAC地址用于实例provisioning和配置合适的网络:
$ ironic port-create -n $NODE_UUID -a $MAC_ADDRESS
3.2 添加调度信息
1,为节点分配一个资源类。资源类应该在你的数据中心中表示一个硬件类,它对应于计算的flavor。
例如,让我们将硬件分成这三组:
  • a,具有大量RAM的节点和用于计算任务的强大CPU,
  • b,用于OpenCL计算的强大GPU节点,
  • c,用于开发和测试的小节点。
我们可以定义三个资源类来反映这些硬件组,分别命名为large-cpu, large-gpu ,small r。然后,对于每个硬件组中的每个节点,我们将通过以下命令设置它们的resource_class :
$ openstack --os-baremetal-api-version 1.21 baremetal node set $NODE_UUID \
    --resource-class $CLASS_NAME
--resource-class参数也可用于创建节点时:
$ openstack --os-baremetal-api-version 1.21 baremetal node create \
    --driver $DRIVER --resource-class $CLASS_NAME
使用资源类来调度,你需要更新你的flavors,参考链接: Create flavors for use with the Bare Metal service.

警告:
基于资源类的调度将在Queens版本中,替换基于properties的调度。

注意:
对于独立部署来说这不是必需的,只是对于那些使用计算服务来提供裸金属实例的人来说。

2,更新节点的属性以匹配实际硬件。
$ ironic node-update $NODE_UUID add \
    properties/cpus=$CPU_COUNT \
    properties/memory_mb=$RAM_MB \
    properties/local_gb=$DISK_GB \
    properties/cpu_arch=$ARCH
如上,也可以在node-create节点创建时,多次使用-p参数来指定:
$ ironic node-create -d pxe_ipmitool \
    -i ipmi_username=$USER \
    -i ipmi_password=$PASS \
    -i ipmi_address=$ADDRESS \
    -p cpus=$CPU_COUNT \
    -p memory_mb=$RAM_MB \
    -p local_gb=$DISK_GB \
    -p cpu_arch=$ARCH
在硬件检查期间也可以发现以上需要的这些值。
(Hardware Inspection链接:https://docs.openstack.org/ironic/pike/admin/inspection.html

警告:
如果没有使用基于资源类resource classes的调度,那么三个属性cpus, memory_mb 和local_gb必须与所创建的flavor定义一致。参考:https://docs.openstack.org/ironic/pike/install/configure-nova-flavors.html

为local_gb属性提供的值必须与将要部署的根设备的大小相匹配。默认情况下,ironic-python-agent选择不小于4 GiB的最小磁盘,
如果你使用根设备提示来覆盖这个逻辑,local_gb需要匹配选中目标盘的大小。
指定系统盘raid,具体参考: Specifying the disk for deployment (root device hints)

3,如果你希望基于硬件能力执行更高级的实例调度,可以将metadata添加到每个将要被调度的节点(参见:ComputeCapabilitiesFilter)。对这一问题的具体解释超出了本文件的范围。它可以通过指定节点属性的capabilities来完成。
$ ironic node-update $NODE_UUID add \
    properties/capabilities=key1:val1,key2:val2

3.3 验证节点信息
1,检查裸金属服务是否具有节点驱动程序功能所需的最小信息,可以用命令行验证:

$ ironic node-validate $NODE_UUID
+------------+--------+--------+
| Interface  | Result | Reason |
+------------+--------+--------+
| console    | True   |        |
| deploy     | True   |        |
| management | True   |        |
| power      | True   |        |
+------------+--------+--------+
如果节点失败了验证,那么每个驱动程序接口都会返回关于为什么失败的信息
$ ironic node-validate $NODE_UUID
+------------+--------+-------------------------------------------------------------------------------------------------------------------------------------+
| Interface  | Result | Reason                                                                                                                              |
+------------+--------+-------------------------------------------------------------------------------------------------------------------------------------+
| console    | None   | not supported                                                                                                                       |
| deploy     | False  | Cannot validate iSCSI deploy. Some parameters were missing in node's instance_info. Missing are: ['root_gb', 'image_source']        |
| management | False  | Missing the following IPMI credentials in node's driver_info: ['ipmi_address'].                                                     |
| power      | False  | Missing the following IPMI credentials in node's driver_info: ['ipmi_address'].                                                     |
+------------+--------+-------------------------------------------------------------------------------------------------------------------------------------+
当裸金属服务使用计算服务时,由于缺乏image信息而导致部署接口验证错误可以忽略。你可以继续enrollment。当请求部署实例时,这些信息将会在部署之前由Compute Service设置。
$ ironic node-validate $NODE_UUID
+------------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Interface  | Result | Reason                                                                                                                                                           |
+------------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| console    | True   |                                                                                                                                                                  |
| deploy     | False  | Cannot validate image information for node because one or more parameters are missing from its instance_info. Missing are: ['ramdisk', 'kernel', 'image_source'] |
| management | True   |                                                                                                                                                                  |
| power      | True   |                                                                                                                                                                  |
+------------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
3.4 使节点可部署
为了能够在节点上执行部署工作,节点必须处于available供应状态。要做到这一点,使用API1.1.11和以上版本的节点必须从enroll状态转移到manageable状态,然后转移到available状态。
如果使用API版本1.10或更早版本(默认情况下是这样),可以安全地跳过这一部分。
在创建节点之后,从最初供应状态enroll转移状态之前,需要在节点上配置基本电源和端口信息。
裸金属服务需要这些信息,因为它可以证明在将节点从enroll到manageable状态时能够控制节点。

把节点从enroll状态切换到manageable状态 :
$ ironic --ironic-api-version 1.11 node-set-provision-state $NODE_UUID manage
$ ironic node-show $NODE_UUID
+------------------------+--------------------------------------------------------------------+
| Property               | Value                                                              |
+------------------------+--------------------------------------------------------------------+
| ...                    | ...                                                                |
| provision_state        | manageable                                                         | <- verify correct state
| uuid                   | 0eb013bb-1e4b-4f4c-94b5-2e7468242611                               |
| ...                    | ...                                                                |
+------------------------+--------------------------------------------------------------------+
注意:
由于它是一个异步调用,因此对于ironic node-set-provision-state,不论转换是否成功,响应都不会显示。
你可以通过ironic node-show来检查操作的状态。如果成功,provision_state将变为预想的状态。如果失败,将会在节点的last_error中查看报错信息。

当节点从manageable状态转移到available供应状态时,如果配置cleaning,节点将会执行自动清理。链接: (see Configure the Bare Metal service for cleaning).

从manageable状态转移到available状态:
$ ironic --ironic-api-version 1.11 node-set-provision-state $NODE_UUID provide
$ ironic node-show $NODE_UUID
+------------------------+--------------------------------------------------------------------+
Property               | Value                                                              |
+------------------------+--------------------------------------------------------------------+
| ...                    | ...                                                                |
| provision_state        | available                                                          | < - verify correct state
| uuid                   | 0eb013bb-1e4b-4f4c-94b5-2e7468242611                               |
| ...                    | ...                                                                |
+------------------------+--------------------------------------------------------------------+
有关裸金属服务的状态机详细信息,可参考:  Ironic’s State Machine
ironic状态机

3.5  将节点映射到计算cells中
如果计算服务用于调度,且裸金属服务的计算节点配置中没有设置discover_hosts_in_cells_interval,那么可以登录任何控制器节点,运行以下命令来把新节点映射到compute cells中。
配置计算节点用于裸金属服务的配置:  Configure the Compute service to use the Bare Metal service
nova-manage cell_v2 discover_hosts
4,逻辑name
创建以example命名的节点:
$ ironic node-create -d agent_ipmitool -n example
或者更新已有节点:
$ ironic node-update $NODE_UUID add name=example
一旦分配了一个逻辑名,就可以通过替换为名称或UUID指向一个节点。
$ ironic node-create -d agent_ipmitool -n example
+--------------+--------------------------------------+
| Property     | Value                                |
+--------------+--------------------------------------+
| uuid         | 71e01002-8662-434d-aafd-f068f69bb85e |
| driver_info  | {}                                   |
| extra        | {}                                   |
| driver       | agent_ipmitool                       |
| chassis_uuid |                                      |
| properties   | {}                                   |
| name         | example                              |
+--------------+--------------------------------------+

$ ironic node-show example
+------------------------+--------------------------------------+
| Property               | Value                                |
+------------------------+--------------------------------------+
| target_power_state     | None                                 |
| extra                  | {}                                   |
| last_error             | None                                 |
| updated_at             | 2015-04-24T16:23:46+00:00            |
| ...                    | ...                                  |
| instance_info          | {}                                   |
+------------------------+--------------------------------------+


5,默认硬件接口
对于传统驱动程序,所有硬件接口实现(网络接口除外)都是硬编码的,不能更改。 对于硬件类型,用户可以在创建或更新节点时请求一个可用的实现接口。

在创建节点或更改节点的硬件类型时,没有指定interface,则使用默认值。 可以使用driver details命令列出当前enabled和default的硬件类型(用于部署):
$ openstack --os-baremetal-api-version 1.31 baremetal driver show ipmi
+-------------------------------+----------------+
| Field                         | Value          |
+-------------------------------+----------------+
| default_boot_interface        | pxe            |
| default_console_interface     | no-console     |
| default_deploy_interface      | iscsi          |
| default_inspect_interface     | no-inspect     |
| default_management_interface  | ipmitool       |
| default_network_interface     | flat           |
| default_power_interface       | ipmitool       |
| default_raid_interface        | no-raid        |
| default_vendor_interface      | no-vendor      |
| enabled_boot_interfaces       | pxe            |
| enabled_console_interfaces    | no-console     |
| enabled_deploy_interfaces     | iscsi, direct  |
| enabled_inspect_interfaces    | no-inspect     |
| enabled_management_interfaces | ipmitool       |
| enabled_network_interfaces    | flat, noop     |
| enabled_power_interfaces      | ipmitool       |
| enabled_raid_interfaces       | no-raid, agent |
| enabled_vendor_interfaces     | no-vendor      |
| hosts                         | ironic-host-1  |
| name                          | ipmi           |
| type                          | dynamic        |
+-------------------------------+----------------+

默认情况下是这样计算的:
1),如果配置了default_<IFACE>_interface选项,它的值就会被用作默认值。 如果这个实现与节点的硬件类型不兼容,则会返回给用户一个错误。在这种情况下,必须为节点的接口字段提供显式的值。
2),否则,由操作员启用的第一个支持的实现类型将被用作缺省值(可以设置多个)。

如果所支持的实现列表不是空的,那么第一个被使用。否则,会返回给用户一个错误。在这种情况下,必须为其提供显式的值 <IFACE>_interface字段
6,硬件检查

裸金属服务支持简化注册节点的硬件检查——请参阅硬件检查以了解详细情况。  Hardware Inspection

7,租户网络和端口组

七,裸金属服务作为独立的服务使用

略。

在没有其他OpenStack服务的情况下使用裸金属服务的操作步骤,详见:

八, 使能configdrive

裸金属服务支持给实例配置configuration drive image。
配置驱动器(configuration drive)用于存储实例指定的metadata,并将其作为一个标记为config-2的磁盘分区呈现给实例。配置驱动器的最大大小为64MB。
configuration drive的一个使用场景就是,当没有使用DHCP 给实例指定IP时,可以使用configuration drive显示(指定)实例的网络配置。

配置驱动通常与计算服务一起使用,但是裸金属服务也提供了一种独立的使用方法。以下部分将描述这两种方法。

1,使用计算服务时的configdrive

(1)在nova boot时,通过添加 --config-drive true参数,启用 configuration drive
nova boot --config-drive true --flavor baremetal --image test-image instance-1
(2)在配置文件 /etc/nova/nova.conf中,通过以下配置,开启对所有实例的config drive功能,
force_config_drive=True

2,standalone模式下的使用configdrive

3,Configuration drive在对象存储中的存储
4,访问configdrive数据
当启用configuration drive时,裸金属服务将在实例磁盘上创建一个分区,并将configuration drive镜像写入实例的磁盘(系统盘倒数64MB空间)。configuration drive必须在使用前安装。可以由许多工具自动执行的,比如cloud-init和cloudbase-init。要在支持通过标签访问设备的Linux发行版上手动安装它,只需运行以下操作:
mkdir -p /mnt/configmount /dev/disk/by-label/config-2 /mnt/config
如果guest操作系统不支持通过标签访问设备,可以使用如blkid之类的其他工具来识别哪个设备对应configuration drive并挂载它,例如:
CONFIG_DEV=$(blkid -t LABEL="config-2" -odevice)
mkdir -p /mnt/config
mount $CONFIG_DEV /mnt/config
5,Cloud-init集成
若通过disk-image-builder制作用户镜像,则需要在执行制作命令时,添加对应参数
DIB_CLOUD_INIT_DATASOURCES="ConfigDrive, OpenStack" disk-image-create -o fedora-cloud-image fedora baremetal
如果是使用在虚拟化环境中,自定义制作裸金属用户镜像,则需要在制作镜像时,安装cloudinit相关包。

九,高级功能

(一)本地引导partition镜像

    裸金属服务支持分区镜像的本地引导,这意味着在节点部署后,后续重启不会再通过PXE或虚拟介质。相反,它将从安装在磁盘上的本地引导加载程序启动。

注意:
  相反,Whole磁盘镜像只支持本地引导,并在默认情况下使用它。

需要注意的是,为了能够正常工作,使用裸金属服务的镜像必须在其中安装的grub2。

当使用裸金属服务与计算服务一起使用时或裸金属服务单独使用时,启用本地引导是不同的。以下部分将描述这两种方法。
1, 使用计算服务时,启用本地引导
为了启用本地引导,我们需要在裸金属节点上设置一个功能。
ironic node-update <node-uuid> add properties/capabilities="boot_option:local"
通过在计算服务的flavor中添加额外的规范,可以请求将启动选项设置为本地的节点。
nova flavor-key baremetal set capabilities:boot_option="local"
注意:
  如果节点被配置为使用UEFI引导,裸金属服务将在磁盘上创建EFI分区,并将分区表格式转换为gpt。EFI分区稍后将由引导加载程序(从deploy ramdisk中安装)使用。
2, 没有计算服务时,启用本地引导(stancalone)
  由于向节点属性添加的属性只会被nova scheduler用于执行更高级的实例调度,我们需要一种当计算不存在时启用本地引导的方法。为了做到这一点,我们可以简单地通过节点的instance info来指定属性,例如 :
ironic node-update <node-uuid> add instance_info/capabilities='{"boot_option": "local"}'

(二)指定部署的磁盘(根设备所在磁盘)

裸金属服务支持将提示传递给部署ramdisk,用来指定它应该选择哪个磁盘进行部署。所支持的提示列表是:
  • model模型(字符串):设备标识符
  • vendor供应商(字符串):设备供应商
  • serial串行(字符串):磁盘序列号。
  • size尺寸(INT):以GiB为单位的设备尺寸。

注意:
  一个节点的“local_gb”属性通常被设置为小于实际磁盘大小的1 GiB,用于计算分区(举几个例子,这是DevStack、TripleO和ironic检查等功能运行需要的)。但是,在这种情况下,大小应该是实际大小。例如,对于一个128 GiB磁盘local_gb将是127,但是大小提示将是128。

  • wwn(字符串):唯一的存储标识符
  • wwn_with_extension (字符串)带有供应商附加扩展的唯一的存储标识符
  • wwn_vendor_extension(字符串):唯一的供应商存储标识符
  • rotational转动(布尔类型):不管它是否是旋转装置。当选择判断用哪个磁盘来部署ironic镜像时,这个提示可以很容器区分HDDs(旋转-磁盘)和SSDs(非旋转-固态硬盘)。
  • hctl(字符串):SCSI地址(主机名、channel通道、Target和Lun),例如‘1:0:0:0’
  • name(字符串):设备名称,例如/dev/md0
警告:
    根设备提示名称应该只用于具有常量名称的设备(例如RAID卷)。对于SATA, SCSI和IDE磁盘控制器,这个提示是不推荐的,因为在Linux中添加设备节点的顺序是任意的,导致了诸如/dev/sda和/dev/sdb这样的设备在引导时切换。

要将一个或多个显示与节点关联起来,用root设备的key值,更新节点的属性。例如:
ironic node-update <node-uuid> add properties/root_device='{"wwn": "0x4000cca77fc4dba1"}'
  这将保证裸金属服务将选择具有wwn且等于指定wwn值的磁盘设备,如果不能找到它,则会失败部署。
  提示可以在这个字符串值的开头有一个运算符。如果没有指定操作符,默认值是==(用于数值)和s==(用于字符串值),支持的操作符有:
数值:
  • = equal to or greater than. This is equivalent to >= and is supported for legacy reasons
  • == equal to
  • != not equal to
  • >= greater than or equal to
  • > greater than
  • <= less than or equal to
  • < less than
字符串值:
  • s== equal to
  • s!= not equal to
  • s>= greater than or equal to
  • s> greater than
  • s<= less than or equal to
  • s< less than
  • <in> substring
集合:
  • <all-in> all elements contained in collection
  • <or> find one of these
找到一个大于或等于60 GiB且非旋转的磁盘(SSD):
ironic node-update <node-uuid> add properties/root_device='{"size": ">= 60", "rotational": false}'
找出一个供应商是samsung或winsys的磁盘:
ironic node-update <node-uuid> add properties/root_device='{"vendor": "<or> samsung <or> winsys"}'
如果指定了多个提示,则设备必须满足所有提示。

(三)引导实例时添加内核参数

裸金属服务支持将自定义内核参数传递到引导的实例中,以满足用户需求。添加内核参数的方法取决于如何启动实例。
3.1 网络引导
目前,裸金属服务支持为PXE启动实例分配统一的内核参数。
1,修改 [pxe]/pxe_append_params配置文件选项,例如:
[pxe]

pxe_append_params = quiet splash
2,将模板复制到另一个地方。例如:
https://git.openstack.org/cgit/openstack/ironic/tree/ironic/drivers/modules/pxe_config.template
通过 [pxe]/pxe_config_template 和 [pxe]/uefi_pxe_config_template两个配置选项,修改并指向自定义模板。
3.2 本地引导
对于本地引导实例,用户可以使用configuration drive的方式(请参阅),以通过一个自定义脚本来在创建实例时附加内核参数。这样可以更灵活的改变每个实例。这里有一个使用ubuntu的grub2的例子,用户可以定制它以适应他们的用例。
3.3 控制台
为了在裸金属服务配置文件中修改缺省console控制台配置(在/etc/ironic/ironic.conf文件的[pxe]部分),包括端口终端和串行速度。串行速度必须与BIOS设置中的串行配置相同,这样操作系统启动过程就可以在串行控制台或web控制台中看到。下面的例子分别代表了串行和web控制台的可能参数:
1,节点串行console,console参数 console=ttyS0,115200n8 在 115200bps, 8bit, non-parity 条件下使用 ttyS0 ,例如:
[pxe]

# Additional append parameters for baremetal PXE boot.pxe_append_params = nofb nomodeset vga=normal console=ttyS0,115200n8
2,web console使用 ttyX 形式的参数,例如:
[pxe]

# Additional append parameters for baremetal PXE boot.pxe_append_params = nofb nomodeset vga=normal console=tty0 console=ttyS0,115200n8
有关如何添加控制台的详细信息,请参阅参考文档 kernel params 和 serial console,在本地启动时,裸金属服务无法控制内核引导参数。要在本地配置控制台,请遵循上面的本地引导部分。 

(四) 引导模式支持

下面的驱动程序支持启动模式(Legacy BIOS或UEFI)。
  • pxe_ipmitool
引导模式可以在裸金属服务中以如下方式配置:
1)当没有提供引导模式设置时,这些驱动程序的引导模式默认是LegacyBIOS。
2)只有一个启动模式(uefi或bios)可以为节点配置。
3)如果操作员想要一个节点总是在uefi模式或bios模式下启动,那么他们可能会在一个裸金属节点的属性域中使用功能参数。操作人员必须在裸金属节点上手动设置适当的启动模式。
要在uefi模式中配置节点,然后设置如下所示的功能:
ironic node-update <node-uuid> add properties/capabilities='boot_mode:uefi'
可以通过在计算服务风格中添加额外的规范来请求 ,将boot_mode设置为uefi的节点,需要在计算服务的flavor中添加extra_spec额外属性,如下:
nova flavor-key ironic-test-3 set capabilities:boot_mode="uefi"nova boot --flavor ironic-test-3 --image test-image instance-1
如果在上述extra_spec中使用了capabilities ,nova调度程序(ComputeCapabilitiesFilter)将只匹配在properties/capabilities中设置boot_mode 的裸金属节点。它会过滤掉节点的其余部分。

上面的计算服务中匹配的设施,可以在混合了uefi和bios服务器的异构环境中使用,操作者(云运营商)希望为用户提供关于启动模式的选择。如果flavor不包含boot_mode,且在裸金属节点中有配置boot_mode,那么nova调度程序将考虑所有节点,那么用户就可能获得bios或uefi机器。

(五)选择磁盘标签

 注意:
  “磁盘标签disk_label”在Ironic一直都有使用,而且它是从parted中而来。显然,每个人似乎对disk_label有不同的定义——认为这些都是相同的东西:磁盘类型、分区表、分区映射等等。
  当ironic负责对磁盘进行分区时,Ironic允许操作者来自定义选择想要把裸金属节点部署到哪一个disk label上;因此,当部署的镜像是whole disk image时,不支持选择disk label来部署。
  有些情况下,有的人可能希望为正在部署的镜像选择特定的disk label磁盘标签,包括但不限于:
1)对于磁盘大于2TB,且以bios模式启动的机器,建议使用gpt磁盘标签。这是因为超过2TB的容量不能通过使用MBR分区类型来寻址。但是,尽管GPT声称要向后兼容遗留的BIOS系统,但并不总是这样。
2)操作人员可能希望强制分区始终是MBR(即使机器是以uefi引导模式部署的)以避免在这些实例上运行的应用程序和工具的破坏。

  在计算服务或独立模式中使用Ironic的时候 ,disk label可以通过两种方式配置。下面的要点和章节将描述这两种方法:
1)当没有提供磁盘标签disk label时,Ironic会根据引导模式对其进行配置(请参考);bios启动模式将使用msdos,uefi启动模式将使用gpt。
2)裸金属节点只能配置一个disk label:msdos或gpt

5.1 使用计算阶段服务的情况下
  当ironic用于计算服务时,应该将 disk label设置到裸金属节点的properties/capabilities字段,并将其设置到需要此功能的flavor中,例如:
ironic node-update <node-uuid> add properties/capabilities='disk_label:gpt'
关于flavor:
nova flavor-key baremetal set capabilities:disk_label="gpt"
5.2 standalone模式下
  当ironic不使用计算服务时, disk label应该直接设置到裸金属节点的 instance_info字段,如下:
ironic node-update <node-uuid> add instance_info/capabilities='{"disk_label": "gpt"}'

(六)可信任的partation镜像

  裸金属服务支持partition镜像的可信引导。这意味着在部署过程结束后,当节点被重新引导时,将执行新的用户镜像。它将检测节点的BIOS、引导加载程序、可选ROM以及Kernel/Ramdisk,以确定此节点是否是ironic信任的裸金属节点。

  需要注意的是,为了使其工作,部署的节点必须具有Intel TXT硬件支持。被ironic部署的镜像必须在镜像内部安装oat-client。

  下面将描述如何启动trusted boot,以及通过PXE和Nova来执行引导程序:
1,创建一个安装oat-client的自定义镜像:
disk-image-create -u fedora baremetal oat-client -o $TRUST_IMG
创建自定义镜像,详情查看:Create and add images to the Image service.
2,在节点上启用VT-x, VT-d, TXT和TPM功能,可以通过在BIOS手动启动,根据平台的不同,可能需要有多次重启。
3,注册节点,更新节点capability的值:
ironic node-create -d pxe_ipmitool

ironic node-update $NODE_UUID add properties/capabilities={'trusted_boot':true}
4,创建一个执行的flavor:
nova flavor-key $TRUST_FLAVOR_UUID set 'capabilities:trusted_boot'=true
5,准备 tboot和mboot.c32,把它们放到ironic-conductor进程控制的所有节点的tftp_root或http_root的目录下:
Ubuntu:
    cp /usr/lib/syslinux/mboot.c32 /tftpboot/

Fedora:
    cp /usr/share/syslinux/mboot.c32 /tftpboot/
注意:mboot.c32的实际位置,在不同的发行版本中有所不同。
tboot下载:
6,安装OAT服务。OAT服务器应该正确地运行和配置。
7,通过Nova引导一个实例:
nova boot --flavor $TRUST_FLAVOR_UUID --image $TRUST_IMG --user-data $TRUST_SCRIPT trusted_instance
注意节点将会在trusted boot时被检测,哈希值会存到TPM。TRUST_SCRIPT的例子可以查看:
8,通过AOT服务验证结果:
这已超出ironic的范围。目前,用户可以通过手动验证步骤手动验证结果。链接:  manual verify steps.

(七)通知

  裸金属服务支持发送通知,通知是消息代理发送的消息(如RabbitMQ或oslo消息库支持的其他任何东西),这些消息指示发生的各种事件,比如节点改变了电源状态。可以通过消息总线的外部服务读取这些数据。例如,Searchlight是一个OpenStack服务,它使用通知来从裸金属服务中索引(并创建可搜索的)资源。
默认情况下Notifications功能是禁用的。有关如何启用可用的Notifications和说明的完整列表,请参阅: Notifications.

(八) 配置节点控制台


十,Troubleshooting疑难问题

  一旦所有的服务都正确地运行和配置,并且一个节点已经加入了裸金属服务且处于available 的预分配状态,计算服务应该将节点检测为可用的资源,并将其暴露给调度器。
注意:
  有一个延迟,计算服务可能需要一分钟(一个周期的任务周期)来识别裸金属服务资源(增加和删除)的任何变化。

  除了查看nova-compute日志文件之外,还可以通过查看计算管理程序的列表来查看可用的资源。所报告的资源应该与裸金属节点属性和计算服务的flavor相匹配。
下面是一个示例集,用于比较计算服务和裸金属服务的资源:
$ ironic node-list
+--------------------------------------+---------------+-------------+--------------------+-------------+
| UUID                                 | Instance UUID | Power State | Provisioning State | Maintenance |
+--------------------------------------+---------------+-------------+--------------------+-------------+
| 86a2b1bb-8b29-4964-a817-f90031debddb | None          | power off   | available          | False       |
+--------------------------------------+---------------+-------------+--------------------+-------------+

$ ironic node-show 86a2b1bb-8b29-4964-a817-f90031debddb
+------------------------+----------------------------------------------------------------------+
| Property               | Value                                                                |
+------------------------+----------------------------------------------------------------------+
| instance_uuid          | None                                                                 |
| properties             | {u'memory_mb': u'1024', u'cpu_arch': u'x86_64', u'local_gb': u'10',  |
|                        | u'cpus': u'1'}                                                       |
| maintenance            | False                                                                |
| driver_info            | { [SNIP] }                                                           |
| extra                  | {}                                                                   |
| last_error             | None                                                                 |
| created_at             | 2014-11-20T23:57:03+00:00                                            |
| target_provision_state | None                                                                 |
| driver                 | pxe_ipmitool                                                         |
| updated_at             | 2014-11-21T00:47:34+00:00                                            |
| instance_info          | {}                                                                   |
| chassis_uuid           | 7b49bbc5-2eb7-4269-b6ea-3f1a51448a59                                 |
| provision_state        | available                                                            |
| reservation            | None                                                                 |
| power_state            | power off                                                            |
| console_enabled        | False                                                                |
| uuid                   | 86a2b1bb-8b29-4964-a817-f90031debddb                                 |
+------------------------+----------------------------------------------------------------------+

$ nova hypervisor-show 1
+-------------------------+--------------------------------------+
| Property                | Value                                |
+-------------------------+--------------------------------------+
| cpu_info                | baremetal cpu                        |
| current_workload        | 0                                    |
| disk_available_least    | -                                    |
| free_disk_gb            | 10                                   |
| free_ram_mb             | 1024                                 |
| host_ip                 | [ SNIP ]                             |
| hypervisor_hostname     | 86a2b1bb-8b29-4964-a817-f90031debddb |
| hypervisor_type         | ironic                               |
| hypervisor_version      | 1                                    |
| id                      | 1                                    |
| local_gb                | 10                                   |
| local_gb_used           | 0                                    |
| memory_mb               | 1024                                 |
| memory_mb_used          | 0                                    |
| running_vms             | 0                                    |
| service_disabled_reason | -                                    |
| service_host            | my-test-host                         |
| service_id              | 6                                    |
| state                   | up                                   |
| status                  | enabled                              |
| vcpus                   | 1                                    |
| vcpus_used              | 0                                    |
+-------------------------+--------------------------------------+
维护模式
如果需要从资源池中取出一个节点,则可以使用维护(Maintenance)模式。将节点置为维护模式,用于阻止裸金属服务执行与节点相关的周期性任务。还将防止计算服务通过将节点暴露给nova调度程序而将一个租户实例置入节点上。可以使用以下命令将节点置为维护模式:
$ ironic node-set-maintenance $NODE_UUID on
一个维护原因是一个可选的——可一使用--reason命令行参数指定。这是一个自由的文本字段,将显示在node-show命令的maintenance_reason部分中。
$ ironic node-set-maintenance $UUID on --reason "Need to add ram."

$ ironic node-show $UUID

+------------------------+--------------------------------------+
| Property               | Value                                |
+------------------------+--------------------------------------+
| target_power_state     | None                                 |
| extra                  | {}                                   |
| last_error             | None                                 |
| updated_at             | 2015-04-27T15:43:58+00:00            |
| maintenance_reason     | Need to add ram.                     |
| ...                    | ...                                  |
| maintenance            | True                                 |
| ...                    | ...                                  |
+------------------------+--------------------------------------+
移除维护模式、并清理maintenance_reason,使用一下命令:
$ ironic node-set-maintenance $NODE_UUID off

十一,Next steps

你的OpenStack环境现在已经包含了裸金属服务。

参考:

https://docs.openstack.org/ironic/pike/install/index.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章