使用 UEFI 取代 BIOS

dell 12G 的机器默认已经通过 UEFI 来取代了 BIOS 了。这个起初没注意,后来在 batch 安装的过程中发现一个都没起来,开 idrac 才发现连 pxe 都没进去,调查了下情况,发现 12G 的产品已经用 UEFI 替代了 BIOS 了,这篇博客的作者讲述了这个情况的心酸经历。根据之前的调研来看,目前 UEFI 还未广泛的使用,并且该技术还相对的年轻,RH 6.0 以后支持的 2.2 的版本。

先来看下最原始的 BIOS 的方式是怎么做的。在使用 BIOS 的情况下,/var/lib/tftp/ 目录下的情况是这样的:
# tree
.
├── etc
├── grub
│   ├── 01-14-FE-B1-DA-74-0F
│   ├── 01-90-B1-3C-43-29-7C
│   ├── efidefault
│   └── images -> ../images
├── images
│   └── rhel-x86_64
│       ├── initrd.img
│       └── vmlinuz
├── memdisk
├── menu.c32
├── ppc
├── pxelinux.0
├── pxelinux.cfg
│   ├── 01-14-fe-b1-da-74-0f
│   ├── 01-90-b1-3c-43-29-7c
│   └── default
└── s390x
    └── profile_list

BIOS 默认会使用 SYSLINUX 作为 boot image,也就是 pxelinux.0 这个文件。要获取该文件很简单:
# mount -t iso9660 /path_to_image/name_of_image.iso /mnt -o loop,ro
# cp -pr syslinux-4.02-4.el6.x86_64.rpm /tmp
# umount /mnt
# rpm2cpio syslinux-4.02-4.el6.x86_64 | cpio -imdv
# mkidr /var/lib/tftp/pxelinux
# cp /tmp/usr/share/syslinux/pxelinux.0 /var/lib/tftp/pxelinux

这样,dhcpd.conf 里面的 filename 则应该如下定义:
host xxxx {
    …
    filename "pxelinux/pxelinux.0";
    …
}

将其余的文件拷贝至 tftp 目录:
# cp /boot/grub/splash.xpm.gz /var/lib/tftpboot/pxelinux/splash.xpm.gz
# cp /mnt/images/pxeboot/{vmlinuz,initrd.img} /var/lib/tftpboot/pxelinux/rhel6/

上面所有的步骤其实 cobbler 已经帮我们做好了。2.2.3 的默认是不支持 UEFI 的,这里是他的一个 patch

# cobbler get-loaders
trying hardlink /var/lib/cobbler/loaders/grub-x86_64.efi -> /var/lib/tftpboot/grub/grub-x86_64.efi
trying hardlink /var/lib/cobbler/loaders/grub-x86.efi -> /var/lib/tftpboot/grub/grub-x86.efi

此时如果还需要修改 grub 的话,修改的是 /boot/efi/grub/grub.conf 这个文件而非 /boot/grub.conf。下面就是 ks 文件的书写了。

bootloader --location=partition --driveorder=sda --append="crashkernel=auto rhgb quiet"

part /boot/efi --fstype efi --size 128 --asprimary --ondisk=sda
part /boot --fstype="ext4" --size=150 --ondisk=sda
part / --fstype="ext4" --size=20000 --fsoptions="defaults,noatime" --ondisk=sda
part /var --fstype="ext4" --size=40000 --fsoptions="defaults,noatime" --ondisk=sda
part /home --fstype="ext4" --grow --size=1 --fsoptions="defaults,noatime" --ondisk=sda

sda 的第一块分区 sda1 需要制定给 UEFI 分区,格式化为 efi 或者 vfat 格式,并将其挂载到 /boot/efi/ 目录下面;第二块分区 sda2 则需要分配给 /boot/ 目录,此分区不能分配的太大,否则会出现问题(具体的我也不清楚),官方推荐在 500M 或者同等的量级。接下分区可以随意。
另外,还需要将下面两行注释掉:
#zerombr
#clearpart –all –initlabel

