Ironic 中 Clean/deploy Step 延迟执行的原因分析

Ironic 中 Clean Step 延迟执行的原因分析

当使用 OpenStack client 执行 clean step 后,确实不会立即执行,而是需要等待一段时间。这是由 Ironic 的架构设计和工作机制决定的,主要原因如下:


1. 异步架构设计

1.1 API 与 Conductor 分离

python 复制代码
# ironic/api/controllers/v1/nodes.py
@expose.expose(None, types.uuid, body=types.jsontype,
               status_code=http_client.ACCEPTED)
def set_provision_state(self, node_ident, target, configdrive=None):
    """设置节点的供应状态"""
    
    # API 只是接收请求并更新节点状态
    node = api_utils.get_rpc_node(node_ident)
    
    # 通过 RPC 发送到 conductor
    topic = pecan.request.rpcapi.get_topic_for(node)
    pecan.request.rpcapi.do_node_clean(
        pecan.request.context, node.uuid, clean_steps, topic)
    
    # 立即返回 202 Accepted,而不等待执行完成
    return None

关键点

  • API 服务接收请求后立即返回 202 状态
  • 实际执行由 Conductor 服务异步处理
  • 这种设计避免了 API 请求超时

1.2 RPC 消息队列机制

python 复制代码
# ironic/conductor/rpcapi.py
def do_node_clean(self, context, node_id, clean_steps, topic=None):
    """通过 RPC 发送清理任务"""
    
    # 消息放入队列,等待 conductor 处理
    cctxt = self._prepare_call(topic=topic)
    return cctxt.cast(context, 'do_node_clean',
                      node_id=node_id, 
                      clean_steps=clean_steps)

2. Conductor 的处理延迟

2.1 节点锁定机制

python 复制代码
# ironic/conductor/manager.py
def do_node_clean(self, context, node_id, clean_steps):
    """执行节点清理"""
    
    # 等待获取节点锁(可能需要等待)
    with task_manager.acquire(context, node_id, shared=False) as task:
        node = task.node
        
        # 验证节点状态
        if node.provision_state != states.MANAGEABLE:
            raise exception.InvalidStateRequested(...)
        
        # 开始清理流程
        self._do_node_clean(task, clean_steps)

延迟原因

  • 需要获取节点独占锁
  • 如果节点正在被其他操作使用,需要等待
  • 多个 conductor 可能竞争同一节点

2.2 状态转换验证

python 复制代码
def _do_node_clean(self, task, clean_steps):
    """实际执行清理"""
    
    # 状态转换:MANAGEABLE -> CLEANING
    task.process_event('clean', target_state=states.CLEANING)
    
    # 准备清理环境(可能需要时间)
    task.driver.deploy.prepare_cleaning(task)
    
    # 启动 ramdisk(需要等待节点启动)
    self._spawn_worker(self._do_node_clean_steps, task, clean_steps)

3. 节点启动和 Agent 连接延迟

3.1 Ramdisk 启动过程

python 复制代码
# ironic/drivers/modules/pxe.py
def prepare_ramdisk(self, task, ramdisk_params):
    """准备 ramdisk 启动"""
    
    # 1. 生成 PXE 配置文件
    pxe_utils.create_pxe_config(task, ramdisk_params)
    
    # 2. 设置启动设备为 PXE
    task.driver.management.set_boot_device(task, 'pxe')
    
    # 3. 重启节点
    manager_utils.node_power_action(task, states.REBOOT)
    
    # 节点需要时间来:
    # - 关机
    # - 启动
    # - PXE 启动
    # - 下载 ramdisk
    # - 启动 agent

3.2 Agent 心跳等待

python 复制代码
# ironic/conductor/manager.py
def _spawn_worker(self, func, *args, **kwargs):
    """在后台线程中执行任务"""
    
    # 创建后台任务
    self._spawn(func, *args, **kwargs)

def _do_node_clean_steps(self, task, clean_steps):
    """执行清理步骤"""
    
    # 等待 agent 上线并发送心跳
    # 这可能需要几分钟时间
    self._wait_for_agent_heartbeat(task)
    
    # 开始执行清理步骤
    for step in clean_steps:
        self._execute_clean_step(task, step)

4. 实际时间线分析

4.1 典型的 Clean Step 执行时间线

bash 复制代码
# T+0s: 用户执行命令
openstack baremetal node clean --clean-steps '[...]' <node-uuid>

# T+0.1s: API 返回 202 Accepted
# 节点状态: MANAGEABLE -> CLEANING

# T+0.5s: Conductor 获取节点锁,开始准备清理
# 节点状态: CLEANING

# T+1-30s: 准备 ramdisk,设置 PXE,重启节点
# 等待时间取决于:
# - 节点关机时间
# - BIOS 启动时间
# - 网络速度(下载 ramdisk)

