使用 Ansible 进行硬件引导

175 位读者喜欢这篇文章。
computer servers processing data

Opensource.com

在最近的 Ansible London Meetup 上,我和某人聊到了自动硬件构建。"现在都是云了!" 我听到你这么说。啊,但是对于许多大型组织来说,情况并非如此——他们仍然有巨大的数据中心,里面装满了硬件。几乎经常有人在我们的内部邮件列表中跳出来问,"Ansible 可以进行硬件配置吗?" 嗯,是的,你可以使用 Ansible 配置硬件……

要求

引导硬件主要涉及网络服务。在进行任何操作系统 (OS) 安装之前,我们必须设置一些服务。我们需要

  • DHCP
  • PXE
  • TFTP
  • 操作系统介质
  • Web 服务器

设置

除了 DHCP 配置外,本文中的其他所有内容都由 此存储库 中包含的 Ansible playbook 处理。

DHCP 服务器

我在这里写作的前提是你可以控制你的 DHCP 配置。如果你无法访问你的 DHCP 服务器,你需要请求所有者设置两个选项。DHCP 选项 67 需要设置为 pxelinux.0,并且 next-server(这是选项 66——但你可能不需要知道;通常 DHCP 服务器会有一个用于“next server”的字段/选项)需要设置为你的 TFTP 服务器的 IP 地址。

如果你可以拥有 DHCP 服务器,我建议使用 dnsmasq。它很小而且很简单。我不会在这里介绍如何配置它,但请查看 手册页--enable-tftp 选项。

TFTP

上面我们 DHCP 服务器的 next-server 设置将指向一台提供 TFTP 的机器。在这里,我使用了一个 CentOS Linux 虚拟机,因为它只需要一个包 (syslinux-tftpboot) 和一个服务启动就可以运行 TFTP。我们将坚持默认路径 /var/lib/tftpboot

PXE

如果你还不熟悉 PXE,你可能想快速浏览一下 维基百科页面。对于本文,我将保持简短——我们将通过 TFTP 提供一些文件,DHCP 将引导我们的硬件。

你需要来自操作系统发行介质的 images/pxeboot/{initrd.img,vmlinuz} 用于 pxeboot。这些需要复制到 /var/lib/tftpboot/pxeboot。引用的 Ansible playbook **不会执行此步骤,**所以你需要自己复制它们。

我们还需要提供操作系统安装文件。有两种方法:1) 通过 HTTP 从互联网安装,或 2) 再次通过 HTTP 从本地服务器安装。对于我的测试,因为我在一个私有 LAN 上(我猜你也是),最快的安装方法是第二种。准备这个的最简单方法是挂载 DVD 镜像并将 imagesPackagesrepodata 目录 rsync 到你的 Web 服务器位置。引用的 Ansible playbook 将安装 httpd,但不会复制这些文件,所以不要忘记在运行 该 playbook 后执行此操作。对于本文,为了简单起见,我们将再次坚持默认设置——所以文件需要复制到 Apache 的标准文档根目录 /var/www/html

目录

我们最终应该得到这样的目录结构

PXE/TFTP

[root@c7 ~]# tree  /var/lib/tftpboot/pxe{b*,l*cfg}
/var/lib/tftpboot/pxeboot
└── 6
    ├── initrd.img
    └── vmlinuz

httpd

[root@c7 ~]# tree -d /var/www/html/
/var/www/html/
├── 6 -> centos/6
├── 7 -> centos/7
├── centos
│   ├── 6
│   │   └── os
│   │       └── x86_64
│   │           ├── images
│   │           │   └── pxeboot
│   │           ├── Packages
│   │           └── repodata
│   └── 7
│       └── os
│           └── x86_64
│               ├── images
│               │   └── pxeboot
│               ├── Packages
│               └── repodata
└── ks

你会注意到我的 Web 设置看起来比上面的文字复杂一点!我粘贴了我的实际结构,给你一些想法。我使用的硬件真的很旧,即使让 CentOS 7 工作也很糟糕(如果你感兴趣,这是因为缺少用于 HP Smart Array 控制器的 cciss 驱动程序——是的,这里有一个答案,但需要很多功夫才能让它工作),所以所有示例都是 CentOS 6 的。我也想要一个灵活的设置,可以安装多个版本。在这里,我使用符号链接完成了这一点——例如,这种安排也适用于 RHEL。基本结构仍然存在——注意 images、Packages 和 repodata 目录。