UEFI 的启动流程如下:

基本上需要注意的就是上面这两点,其他的分区选项看 manual 就好了。

ref:
https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Installation_Guide/s1-netboot-pxe-config.html
https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Installation_Guide/s1-netboot-pxe-config-efi.html
https://access.redhat.com/site/solutions/315133

cobbler 的电源管理

cobbler 的电源管理是通过 ipmi 实现的,因此在 cobbler server 上安装好 ipmitool 就好了。不过对于 2.2.3 的版本来说,并不是很好用,问题比较多。
后来我们研究了一下,还是决定直接使用 dell 的 racadm 工具来管理机器的电源。写个脚本就可以直接 pxe,之后的启动都从 hd 启动了。
$ cat pxe2hd.sh
#! /bin/bash

USER=root
PASSWD=calvin

echo "———————————- change to pxe boot ———————————–"
/opt/dell/srvadmin/sbin/racadm -r $1:22 -u $USER -p $PASSWD config -g cfgServerInfo -o cfgServerBootOnce 1
/opt/dell/srvadmin/sbin/racadm -r $1:22 -u $USER -p $PASSWD config -g cfgServerInfo -o cfgServerFirstBootDevice PXE
/opt/dell/srvadmin/sbin/racadm -r $1:22 -u $USER -p $PASSWD serveraction powercycle
echo "———————————— pxe boot done —————————————"

sleep 200

echo "———————————- change to hd boot ———————————–"
/opt/dell/srvadmin/sbin/racadm -r $1:22 -u $USER -p $PASSWD config -g cfgServerInfo -o cfgSErverFirstBootDevice "HDD"
/opt/dell/srvadmin/sbin/racadm -r $1:22 -u $USER -p $PASSWD config -g cfgServerInfo -o cfgServerBootOnce 0
echo "———————————-  hd boot done —————————————-"

写这篇博客的目的就是告诉大家,2.2.3 的电源管理不好用,自己找其他方案代替。上面是其中一种可行的,经过考验的方案。

kickstart 下的 gpt

对于 cobbler 来说,最重要的估计就是 ks 文件的书写了,这个跟 preseed 类似,但是可以精确的划分各个分区,而想要通过 preseed 精确的控制 debian 分区几乎是不可能的,没有经验的话,其最终的结果可能会相差数十倍之多。之前曾经对着 preseed 文件调试了不下百来次,最后的结果依然差强人意。如果磁盘的大小换了,就需要重新书写对应的 preseed,这个基本就是个灾难。对于 ks 来说,则不会存在这类问题。

目前线上的机器小于、大于 2T 的磁盘大概是一半一半的样子,为了维护方便,决定后面所有的机器不管是多大的磁盘都采用 gpt 的方式分区。下面这个是一个范例:

zerombr
bootloader –location=mbr –driveorder=/dev/sda

part /boot –fstype="ext4" –size=150 –ondisk=sda
part / –fstype="ext4" –size=20000 –ondisk=sda
part /var –fstype="ext4" –size=40000 –ondisk=sda
part /home –fstype="ext4" –grow –size=1 –ondisk=sda

part /data/data1 –fstype="ext4" –grow –size=1 –fsoptions="defaults,noatime" –ondisk=sdb

%pre

clearpart –all
/usr/sbin/parted –script /dev/sda mklabel gpt
/usr/sbin/parted –script /dev/sdb mklabel gpt

%end

这个 gist 是一个完整的 ks,根据我们的需求划分了磁盘,服务器的开启关闭以及 post install 方面的一些内容,这个在 gist 里面都做了详细的说明。

cobbler snippet 的使用

cobbler 可以通过 cheetah 来做一些定制话的事情。因此需要严格遵循其语法,可以先参考下 /var/lib/cobbler/snippets/ 目录下的 snippet 是怎么写的。这里面会涉及到很多的变量,可以使用下面这条命令将其 dump 出来:
# cobbler system profile dumpvars --name=jaseywang_profile