# T+30s-2min: Agent 启动并发送第一次心跳
# 节点状态: CLEANING (等待 agent)

# T+2min+: 开始执行实际的清理步骤
# 节点状态: CLEANING (执行中)

4.2 查看实际进度

bash 复制代码
# 查看节点当前状态
openstack baremetal node show <node-uuid> -c provision_state -c last_error

# 查看详细的 provision_state 信息
openstack baremetal node show <node-uuid> -c provision_updated_at -c target_provision_state

# 查看 conductor 日志
sudo journalctl -u ironic-conductor -f

# 查看 API 日志
sudo journalctl -u ironic-api -f

5. 配置优化建议

5.1 减少启动等待时间

ini 复制代码
# /etc/ironic/ironic.conf
[conductor]
# 减少心跳超时时间
heartbeat_timeout = 60

# 增加并发处理数量
workers_pool_size = 100

[deploy]
# 启用快速启动
fast_track = true

# 减少电源操作等待时间
power_state_change_timeout = 30

5.2 使用本地 ramdisk 缓存

ini 复制代码
[pxe]
# 启用 HTTP 服务
enable_pxe_http = true
http_root = /tftpboot
http_url = http://ironic-conductor:8088

# 预缓存 ramdisk 镜像
kernel = file:///var/lib/ironic/images/deploy.kernel
ramdisk = file:///var/lib/ironic/images/deploy.ramdisk

6. 监控和调试

6.1 实时监控节点状态

python 复制代码
#!/usr/bin/env python3
# monitor_clean_progress.py

import time
import subprocess
import json

def monitor_node_cleaning(node_uuid):
    """监控节点清理进度"""
    
    while True:
        # 获取节点状态
        result = subprocess.run([
            'openstack', 'baremetal', 'node', 'show', 
            node_uuid, '-f', 'json'
        ], capture_output=True, text=True)
        
        node_data = json.loads(result.stdout)
        provision_state = node_data['provision_state']
        
        print(f"[{time.strftime('%H:%M:%S')}] "
              f"State: {provision_state}")
        
        if provision_state in ['available', 'clean failed']:
            break
            
        time.sleep(10)

if __name__ == '__main__':
    import sys
    monitor_node_cleaning(sys.argv[1])

6.2 查看详细日志

bash 复制代码
# 过滤特定节点的日志
sudo journalctl -u ironic-conductor | grep "node-uuid-here"

# 查看 agent 相关日志
sudo journalctl -u ironic-conductor | grep -i "agent\|heartbeat"

# 查看清理步骤执行日志
sudo journalctl -u ironic-conductor | grep -i "clean.*step"

7. 常见延迟问题和解决方案

7.1 节点启动慢

原因

  • BIOS 启动时间长
  • 网络下载 ramdisk 慢
  • 硬件自检时间长

解决方案

ini 复制代码
# 优化 BIOS 设置
# - 禁用不必要的自检
# - 设置快速启动
# - 优化启动顺序

# 使用本地镜像服务器
[glance]
glance_api_servers = http://local-glance:9292

# 启用镜像缓存
[agent]
image_download_source = local

7.2 心跳超时

原因

  • Agent 启动失败
  • 网络连接问题
  • 防火墙阻塞

解决方案

bash 复制代码
# 检查网络连接
ping <node-ip>

# 检查端口访问
telnet <ironic-api-ip> 6385

# 查看 DHCP 分配
sudo journalctl -u isc-dhcp-server

总结

Ironic Clean Step 延迟执行的主要原因:

  1. 架构设计:异步处理模式,API 立即返回
  2. 资源竞争:节点锁定和 conductor 调度
  3. 物理限制:节点重启和 ramdisk 启动时间
  4. 网络因素:镜像下载和心跳建立

这种设计虽然增加了等待时间,但提供了更好的可扩展性稳定性并发处理能力。通过合理的配置优化和监控,可以有效减少延迟时间。

相关推荐
哈里谢顿3 天前
ironic中为什么 IPMI Hardware Type 必须支持 IPMIManagement
openstack
哈里谢顿6 天前
Ironic 中各个接口的作用详解
openstack
CZIDC7 天前
博客摘录「 华为云平台-FusionSphere OpenStack 8.2.1 系统加固」2025年7月15日
linux·服务器·笔记·华为云·openstack
行止618 天前
OpenStack云平台管理
linux·openstack
曼汐 .18 天前
私有云平台实战-OpenStack
openstack
哈里谢顿19 天前
python的Mixin设计模式学习,以ironic-python-agent代码为例
openstack
曼汐 .19 天前
私有云平台实战-OpenStack入门体验
openstack
果子⌂20 天前
OpenStack入门体验
openstack
zkyqss1 个月前
OVS Faucet练习(下)
linux·笔记·openstack