为CentOS 6.8安装ENA增强网络驱动以支持AWS EC2 5系列实例

一、背景和挑战

1、需求背景

CentOS 6系列是2016年发布的系统,在2020年已经是比较老的系统,一般建议通过yum update升级版本,最高可升级到6.10。有些特殊的客户环境和应用程序,存在一些库文件版本的依赖,需要精确的用到6.8版本提供的库文件,不能很好的兼容6.9或者最新的6.10版本。例如6.8的从ISO安装后原始内核版本是2.6.32-642,而升级到2.6.10后是2.6.32-754,此外其他一些程序包也存在库文件版本差异。那么上云的时候,就必须提供特定的6.8版本的云上镜像(AMI)的支持。

2、CentOS 6.8迁移到AWS的挑战

AWS支持通过CLI工具执行vmimport,将自己的私有环境的镜像上传并导入到云上。不过,CentOS 6.8版本在上传后,是缺少AWS这两年广泛使用的5系列实例的ENA功能,即增强网络驱动的支持。由CentOS 6.8原始镜像创建的EC2只能选择T2、C4、M4、R4等规格,各方面性能都受到很大影响。因此,为CentOS 6.8安装ENA增强网络驱动,成为了迁移到AWS的一个重要步骤。

3、跳过手工安装ENA支持的办法

第一种办法:采用Amazon Linux 去替代CentOS 6.8系统。我们知道Amazon Linux 2是与CentOS 7保持较好兼容的,而Amazon Linux是上一代系统,是与CentOS6保持较好兼容的。Amazon Linux 虽然是基于2.6内核的发行版,但提供了一般CentOS没有的NVMe、ENA等支持,是非常好的云上优化方案。需要注意的是,2020年12月31日Amazon Linux将结束标准支持(Standard Support),转入维护支持(Maintain Support),这意味着,未来一年或者两年使用Amazon Linux依然可以继续获取升级包的,对于生产环境的安全是非常重要重要的。因此第一种办法是尝试换用Amazon Linux。

第二种办法:在尝试解决问题的过程中,我们发现从AMI社区镜像和Marketplace中,有很多基于CentOS6基础的镜像。但是,他们的版本大多已经是通过yum update提升到了6.9或者6.10版本,才打开了ENA支持。在社区和市场中,并未找到不含第三方应用的空白的6.8版本。因此,本文这里还是需要探讨如何自行安装CentOS6.8的ENA支持。

4、思路

我们安装过程中,必须保证CentOS 6.8版本,不能执行yum update。同时,不可避免需要内核开发模块、GCC等编译。在这个思路下,我们有多种解决办法:

  • 1)在本地用Virtualbox等虚拟化软件,搭建一个全白开发环境,编译模块,调试完成后,卸载gcc等生产不需要的开发环境,然后上传到AWS形成AMI镜像文件;
  • 2)在上一步的方式上做一些优化,在编译完成后,将编译出来的ENA内核模块copy到另一个不带开发环境的准生产环境上,直接挂载到内核,然后测试,并打包新的AMI镜像。如此不需要后期再去卸载生产环境不需要的各种工具;
  • 3)另一种完全不一样的方法是,从本地上传一个不支持ENA驱动的CentOS 6.8到AWS上做成AMI镜像,然后用EC2的上一代规格例如 c4.large 启动,然后在这个C4实例上,完成ENA驱动安装。安装完毕后,通过CLI为这个实例启动ENA Support,执行将C4升级到C5的过程。升级完毕后,获得5系列实例一个。最后将这个5系列实例转换为一个AMI镜像,今后直接使用。

以上方法中,可以看到方法三是最复杂的,需要做实例升级方法1相对最简单。本文按照方法2编写。

二、在本地开发环境编译内核模块

从CentOS官网或者Kernel.org下载centos 6.8版本的ISO,很多国内源都再不提供镜像。本文最后参考连接位置附上了官网下载网址。下载版本请选择CentOS-6.8-x86_64-bin-DVD1.iso,即第一张DVD即可,注意选择Live版本是不包含gcc的,无法安装编译。

在本地用Virtualbox创建虚拟机时候,选择磁盘格式VHD,动态扩展即可,这样下边的步骤可以直接upload到AWS,无需转化磁盘格式。安装时候,软件包选择basic server。安装过程记得不要联网。不要yum update。

安装完毕后,把iso挂载上,执行如下命令:

mkdir /mnt/cdrom
mount /dev/cdrom /mnt/cdrom
cd /etc/yum.repos.d/
mv *.repo ~/
vi cdrom.repo

在cdrom.repo内输入以下内容:

[local]
name=iso
baseurl=file:///mnt/cdrom
gpgcheck=1   

执行如下命令清空缓存:

yum clean all

这样就建立了一个local的yum repo,完全不联网。接下来继续安装开发工具,执行如下命令:

yum install gcc git openssh-server kernel-devel -y
chkconfig --add sshd
chkconfig sshd on
chkconfig iptables off

这样就获得了一个好的开发环境。