这样就可以在 snippet 里面直接引用了。比如我在 snippets/ 目录下面再建立一个 custom/ 目录,专门存放我们自己写的 snippet。
一个标准的 hosts 文件应该像下面这样:
127.0.0.1   localhost.localdomain    localhost
192.168.1.2 system1.jaseywang.me     system1

下面这个 snippet 要做的事情就是完成上面 hosts 的标准:
$ cat /var/lib/cobbler/snippets/custom/hosts
#set $hostname = $getVar('$hostname', None)
#set $hostpart = $hostname.split('.')[0]

#set $ikeys = $interfaces.keys()
#for $iface in $ikeys
#set $idata = $interfaces[$iface]
#set $my_interface_hostname_short = $idata["dns_name"].split('.',1)[:1][0]
#end for

cat > /etc/hosts << EOF
127.0.0.1           localhost.localdomain       localhost
$idata["ip_address"]        $idata["dns_name"].lower()          $my_interface_hostname_short.lower()
EOF

注意其语法,虽然感觉有点奇怪。这样书写好了以后就可以在 ks 的 %post 里面将其添加进去了:
%post

#$SNIPPET('custom/hosts')

以上就完成了一个 post install 的 snippet 的书写,其他的跟以上的类似。

使用 cobbler 2.2.3 遇到的一些问题

我们线上的机器使用 2.2.3 这个版本已经很长一段时间,使用过程中也发现不少问题,包括本篇在内,后续会陆续跟大家分享一下。
要理解 cobbler 的整体架构,可以参见这张截取自官方的图,十分清晰的表明了各个部分的关系。

另外我之前的一篇博客总结过跟 cobbler 相关的所有目录文件的结构,这次官方提供了一个更加详细的。

在 RH 上安装 cobbler/cobblerd 需要如下的软件包,可以通过包管理器(yum)直接安装:
createrepo
httpd(apache2 for Debian/Ubuntu)
mkisofs
mod_wsgi(libapache2-mod-wsgi for Debian/Ubuntu)
python-cheetah
python-netaddr
python-simplejson
python-urlgrabber
PyYAML(python-yaml for Debian/Ubuntu)
rsync
tftp-server(atftpd for Debian/Ubuntu, though others may work)
yum-utils

如果需要安装 cobbler web,还需要如下的包:
Django(python-django for Debian/Ubuntu)

如果需要重新安装系统,则需要 koan 这个包,他依赖于下面的软件包:
python-simplejson
koan
Continue reading

AHCI, ATA, RAID 比较

BIOS 里的 SATA setting 有 AHCI mode, ATA mode, RAID mode,g 了些资料。以下大部分内容源于 differencebetween,根据自己的理解整理而成。

AHCI vs ATA

ATA(AT Attachment) 是一个很久远的标准,最初是定义诸如硬盘等存储设备和 CPU 的接的标准。一共有两种类型的 ATA,第一种叫 Parallel ATA(PATA),第二种叫 Serial ATA(SATA),现在使用 ATA 这个词汇默认是指前者,也就是 PATA,他是在 SATA 之前出现的。而 AHCI 则是为 SATA 设计的控制器接口,AHCI(Advanced Host Controller Interface) 的全称是 Serial ATA Advance Host Controller Interface,他定义了存储设备和主机之间的信息如何传递。
AHCI 是一个相对较新的技术,跟老的 ATA(PATA)不兼容,因此,只有 SATA 接口的主板和硬盘才能使用 AHCI 这个技术。当使用 SATA 的时候,依然可以选择是使用 AHCI 还是古老的 PATA 实现,一些配有 SATA 控制器的设备可能由于驱动等原因无法使用 AHCI 可以选择 ATA 的模式,他是兼容性最好的一种,但是性能也相对较差。
PATA 的实现在 DELL 的服务器的 BIOS SATA setting 里面叫做 ATA mode,而 AHCI 的则叫 AHCI mode。因此对症下药的话,SATA/SAS 的硬盘一般选择 AHCI mode。
相比使用 ATA mode,AHCI 有两个最明显的优势,第一个就是热插拔(hot-plugging),第二个则是原生指令队列(NCQ, Native Command Queuing),该技术会让磁盘的寻道时间缩短,NCQ 除了需要有 AHCI 模式的支持外,其 OS 也需要有对应的 driver 支持。

