使用 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.0next-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,你可能想快速浏览一下 Wikipedia 页面。对于本文,我将长话短说——我们将通过 TFTP 提供一些文件,DHCP 会引导我们的硬件访问这些文件。

你需要来自 pxeboot 的 OS 发行介质中的 images/pxeboot/{initrd.img,vmlinuz}。这些需要复制到 /var/lib/tftpboot/pxeboot。引用的 Ansible Playbook 不会执行此步骤, 因此你需要自己复制它们。

我们还需要提供 OS 安装文件。有两种方法: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 菜单并立即重新安装自身。因此,我建议删除符号链接作为“双保险”步骤。我将把它留给你,亲爱的读者,作为一个练习。提示:我将让新服务器在启动时“呼叫家”,到一个地方,该地方运行清理作业。由于你不需要像我在这里那样打开控制台来演示后台发生的事情,“呼叫家”作业也会很好地指示该过程已完成。Ansible,自然地。祝你好运!

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

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

5 条评论

在我的公司,我们正在做类似的事情。但是现在 HPE 具有 http 启动,我们跳过了 dhcp、tftp 和 pxe。在我的例子中,我利用了 rear backup。我创建了一个 EL7 安装的 rear backup,然后编辑了它创建的 ISO,使其指向位于 Web 服务器上的 kickstart 文件。使用 http 启动,我们将其指向也位于 Web 服务器上的 iso,它启动,加载 kickstart,然后开始运行。我确实做了一个奇怪的解决方法,以便能够通过 dhcp 连接到主机。我最终将序列号添加到 DNS,并让 anisble 以这种方式连接到主机以完成服务器设置。

做得好 feeble!是的,我以前也使用过自定义 ISO 来进行“定制 kickstart”。使用 iPXE 和 'kssendmac' 为 kickstart 脚本提供唯一的 ID 以交付定制的配置,效果非常好。几年前,我使用本文中描述的方法来管理一个 24 节点的视频墙——节点可以在飞行中完全远程重建,而 Ansible 的东西非常简单易用。效果非常好。感谢你让我们知道你在做什么,很高兴听到!

回复 ,作者:feeble

谢谢 Mark,解释得很好。我已经添加了 cobbler 以及 cobbler ansible 模块来完成相同的任务,另一种方法是使用 hpilo_boot 通过虚拟介质挂载 Golden 镜像。但是,如果可以使用 j2 自动化 kickstart 文件来配置 IP、Hostname,有什么帮助吗?假设我有 100 台服务器,每台服务器都使用 ansible 进行引导,并指向一个 http kickstart 文件。我想为每台主机使用静态 IP 和静态主机名。

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

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

在阅读本文后,所有人都可以轻松理解基本原理。

© . All rights reserved.