现在重启虚拟机,把虚拟机网卡连回去,注意不要update打补丁。最好在本地局域网,确保安全,不会被别的病毒木马扫描或攻入进来。从本地登录到登录这个虚拟机上,开始联网操作,去checkout git上的代码库。执行如下命令:

git clone https://github.com/amzn/amzn-drivers
cd amzn-drivers/kernel/linux/ena
make

编译完成。可在当前目录下获得ena.ko文件。

三、将ENA内核模块复制到准生产环境加载

按照本文介绍的几种实现方式,我们选择第二种,将编译好的ko文件复制到一个全新的准生产环境上,继续完成模块挂载。

生产环境的CentOS 6.8推荐使用标准安装,例如在软件包界面,选择 Basic Server,然后不需要选择定制,保持默认安装完。如此获得的安装环境是不带gcc和git等工具的,但又包含了ssh server。

执行如下命令。

mkdir /etc/modules-load.d/
touch /etc/modules-load.d/ena.conf
echo "ena" > /etc/modules-load.d/ena.conf
cp ena.ko /lib/modules/2.6.32-642.el6.x86_64
depmod
dracut -f -v

在本文末尾提到的AWS官方参考文档上,还提到 Predictable Network Interface Names 需要被关闭。经过调查,版本是V197的或者更高的systemd需要这个操作,在centos 6.8上低于197,因此可略过本步骤,继续后续操作。

前一个步骤加载完成。重启虚拟机看是否正常启动。启动过程在虚拟机的console上可能有如下信息:

ena: loading out-of-tree module taints kernel.
ena: module verification failed: signature and/or required key missing - tainting kernel

这个信息在AWS官方的github说明里边,表述了是正常的,请略过。重启完成后,连接到本机,验证ena模块加载正常。执行 modinfo ena,输出如下信息则表示正常。

执行如下命令,删除现有网卡信息。

rm /etc/udev/rules.d/70-persistent-net.rules

好了,关机,准备upload到AWS。

四、上传VHD文件到AWS

上传虚拟机到AWS并导入为镜像,需要配置几个IAM角色和身份,还需要CLI发起操作,导入过程与其他Linux、Windows镜像的导入过程完全一致。本文略过权限设置部分,请参考相关资料。

接下来执行导入。注意执行cli默认区域、vmimport、S3 Bucket区域必须相同。如下截图。

监控上传是否完成。可以看到已经完成。

五、找到镜像并用5系列EC2开机

进入EC2界面,在AMI下找到新导入的镜像。

查看镜像,可以看到ENA=yes是可用的。如果配置不正确,这里会显示ENA=no。

然后选择主机规格,例如c5.xlarge。如果ENA配置不正确,所有5系列实例都是灰色,不可选择。可以选择的话就证明ENA驱动安装成功。

另外,不支持结尾是字母d的实例,字母d表示实例包括本地存储,通道是NVMe,但因为CentOS 6.8的内核2.6系列无法安装AWS的NVMe驱动,因此不能支持。如下截图。

创建EC2的过程不再详细描述。

创建好之后登录到EC2,登录过程需要用密码登录。因为是自行创建的镜像,因此创建中选择登录Key步骤可以选择不需要设置Key。登录后执行如下命令,检查确认ENA模式是否正常。

ethtool -i eth0

如果显示如下信息,在driver部分显示vif,则表示ENA没有正确加载。可能的原因是:1)ENA驱动没安装正确,2)本镜像AMI是支持ENA的,但是当前启动的是T2系列实例、4系列实例等不支持ENA增强网络驱动的EC2,由于EC2本身不支持,这里就也会显示如下信息。

driver: vif
version:
firmware-version:
bus-info: vif-0
supports-statistics: no
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no

如果显示如下信息,在driver的部分显示ena,则表示ENA驱动加载成功。

driver: ena
version: 2.2.3g
firmware-version:
bus-info: 0000:00:05.0
supports-statistics: yes
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no

至此配置完成。

六、注意事项

本文操作的整个过程,关键环节是build前准备环境断开联网,不执行yum update,否则会导致很多库被动的升级为CentOS 6.10的库版本。编译环境需要通过本地的DVD ISO上的各种rpm包来装,可完全匹配CentOS 6.8原生版本。

另外的小tips,上传到AWS之前需要把ssh server设置开机自动启动,并关闭iptables。上云后的最佳实践是使用EC2的Security Group来管控端口开放,因此可完全关闭iptables。

七、参考文档

1、CentOS 6.8官方下载网址:

http://archive.kernel.org/centos-vault/6.8/isos/x86_64/

2、将私有镜像导入到AWS之前的IAM权限准备操作说明:

https://docs.aws.amazon.com/zh_cn/vm-import/latest/userguide/vmie_prereqs.html

3、Linux系统启用ENA支持:

https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/enhanced-networking-ena.html#test-enhanced-networking-ena

4、ENA内核模块源代码和编译说明:

https://github.com/amzn/amzn-drivers/tree/master/kernel/linux/ena

全文完。