这些路径直接关系到我们将提供的 PXE 菜单 文件和 kickstart 文件

如果你没有 DHCP

如果你无法管理自己的 DHCP 服务器,或者你的基础设施所有者无法提供帮助,那么还有另一种选择。过去,我曾使用 iPXE 创建一个启动映像,我已将其加载为虚拟介质。现代硬件上的许多带外/远程管理 (LOM) 接口都支持此功能。你可以使用 iPXE 在几秒钟内创建一个自定义的嵌入式 PXE 菜单。我不会在这里介绍它,但如果这对你来说是个问题,那么请在 Twitter 上 给我留言,如果足够多的人提出要求,我将考虑撰写一篇后续博客文章。

安装硬件

我们现在已经建立了结构,我们可以 kickstart 一台服务器。在我们这样做之前,我们必须向 TFTP 设置添加一些配置,以使给定的硬件能够拾取 PXE 启动菜单。

在这里,我们遇到了一个小的先有鸡还是先有蛋的问题。我们需要主机的 MAC 地址来创建一个链接到我们想要 kickstart 的特定硬件。如果硬件已经在运行,并且我们可以使用 Ansible 访问它,那就太好了——我们可以通过 setup 模块找到启动接口 MAC 地址(参见 reinstall playbook)。但是,如果它是一块新的硬件,我们需要获取 MAC 地址并告诉我们的设置如何处理它。这可能意味着一些手动干预——启动服务器并查看屏幕,或者从清单或其他类似的东西中获取 MAC。无论你以何种方式获取它,我们都可以通过清单告诉我们的 playbook。

让我们将一个自定义变量放入我们简单的 INI 格式 清单文件 中,但运行一个 playbook 来设置 TFTP……

(pip)iMac:ansible-hw-bootstrap$ ansible-inventory --host hp.box
{
    "ilo_ip": "192.168.1.68",
    "ilo_password": "administrator"
}
(pip)iMac:ansible-hw-bootstrap$ ansible-playbook plays/install.yml

PLAY [kickstart] *******************************************************************************************************

TASK [Host inventory entry has a MAC address] **************************************************************************
failed: [ks.box] (item=hp.box) => {
    "assertion": "hostvars[item]['mac'] is defined",
    "changed": false,
    "evaluated_to": false,
    "item": "hp.box",
    "msg": "Assertion failed"
}

PLAY RECAP *************************************************************************************************************
ks.box                     : ok=0    changed=0    unreachable=0    failed=1

哦哦,playbook 失败了。它 包含一个检查,即我们要安装的主机实际上已经添加了 MAC 地址。让我们修复它并再次运行 playbook……

(pip)iMac:ansible-hw-bootstrap$ ansible-inventory --host hp.box
{
    "ilo_ip": "192.168.1.68",
    "ilo_password": "administrator",
    "mac": "00:AA:BB:CC:DD:EE"
}
(pip)iMac:ansible-hw-bootstrap$ ansible-playbook plays/install.yml

PLAY [kickstart] *******************************************************************************************************

TASK [Host inventory entry has a MAC address] **************************************************************************
ok: [ks.box] => (item=hp.box) => {
    "changed": false,
    "item": "hp.box",
    "msg": "All assertions passed"
}

TASK [Set PXE menu to install] *****************************************************************************************
ok: [ks.box] => (item=hp.box)

TASK [Reboot target host for PXE boot] *********************************************************************************
skipping: [ks.box] => (item=hp.box)

PLAY RECAP *************************************************************************************************************
ks.box                     : ok=2    changed=0    unreachable=0    failed=0

成功了!它做了什么?查看我们 TFTP 根目录下的 pxelinux.cfg 目录,我们可以看到一个符号链接……

[root@c7 pxelinux.cfg]# pwd
/var/lib/tftpboot/pxelinux.cfg
[root@c7 pxelinux.cfg]# l
total 12
drwxr-xr-x. 2 root root   65 May 13 14:23 ./
drwxr-xr-x. 4 root root 4096 May  2 22:13 ../
-r--r--r--. 1 root root  515 May  2 12:22 00README
lrwxrwxrwx. 1 root root    7 May 13 14:12 01-00-aa-bb-cc-dd-ee -> install
-rw-r--r--. 1 root root  682 May  2 22:07 install