总结一下:
1. AHCI 是一个控制器的接口,ATA 则是用来存储设备的标准
2. AHCI 不兼容于 ATA
3. AHCI 有不少 ATA 无法提供的高级功能

AHCI vs RAID

AHCI 是由 Intel 为 SATA 接口定义的一种操作模式,该技术不会对 SATA 的速度造成任何的影响,但是他在 SATA 的基础上了新增了一些高级功能;而 RAID(Redundant Array of Independent Disk) 相比之下是个古老的技术,他可以提高磁盘的 IO 以及可靠性。由于 AHCI 是由 Intel 发明的,该项功能只能使用在 Intel 的芯片上,其他厂商的则无法使用 AHCI 功能;而 RAID 作为一个标准,很多厂商都可以实现。

总结:
1. AHCI 是为 SATA 接口的硬盘设计的一种操作模式,RAID 则是一项通过多块硬盘组合来提高磁盘性能以及可靠性的机制
2. RAID 相比 AHCI 是一个比较老的技术
3. AHCI 是被 Intel 拥有的专有技术,RAID 则被众多厂商支持的

AHCI vs SATA

SATA 是为了取代 PATA 而出现的技术,相比 PATA,他拥有很多的优势,包括更快的数据传输速度,包括 NCQ 以及热插拔在内的 AHCI 技术。为了尽可能的实现 SATA 的兼容,大部分的厂商提供了包括 AHCI 以及 Legacy IDE(ATA) 的操作模式,前者上面已经提到,后者则是为了给比较老的设备提供兼容。

SATA vs SATA II

最近 5 年内的大部分应该是 SATA,SATA 控制器的很好辨认,比较窄的 cable 以及红色的连接器,目前还出现了 SATA II,最大的区别就是速度有了进一步的提升,前者最大只有 150MB/s 而后者则达到了 300MB/s。

总结:
1. SATA II 比 SATA 更快
2. SATA II 向下兼容于 SATA
3. SSD 更适合使用 SATA II,HDD 则适合使用 SATA

上面介绍的 SATA 按照不同的时间还可以分为 SATA-1, SATA-2 等,对明显的区别就是速度上的提升,可以参考这里

AHCI 从 2.6.19 开始支持,可以看到 2.6.32-220.el6.x86_64 默认已经支持了 AHCI 了:
# lsmod
Module                  Size  Used by

ahci                   40455  0

# dmesg  | grep ahci
ahci 0000:00:1f.2: version 3.0
ahci 0000:00:1f.2: PCI INT A -> GSI 20 (level, low) -> IRQ 20
ahci 0000:00:1f.2: irq 103 for MSI/MSI-X
ahci 0000:00:1f.2: AHCI 0001.0300 32 slots 6 ports 3 Gbps 0x1f impl SATA mode
ahci 0000:00:1f.2: flags: 64bit ncq sntf pm led clo pio slum part ems apst
ahci 0000:00:1f.2: setting latency timer to 64
scsi1 : ahci
scsi2 : ahci
scsi3 : ahci
scsi4 : ahci
scsi5 : ahci
scsi6 : ahci

# dmesg  | grep ncq
ahci 0000:00:1f.2: flags: 64bit ncq sntf pm led clo pio slum part ems apst

ref:
http://www.differencebetween.net/technology/difference-between-sata-and-sata-ii/
http://www.differencebetween.net/technology/difference-between-ahci-and-sata/
http://www.differencebetween.net/technology/difference-between-ahci-and-raid/
http://en.wikipedia.org/wiki/Parallel_ATA
http://en.wikipedia.org/wiki/Serial_ATA