install 文件被符号链接到一个以我们的 MAC 地址命名的文件。这是关键的、有用的部分。它将确保我们的 MAC 地址为 00-aa-bb-cc-dd-ee 的硬件从其网卡启动时获得 PXE 菜单。

那么让我们启动我们的机器。

有用的是,Ansible 有一些 远程管理模块。我们在这里使用 HP 服务器,所以我们可以使用 hpilo_boot 模块来避免直接与 LOM Web 界面交互。

让我们在启动的服务器上运行 reinstall playbook……

你会注意到 hpilo_boot 模块的妙处在于,它将启动介质设置为网络。安装完成后,服务器重新启动并从其硬盘驱动器启动。你当中眼尖的人会发现这个关键问题——如果服务器再次启动到它的网卡会发生什么?它将拾取 PXE 菜单并立即重新安装自己。我建议删除符号链接作为“双保险”步骤。我将把它作为给你的练习,亲爱的读者。提示:我会让新服务器在启动时“phone home”到某个地方,运行一个清理作业。因为你不需要像我在这里那样打开控制台来演示后台发生的事情,所以“phone home”作业也会很好地表明该过程已完成。Ansible,自然。祝你好运!

如果你对这个过程有任何想法或评论,请告诉我。

User profile image.
Mark 拥有四分之一世纪的行业经验,曾在各个层面设计和构建自动化基础设施——从初创公司中的少量主机到投资银行中的数万台主机。

5 条评论

在我公司,我们正在做类似的事情。但是现在 HPE 有了 HTTP 启动,我们跳过了 DHCP、TFTP 和 PXE。在我的例子中,我 piggy-backed 关闭了 rear backup。我创建了一个 EL7 安装的 rear backup,然后编辑了它创建的 ISO,将其指向位于 Web 服务器上的 kickstart 文件。使用 HTTP 启动,我们将其指向也位于 Web 服务器上的 ISO,它启动,加载 kickstart,然后就开始了。我确实做了一个奇怪的 workaround 来通过 DHCP 连接到主机。我最终将序列号添加到 DNS,并让 anisble 通过这种方式连接到主机以完成服务器设置。

做得好,feeble!是的,我以前也用过自定义 ISO 来做“定制化的 Kickstart”。使用 iPXE 和 'kssendmac' 可以为 Kickstart 脚本提供一个唯一的 ID,从而提供定制的配置,效果很好。几年前,我使用了这里介绍的方法来管理一个 24 节点的视频墙——节点可以在运行时完全远程重建,而且 Ansible 的东西非常简单易用。效果很好。谢谢你告诉我们你在做什么,很高兴听到!

回复 ,作者是 feeble

谢谢 Mark,解释得很清楚。我添加了 cobbler 以及 cobbler ansible 模块来做同样的事情,另一种方法是使用 hpilo_boot 通过虚拟介质挂载 Golden image。但是,如果 kickstart 文件可以自动化(使用 j2)来配置 IP、Hostname,有什么帮助吗?假设我有 100 台服务器,每台都使用 ansible 引导,并指向一个 http kickstart 文件。我希望为每台主机使用静态 IP 和静态主机名。

你好!您可以通过让 kernel 'ks=' 行指向一个脚本来制作自定义的 kickstart 文件。使用 'kssendmac',一个 X 头部会随着请求一起发送(记忆中是 X-RHN-Provisioning-MAC-0)。由此,您可以将 MAC 地址绑定到主机名等,并返回自定义的 kickstart 文件。这真的不需要是一个复杂的 CGI 脚本,只要您能解析 X-RHN... 头部,您就搞定了。很久很久以前,当我还在摆弄 Perl 的时候,我写了一些东西来做这个 https://github.com/phips/bacio 我不建议使用它,除非作为灵感!最好是用您习惯编码的任何语言编写一个简单的 CGI。希望对您有帮助!

回复 ,作者是 kanchan Chakraborty (未验证)

读完这篇文章后,所有人都可以轻松理解基本原理。

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