Oracle-Linux-秘籍-全-
Oracle Linux 秘籍(全)
原文:
annas-archive.org/md5/dd839c442d972666d20ab0355581927a译者:飞龙
前言
企业 Linux 脱颖而出,成为寻求强大、安全和可靠操作系统的组织的首选。在 Linux 发行版的领域,企业 Linux 以 Oracle Linux 和 Rocky Linux 等发行版为代表,赢得了全球企业的青睐,成为首选解决方案。本书探讨了 Oracle Linux 被认为是企业环境中最佳发行版的关键原因,并通过一系列易于跟随的步骤示例(称为配方)探讨了多个技术,包括 Oracle 的发行版。这些配方将教你如何在几个关键领域使用这些技术。
安全性在企业环境中至关重要,Oracle Linux 已经为强大的安全功能设立了标准。安全增强 Linux(SELinux)、强制访问控制和主动的安全补丁系统(可进行零停机时间的修补)等功能有助于创建一个安全的环境。定期的安全审计和快速的零停机时间修补有助于减轻漏洞风险,使得 Oracle Linux 成为处理敏感和关键任务数据的可信选择。
企业 Linux 发行版旨在无缝扩展,无论是在单一服务器上,还是在大规模集群环境中。这些发行版集成的性能优化确保它们能够满足现代企业应用程序的需求。Oracle Linux 在性能上领先,提供了使用 Oracle 不可破坏企业内核(UEK)的选项。本书介绍了如何安装这一选项,并展示了它带来的几个关键特性,例如 Btrfs 文件系统。我们还涉及了高可用性,并提供了更多易于遵循的配方,涵盖高可用存储和应用程序集群的内容。
Oracle Linux 受益于一个庞大的软件和应用程序生态系统,这些软件和应用程序都经过认证并且已优化以确保兼容性。这个生态系统包括数据库管理系统、开发工具、中间件和企业应用程序,帮助组织更轻松地构建、部署和管理其软件堆栈。本书突出了其中一些支持 DevOps 和 DevSecOps 团队的技术,如 Ansible 和 Podman。
Oracle Linux 作为企业环境中最佳的发行版,以其坚如磐石的稳定性、强大的安全功能、可扩展性、全面的支持、符合行业标准以及丰富的生态系统脱颖而出。无论是管理关键任务负载、保护敏感数据,还是确保高性能计算,企业 Linux 仍然是寻求可靠和安全操作系统的组织首选。
本书适合谁阅读
本书面向企业 Linux 管理员,特别是管理 Oracle 企业 Linux 的管理员。无论你是从 CentOS 迁移过来,还是正在构建新的系统,本书都充满了有用的技巧和窍门。作者的目标是帮助你成为更高效的管理员,将新的技术添加到你的工具箱中,让你在同行中脱颖而出。
本书面向 Linux 系统管理员以及在 Oracle Linux 8 上运行的应用程序开发人员,因此你需要具备基本的 Linux 管理知识,并能熟练编辑配置文件。
本书内容概述
第一章,Oracle Linux 8 – 明白了吗?懂了吗?好极了!,介绍了如何获取 Oracle Linux,升级 Oracle Linux 版本,以及如何在 ARM 系统和云环境中运行它!
第二章,带自动化与不带自动化的安装,我们将在这一章中自动化 Oracle Linux 的安装,使用 PXE 和 kickstart 来启动安装过程。
第三章,探索 Oracle Linux 中的各种启动选项和内核,介绍了什么是内核以及 UEK 的不同之处。
第四章,创建和管理单实例文件系统,提供了更好地管理 Btrfs、xfs 和 RAID 的技巧和窍门。
第五章,使用 DNF 进行软件管理,我们将探讨如何构建本地仓库、制作自定义 RPM 包,并更好地利用 DNF。
第六章,消除所有单点故障!冗余的实践,介绍了如何通过负载均衡、代理、集群、集群文件系统和网络冗余选项消除单点故障。
第七章,Oracle Linux 8 – 补丁更新不一定需要重启,介绍了如何在不重启的情况下进行补丁更新。我们还将讨论什么是 Ksplice,以及为什么你应该使用它。
第八章,DevOps 自动化工具 – Terraform、Ansible、Packer 等,介绍了如何使用 Terraform、Vagrant 和 Packer 自动化管理。
第九章,保护数据安全 – 系统安全,介绍了如何通过确保系统安全,避免上新闻。我们将讨论如何加密数据、使用 SELinux、扫描系统漏洞,并管理 GPG 密钥进行签名。
第十章,重新审视模块和 AppStreams,探讨了 AppStreams 如何改变软件部署以及如何现代化应用程序部署。
第十一章,狮子、老虎与容器 – 哎呀!Podman 和它的朋友们,介绍了什么是 Podman,如何将其用作 Docker 的替代品,以及如何使用 Podman、Buildah 和 Skopeo 来满足所有容器化需求。
第十二章,畅游 Ansible 的海洋,介绍了 Ansible 的所有内容,从使用 Oracle Linux 自动化管理器 (OLAM) 在企业级部署 Ansible,到编写 playbook。
第十三章,让我们一起进入云端,带我们进入云计算,讨论如何为 AWS 和 OCI 构建自定义镜像,以及如何在云中构建新的虚拟机。
如何最大化利用本书
本书中的许多食谱可以在你的桌面系统上执行,利用 Oracle VM VirtualBox 来运行一些复杂的系统作为虚拟机。我们假设你已经熟悉基本的 Linux 安装过程和管理员技能,例如切换为 root 用户。
| 本书涉及的软件/硬件 | 操作系统要求 |
|---|---|
| Oracle Linux 8 | Oracle Linux 8 |
许多食谱假设你是 root 用户,并且大多数管理员任务都需要此权限。
如果你正在使用本书的数字版,我们建议你亲自输入代码或通过 GitHub 仓库访问代码(链接将在下一节提供)。这样做可以帮助你避免因复制粘贴代码而可能出现的错误。
下载示例代码文件
你可以从 GitHub 下载本书的示例代码文件,链接为 github.com/PacktPublishing/Oracle-Linux-Cookbook。如果代码有更新,现有的 GitHub 仓库将进行更新。
我们还提供了其他代码包,来自我们丰富的图书和视频目录,访问 github.com/PacktPublishing/,赶快看看吧!
使用的约定
本书中使用了许多文本约定。
文本中的代码:表示文本中的代码词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 账号。以下是一个例子:“使用 .efi 文件可以让用户更多地控制启动过程,包括利用新的安全功能。”
一段代码如下所示:
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = extensions
当我们希望引起你对代码块中特定部分的注意时,相关的行或项目将以粗体显示:
</Directory>
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge [NC]
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>
任何命令行输入或输出都如下所示:
root@ol8 # grubby --info=/boot/vmlinuz-0-rescue-c32316cc4b5241b8adb312707ae46458
粗体:表示新术语、重要的词汇或屏幕上看到的文字。例如,菜单或对话框中的词语在文本中会这样显示。以下是一个例子:“从菜单中选择Enroll MOK。”
提示或重要说明
显示为这样。
各节
本书中你会看到几个频繁出现的标题(准备工作、如何做...、它是如何工作的...、还有更多... 和 参见)。
为了清晰地说明如何完成一个步骤,使用以下各节:
准备工作
本节告诉你食谱的内容,并描述如何设置任何所需的软件或任何先决条件。
如何操作…
本节包含遵循该食谱所需的步骤。
它是如何工作的…
本节通常包含对上一节发生的内容的详细解释。
还有更多…
本节包含有关食谱的附加信息,帮助你更深入了解该食谱。
另请参阅
本节提供了其他有用信息的链接,以帮助你更好地理解食谱。
联系我们
我们欢迎来自读者的反馈。
一般反馈:如果你对本书的任何部分有疑问,请在邮件的主题中提到书名,并发送邮件至 [customercare@packtpub.com。
勘误表:虽然我们已经尽力确保内容的准确性,但错误总会发生。如果你在本书中发现了错误,我们非常感激你能报告给我们。请访问 www.packtpub.com/support/errata,选择你的书籍,点击“勘误表提交表单”链接,并填写详细信息。
盗版:如果你在互联网上发现任何非法复制的我们的作品,无论是什么形式,我们都非常感激你提供该地点或网站的地址。请通过 copyright@packt.com 与我们联系,并提供相关材料的链接。
如果你有兴趣成为作者:如果你对某个领域有专业知识,并且有兴趣撰写或参与写书,请访问 authors.packtpub.com。
评价
请留下评价。在阅读和使用了这本书后,为什么不在你购买书籍的网站上留下评论呢?潜在读者可以看到并利用你的公正意见来做出购买决策,我们在 Packt 可以了解你对我们产品的看法,而我们的作者也能看到你对他们书籍的反馈。谢谢!
欲了解更多关于 Packt 的信息,请访问 packt.com。
分享你的想法
一旦你阅读了Oracle Linux Cookbook,我们很想听听你的想法!请点击这里直接访问此书的 Amazon 评价页面并分享你的反馈。
你的评价对我们和技术社区非常重要,将帮助我们确保提供优质的内容。
下载这本书的免费 PDF 副本
感谢你购买这本书!
你喜欢随时随地阅读,但无法随身携带纸质书籍吗?
你的电子书购买是否与选定设备不兼容?
不用担心,现在每本 Packt 书籍你都可以免费获得该书的无 DRM PDF 版本。
在任何地方、任何设备上阅读。可以从你最喜欢的技术书籍中直接搜索、复制和粘贴代码到你的应用程序中。
福利不止这些,你还可以独家获得折扣、新闻通讯,并每天将精彩的免费内容发送到你的邮箱。
按照这些简单的步骤来获得好处:
- 扫描下方的二维码或访问以下链接

packt.link/free-ebook/978-1-80324-928-5
-
提交您的购买凭证
-
就这样!我们将免费的 PDF 和其他福利直接发送到您的电子邮件
第一章:Oracle Linux 8 – 获取了吗?搞定了吗?好!
你终于决定升级到最安全、最可靠的免费 Linux 发行版,现在需要学会一些技巧。接下来该做什么?如何开始?是时候回归基础,回答这个问题了:如何安装 Oracle Linux?
在过去,安装 Linux 发行版是一件简单的事;你只需订购一个 CD-ROM,将其放入电脑并从磁盘启动。简单……有效……对许多系统管理员来说却是个痛苦。谁还想订购一个 CD-ROM,或者说,谁还在使用 CD-ROM、DVD 或 Blu-ray 光盘?你甚至需要介质吗?难道不能直接从网络启动来进行安装吗?更复杂的是,当你在云环境中时该怎么办?云不都是帮你做这一切吗?那么 CPU 类型呢,比如 Arm 或 x86?你如何自动化这些过程?
我们还需要考虑到不仅仅是 x86-64 架构,随着 Arm 架构因其优势越来越受欢迎,它也逐渐成为一个重要选择。那么,旧系统怎么办?是否必须从零开始安装 Oracle Linux 8,还是可以直接升级 Oracle Linux 7 系统?说到升级,RHEL 和 CentOS 系统怎么办?它们能迁移到 Oracle Linux 吗?毕竟它们都是基于 Fedora,就像 Oracle Linux 一样。
本章将解答这些问题,并帮助你学习一些自动化安装 Oracle Linux 的技巧,以及如果安装过程中出现问题,如何进行故障排除。
本章将涵盖以下主要内容:
-
Oracle Linux 8 – 哪个 ISO 版本适合?USB 吗?还有人用 DVD 吗?
-
烧录一个可引导的 ISO
-
一举两得 – 在 Windows 子系统 上运行 Linux (WSL)
-
为 IT 的未来做好准备 – 它不仅仅是一个 Raspberry Pi 的小切片
-
从 Oracle Linux 7 升级到 8
-
从 CentOS 迁移到 Oracle Linux
技术要求
本书中许多食谱相关的配置文件可在 GitHub 上找到,链接:github.com/PacktPublishing/Oracle-Linux-Cookbook。
Oracle Linux 8 – 哪个 ISO 版本适合?USB 吗?还有人用 DVD 吗?
在我们开始其他内容之前,先来看看如何安装 Oracle Linux。
准备工作
安装 Oracle Linux 时,您必须首先决定如何进行安装。您可以选择多种方式,从启动新计算机并使用可安装映像、克隆来自其他系统的硬盘,甚至通过网络启动。所有这些选项都需要正确的介质。如果您尝试使用源代码Red Hat 包管理器(RPM)或错误的 CPU 架构进行安装,结果是不可行的。在下载任何内容之前,您需要有互联网连接,并确保有足够的空闲磁盘空间来保存 ISO 文件。通常,建议至少预留 10 GB 的空间来下载 ISO 文件。如果您打算使用 Oracle VM VirtualBox 来运行基于 ISO 的虚拟机,还需要额外的空间。通常,为每个虚拟机分配 100 GB 或更多空间,因为这样可以让文件系统快速扩展,而无需向卷组中添加另一块磁盘。也就是说,50 GB 是 Oracle 云镜像的默认设置,适合许多用户。在云环境中,使用较小磁盘的优势是降低成本,因为较小的磁盘意味着较低的费用。
注意
RPM 也定义为 RPM 包管理器,但这对于许多人来说是递归的,并且可能引起混淆。
如何操作...
您还需要了解您用于安装的硬件。将 ISO 刻录到 DVD(或其他光盘格式)可能适用于旧系统,这些系统配有光驱,但现代系统通常通过 USB 启动进行安装。企业级服务器将这一点提升到了一个更高的层次,允许您从网络挂载的 ISO 文件或虚拟控制台启动。您还可以通过预启动执行环境(PXE)服务器启动大多数系统,从而实现更自动化的基于网络的安装。选择哪种方法取决于您的硬件,然后是您需要多少自动化。
注意
小心自动化陷阱。通常,您花费的时间来自动化安装可能比手动安装还要长。在较小的环境中,虽然自动化很方便,但相比于每年做 3-4 次手动安装,构建和维护自动化系统可能需要花费更多的时间。
注意
虽然磁盘映像通常称为 ISO,但 ISO 文件的实际格式是 ISO 9660 Joliet,这是一种用于光盘介质的格式。ISO 实际上是国际标准化组织(www.iso.org/home.html)的缩写。ISO 组织成立于 1947 年,制定了从质量管理(ISO 9001)到食品安全(ISO 22000)等各方面的标准。
获取介质的最简单方法是从 yum.oracle.com/oracle-linux-isos.html 下载 ISO 文件。
在该网站上,有四种类型的 ISO 文件:
-
完整 ISO:这是 Oracle Linux 的完整安装包。ISO 文件包含了安装 Oracle Linux 所需的所有文件,并且是可引导的。你可以通过将文件刻录到 USB 闪存盘或 DVD 上来引导系统。在许多服务器上,你还可以通过远程管理软件虚拟挂载 ISO 来引导系统。系统上有多种远程控制选项,包括通用的 智能平台管理接口 (IPMI),其具有基本功能,以及开源的 基板管理控制器 (BMC),该控制器提供了额外的功能。大多数主要硬件供应商还提供特定技术,例如 Oracle 的 集成灯管理器 (ILOM)、Dell 的 集成远程访问控制器 (iDRAC),以及 HP 的 集成灯管理 (ILO).
-
启动 ISO:这个 ISO 使用 Red Hat 兼容内核进行引导,以便进行安装过程。它不包含所有安装所需的文件。虽然文件更小,但你需要通过网络或本地设备来获取其余的安装 RPM 文件。你可以通过 HTTP 访问这些文件,从
yum.oracle.com/或本地 HTTP 服务器上获取文件。
注意
不可破坏企业内核 (UEK) for Oracle Linux 有许多优点,例如为根目录启用 BTFS 文件系统,或使用与主流 Linux 内核匹配的更现代的内核,并包括对现代设备的更好支持。
-
UEK 启动 ISO:这个 ISO 可引导到更新版的 UEK,但和启动 ISO 一样,它不包含安装所需的所有文件。使用更新版的 UEK 进行安装尤其对那些无法在旧版 Red Hat 兼容内核 (RHCK) 上正确安装的系统有帮助。虽然这个文件更小,但你仍然需要通过网络获取其余的安装 RPM。UEK 是唯一可以在 Arm 架构上进行安装的选项。
-
源 ISO:这个 ISO 不是可引导的,但它很有用,因为它包含了所有的源 RPM,可以帮助你审计源代码。
注意
对于这两种启动 ISO 选项,介质必须通过网络提供,支持 FTP 服务器、HTTP/HTTPS 服务器或 NFS 服务器。
此外,有两种 CPU 架构可供选择。请确保为安装选择正确的架构。让我们来看看它们:
- x86_64:这是最常见的架构,广泛用于大多数 Intel 和 AMD 系统。包括 Intel X 系列处理器,以及 i9、i7、i5 和 i3 处理器。对于 AMD 系统,这包括 AMD EPYC 处理器、Ryzen 处理器以及 Athlon 系列处理器。虽然这是最常见的选项,但它在行业中正受到 Arm 架构的挑战。从下载站点查看 x86 的完整选项列表,可以参考以下图示:

图 1.1 – x86_64 ISO
-
AArch64:这是在使用 Oracle Linux 运行 Arm 服务器时所需要的,例如 Raspberry Pi 或 Ampere 的高性能云原生处理器 CPU。云原生处理器是专门为运行云原生应用程序设计的 CPU,优化了更低的功耗,并具有更可扩展的架构。
在 Arm 上运行 Oracle Linux 是一个非常有趣的选择,因为诸如 Java、Apache、Python 和 Podman 等应用构建块使用与 x86 架构相同的软件版本运行。所有这些构建块的运行几乎与它们在 x86 架构上的运行方式完全相同,这使得通过 Oracle Linux 切换到 Arm 对应用程序来说非常容易。Arm 的优势在于其运行成本较低,密度更高,提供了非常有吸引力的性价比故事,使得组织能够轻松降低成本同时提高性能。从下载网站下载 Arm ISO 的当前可用选项矩阵可以在下图中找到:

图 1.2 – Arm ISOs
一旦我们理解了平台,我们还需要做出另一个决策,选择使用哪个版本。有时你可能能够下载旧版本,并且你可能需要验证该版本是否会得到支持。在撰写本文时,虽然可以下载 6 版本,但如果你购买了扩展支持,则该版本会得到支持,该支持仅持续到 2024 年 6 月。
注意
Oracle 的扩展支持允许你支付费用以获得支持,包括对关键安全问题的修补程序和修复方案以及一些高影响的关键错误的修复。此支持并不涵盖所有 RPM。鉴于此,你可能需要重新考虑下载和使用旧版本的 Linux,并避免延迟操作系统的升级,直到它不再普遍可用。扩展支持的价值在于,它可以为你提供额外的时间来升级那些需要旧版 Oracle Linux 的应用程序。
在选择发布版本之前,请与你的应用团队核实该版本是否受到支持。不同的主要版本号(如 7 与 8 等)之间存在差异,一些软件可能不会在所有主版本号上提供。例如,Oracle Linux 自动化管理器(这是基于 AWX 项目的 Ansible 集中控制,几乎与 Red Hat 的 Ansible Tower 相同),需要 Oracle Linux 8 版本。另一个例子是 Oracle Linux 管理器(也叫 Spacewalk),需要 Oracle Linux 7 版本作为服务器。
注意
由于 Oracle Linux 跟踪 Red Hat Enterprise Linux,因此主版本号和次版本号是相同的。Oracle Linux 7.10 与 Red Hat Enterprise Linux 7.10 是一样的。
刻录一个可启动的 ISO
一旦你下载了 ISO 文件,可能还需要进行一些额外的准备。如果你使用 USB 设备安装,单纯将文件复制到闪存驱动器上是行不通的,因为 ISO 文件实际上并没有被解压到媒体上。如果 ISO 文件没有正确解压,且媒体没有被设置为可启动,你将无法从该媒体启动并进行安装。将 ISO 文件正确写入媒体的过程会将媒体解压成单独的文件和目录,并使媒体变得可启动。如果没有这样做,媒体上只会有一个 ISO 文件的副本。
有多种工具可以用来完成此任务。随着大多数系统不再使用光盘介质,最常见的方式是从闪存驱动器或虚拟磁盘启动服务器。
准备工作
在开始之前,你首先需要下载一个 ISO 镜像。你还需要一个 USB 闪存驱动器,理想情况下其空间大于 16 GB。随着发行版的增大,8 GB 的驱动器已不再足够用于完整的媒体安装 ISO。
如何操作…
在你可以从闪存驱动器启动之前,必须先将 ISO 文件写入闪存驱动器。在 Windows 系统中,一种常用的免费工具是balenaEtcher,可以从www.balena.io/etcher/下载。按照以下步骤操作:
-
一旦安装了Etcher,你需要运行它(确保右键点击并以管理员身份运行),然后选择镜像文件作为源,选择闪存驱动器作为目标。
-
在以下截图中,源是用于x64的Oracle Linux 8.7 ISO,目标是闪存驱动器:

图 1.3 – 使用 Etcher 选择源和目标
- Etcher 可以自动处理压缩文件,因此在几分钟内(如以下截图所示),你应该可以得到一只已安装镜像并准备启动的闪存驱动器:

图 1.4 – balenaEtcher 写入 ISO
注意
在使用闪存设备时,要小心低价品牌。通常,非品牌的卡片性能可能比品牌卡要慢得多。另外,在网上购买时,要注意防止购买到假卡。始终从可信的供应商那里购买闪存设备。
工作原理…
一旦你将 ISO 文件写入 USB 设备,就可以从该媒体启动服务器。如何从 USB 设备启动取决于系统的品牌和型号。Arm x86 系统在其基本输入/输出系统(BIOS)中有一个设置,允许你从新写入的媒体启动。Arm 系统通常使用统一可扩展固件接口(UEFI)固件从 ISO 或 USB 设备启动。
安装 Oracle Linux 到服务器上的最常见方法之一是直接从 ISO 文件启动。企业级服务器,例如 Ampere Arm 系统,可以通过将 ISO 文件挂载为虚拟驱动器来支持从 ISO 文件启动。此外,你还可以使用一种名为 PXE 的网络启动技术来启动,PXE 发音为pixie。
一石二鸟 – 在 Windows 子系统 Linux(WSL)上运行 Oracle Linux
还有一种方法可以在 Microsoft Windows 桌面上安装 Oracle Linux,使用 WSL。
WSL 使你可以轻松在 Windows 上直接安装 Oracle Linux,无需安装传统的虚拟机(如 VirtualBox)。WSL 包含一个集成的虚拟机,已为 Windows 预先配置,用户看不到虚拟化程序。WSL 还具有一个优点,即允许你直接从 Windows 执行 Linux 命令,包括 Linux 服务,如 Apache、MySQL、SSHD、Nginx 和 PostgreSQL。
准备工作
在开始之前,你需要一个可以连接互联网的 Windows 10 或 Windows 11 系统,并且你需要具有本地管理员权限。这不是一个复杂的步骤,非常值得花时间进行操作。
如何操作…
安装 WSL 相对简单。你需要执行以下步骤:
- 以管理员身份启动命令提示符。别忘了右键点击命令提示符,以管理员身份运行,如下图所示:

图 1.5 – 以管理员身份运行命令提示符
注意
虽然这些说明是针对 WSL 的,但请注意,它实际上是覆盖WSL2。之前有一个早期版本的 WSL,也称为WSL1,其工作方式略有不同,且不再使用或部署。通常应该避免使用旧版本的 WSL。操作系统版本也应如此;尽可能使用最新的 8.X 版本。
-
从命令提示符运行
wsl.exe –install命令。此操作将启动几个任务,包括安装启用 WSL 的 Microsoft VM 平台、安装 WSL 子系统本身以及安装 Ubuntu Linux 发行版。安装完成后,如下图所示,Windows 需要重启:

图 1.6 – WSL 安装
- 在备份好系统之后,我们将安装 Oracle Linux 8.5 作为 WSL 使用的 Linux 操作系统。为此,在搜索栏中启动
Oracle Linux:

图 1.7 – Microsoft Store 搜索 Oracle Linux 8.5
- 在搜索结果中,选择Oracle Linux 8.5应用程序。这将带你进入一个可以在 WSL 下下载并安装 Oracle Linux 8.5 的页面:

图 1.8 – 在 Microsoft Store 中的 Oracle Linux 8.5
- 点击
Oracle Linux。这不仅会找到子系统,还会给你一个选项,将子系统固定到任务栏或开始菜单中,如下图所示:

图 1.9 – Oracle Linux 8.5 子系统应用选项
- 当你运行 WSL 子系统时,它几乎与其他任何 Oracle Linux 8.5 系统一样工作。现在你可以轻松地在 Windows 下运行 Oracle Linux 命令。这包括检查存储容量,使用
dnf安装程序,编辑文件,以及通过 SSH 连接到其他主机:

图 1.10 – WLS 操作系统命令
你还可以使用 dnf 安装新软件。以下图展示了安装 nmap 的示例:

图 1.11 – 使用 dnf 安装 nmap 的 WSL
你还可以通过 WLS 访问 Windows 驱动器。它们将分别以 /mtn/DRIVE 位置呈现,其中 C: 驱动器是 /mnt/c。Windows 系统也可以通过 \\wsl$\OracleLinux_8_5 路径访问 Linux 目录:

图 1.12 – Windows 文件资源管理器与 WSL
小心
提醒注意,在编辑文件时要小心。Windows 和 Linux 在文本格式上有所不同,如果不小心,很容易损坏文件。建议使用 Windows 存储和访问 Windows 文件,使用 WSL 映像编辑和存储 Linux 文件。
将 Oracle 8.5 作为 Windows 子系统运行是系统管理员和开发人员的一个非常棒的工具。它与 Windows 的集成使得安装变得快速简便,同时还允许在个人系统上透明地访问 Linux 系统。
为 IT 的未来做准备——这不仅仅是一片树莓派
首先,让我们聊一聊 高级 RISC 机器(更常见的叫法是 Arm CPU)上的 Oracle Linux。这种较新的架构相比于 Intel 和 AMD 使用的较老的 x86_64 架构有许多优点,包括更低的功耗;更低的延迟,提供更好的性能;以及简化的架构,支持更高密度的系统。在 Arm 系统上利用 Oracle Linux 已经成为 Oracle 和 Microsoft 等云规模运营商,以及那些希望降低计算能力和冷却需求的小型组织的热门选择。
在所有 Linux 系统上使用单一的 企业操作系统 有几个优点,例如可以在所有服务器上使用相同的工具,并且可以获得相同的商业支持。对于你的服务器库存中的 Arm 用例也很有趣。总体而言,Arm 处理器由于其更高的 潜在 核心密度和更低的 功耗,提供了更低的成本。在企业领域,Ampere 占据主导地位,并提供最多 128 核心的 Arm 处理器,这些处理器可以在一个单一的 机架单元(RU)空间内工作。
性能也毫不逊色,每个处理器支持最多 128 个 Arm 核心,两个 RU 空间内的 CPU 频率最高可达每核心 3.0 GHz。I/O 也非常强大,提供 128 条高速 PCIe Gen4 通道和 8×72 ECC 保护的 DDR4 3200 内存。配备 64 GB 双列直插内存模块(DIMMs),相当于4 terabytes的内存!这些都是企业级系统,具备 Oracle Linux 的所有强大功能、安全性和可靠性。
Arm 不仅适用于数据中心;当你需要一个小型系统时,比如 DNS 服务器或远程访问设备,著名的树莓派非常适合。凭借其小巧的体积,树莓派非常适合藏在配线室里作为备份 DNS 服务器,或者放在 Oracle Exadata 机柜内以启用远程访问。你甚至可以将树莓派用作监控系统或 DMZ 中的 Web 服务器。
无论你使用的是哪种 Arm 平台(Ampere 还是树莓派),运行 Oracle Linux 时,你还可以访问 UEK 及其增强功能,包括 Ansible 等工具。Oracle Linux 包含了所有主要技术,支持价格低廉,而且你总是可以选择免费使用;你甚至可以免费打补丁。就 Arm 平台而言,它也没有限制。你可以使用商业软件,如 MySQL 8.0,以及大量的开源软件。
不仅是树莓派的应用案例非常强大。当你使用更大的基于 Arm 的服务时,你会开启大量边缘计算的应用场景。边缘计算需要将数据从云端带到需要低延迟访问数据的位置。借助 MySQL 8.0 的复制功能,你可以轻松地将数据从云端复制到边缘,保持性能的同时,还能利用如 Ampere 等公司生产的 Arm 系统的高核心数和低功耗要求。Ampere 提供的 80 核 CPU 功耗仅为 210w。高核心数结合 Docker 和 Kata 容器等容器技术,支持分布式微服务架构,通过集中管理的应用程序既能利用云的自动化特性,又能提供传统本地解决方案的性能。这就是 IT 的未来。
准备工作
在开始之前,你需要一台带有 Micro SD 卡槽的树莓派。你还需要一张可以用来安装操作系统的 Micro SD 卡。如果你正在使用树莓派计算模块或 Ampere 系统等企业级 Arm 服务器,请跳转到第二章并通过 PXE 启动系统。
如何操作...
话虽如此,让我们在树莓派上安装 Oracle Linux 吧。虽然我一直在使用 Oracle Linux for Arm 并通过繁琐的方式安装它,但现在已经有了一种更简单的安装方法。Oracle 提供了免费的树莓派镜像,操作系统已经安装好了。
接下来,我们将执行以下步骤:
-
下载 Oracle 镜像,请访问以下链接:
www.oracle.com/linux/downloads/linux-arm-downloads.html。 -
接下来,您需要将镜像写入 SD 卡。从 Windows 系统执行此操作最简单的方法是使用 balenaEtcher,这是一个免费的实用工具,可以轻松地将镜像写入 SD 卡和 USB 驱动器。您可以从
www.balena.io/etcher/下载。
注意
虽然示例中使用的是 balenaEtcher,但还有许多其他方式可以将文件写入闪存驱动器,例如使用 Raspberry Pi Imager,或者在 Linux 中直接使用dd命令将文件写入闪存驱动器。
- 运行 Etcher(确保右键点击并以管理员身份运行),并将镜像文件选为源,将 SD 卡选为目标:

图 1.13 – 烧录 Pi SD 卡
Etcher 可以自动处理压缩文件,所以一两分钟后,您就应该拥有一张已经安装了镜像的 SD 卡。
- 接下来,将 SD 卡插入您的 Pi 并启动 Pi。正常的 GRUB 启动加载程序将启动,并且应该会出现登录提示符。

图 1.14 – 启动 Pi
是的,就是这么简单!
- 一旦启动,使用
root用户登录,密码是oracle。系统会要求您更改密码。

图 1.15 – 首次登录
-
现在由您决定要安装什么。默认情况下,它可以访问免费的 Oracle 公共 yum 服务器,因此 yum 开箱即用。
-
对于 Oracle Linux 8,您可以访问以下软件仓库:
-
/etc/yum/repos.d目录下的EPEL.repo文件,包含以下文本:[ol8_EPEL] name=Oracle Linux 8 EPEL ($basearch) baseurl=https://yum$ociregion.oracle.com/repo/OracleLinux/OL8/developer/EPEL/$basearch/ gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-oracle gpgcheck=1 enabled=1
可以使用
dnf命令通过以下命令添加 EPEL 库:dnf install oracle-epel-release-el8 -
花几分钟玩一下 Arm 系统。它们多功能、低成本且非常灵活。您应该能找到很多 Oracle Linux 在 Arm 上的使用场景。
从 Oracle Linux 7 升级到 8
系统管理员经常面临的一个挑战是,当部署了较旧版本的操作系统,并且即将达到支持结束的日期时该怎么办。这种情况确实会发生,而且并不轻松。这将使您处于一个需要在新系统上重新安装较新操作系统,然后迁移工作负载的局面。对于许多系统,存在一种更好的方式,称为Leapp。
Leapp 允许您将操作系统从 Oracle Linux 7 升级到 Oracle Linux 8。无需在新系统上重新安装一切。Leapping 包含两个阶段:
-
一个检查系统以确定软件是否可以升级的预升级阶段
-
一个实际执行升级的第二阶段
听起来不错。但有一些事情是你需要了解的。
准备就绪
首先,Leapp 从 7 到 8 的升级并不支持所有用例。表 1.1展示了 Oracle 在执行此操作时将提供支持的内容。Leapp 在与复杂应用程序(如根据底层操作系统版本有特定安装选项的数据库系统)一起使用时,并不总是表现良好。它也可能会破坏一些操作系统未包含的应用程序:
| Leapp 支持 | Leapp 不支持 |
|---|
| 平台(最新发布的更新):
-
x86_64
-
Arm (AArch64)
操作系统:
- 当前 Oracle Linux 7 版本仅适用
配置:
-
最小安装
-
虚拟化主机
-
带图形界面的服务器
-
基本 Web 服务器
-
基础设施服务器
-
文件和打印服务器
| 安装了以下内容的系统:
- ISV 应用程序,包括 Oracle 数据库和中间件
ISV 必须提供并验证 Leapp 角色,以协调其应用程序的升级:
-
Oracle Linux Manager 或 Spacewalk for Oracle Linux
-
未使用 ISO 镜像的安装,如 Ceph 和 GlusterFS
-
LUKS 加密磁盘的迁移
-
已注册到 ULN 的系统
-
处于 FIPS 模式或运行 Secure Boot 的系统
-
配置了 Docker 容器的系统
|
表 1.1 – Oracle 提供的 Leapp 支持矩阵
接下来,Leapp 在升级内核时也存在一些限制。以下表格展示了 Oracle 提供的矩阵:
| 平台说明 | 起始内核(Oracle Linux 7) | 结束内核(Oracle Linux 8) | 支持 |
|---|---|---|---|
| 未使用 Btrfs 文件系统的 x86_64 | RHCK | RHCK | 是 |
| RHCK | UEK | 否 | |
| UEK | UEK | 是 | |
| UEK | RHCK | 否 | |
| 使用 Btrfs 文件系统的 x86_64 | RHCK | RHCK | 否 |
| RHCK | UEK | 是 | |
| UEK | UEK | 是 | |
| UEK | RHCK | 否 | |
| AArch64 | UEK | UEK | 是 |
表 1.2 – Oracle 支持的内核升级
在进行 Leapp 操作之前,请务必先查看
在从 7 到 8 进行 Leapp 操作之前,您需要检查以下几点:
-
请确保您有一个可靠的备份。如果情况不顺利,系统快照最为有效。
-
如果 Secure Boot 正在运行,请使用
mokutil --sb-state禁用它。您可以通过运行bootctlstatus命令检查其状态。 -
请确保您有控制台访问权限,以防需要排查问题。
-
禁用任何网络挂载,例如 NFS 挂载、Samba 挂载、GlusterFS 挂载等。请在
/etc/fstab文件中禁用它们。 -
如果您使用
yum-plugin-versionlock,请使用yum versionlockclear命令清除任何锁定。 -
如果您正在运行任何 KVM 虚拟机,请停止它们。您可以使用
virsh shutdown $VM_NAME命令完成此操作。如果不确定是否运行任何虚拟机,您可以通过virsh list --all命令列出所有虚拟机。 -
如果您使用 Spacewalk、Oracle Linux Manager、Unbreakable Linux Network 或任何其他集中式 yum 管理器,请将系统从中注销。您必须使用
yum.oracle.com仓库进行 Leapp 操作。 -
如果您需要通过 HTTP 代理访问
yum.oracle.com仓库,请确保它已添加到您的/etc/yum.conf文件中。 -
验证你是否在
/etc/locale.conf中使用了en_US.UTF-8。你可以通过localectl set-locale LANG=en_US.UTF-8命令切换。 -
在你的
/etc/ssh/sshd_config文件中,验证是否可以以 root 用户登录。配置文件中应该有PermitRootLogin yes。
一旦你验证了这个列表,使用yum update -y通过yum.oracle.com对你的系统进行补丁更新,然后重启。
最后,你可以通过以下命令添加Leapp仓库:
yum install -y leapp --enablerepo=ol7_leapp,ol7_latest
接下来,再次进行一次重启,并可能做第二次备份。重启后,如果你使用代理来访问它们,那么你需要在/etc/yum.repos.d/leapp-upgrade-repos-ol8.repo的每个仓库条目中添加代理服务器。你可以使用简单的sed命令来完成:sed -I '/^enabled=0.*/a proxy=http://proxy-host:proxy-port' /etc/yum.repos.d/eap-upgrade-repos-ol8.repo。
恭喜,你现在已经准备好分析系统了!
如何操作…
你需要执行以下步骤:
-
如果你不在 Oracle 云(OCI)上运行,可以通过以下命令运行报告:
leapp preupgrade --oraclelinux -
如果你在 OCI 上,运行以下命令:
leapp preupgrade --oci这两个命令将执行多个检查,并在发现重大问题时发出警告。但你需要深入分析这些问题:

图 1.16 – Leapp 升级前结果
-
现在,你应该会看到一些有趣的输出。
/var/log/leapp/leapp-report.txt文件会标识出升级过程中的任何风险。风险按三种等级分类,最高等级为致命错误。处理任何风险,重新运行分析工具,并再次检查报告。一旦你对结果满意,就可以继续操作。 -
下一步是查看
/var/log/leapp/answerfile文件。该文件包含 Leapp 在系统上执行的具体检查。每个检查都包含关于系统的信息,并提示你确认要执行的操作:

图 1.17 – Leapp 答案文件
在这个例子中,只有一个回答需要确认。要接受文件中的项目,请在该部分添加confirm = True。你也可以选择使用leapp命令来确认该行项,确保该部分匹配:
leapp answer --section remove_pam_pkcs11_module_check.confirm=true
现在是时候进行 Leapp 并开始第二阶段了
现在我们已经准备好了,是时候向前迈进了!与Leapp 升级前一样,OCI 中的 Leapp 操作与其他环境略有不同:
- 对于非 OCI 环境(如以下截图所示),运行
leapp upgrade --oraclelinux。对于 OCI 环境,运行leapp upgrade --oci:

图 1.18 – Leapp 升级开始
- Leapp 将需要一些时间。你记得做备份了吗?当 Leapp 运行时,它将下载所有 Oracle Linux 8 软件包,小型系统大约下载 600MB,较大的安装则为 1GB:

图 1.19 – Leapp 升级完成
当 Leapp 过程完成后(如上图所示),请重启。
它是如何工作的……
Leapp 执行就地升级,安装或升级新的 RPM 包,并重新配置启动加载程序为升级后的操作系统版本。此过程会升级 Oracle Linux 支持的应用程序,并将配置和偏好迁移到新版本。
还有更多内容……
当你完成重启后,你应该看到/etc/oracle-release更新为 Oracle Linux 8。你也可以使用uname -r检查内核版本。升级后,你还需要完成其他一些任务:
-
如果你禁用了安全启动,你需要在系统固件中重新启用它。
-
重新启用防火墙,因为在升级过程中它被禁用了:
sytemctl start firewalld setenforce enforcing command to do this. You can also check the current state of SELinux with the getenforce command. -
如果你有运行中的 KVM 虚拟机,你需要使用
virsh start $``VMNAME命令重新启动它们。 -
你可以删除
/root/tmp_leapp_py3目录。这是可选的,但可以释放磁盘空间。 -
你可以将系统重新连接到正常的补丁和管理系统。这些系统应该被重新添加为 Oracle Linux 8 系统。请验证你的管理软件是否反映了新版本;并非所有管理系统都会正确更新主版本。
从 CentOS 迁移到 Oracle Linux
第一个问题是为什么? 为什么我们要讨论从CentOS迁移到 Oracle Linux?
在解释这个问题之前,让我们先聊聊 IBM Red Hat 在 2020 年 12 月 8 日给 Linux 社区带来的惊喜。我们所熟知的 CentOS 已经死亡!它已经> /``dev/null了。
2020 年 12 月 8 日,CentOS(由 IBM Red Hat 控制)发布了新闻:“CentOS Linux 8,作为 RHEL 8 的重建版,将于 2021 年底结束。”2021 年的日期比原计划提前了八年,原定于 2029 年结束 CentOS 8 版本的开发。这意味着,如果你使用 CentOS 8 并希望继续使用稳定且可预测的版本,那么你需要进行更改。
CentOS 团队正在“将焦点从 CentOS Linux,即 Red Hat Enterprise Linux(RHEL)的重建,转向 CentOS Stream,它紧跟当前 RHEL 发布的前沿。”记得 Fedora 吗?新技术不断引入和撤回,变化是常态并且是预期的?这基本上就是社区对 CentOS Stream 的看法。这个改变基本上摧毁了企业系统管理员在生产环境中使用 CentOS 8 及以后版本的能力,以及开发、测试和质量保证(QA)环境的使用。
那么,接下来是什么? 已经有几个项目分叉或克隆了 CentOS 的模型,复制该工作并提供一个稳定的发行版,跟踪 RHEL,拥有可预测的发布计划和稳定的组织来支持项目。你应该关心的一个问题是,如何选择正确的项目。你无法预知哪些新发行版会成功或失败。这些分叉可能需要多年才能稳定,而用户现在就需要一个解决方案。作为管理员,你不需要一个可能会改变方向的分叉或不成熟的发行版。你需要的是一个稳定的发行版,其目标是保持与 RHEL 的兼容性。Oracle Linux 提供了两者:经验证的稳定性,并通过开放企业 Linux 协会(OpenELA.org)积极投资保持与 RHEL 的兼容性。
OpenELA 由 Oracle、SUSE 和 CIQ(RockyLinux 背后的公司)共同创建。OpenELA 是一个行业协会,致力于构建一个兼容的代码库,作为 RHEL 的替代品。这使得开源社区能够合力证明 CentOS 的稳定替代品。
CentOS 如我们所知已经不存在了,你有考虑过 Oracle Linux 吗?
Oracle Linux 追踪 RHEL,今后将 OpenELA 作为其基础代码,因此 Oracle Linux 8.3 基本上与 RHEL 8.3、CentOS 8.3 甚至 RockyLinux 8.3 相同。它被超过 86%的《财富》全球 100 强公司使用,成为企业中最受欢迎的 Linux 选项之一。由于 Oracle 在其业务和 Oracle Cloud 中使用 Oracle Linux,你可以放心,它将得到支持,不管 IBM Red Hat 对用户施加了什么新变化。
我提到过 Oracle Linux 是免费的么?它是免费下载的,免费分发的,免费打补丁的!如果你要分发,我可以免费提供一份副本,不需要律师。如果要打补丁,系统也无需注册或支付任何费用,而且下载也是免费的。获取它不需要支付许可费用!
是的,Oracle 提供了一个付费支持服务,比 RHEL 便宜得多,而且由于免费下载和打补丁的免费模式,你可以在非生产系统中免费使用 Oracle Linux,同时在生产系统上使用付费支持,且两者都使用同一个发行版。它也非常稳定,自 2006 年起就已经推出了。如今他们还支持 Arm 架构(有人需要 Raspberry Pi 吗?),并且有多个公共镜像站点供你下载,如果你不想从yum.oracle.com/oracle-linux-isos.html下载。
如果你为支持付费,你可以获得一些非常酷的功能,但这些功能远远超出了 RHEL 提供的支持范围。包括以下几项技术:
-
Ksplice:这项技术允许你在运行时对内核和用户空间库进行补丁更新
-
DTrace:这项技术源自 Solaris,能够为你提供内核和应用程序内部的实时视图
-
企业管理器:用于管理和监控操作系统、日志等
如果你正在使用 CentOS,迁移到 Oracle Linux 非常简单。最棒的是,迁移后你能保持一切不变,这样所有应用程序都会继续运行。记住,Oracle Linux 跟踪 RHEL,是一个简单的替代品。Oracle 将迁移脚本免费提供给任何人使用,你可以从以下 GitHub URL 获取: github.com/oracle/centos2ol。
准备工作
在开始之前,你需要一台运行 Scientific Linux 7.x 和 8.x、Rocky 8.x、CentOS 7.x 和 8.x 的系统。如果你的 CentOS 系统是 CentOS Stream,脚本将无法工作。运行 Oracle 脚本之前还有一些其他事项需要考虑,如下所示:
-
确保你有可靠的备份。如果系统出现问题,快照是最好的选择。
-
如果启用了 Secure Boot,请使用
mokutil --sb-state禁用它。你可以通过运行bootctlstatus命令来检查状态。 -
确保你有控制台访问权限,以防需要排查问题。
-
禁用任何网络挂载,例如 NFS 挂载、Samba 挂载和 GlusterFS 挂载。在
/etc/fstab文件中禁用它们。 -
如果你使用
yum-plugin-versionlock,请使用yum versionlockclear命令清除任何锁定。 -
如果你正在运行 任何 KVM 虚拟机,请停止它们。你可以使用
virsh shutdown $VM_NAME=来做到这一点。如果你不确定是否正在运行虚拟机,可以通过运行virsh list --all命令来列出所有虚拟机。 -
如果你使用的是 Spacewalk、Oracle Linux Manager、Unbreakable Linux Network 或其他集中式的 yum 管理器,请确保
yum命令能够正常工作。与 Leapp 不同,你可以针对私有仓库运行该脚本。 -
如果你需要一个 HTTP 代理来访问你的 yum 服务器,请确保它已经添加到
/etc/yum.conf文件中。 -
如果你使用任何第三方 yum 仓库,请确认它们的包不会与正在运行的内容冲突。在进行切换时,最好禁用这些仓库。
-
检查过时的仓库。如果仓库无法正常工作,禁用它。
-
确保
/var/cache目录中至少有 5 GB 的可用空间。 -
禁用所有自动 yum 更新。
如何操作…
现在你已经检查并准备好系统进行从 CentOS 的迁移,实际从 CentOS 8.x 的迁移非常简单。你现在需要按照以下步骤进行:
-
升级的简便方法是使用
wget从 GitHub 下载原始脚本文件:raw.githubusercontent.com/oracle/centos2ol/main/centos2ol.sh。 -
接下来,你需要执行
chmod +x操作,使脚本具备执行权限,命令如下:chmod +x centos2ol.sh -
还记得 CentOS 8 早早就停止支持了吗?这也意味着 CentOS 8 的 yum 仓库 已经不再可用。不过,还是有解决这个小问题的办法。现在,你可以使用位于 vault.centos.org 的一个副本,但每个仓库文件需要更新。这可以通过以下命令完成:
./centos2ol.sh:

图 1.20 – 从 CentOS 迁移到 Oracle Linux 过程开始
在一个速度为 1GB/s 的快速系统上,这个过程大约会持续 5 分钟。其他系统可能需要长达 45 分钟。当脚本完成时,重启系统。和 Leapp 一样,你可以通过查看/etc/oracle-release以及使用uname -r检查内核版本来确认升级是否完成:

图 1.21 – 从 CentOS 8 迁移完成
一旦重启完成并且服务器启动,/etc/oracle-release应该正确显示 Oracle Linux。
工作原理……
这个脚本会将你的系统连接到新的补丁仓库,然后基本上执行一个针对 Oracle 仓库的扩展补丁过程。旧的 RPM 包会被 Oracle 的 RPM 包替换。这个脚本还可以将你从旧的 Linux 4.x 内核升级到 UEK,届时你将能享受到更高性能的 Linux 5 内核的优势。
第二章:使用与不使用自动化魔法进行安装
虽然你可以从 USB 或 ISO 镜像手动安装 Oracle Linux,但在企业级别上,更常见的是自动化安装。本章最后的附录 – kickstart 选项涵盖了手动安装,适合偶尔需要安装的情况。
大多数数据中心安装使用自动化方法,因为这样可以快速扩展。
本章提供了不同的方案,帮助构建一个可操作的预启动执行(PXE;发音为pixie)系统。
PXE 启动是由英特尔开发的一项技术。它允许具有适当 ISO(或操作系统 RPM 包)的系统从网络启动,下载服务器上的所有必需文件。虽然存在更旧的方法,如引导协议(BOOTP),但行业已经迅速采用PXE 启动作为最常见的标准。虽然 PXE 启动最初是为英特尔系统设计的,但 ARM 系统也可以使用 TFTP 进行启动。为了使 PXE 启动过程正常工作,通常需要在网络上配置 DHCP 服务器和 PXE 服务器。该过程的高级概述可以通过以下图表看到:

图 2.1 – PXE 启动过程
以下是每个步骤的高级描述:
-
PXE 客户端将从可用的DHCP 服务器请求 IP 地址。
-
网络上第一个响应客户端的 DHCP 服务器将为其提供 IP 地址、网络掩码、DNS 信息、默认路由和其他所需的网络参数。
-
PXE 客户端将进行启动服务发现,查找PXE 服务器。可选地,DHCP 服务器可以配置为指向 PXE 服务器以进行启动。
-
PXE 服务器将网络引导程序和文件下载位置的 IP 信息发送给客户端。这使得客户端可以从网络启动,安装操作系统。
-
PXE 客户端根据需要从HTTPS 服务器请求媒体(RPM 包和控制文件)。HTTPS 并不是唯一需要的协议;NFS 和 FTP 服务器也可以使用,尽管 HTTPS 是最常见的方法。PXE 系统还通过 kickstart 文件将kickstart参数发送给客户端。这些参数包含配置系统存储、网络和要安装的软件包的具体信息。
-
媒体服务器将请求的文件发送到 PXE 客户端,从而允许操作系统安装。
在本示例中配置 PXE 服务器时,需要三个组件:
-
DHCP 服务器:它不仅为服务器分配 IP 地址,还分配启动时所需的重要参数,支持 PXE 启动。
-
简易文件传输协议守护进程(TFTPD):该服务作为 TFTP 服务器工作,允许客户端运行启动加载程序,从而启动操作系统安装。
-
超文本传输协议守护进程(HTTPD):这是一个 Web 服务器,用于托管安装所需的配置文件和 RPM 包。
注意
还有一些其他选项,例如使用 dnsmasq 作为一个结合的服务器,它同时充当 DHCP 服务器、TFTP 服务器(最常见的是 TFTPD)和 DNS 转发器。然而,在许多企业环境中,往往需要单独的系统。例如,网络中可能已经使用了 Microsoft DHCP 服务器。
在这个例子中,有两台逻辑服务器运行着三个不同的服务,第一台系统上运行 DHCP 服务器和 TFTP 服务器。第二台系统是 PXE 服务器,也将作为 HTTP 服务器,负责提供 Red Hat 包管理器(RPM)文件和安装所需的控制文件。两台系统都是多网卡的,并将在它们的辅助接口上运行 DHCP 和 PXE。系统还在辅助接口上设置了静态 IP 地址。
本章将涵盖以下主要食谱,这些组成了 PXE 的盛宴:
-
使用 kickstart 自动化操作系统安装选项
-
DHCP 服务器 – 不仅仅是 IP
-
设置 Web 服务器 – HTTPD
-
启动服务 – TFTPD
-
回顾过去 – 手动安装
注意
多网卡服务器是指同时连接多个网络的系统。这通常在企业数据中心中进行,用以隔离系统,同时允许一些受控系统传递数据。也可以在单一网络上设置 PXE 服务器。
技术要求
创建新的 kickstart 文件的简单方法是通过构建一个新的操作系统,因为此过程会自动创建文件,之后可以根据需要进行修改。PXE 环境还需要额外的系统或虚拟机来充当 DHCP 服务器和 HTTPS 服务器。开始之前,首先需要下载 ISO 镜像。推荐使用如 Oracle VM VirtualBox 之类的桌面虚拟化产品。
本书中许多食谱的相关配置文件可以在 GitHub 上找到,网址为 github.com/PacktPublishing/Oracle-Linux-Cookbook。
使用 kickstart 自动化操作系统安装选项
Kickstart 文件是自动化安装过程中的重要组成部分。该文件包含自动安装和配置操作系统所需的所有信息。Kickstart 文件是一个简单的文本文件,包含了实现无人值守安装的指令。
准备工作
要使用 kickstart 文件,您需要一个地方来构建系统,例如 Oracle VM VirtualBox。该系统可用于创建您的第一个 kickstart 文件,也可以在将其移入 PXE 环境之前测试新创建的 kickstart 文件。
注意
Anaconda 是 Oracle Linux 安装程序。它可以通过使用 kickstart 文件进行自动化安装,或者通过图形界面或文本安装界面进行交互式操作。
如何操作……
虽然你可以手动创建一个文件,但从 Anaconda 在安装过程中创建的文件开始会更加容易。这个 kickstart 文件在手动安装时自动创建,并保存在新系统的 /root/anaconda-ks.cfg 中。这个文件可以很容易地编辑并用于未来的构建。我们通过将文件分解为更小的部分来查看它。这个系统是图形安装。其他选项包括文本或命令行:
注
kickstart 有许多选项,详见附录 – kickstart 选项。
#version=OL8
# Use graphical install
graphical
用于安装 Oracle Linux 的仓库是从 ISO 文件以环回挂载的目录。baseurl 也可以是 HTTPS 服务器、NFS 位置或 FTP 服务器。例如,--baseurl=https://pxe.m57.local/ol8 将告诉 kickstart 从 Web 服务器中提取 RPM 包:
repo --name="AppStream" --baseurl=file:///run/install/sources/mount-0000-cdrom/AppStream
软件包是所选的软件包。以 @ 符号开头的名称是包组,没有 @ 的行是单独的软件包。此外,^ 符号用于仅启用安装包组中所需的包。如果没有设置 ^,则包组中的所有包都会被安装。在此示例中,安装了 graphical-server-environment 包组 RPM 和 kexec-tools 包:
%packages
@^graphical-server-environment
kexec-tools
%end
这是选择默认键盘和语言的地方:
# Keyboard layouts
keyboard --xlayouts='us'
# System language
lang en_US.UTF-8
这是新服务器的主机名。理想情况下,它应该是系统的完全限定域名(FQDN):
# Network information
network --hostname=ol802.lab.m57.local
用于选择一个 CD-ROM 或挂载在文件系统上的 CD-ROM 作为安装介质:
# Use CDROM installation media
cdrom
用于在第一次启动时运行设置代理:
# Run the Setup Agent on first boot
firstboot --enable
在这里,选择了安装磁盘,以及逻辑卷管理器和文件系统的配置:
ignoredisk --only-use=sda
# Partition clearing information
clearpart --none --initlabel
# Disk partitioning information
part /boot --fstype="xfs" --ondisk=sda --size=1024
part pv.116 --fstype="lvmpv" --ondisk=sda --size=80868
volgroup ol --pesize=4096 pv.116
logvol /home --fstype="xfs" --size=5120 --name=home --vgname=ol
logvol / --fstype="xfs" --size=51200 --name=root --vgname=ol
logvol /u01 --fstype="xfs" --size=10240 --name=u01 --vgname=ol
logvol /var --fstype="xfs" --size=5120 --name=var --vgname=ol
logvol swap --fstype="swap" --size=4056 --name=swap --vgname=ol
logvol /var/log --fstype="xfs" --size=5120 --name=var_log --vgname=ol
这是服务器的时区:
# System timezone
timezone America/New_York --isUtc
可以为新系统设置加密的 root 密码。通常,密码是加密的,但你也可以选择使用 --plaintext 选项设置明文密码。你也可以通过运行 python3 -c 'import crypt,getpass;pw=getpass.getpass();print(crypt.crypt(pw) if (pw==getpass.getpass("Confirm: ")) else exit())' Python 命令生成加密密码:
# Root password
rootpw --iscrypted $6$W5fC.GDUSIVXPDS7$zQFm49tGCtRbfyAd/0f57QcuPZYtOB/gobgN2oKNG
zqrseiNtm7QqkthCcdiNxGJhzLSIQpNyxRQXEPJPuaYM.
启用 kdump,允许内核将崩溃转储保存到设备中以供故障排除:
%addon com_redhat_kdump --enable --reserve-mb='auto'
%end
这是 root、用户和 Linux 统一密钥设置(LUKS)密码策略:
%anaconda
pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty
pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok
pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty
%end
你可以根据需要编辑文件。在使用新文件之前,可以通过 ksvalidator 命令进行测试。该命令是 pykickstart 包的一部分,可通过 dnf install -y pykickstart 安装。
软件包安装完成后,运行 ksvalidator $FILE 测试新的 kickstart 文件。带有错误的示例将如下所示,其中第 3 行将安装定义为 xgraphical,这是一个未知选项:
[root@localhost ~]# ksvalidator anaconda-ks.cfg
The following problem occurred on line 3 of the kickstart file:
Unknown command: xgraphical
解决错误并重新运行验证。在此示例中,graphical 是正确的参数。清理后的验证返回空值,结果如下:

图 2.2 – 清理 ksvalidator
Kickstart 选项!
现在你对 Kickstart 文件有了基本的了解,可以开始添加新选项。这些选项可以帮助你自动化安装过程,并且让你拥有更多控制权。选项详细介绍请参见附录 – kickstart 选项。
它是如何工作的……
你可以通过手动添加ks参数到ks=PATH_TO_FILE,启动任何系统,其中PATH_TO_FILE是 Kickstart 文件的 URL 路径。通常,这个文件放在 HTTP 服务器上,客户端可以访问。
DHCP 服务器 – 不仅仅是分配 IP
DHCP 服务器将运行一个标准的 DHCP 服务器,该服务器可以在 Oracle Linux 8 中使用。DHCP 的安装非常简单。
准备工作
要设置 DHCP 服务器,你需要一台运行 Oracle Linux 8 的虚拟机,并且它需要与将要安装的虚拟机处于同一子网。
如何操作……
使用dnf install -y dhcp-sever命令安装 DHCP 服务器。以下截图展示了完整的过程:

图 2.3 – DHCP 服务器安装
安装完成后,通过防火墙启用 DHCP 流量(如下面截图所示),使用firewall-cmd --add-service=dhcp --permanent和firewall-cmd --reload命令:

图 2.4 – DHCP 防火墙命令
DHCP 服务器在/usr/share/doc/dhcp-server目录下有一个示例的 DHCP 配置文件。这个文件包含 IPv4 的示例配置/usr/share/doc/dhcp-server/dhcpd.conf.example和 IPv6 的示例配置/usr/share/doc/dhcp-server/dhcpd6.conf.example。对于这个 DHCP 服务器,我们将使用 IPv4,并将示例配置文件复制到/etc/dhcp/dhcpd.conf。该目录下已有一个配置文件,但默认情况下它几乎是空的,没有任何配置,可以按照以下截图进行替换:

图 2.5 – 复制 dhcp.conf
接下来,需要更新配置文件,修改 IP 地址范围,并且通过option ntp-servers 192.168.200.1选项将 NTP 服务器添加到配置中,该选项将 NTP 服务器设置为192.168.200.1。虽然配置 NTP 服务器是可选的,但强烈推荐这么做。此外,当 PXE 服务器不是DHCP 服务器时,你需要在子网中添加“next server”参数,这将指示 DHCP 客户端从 PXE 服务器的 TFTP 进行启动。
注意
如果你正在使用现有的 DHCP 服务器,请确保添加next-server参数,指向包含 TFTP 服务器的 PXE 服务器。
由于 TFTP 服务器在 PXE 服务器上运行,因此 DHCP 服务器需要将“next server”选项设置为 PXE 服务器的 IP 地址。以下是一个完整的示例配置文件:
# dhcpd.conf
#
# These options are common to all networks
option domain-name "lab.m57.local";
option domain-name-servers 192.168.56.10;
default-lease-time 600;
max-lease-time 7200;
# If the DHCP server is the main server for the network, this should be set authoritative;
# This sets where logs are sent. By default they are sent to syslog. You can reconfigure sysylog to send to a different location as needed.
log-facility local7;
subnet 192.168.56.0 netmask 255.255.255.0 {
range dynamic-bootp 192.168.56.100 192.168.56.150 ;
option broadcast-address 192.168.56.255;
option routers 192.168.56.1;
option domain-name-servers 192.168.56.10 ;
option domain-name "lab.m57.local";
option ntp-servers 192.168.200.1;
next-server pxe.lab.m57.local;
}
# Hosts which require special configuration options can be listed here, with the host details. This could be used to hard-code an IP address to a host, or define host-specific parameters like a non-0standard vmunix filename or a fixed IP address.
host fixedhost {
hardware ethernet 0:0:aa:bb:cc:dd;
filename "vmunix.fixedhost";
server-name "fixedhost.m57.local;
}
# When using a fixed IP address, it is more common to assign the host an IP address outside of the DHCP managed IP address range. set.
host fantasia {
hardware ethernet 08:01:02:03:04:05;
fixed-address fixedhost2.m57.local;
}
接下来,我们需要测试 DHCP 服务器。为此,使用dnf install -y nmap命令安装nmap程序。
Nmap 是一个功能强大的工具,可以用于许多用途。它最为人知的是作为端口扫描工具,允许用户扫描网络,寻找响应 ping 的服务器,使用命令 nmap -sP 192.168.200.1/28,如下所示:

图 2.6 – Nmap ping 扫描
它还可以用于识别特定服务器的操作系统和开放端口,使用 nmap 192.168.200.34 -O 命令:

图 2.7 – Nmap ID 服务器
虽然 Nmap 是一个强大的网络扫描工具,但它也可以用于许多额外的任务,包括检查 DHCP 服务器是否正确响应。这可以通过 broadcast-dhcp-discover 脚本实现,并通过 nmnap ––script 选项使用。此外,如果你的系统有多个接口,可以使用 -e 选项指定扫描所使用的网络接口。在这个环境中,DHCP 服务器通过 nmap --script broadcast-dhcp-discover -e enp0s8 命令进行验证:

图 2.8 – Nmap DHCP 发现
我们现在已经了解了 DHCP 服务器的工作原理,接下来是 Apache HTTPD 服务器。
设置 web 服务器 – HTTPD
PXE 服务器的下一步是安装 web 服务器。在本例中,我们将使用 Apache。其他 web 服务器也可以使用,但 Apache 是最常见的之一。
准备工作
要设置一个 HTTP 服务器,你需要在环境中运行一个 Oracle Linux 8 虚拟机。服务器的 IP 地址应能路由到虚拟机使用的子网,并且防火墙端口应允许 HTTP/HTTPS 流量。理想情况下,你还应有足够的空间存储多个 ISO 文件。通常,20-30 GB 的数据空间就足够了。
如何操作…
启动 Apache HTTPD 服务器的安装很简单;只需运行 yum install -``y httpd。
一旦安装了 web 服务器,将完整的 ISO 文件复制到服务器的任意目录。在我们的示例中,OracleLinux-R8-U5-x86_64-dvd.iso 被复制到 /root 目录,如 图 2.9 所示。

图 2.9 – Oracle Linux ISO 位于 /root 目录
下一步是将 ISO 文件挂载到 docroot 目录下。对于 Apache 的标准安装,docroot 位于 /var/www/html,因此创建了一个名为 OL8 的目录。当 ISO 挂载后,使用回环挂载方法会更高效。这使得 ISO 文件可以作为普通文件系统挂载。接下来,使用回环挂载方法,将 ISO 文件挂载到 /var/www/html/OL8 作为挂载点,使用以下命令:
mount -o ro,loop /root/OracleLinux-R8-U5-x86_64-dvd.iso /var/www/html/OL8
挂载后,使用 df 命令可以显示挂载的文件系统。整个命令链可以在以下截图中看到,图 2.10。

图 2.10 – ISO 已挂载
现在文件系统已挂载,我们来打开防火墙中的 80 和 443 端口。可以通过 firewall-cmd 命令轻松完成,添加 http 和 https 端口,并将其作为永久更改保存到防火墙中。一旦端口打开,防火墙规则将被重新加载。以下三个命令执行这些任务:
firewall-cmd --add-service=http --permanent
firewall-cmd --add-service=https --permanent
firewall-cmd --reload
现在防火墙已打开,Apache 已安装,并且 ISO 已通过环回设备挂载,我们可以通过 systemctl start httpd 命令启动 Apache 服务器。
你可以通过将浏览器指向服务器的 IP 地址和 OL8 目录来验证一切是否按预期工作,如下截图所示。这将显示 ISO 的内容,包括发布说明和 BaseOS 目录下的 RPM 文件,如 图 2.11 所示。

图 2.11 – 可通过 httpd 访问的 ISO 文件
启动服务 – TFTPD
TFTP 用于通过网络传输简单文件。它最常用于加载操作系统的初始引导程序,或嵌入式设备和旧硬件的固件更新。在 PXE 服务器的上下文中,TFTP 系统用于初始引导程序。
准备工作
要设置 TFTP 服务器,你需要在你的环境中运行一个 Oracle Linux 8 虚拟机。服务器应与正在构建的系统使用相同的网络子网。理想情况下,你还应有足够的空间来存放几个引导文件。通常,5 GB 的数据空间就足够了。
如何操作…
安装 TFTP 很简单。运行 dnf install -y tftp-server 命令,如 图 2.12 所示。

图 2.12 – TFTP 安装
安装完成后,我们需要为 TFTP 打开防火墙并重新加载它:
firewall-cmd --add-service=tftp --permanent
firewall-cmd --reload
这些命令的输出如以下截图所示:

图 2.13 – TFTP 防火墙
安装和打开防火墙后,我们需要通过安装引导程序、准备 Oracle Linux 8 TFTP 位置并创建启动菜单来准备系统。
注意
本示例使用的是基于 BIOS 的主机。如果你想使用 UEFI 主机,你需要安装 grub2-efi 并配置 UEFI 特定的参数。Oracle 文档可以在 docs.oracle.com/en/operating-systems/oracle-linux/8/install/install-CreatingaNetworkInstallationSetup.html#uefi-clients 找到。
为了安装 BIOS 安装的引导程序,我们将安装 syslinux 包。syslinux 包包括用于网络启动的引导程序(PXELINUX)、Linux(ext2/ext3/ext4)或 btrfs 文件系统(EXTLINUX)、MS-DOS FAT 文件系统(SYSLINUX)和可启动的 El Torito CD-ROM(ISOLINUX)。对于网络启动,我们将使用 PXELINUX:

图 2.14 – Syslinux 安装
接下来,我们将复制启动镜像文件 pxelinux.0,并将文件复制到 /var/lib/tftpboot:
cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/
然后,我们将在 tftpboot 目录下创建一个 Oracle Linux 8 启动目录:
mkdir /var/lib/tftpboot/ol8
现在,我们需要将之前挂载的 ISO 文件中的 PXE 启动文件复制到新的 Oracle Linux 8 启动目录:
cp /var/www/html/OL8/images/pxeboot/* /var/lib/tftpboot/ol8/
接下来,我们需要一个启动菜单。幸运的是,我们可以复制示例并快速启动。我们只需要菜单文件,因此使用以下命令复制文件就能顺利进行:
cp -v /usr/share/syslinux/{ldlinux.c32,libcom32.c32,libutil.c32,menu.c32,vesamenu.c32} /var/lib/tftpboot/
快完成了。为了创建一个 PXS 配置文件目录并构建默认菜单,请使用以下命令:
mkdir /var/lib/tftpboot/pxelinux.cfg
我们最终可以安装一个配置文件。将这个示例配置文件复制到 /var/lib/tftpboot/pxelinux.cfg/default:
default linux-auto
prompt 1
timeout 60
display boot.msg
label linux-auto
menu label ^Install OL8 in Graphical Mode using the kickstart file
menu default
kernel ol8/vmlinuz
append initrd=ol8/initrd.img ip=dhcp inst.repo=http://pxe.lab.m57.local/ol8 ks=http://pxe.lab.m57.local/ks_files/ol8ks.cfg
label linux-manual
menu label ^Install OL8 in Graphical Mode with manual input
menu default
kernel ol8/vmlinuz
append initrd=ol8/initrd.img ip=dhcp inst.repo=http://pxe.lab.m57.local/ol8
label rescue
menu label ^Rescue installed system
kernel ol8/vmlinuz
append initrd=ol8/initrd.img rescue
label local
menu label Boot from ^local drive
localboot 0xffff
在这个示例中,默认安装将是 linux-auto,它将在 60 秒内自动启动,除非用户手动选择以下选项之一:
-
linux-auto:这是默认选项,将使用 kickstart 参数安装 Oracle Linux -
linux-manual:这将启动一个传统的 Oracle Linux 安装,提示用户手动选择 Anaconda 中的所有选项 -
rescue:这将以救援模式启动 -
local:这将从现有的本地磁盘启动
你可以根据需要轻松修改菜单,以满足你的具体需求。虽然 PXE 启动一开始可能让人感到棘手,但它提供了一个强大的工具来管理你的 Linux 安装。
它是如何工作的…
当系统启动时,它们会根据 DHCP 服务器的配置加载引导加载程序。然后,系统将从 TFTP 服务器启动,开始 PXE 过程。
曾几何时——手动安装
自动化安装很棒,但对于一些管理员来说,配置和维护支持自动化安装的基础设施的复杂性比手动安装更费力。这个指南将介绍手动安装的过程。
准备工作
为此,你需要一个安装源。在这个示例中,将使用 Oracle VM VirtualBox,但同样可以在裸机服务器或其他虚拟化平台上进行。你还需要安装介质。通常,ISO 文件就可以正常工作,但你也可以使用启动 ISO 文件和 HTTP 服务器、FTP 服务器,甚至是网络文件共享。
如何操作…
无论你是从 ISO、USB 驱动器,还是通过设置图形化安装选项的 kickstart 文件启动,过程都是一样的!
如果你是从仅有启动功能的镜像启动,你需要启用网络,并指向一个安装源。接下来的步骤将展示如何操作。如果你是从 ISO 或 USB 安装,跳到 它是如何 工作的… 部分:
- 当从启动镜像启动时,你需要选择安装 Oracle Linux X来开始安装过程。尽可能使用最新版的 Oracle Linux。在安装过程中,你会看到第一个屏幕,你可以选择测试启动镜像或继续:

图 2.15 – Linux 安装程序启动
- 接下来,选择你的语言:

图 2.16 – 安装语言
- 选择你的语言后,点击继续。接下来,你应该会看到安装 总结部分:

图 2.17 – 安装总结
目前,我们需要完成两个任务:
-
启用网络
-
设置安装源为 Oracle 的 yum 仓库
要启用网络,点击网络与主机名选项。
- 在这里,你需要开启以太网,并更新主机名为服务器名称。网络将自动使用 DHCP 配置启动镜像。你也可以选择手动配置 IP 堆栈,点击配置选项。

图 2.18 – 网络与主机名
- 接下来,点击应用,然后点击完成。这将带你回到安装总结页面。接下来,我们需要选择安装源来设置安装文件的位置。

图 2.19 – 安装源
在这个示例中,我们使用 Oracle 公共 YUM 服务器作为安装源。你可以根据需要选择性地添加其他仓库,以及在需要时设置代理设置。你也可以为 NFS 服务器路径设置 FTP:// 补丁。一旦你设置了路径,点击完成。
- 这将带你回到安装总结页面。等待几分钟以加载仓库索引。加载完成后,你应该能看到安装源选项,以及软件选择选项。

图 2.20 – 选择安装源
手动网络启动与 ISO 或 USB 启动基本相同。
它的工作方式……
手动启动过程相对简单。一旦启动,在安装总结屏幕上,你有许多选项:
-
本地化:在这里你可以设置与国家相关的选项,如语言、键盘类型、时间等:
-
键盘:这让你可以设置使用的键盘类型。你可以使用非美国键盘。
-
语言支持:这设置所使用的语言。
-
时间和日期:这设置系统时间,以及将用于自动同步时间的网络时间协议(NTP)服务器。
-
-
软件:这设置了软件源以及要安装的软件组或软件包:
-
安装源:这设置了安装的软件源和软件包
-
软件选择:此项设置将安装哪些软件组和包。
-
-
系统:这些是系统级参数:
-
安装目标:这是安装的目标位置,包括初始的文件系统布局。
-
KDUMP:这允许你设置 kdump,这是一个内核崩溃转储工具,将系统信息写入磁盘,以便稍后分析。
-
网络与主机名:在这里你可以设置主机名和网络信息。
-
安全策略:此项启用更安全的安装,允许你使用符合流行安全标准(如 STIG 和 PCI-DSS)要求的系统。
-
-
用户设置:在这里你可以设置用户、组和密码:
- 根密码:此项设置初始的 root 密码。
通常,首先设置的是网络。这对于网络安装以及设置 NTP 进行时间同步至关重要:
- 要设置网络,请选择网络与主机名:

图 2.21 – 设置主机名和 IP 信息
默认情况下,网络端口未启用,且主机名未设置。你可以手动设置主机名。设置主机名时,别忘了使用 FQDN。它应包括名称和域名。启用网络时,系统会自动获取 DHCP 的 IP 信息。如果你想手动配置此信息,请点击配置…:

图 2.22 – 访问手动网络设置
- 这将带你进入网络详细信息页面,你可以手动设置 MTU、IP 地址和其他与网卡相关的设置。如果需要,你也可以禁用 IPv6。

图 2.23 – 手动网络设置
- 网络设置完成后,你可以使用网络资源,如 NTP 服务器,同步时钟。为此,在时间和日期下,点击齿轮图标:

图 2.24 – 访问 NTP 设置
- 然后,你可以添加 NTP 服务器。默认情况下,使用公共服务器,但如果你运行本地 NTP 服务器,确保在此添加它们。

图 2.25 – NTP 设置
-
接下来,根据需要可以在安装源下添加其他软件源。在进行网络安装时,这项操作已经完成。
你还可以设置要安装的 RPM 组以及任何附加软件。这可以在软件选择下进行:

图 2.26 – 软件选择
-
在设置了基本环境并添加了任何附加软件之后,下一步是设置安装目标。你可以通过点击安装目标来完成这项工作。
从这里,你应该能看到系统可用的物理和逻辑驱动器。默认设置为将存储配置设置为自动,但我们可以通过选择自定义配置来探索一种不同的启动磁盘结构。一旦选择了自定义,点击完成按钮。

图 2.27 – 安装目标
- 从这里,你可以选择默认的卷管理策略,并手动创建新的布局。大多数系统将使用 LVM 安装,因为这使你能够在以后调整分区大小。

图 2.28 – 手动分区
别忘了点击完成并接受所有对布局的更改。
- 需要注意的是,如果你从基于 UEK 的安装启动,现在可以选择使用 Btrfs 作为根文件系统。

图 2.29 – Btrfs 分区
Btrfs 看起来会有些不同,因为系统将卷管理器和文件系统的角色结合成一个系统。这意味着在安装时,所有文件系统将显示出所有可用的空间。安装操作系统后,可以更新这些空间,并为每个需要限制的目录设置配额。有关详细信息,请参阅 第四章中的 Btrfs 配方。
你现在可以通过给 root 设置一个密码来完成这一步……但还有一个基本任务,那就是为系统应用安全政策。安全政策允许安装程序预先配置系统,以遵循设定的政策。这对于安装支持诸如 HIPPA、PCI DSS(用于信用卡处理)或 STIG(用于公共部门工作负载)等工作负载的系统非常有帮助。
- 要设置一个政策,请从安装总结中选择安全政策:

图 2.30 – 安全政策
- 一旦你知道要使用的政策,选择它并点击选择配置文件:

图 2.31 – 应用安全政策
现在你将看到政策以及所有正在对系统进行的更改的列表。你还会看到一些可能需要对文件系统布局进行更改的地方。像 STIG 这样的政策中就要求 /var 和 /var/log 必须是独立的文件系统。
完成后,从安装总结中点击开始安装以开始安装。
附录 – kickstart 选项
以下表格列出了控制安装的最常见选项及其语法:
| 选项名称 | authselect |
||
|---|---|---|---|
| 描述 | 它使用 authselect 命令配置系统的身份验证选项。authselect 选项与 authselect 命令相同,直接传递给该命令。 |
||
| 选项 | 查看authselect命令。 |
||
| 选项名称 | autostep |
||
| 描述 | 此选项不推荐用于生产环境。它更像是一个故障排除命令,使安装程序逐步显示每个屏幕,每个屏幕显示的时间较短。 | ||
| 选项 | --autoscreenshot 将自动截图每个安装屏幕。图像会在安装过程中存储在 /tmp/anaconda-screenshots/,安装完成后移动到 /root/anaconda-screenshots。这对于故障排除非常有帮助,因为如果您错过了必需的 kickstart 选项,安装未能自动运行,您将会看到缺少数据的屏幕,并可以手动输入缺失的配置数据。然后,点击继续时,屏幕会自动捕获您手动输入的数据。 |
||
| 选项名称 | cmdline |
||
| 描述 | 当使用此选项时,安装将在非交互式命令行模式下运行。Anaconda 的任何输入提示将停止安装。请确保先使用 autostep 选项进行测试。 |
||
| 选项 | 无 | ||
| 选项名称 | eula |
||
| 描述 | 如果使用此选项,则需要 –-agreed 选项。此选项允许您自动接受 最终用户许可协议(EULA)。使用此选项时,安装程序在系统第一次重启时将不会提示接受 EULA。这对于使用 PXE 启动作为自动扩展策略的一部分的环境非常有用。 |
||
| 选项 | --agreed 强制接受 EULA(最终用户许可协议),必须使用此选项。如果未使用该选项,EULA 参数将被忽略。 |
||
| 选项名称 | firewall |
||
| 描述 | 该选项配置已安装系统上的防火墙。 | ||
| 选项 |
-
--enabled或–enable是必需的。它启用或禁用防火墙。 -
--disabled或–disable是必需的。如果禁用,iptables规则将不会配置。 -
--trust设置受信网络设备,允许所有流量通过防火墙。要配置多个设备,请分别列出每个设备项,不使用逗号,例如–trust eth0 –``trust eth8。 -
--incoming添加以下每个标签以允许这些常见服务的入站流量:-
–``ssh -
–``smtp -
–``http -
–``ftp
-
-
--port=指定一个特定的端口以允许访问服务器。可以使用/etc/service中的端口来指定特定的端口:协议组合。多个端口之间使用逗号分隔。例如ldap:tcp, 1521:tcp。 -
--service=提供了一种简便的方法来启用特定服务,如 CUPS,或需要打开多个 UDP/TCP 端口的服务。这为打开这些端口提供了一种易于阅读的格式。 -
--use-system-defaults不配置防火墙。如果指定了其他选项,则它们将被忽略。
| |
| 选项名称 | firstboot |
||
|---|---|---|---|
| 描述 | 此选项可以禁用在系统启动时运行设置应用程序。如果启用,请确保已安装 initial-setup.rpm(如果需要图形界面,则为 initial-setup-gui.rpm)。此选项默认禁用。 |
||
| 选项 |
-
--enable或–enabled会在系统第一次启动时启动设置程序。 -
--disable或–disabled不会在系统第一次启动时启动设置程序。 -
--reconfig启用设置程序在启动时以重新配置模式启动。这使得可以设置网络配置、root 密码、时区、语言、鼠标和键盘选项,除了默认选项之外。
| | | | |
| 选项名称 | graphical |
||
|---|---|---|---|
| 描述 | 如果没有设置,graphical 命令是默认选项。安装将继续进行完全图形化安装。 |
||
| 选项 | --non-interactive 在完全非交互模式下执行安装。此模式将在需要用户交互时终止安装。 |
||
| 选项名称 | group |
||
| 描述 | 此选项在系统上创建一个用户组。 | ||
| 选项 |
-
--name=是必需的,并设置组的名称。 -
--gid=是一个可选参数,将设置组的 GID。
|
| 选项名称 | halt |
||
|---|---|---|---|
| 描述 | 如果使用,安装完成后系统将停止。这是默认的完成方法,如果没有设置其他方法。其他完成方法包括 poweroff、reboot 和 shutdown。 |
||
| 选项 | 无 | ||
| 选项名称 | logging |
||
| 描述 | 这对于故障排除 PXE 安装非常有用。它控制安装过程中安装程序的日志记录。它不会配置正在安装的系统的日志记录。 | ||
| 选项 |
-
--host=是 syslog 主机,日志会发送到该主机。 -
--port=是用于远程 syslog 主机的 syslog 端口。如果未设置,则使用默认端口(UDP 514)。 -
--level=指定发送到设备tty3的最小消息级别。无论此级别如何,所有消息仍会发送到日志主机和文件。有效值包括critical、debug、error、info和warning。
|
| 语法 | `logging [--host=host] [--port=port] [--level=critical | debug | error | info]` |
|---|---|---|---|---|
| 选项名称 | poweroff |
|||
| 描述 | 使用时,安装完成后会执行关机并关闭系统电源。 | |||
| 选项 | 无 | |||
| 选项名称 | reboot |
|||
| 描述 | 安装完成后重新启动系统。 | |||
| 选项 | --eject 在重新启动系统之前弹出可引导介质(DVD、USB 等)。 |
|||
| 选项名称 | repo |
|||
| 描述 | 启用额外的 DNF/YUM 仓库作为安装源。每个仓库需要单独的一行。 | |||
| 选项 |
-
--name=是必需的,它设置仓库的名称和 URL。如果名称与现有仓库冲突,将被忽略。格式为--name=repoid [--baseurl=url|--mirrorlist=url|--metalink=url] [options]。以下是可以添加到 URL 的附加选项。作为警告,yum 仓库配置文件中可以使用的变量不受支持。但是,你可以使用$releasever和$basearch:-
--baseurl:这是仓库的 URL -
--mirrorlist:这是仓库的镜像列表 -
--metalink:这是仓库的metalinkURL
-
-
--proxy=[protocol://][username[:password]@]host[:port]设置仓库的代理。 -
--noverifyssl禁用 HTTPS 服务器的 SSL 验证。
|
| 选项名称 | selinux |
||
|---|---|---|---|
| 描述 | 用于配置 selinux 的初始策略和状态。默认策略为强制执行。 |
||
| 选项 |
-
--enforcing启用 SELinux,并将策略设置为强制执行。这是默认设置。 -
--permissive启用 SELinux,并将策略设置为宽松。这允许警告输出到控制台的 syslog,但不强制执行策略。 -
--disabled禁用 SELinux。
|
| 选项名称 | shutdown |
||
|---|---|---|---|
| 描述 | 安装完成后,在系统上运行 shutdown 命令。 |
||
| 选项 | 无 | ||
| 选项名称 | sshkey |
||
| 描述 | 将 SSH 密钥添加到指定用户的授权密钥文件中。 | ||
| 选项 | --username 是必需的。其用法为:sshkey --``username=user KEY |
||
| 选项名称 | text |
||
| 描述 | 使用时,安装将以文本模式运行。默认情况下,安装程序使用 GUI 安装方法。只能使用文本/图形模式中的一种选项。 | ||
| 选项 | --non-interactive 以非交互模式进行安装。如果需要用户操作,该模式将终止安装。 |
||
| 选项名称 | url |
||
| 描述 | 使用时,它将使用为安装文件指定的 URL,该文件来自 ISO。URL 可以格式化为 FTP、HTTP 或 HTTPS。 | ||
| 选项 |
-
--url是必需的。这是用于源文件的 URL。以下是语法示例:http://server/direcortftp://username:password@server/path -
--mirrorlist是一个可选参数,用于设置用于安装的镜像 URL。 -
--proxy是一个可选参数,用于在从 HTTP/HTTPS 或 FTP 服务器安装时设置代理。 -
--noverifyssl是一个可选参数,禁用使用 HTTPS 服务器时的 SSL 验证。 -
--metalink是一个可选参数,用于设置用于安装的 ULN/metalink URL。变量替换会对$releasever和$basearch进行。
|
| 选项名称 | user |
||
|---|---|---|---|
| 描述 | 在系统上创建一个新用户 | ||
| 选项 |
-
--name是一个必需的参数,表示用户名。 -
--uid是用户的用户 ID(UID)。 -
--gid是用户的组 ID(GID)。 -
--groups是一个以逗号分隔的用户应属于的组名列表。 -
--homedir是用户的主目录。 -
--lock如果使用,将默认锁定新用户的帐户。 -
--password是新用户的密码。 -
--iscrypted,如果使用,意味着密码参数是加密后的密码。你可以从运行中的系统的/etc/shadow文件中获取。 -
--plaintext,如果使用,意味着密码参数是明文密码。 -
--shell是用户默认 shell 的路径。
|
表 2.1 – Kickstart 选项
第三章:探索 Oracle Linux 中的各种启动选项和内核
本章将教你关于启动及其选项、内核等内容。你还将学习到许多令人兴奋的机会、工具和应用,帮助你使生活更加轻松愉快。例如,你将学会如何更改启动内核,移除并重新安装系统上的内核。你甚至将学会如何利用启动过程在不同的 Linux 内核之间切换。
启动不仅仅是加载操作系统,它还通过使用安全启动(Secure Boot)或 TrenchBoot 来帮助保护系统安全。
本章包含以下内容:
-
内核基础 – UEK 和 RHCK
-
玩转 UEFI
-
玩转安全启动
-
TrenchBoot – 提升启动安全性和完整性
-
移除 RHCK
内核基础 – UEK 和 RHCK
在我们开始讨论 UEK 和 RHCK 之前,首先来了解什么是 Linux 内核。Linux 内核发布指的是 Linux 操作系统核心组件的更新版本。它的主要功能是作为计算机系统硬件和软件层之间的桥梁。Linux 内核是由全球大量开发者共同开发的,Linus Torvalds 是内核主线的原始创建者和官方维护者。这些内核更新定期发布,提供新功能、改进、错误修复、安全补丁和硬件支持。
Linux 内核发布会分配一个由三个部分组成的版本号:主版本、次版本和补丁级别。例如,一个内核版本表示为 X.Y.Z,其中 X 代表主版本,Y 是次版本,Z 是补丁级别。主版本通常在发生可能影响兼容性的重大更改时增加,而次版本和补丁级别则表示增量更新和错误修复。
Linux 内核发布作为源代码分发,各种基于 Linux 的发行版或操作系统通常会打包并分发他们自己的内核版本,将其纳入各自的发行版中。此外,用户如果希望在自己的系统上直接编译和安装内核,可以访问源代码。下表显示了 Linux 7、8 和 9 版本的 Linux 内核主线发布。
| 操作系统版本 | RHCK 版本 | 最新的 UEK 版本 |
|---|---|---|
| Linux 7 | Linux 3.x | UEK 6/Linux 5.4 |
| Linux 8 | Linux 4.x | UEK 7/Linux 5.15 |
| Linux 9 | Linux 5.14 | UEK 7/Linux 5.15 |
表 3.1 – 按版本列出的可用内核选项
内核基础 – UEK 和 RHCK
在全新安装的 Oracle Linux 系统中,Unbreakable Enterprise Kernel(UEK)是默认内核。然而,在某些情况下,你可能希望切换到Red Hat Compatible Kernel(RHCK)。
默认内核在某些场景下可能不是最合适的版本:
-
UEK 发布版本是基于比 RHCK 版本更新的内核版本,后者是 Red Hat 服务器的标准。使用 Oracle Linux 时,您可以选择使用 UEK,该版本提供了更新的内核发布。
-
当前的内核版本可能与您的特定硬件不兼容。UEK 系统将在新硬件上引导,而较旧的 RHCK 则不会。一个例子是 UEK 7,它支持 Microsoft Azure Network Adapter(MANA),而 UEK 6 则不支持。
-
假设系统上安装了 UEK 的 beta 或技术预览版本。在这种情况下,UEK 需要降级,以确保内核只有在管理员有意识并手动选择作为引导内核时才会使用。
-
Oracle Linux 的 UEK 提供了许多优势,如显著的性能改进和新功能。Linux 操作系统是一个模块化系统,其中内核与硬件交互,并在应用程序代表访问资源时控制和调度访问。大多数应用程序运行在称为用户空间的地方,并且只调用一组稳定的系统库来请求内核服务。唯一的例外是直接访问内核的应用程序,最常见的是安全应用程序。
-
安装 UEK 不会更改系统库,例如几乎所有应用程序(包括 Oracle 数据库)使用的接口 glibc。无论您是否使用 UEK 或 RHCK 运行 Oracle Linux,glibc 版本都是相同的。这不仅限于 gloc,对于所有系统库,如 libssl、libcurl 和 libcrypt,情况都是如此。
注意
对于任何基线操作系统发布,可能会有多个 UEK 版本可用。选择 UEK 的版本取决于应用团队,并且必须反映出任何兼容性要求。
这些示例及类似情况需要您在不同的内核类型之间进行切换。在旧版本中,管理默认内核是通过配置 GRUB 引导加载程序完成的。但是,从 Oracle Linux 8 开始,您应该使用 grubby 命令来控制和管理引导内核的配置。grubby 是 Grand Unified Bootloader version 2(GRUB 2)引导加载程序的一部分,它来自 GNU 项目。GRUB 是市场上许多 Linux 发行版的默认引导加载程序。加载到内存后,它将控制权转移给操作系统内核。
GRUB 2 是 Oracle Linux 上使用的默认引导加载程序,它可以加载许多不同的操作系统,包括 Microsoft Windows。
准备就绪
让我们从更深入地了解引导过程开始。
引导过程
您了解 Oracle Linux 引导选项如何帮助您解决系统引导时遇到的问题是很有益的。在使用新硬件或云环境时,这种知识尤其重要。
当 Oracle Linux 系统启动时,它会执行许多任务,这些任务可能会根据硬件使用的固件类型来改变,以处理系统的启动。它可能是系统驱动器上某个分区中的 .efi 文件。使用 .efi 文件让用户对启动过程有更多控制,包括能够利用新的安全功能。一个新的安全功能示例是安全启动(Secure Boot),该功能将在本章中介绍。
基于 UEFI 的启动顺序
以下是基于 UEFI 启动硬件使用的顺序:
-
系统首先执行 自检启动(POST),以识别系统的配置和所有可能的启动标识符。
-
UEFI 会搜索具有特定 全球唯一标识符(GUID)的 GUID 分区表(GPT)分区,将其标识为 EFI 系统分区(ESP),该分区包含诸如启动器等 可扩展固件接口(EFI)应用程序。如果有多个启动设备,UEFI 启动管理器将根据启动管理器中定义的顺序确定适当的 ESP。使用 efibootmgr 工具,如果你不使用默认定义,可以指定一个不同的顺序。
-
UEFI 启动管理器检查是否启用了安全启动。如果没有启用安全启动,启动管理器将运行 ESP 上的 GRUB 2 启动加载程序。否则,启动管理器将请求启动加载程序的证书,并将其与存储在 UEFI 安全启动密钥数据库中的密钥进行验证。环境配置为执行两阶段启动过程,负责证书验证的
process.efi应用程序的 shim 首先加载,然后才加载 GRUB 2 启动加载程序。如果证书有效,启动加载程序运行,并进一步验证其配置要加载的内核。启动加载程序首先将
vmlinuz内核镜像加载到内存中,然后创建一个名为tmpfs的临时 RAM 文件系统。然后它用于提取initramfs镜像文件的内容。vmlinuz是可引导的压缩 Linux 内核可执行文件的名称。内核中嵌入的根文件系统,并在启动过程中早期加载,称为initramfs。 -
驱动程序模块随后从
initramfs文件系统加载。这些模块允许内核访问根文件系统。 -
然后系统从第一个进程 systemd 启动。所有未来的进程都将从这个进程派生。systemd 进程的进程 ID 始终为 1。
-
systemd 进程将运行为其定义的任何额外进程。你可以通过定义你的 systemd 单元来指定在启动过程中要处理的其他操作。建议使用这种方法,而不是使用
/etc/rc.local文件的方法。
传统 BIOS 启动顺序
传统 BIOS 启动硬件使用以下顺序:
-
系统首先执行 POST(开机自检),它识别系统的配置、测试内存并识别所有可能的启动设备。
-
一旦 BIOS 识别了启动设备,它就会读取设备的第一个扇区,即主引导记录(MBR)。MBR 包含引导加载程序,它是一个负责加载操作系统的小程序。MBR 读取分区表,以确定启动分区。此外,MBR 还包含指向名为 GRUB 2 的引导加载程序的指针。GRUB 接着可以在安装了 GRUB 的同一设备或其他设备上运行引导。这在进行双系统引导(例如同时运行 Linux 和 Windows)时非常有用。
-
引导加载程序首先将
vmlinuz内核镜像加载到内存中,然后创建一个名为tmpfs的临时基于内存的文件系统。接着,tmpfs用于提取initramfs镜像文件的内容。vmlinuz是可引导的压缩 Linux 内核可执行文件的名称。嵌入在 Linux 内核中并在引导过程中早期加载的根文件系统称为 initramfs。 -
驱动程序模块随后从 initramfs 文件系统中加载。这些模块是允许内核访问根文件系统所必需的。
-
内核随后启动 systemd 进程。
-
systemd 进程运行任何为其定义的其他进程。你可以通过定义 systemd 单元来指定在引导过程中处理的任何额外操作。推荐使用这种方法,而不是使用
/etc/rc.local文件方法。
如何操作…
现在我们已经讨论了基础知识,接下来可以告别那些枯燥的部分,进入实际操作。是时候玩起来并学习了!
我们可以做的第一件事是确定当前加载的内核。以下命令将显示我们 Linux 系统中已安装并配置的所有内核(请以 root 身份运行):
# grubby -–info=ALL
这是一个输出示例:

图 3.1 – grubby 输出
注意
该示例使用的是 Arm 系统,因此显示了aarch64后缀。x86_64 系统将显示x86_64后缀。
我们还可以通过执行以下命令来确定当前使用的默认内核:
#grubby -–info=DEFAULT
这是一个输出示例:

图 3.2 – grubby 默认内核
我们可以通过运行以下命令来配置特定的内核作为默认引导内核:
#grubby –-set-default <Kernel>
这是使用前述命令更改正在使用的默认内核的示例。我们知道 RHCK 将是一个版本 4 内核,因此我们将使用4.18.0-425.13.1.el8_7.x86_64。接下来,我们需要指向/boot中的文件,并在名称前加上vmlinuz-。

图 3.3 – 使用 grubby 更改默认内核
另一个可能用途是使用grubby命令更新内核配置条目,或者添加或删除应默认传递给内核的启动参数;以下是一个示例。但首先,我们将展示系统中特定内核的所有信息:
root@ol8 # grubby --info=/boot/vmlinuz-0-rescue-c32316cc4b5241b8adb312707ae46458
这将显示指定内核的详细信息,包括内核的修补程序和任何参数:

图 3.5 – 在进行更改后的 grubby 信息
工作原理…
如前所述,Oracle Linux 提供两种内核版本:UEK,这是 Oracle 的默认 Linux 内核版本,以及 RHCK,与 RHEL 内核兼容。无论使用哪种内核,操作系统的其余部分都是相同的;即具有相同的应用程序、库和文件位置。
本节将教您如何将默认内核(UEK)切换到 RHCK 或反之。让我们开始吧。
首先,我们再次使用grubby命令来检查正在使用的默认内核,并再次使用grubby -–info=DEFAULT和grubby –-info=ALL命令来检查系统中所有可用的内核。两个命令的区别在于DEFAULT选项仅显示引导信息。使用ALL选项,则显示所有可用的内核:

图 3.6 – 切换到 RHCK 前的内核版本
在上述示例中,您可以看到,在这种情况下,正在使用的默认内核是/boot/vmlinuz-5.15.0-8.91.4.1.el8uek.x86_64,这是一个 UEK 内核的变种。UEK 系统应该在el#后始终有uek。您还可以使用uname -a命令检查当前内核:

图 3.7 – 在切换到 RHCK 之前的 uname -a
要检查系统上所有可用的内核,我们可以使用先前运行的grubby –info命令中的数据,或者使用rpm -qa kernel*core*命令:

图 3.8 – 使用 rpm 命令检查内核
在检查所有可用内核时,我们可以快速识别出两种版本的 UEK 和两种版本的 RHCK。在这个例子中,我们将使用名为 4.18.0-425.13.1.el8_7 的 RHCK 版本,它位于 /boot/vmlinuz- 4.18.0-425.13.1.el8_7。所以现在,我们使用 grubby --set-default 命令将所选的 RHCK 设置为默认内核。然后,我们使用 grubby --info=DEFAULT 命令检查默认内核:

图 3.9 – 切换到 RHCK
就是这样。现在,我们需要做的就是重启系统以反映内核更改。然后,如果你想将其切换回之前的 RHCK 内核版本,只需再次运行grubby --set-default命令,但这次指定你想要的 RHCK 版本名称。
玩转 UEFI
黑客入侵系统的一种方式是在系统启动之前攻击它。为了防止这种情况,你必须通过启用 UEFI 中的安全性来保护操作系统。换句话说,如果无法信任软件正确执行代码,就不能运行该软件,因为不受信任的软件可能会篡改引导加载程序,甚至更糟,危害固件。为了解决这个问题,启动系统需要一种新的安全方法,这就是 UEFI。UEFI 实现于固件中,已经成为硬件和操作系统之间的接口,取代了之前行业默认的传统 BIOS 固件。UEFI 的一项功能是安全启动(Secure Boot),它确保系统仅使用硬件制造商信任的软件来启动系统。此外,它提供了一个验证机制(通过使用加密校验和和签名验证每个启动软件),以确保在执行之前通过验证启动加载程序来确保启动的代码是受信任的(甚至在加载操作系统之前)。如果该功能可用,UEFI 系统还可以通过兼容性支持模块以传统 BIOS 模式启动。
准备工作
要在 UEFI 模式下启动,Oracle Linux 在系统安装过程中需要检测到 UEFI 固件。接下来,GPT 会自动设置,并在 /boot/efi 挂载点创建一个 ESP,其中包含用于 UEFI 启动所需的文件。GPT 是一种存储驱动器分区信息的方式,包括分区在物理磁盘上的起始和结束位置等信息。GPT 是一种新的标准,逐步取代了以前广泛使用的 MBR 标准。GPT 不受 MBR 的限制,如分区数量和驱动程序大小,且大小限制取决于操作系统及其文件系统。请注意,GPT 是 UEFI 所要求的分区表类型,由英特尔发起。
MBR 与 GPT
对于硬盘和固态硬盘等存储设备的分区方案,MBR 和 GPT 是两种不同的选项。为了帮助区分它们,以下是需要记住的主要差异。
-
分区容量:
-
MBR:计算机的 MBR 允许最多四个主分区,或者三个主分区和一个扩展分区,后者可以进一步划分为多个逻辑分区。然而,MBR 的最大磁盘容量限制为 2 TB。
-
GPT:默认情况下,GPT 支持最多 128 个分区,并且没有分区数量的限制。此外,它还能支持最大 9.4 ZB 的较大磁盘容量。
-
-
兼容性:
-
MBR:MBR 提供更好的与旧版系统和操作系统的兼容性。它在基于 BIOS 的计算机以及旧版 Windows 和 Linux 系统中得到了广泛支持。
-
GPT:现代系统,特别是那些使用 UEFI 而非 BIOS 的系统,在兼容性方面表现更好。大多数现代操作系统(如 Windows、macOS 和 Linux)都支持这种分区方案。
-
在决定使用 MBR 还是 GPT 时,需要考虑磁盘大小、所需的分区数量、兼容性需求以及你计划使用的具体系统或操作系统等因素。对于大磁盘和新系统,GPT 通常是更好的选择,而 MBR 仍然适用于需要与旧版引导分区兼容的老旧系统或小磁盘。
如何执行…
我们运行 df -h 命令来查看系统中的分区。请注意,在此示例中,/boot/efi 被挂载在 /dev/sda1 分区:

图 3.10 – df -h 命令
如果你运行 ls -l /boot/efi/EFI/redhat 命令,目录中包含一个名为 shimx64.efi 的第一阶段引导加载程序,一个名为 grubx64.efi 的 GRUB 2 引导加载程序,以及一个名为 grub.cfg 的 GRUB 2 配置文件。在 BIOS 模式下,grub.cfg 文件的位置有所不同,它位于 /boot/grub2:
[root@demo2 ~]# ls -l /boot/efi/EFI/redhat
total 4112
-rwx------. 1 root root 134 Aug 27 15:51 BOOTX64.CSV
drwx------. 2 root root 4096 Oct 15 19:59 fonts
-rwx------. 1 root root 6545 Feb 14 20:45 grub.cfg
-rwx------. 1 root root 1024 Feb 14 22:31 grubenv
-rwx------. 1 root root 1024 Feb 14 21:15 grubenvRvxfzJ
-rwx------. 1 root root 2288320 Oct 15 19:59 grubx64.efi
-rwx------. 1 root root 905400 Aug 27 15:51 mmx64.efi
-rwx------. 1 root root 984688 Aug 27 15:51 shimx64.efi
[root@localhost falvarez]#
/etc/default/grub 文件负责包含用户对 grub.cfg 文件的设置。请注意,当处于 BIOS 模式时,该文件的位置也是相同的。此外,如果你对该文件进行了更改,grub.cfg 文件需要重新生成:
[root@demo2 ~]# cat /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto resume=/dev/mapper/ol-swap rd.lvm.lv=ol/root rd.lvm.lv=ol/swap rhgb quiet"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
要重建 grub.cfg 文件,请使用 grub2-mkconfig 命令并指定输出文件,使用 -o 选项,例如 /boot/efi/EFI/redhat/grub.cfg:
[root@demo2 ~]# grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg
Generating grub configuration file ...
Adding boot menu entry for EFI firmware configuration
done
用于管理 UEFI 引导过程的工具称为 efibootmgr(它提供一个显示引导条目的引导菜单)。它还允许我们通过以下方式操作引导条目:
-
修改引导顺序
-
创建引导条目
-
删除引导条目
-
指定下次引导时使用的引导条目
它是如何工作的…
你可以通过运行不带选项的 efibootmgr 命令来查看引导条目的摘要。若要查看更多详细信息,可以添加 -v 选项:
[root@demo2 ~]# efibootmgr -v
BootCurrent: 0004
Timeout: 0 seconds
BootOrder: 0004,0000,0001,0002,0003
Boot0000* UiApp
Boot0001* UEFI VBOX CD-ROM VB2-01700376
Boot0002* UEFI VBOX HARDDISK VB2d5be0c5-80049c5d
Boot0003* EFI Internal Shell
Boot0004* Oracle Linux
[root@demo2 ~]# efibootmgr -v
BootCurrent: 0004
Timeout: 0 seconds
BootOrder: 0004,0000,0001,0002,0003
Boot0000* UiApp FvVol(7cb8bdc9-f8eb-4f34-aaea-3ee4af6516a1)/FvFile(462caa21-7614-4503-836e-8ab6f4662331)
Boot0001* UEFI VBOX CD-ROM VB2-01700376 PciRoot(0x0)/Pci(0x1,0x1)/Ata(1,0,0)N.....YM....R,Y.
Boot0002* UEFI VBOX HARDDISK VB2d5be0c5-80049c5d PciRoot(0x0)/Pci(0xd,0x0)/Sata(0,65535,0)N.....YM....R,Y.
Boot0003* EFI Internal Shell FvVol(7cb8bdc9-f8eb-4f34-aaea-3ee4af6516a1)/FvFile(7c04a583-9e3e-4f1c-ad65-e05268d0b4d1)
Boot0004* Oracle Linux HD(1,GPT,dff50c5d-96ed-406c-9823-212649b405bd,0x800,0x12c000)/File(\EFI\redhat\shimx64.efi)
如你在上面的示例中看到的那样,启动0004(Oracle Linux)是用来启动当前运行系统的启动项,称为BootCurrent。BootOrder是启动管理器中使用的启动顺序;因此,启动管理器将启动列表中的第一个活动项。如果启动失败,它将尝试下一个项,依此类推。如果你的系统使用 UEFI,efibootmgr是一个方便的命令行工具,能够帮助你管理 EFI 启动项。通过这个工具,你可以轻松查看、创建、修改和删除 EFI 启动管理器中的启动项。
如果你想删除启动项,可以使用-B选项。在这种情况下,我们将使用以下命令删除 CDROM 记录(0001)选项:
efibootmgr -b 0001 -B
你还可以使用-o选项更改启动顺序。在以下命令中,我们将更改启动顺序,使 UEFI Shell 成为默认启动项:
efibootmgr -o 0003,0004,0002,0003
请使用man命令了解更多关于efibootmgr命令的信息。
警告
在更改配置时要非常小心。意外地将启动顺序更改为不可启动的设备,可能会导致你进入系统恢复状态。如果你在没有访问控制台的环境中运行系统,这一点尤其重要。
玩转安全启动
安全启动是 UEFI 中实现的一个额外的可选功能,旨在帮助防止在启动过程中恶意软件的执行。要启用或禁用安全启动,你需要访问特定的 UEFI 设置程序。不同系统制造商的设置程序各不相同,请查阅系统文档了解如何访问 UEFI 配置。
安全启动步骤与常规 UEFI 启动相同,但有一个重要的例外,那就是它要求加载和执行的组件必须经过签名和身份验证(使用公私钥对进行身份验证)。它包括两个启动信任根(RoT),以构建传递的信任链:
-
验证 RoT 负责签名验证。验证 RoT 是启动 RoT,这是大多数人在谈论安全启动时所指的内容,它将位于启动闪存驱动器上,作为存储的 RoT 来保护密钥数据库。仅在驱动程序执行环境(DXE)阶段进行验证,而不是在安全(SEC)阶段进行验证。
-
测量 RoT 负责测量数据的收集。
安全启动将通过以下过程建立信任链:
-
首先,会验证由 Oracle 和 Microsoft 签名的第一阶段引导加载程序(shim);然后,它加载 GRUB 2 加载程序。
-
GRUB 2 引导加载程序验证由 Oracle 签名的内核签名,并在加载和执行内核之前进行身份验证。
-
Oracle 签署的内核已通过身份验证并执行。Secure Boot 只加载已签名/已验证的内核模块(例如,所有与内核 RPM 一起包含的内核模块以及与 Oracle Ksplice 一起使用的内核模块都有相应的 Oracle 签名,并且已签名/验证的内核模块运行时得到验证,否则将无法加载)。
现在我们已经讲解了 Secure Boot 的基础知识,接下来让我们学习如何使用它来签署内核模块。首先,在你能够签署模块之前,需要安装几个必需的软件包,包括内核源代码。此外,你还需要为密钥对创建签名证书。私钥用于签署内核模块,公钥会被添加到 Secure Boot 的内核密钥环中,允许系统验证签名。
准备工作
第一步是安装 UEK 开发库。可以使用以下命令完成:
[root@demo2 ~]# dnf -y install kernel-uek-devel-`uname -r`
注意
虽然你可以直接运行dnf install kernel-uek-devel,但在命令中添加uname选项可以确保你安装的是当前运行的内核的devel软件包。另外,别忘了在打补丁后确保更新你的devel软件包。
作为一种好习惯,强烈建议更新系统,以确保你拥有最新的内核和相关软件包:
[root@@demo2 ~]# dnf -y update
这个更新可能需要一些时间,具体取决于你上次更新系统的时间。
如果你使用的是 UEK,编译内核模块所需的内核头文件可以通过kernel-uek-devel包获得。在使用 UEFI Secure Boot 功能时,Oracle 推荐安装并使用 UEK。在安装 UEK 时,还需要安装devel软件包。通过命令中添加uname -r,确保安装正确的头文件。如果你不是使用最新版本的内核,这一点尤其重要。如果你使用的是 RHCK,则应使用kernel-devel,而不是kernel-uek-devel。
现在是时候安装执行模块签名操作所需的工具(openssl、keyutils、mokutil 和 pesign):
[root@demo2 ~]# dnf -y install openssl keyutils mokutil pesign
如果你需要从源代码构建模块,你可以选择安装Development Tools组,以确保可以创建工具的选项:
[root@demo2 ~]# dnf -y group install "Development Tools"
如何操作…
-
创建一个配置文件,供 OpenSSL 在生成证书时使用,以获取默认值。你可以将此文件放在任何位置,但最好将其与其他 OpenSSL 配置文件一起保存在
/etc/ssl/x509.conf中。该文件应类似于以下内容:[ req ] default_bits = 4096 distinguished_name = req_distinguished_name prompt = no string_mask = utf8only x509_extensions = extensions [ req_distinguished_name ] O = Module Signing Example CN = Module Signing Example Key emailAddress = first.last@example.com [ extensions ] basicConstraints=critical,CA:FALSE keyUsage=digitalSignature extendedKeyUsage = codeSigning subjectKeyIdentifier=hash authorityKeyIdentifier=keyid你应编辑
O、CN和emailAddress字段,使其更为合适。注意,在配置的extensions部分,keyUsage字段被设置为digitalSignature。此外,extendedKeyUsage选项被设置为codeSigning,以便与密钥验证工具兼容。 -
使用此配置文件生成新的密钥对:
[root@demo2 ~]# openssl req -x509 -new -nodes -utf8 -sha512 -days 3650 -batch -config /etc/ssl/x509.conf -outform DER -out /etc/ssl/certs/pubkey.der -keyout /etc/ssl/certs/priv.key Generating a RSA private key ........++++ .......++++ writing new private key to '/etc/ssl/certs/priv.key' ----- [root@demo2 ~]#此签名证书有效期为 10 年(3,650 天)。确保密钥得到充分保护。可以通过将密钥从服务器复制并存储在安全位置来实现。将密钥放在 USB 闪存盘上并将其放入办公桌抽屉中是不安全的位置。请使用锁定的位置,如保险箱。
-
导出证书为 PEM 格式:
[root@demo2 ~]# openssl x509 -inform DER -in /etc/ssl/certs/pubkey.der -out /etc/ssl/certs/pubkey.pem [root@demo2 ~]#
签署模块
sign-file工具确保模块已正确签署以适配内核。此工具包含在内核源代码中。以下说明假定您正在为当前运行的内核签署模块。如果您打算为不同的内核签署模块,则必须提供sign-file工具所在的正确内核版本源的路径。如果您使用了错误的工具,模块的签名类型可能与预期的签名类型不匹配。
要签署模块,请运行当前内核的sign-file工具,并提供私钥和您为签署模块而创建的公钥路径(在此示例中,我使用了一个名为hello的公有模块):
[root@demo2 ~]# sudo /usr/src/kernels/$(uname -r)/scripts/sign-file sha512 /etc/ssl/certs/priv.key \
> /etc/ssl/certs/pubkey.der /lib/modules/$(uname -r)/extra/hello.ko
请注意,模块应已安装到/lib/modules/目录中,并且您需要提供正确的模块路径。
更新机器所有者密钥数据库
机器所有者密钥(MOK)是一项安全功能,旨在保护计算机系统的启动过程,防止未经授权的修改或攻击。它通常用于支持UEFI和安全启动的系统,这些系统要求所有启动加载程序和内核模块必须由受信任的实体进行签名。
MOK 数据库存储在系统固件中的非易失性内存位置,包含一个公钥列表,这些公钥允许用于签署启动加载程序和内核模块。MOK 数据库中的每个密钥都与唯一标识符相关联,并用于验证启动加载程序和内核模块的数字签名。如果数字签名有效,启动过程将继续,软件将被加载。如果数字签名无效,或用于签署软件的密钥不在 MOK 数据库中,启动过程将被中止,系统将无法启动。
要注册 MOK 密钥,您必须在每个目标系统上使用 UEFI 系统控制台手动进行。
由于您创建的密钥不包含在 UEFI 安全启动密钥数据库中,因此您必须使用mokutil命令将其注册到 Shim 中的 MOK 数据库:
mokutil --import /etc/ssl/certs/pubkey.der
之前的命令提示您输入一个一次性密码,该密码用于在系统重启后,当 MOK 管理服务注册密钥时使用。
重启系统
- UEFI Shim 应在启动时自动启动 Shim UEFI 密钥管理器,如下图所示。如果在 10 秒钟内未按下任何键,您将无法注册您的 MOK 密钥:

图 3.11 – Shim 工具
按任意键继续。
- 然后您应该会看到 Shim 主菜单。从菜单中选择注册 MOK。

图 3.12 – Shim 主菜单
这样,您可以继续注册密钥或查看密钥。
- 从菜单中选择查看密钥 0(如下图所示)以显示密钥详情。

图 3.13 – 查看密钥
- 这将显示密钥详情。验证显示的值是否与您用于签署模块的密钥匹配,并且该密钥已插入内核映像中:

图 3.14 – 密钥详情
然后按任意键返回到注册 MOK菜单。
-
从菜单中选择继续。
-
显示注册密钥?屏幕,现在可以从菜单中选择是(如下图所示)。

图 3.15 – 注册密钥
选择是以注册密钥。
-
然后会提示您输入密码。请输入使用
mokutil命令导入密钥时使用的密码。密钥已注册到 UEFI 安全启动密钥数据库中。
-
您现在将被重定向到主菜单。从菜单中选择重启。

图 3.16 – 完成后重启
工作原理……
启动系统后,您可以验证密钥是否已包含在适当的内核密钥环中。验证取决于您正在运行的内核版本。此外,您需要检查的密钥环名称有所不同,因为各个内核版本中的实现有所变化。
如果为签署自定义模块生成的密钥已列在正确的密钥环中,您可以在安全启动模式下加载使用此密钥签署的模块。
对于 Oracle Linux 8 上的 RHCK 和 UEK R6U3 内核或更高版本,builtin_trusted_keys密钥环和platform密钥环中的密钥都被信任用于模块签名以及kexec工具,这意味着您可以按照标准程序签署模块并将其添加到 MOK 数据库中,使密钥出现在platform密钥环中,并且会自动被信任。
由于密钥可以加载到builtin_trusted_keys密钥环中,因此您应检查两个密钥环中的模块签名密钥。以下是一个示例:
[root@demo2 ~]# keyctl show %:.builtin_trusted_keys
Keyring
718980051 ---lswrv 0 0 keyring: .builtin_trusted_keys
889527021 ---lswrv 0 0 \_ asymmetric: Oracle CA Server: 23652876a2ec7c7794eb905265a1145e5ad5b873
643918572 ---lswrv 0 0 \_ asymmetric: Oracle IMA signing CA: a2f28976a05984028f7d1a4904ae14e8e468e551
668816900 ---lswrv 0 0 \_ asymmetric: Oracle America, Inc.: Ksplice Kernel Module Signing Key: 09010ebef5545fa7c54b626ef518e077b5b1ee4c
35441076 ---lswrv 0 0 \_ asymmetric: Oracle Linux Kernel Module Signing Key: 2bb352412969a3653f0eb6021763408ebb9bb5ab
[root@demo2 ~]# keyctl show %:.platform
Keyring
858046056 ---lswrv 0 0 keyring: .platform
886150219 ---lswrv 0 0 \_ asymmetric: Oracle America, Inc.: 430c85cb8b531c3d7b8c44adfafc2e5d49bb89d4
698748825 ---lswrv 0 0 \_ asymmetric: Oracle America Inc.: 2e7c1720d1c5df5254cc93d6decaa75e49620cf8
790695213 ---lswrv 0 0 \_ asymmetric: Oracle America, Inc.: 795c5945e7cb2b6773b7797571413e3695062514
227851788 ---lswrv 0 0 \_ asymmetric: Oracle America, Inc.: f9aec43f7480c408d681db3d6f19f54d6e396ff4
TrenchBoot – 提高启动安全性和完整性
TrenchBoot 是一个 GitHub 跨社区、跨平台框架集成,源自 2014 年 Apertus Solutions 的一个想法,旨在解决使用 tboot 启动 Xen 时的局限性,服务于 OpenXT 项目及其他贡献者,如 Oracle(Intel)、3mdep(AMD)和 Citrix(github.com/TrenchBoot)。其主要目的是通过使用统一的标准方法(适用于 Xen、KVM、Linux、BSD 及可能的专有内核),扩展安全性机制和引导过程的完整性。一个常见的应用场景是 Oracle Cloud 的受保护实例。
准备就绪
TrenchBoot 的主要功能之一是安全地启动 Linux。此功能通过引入一个中间阶段来动态启动 AMD 和 Intel 的 Linux 内核。与传统的首次启动场景(如 XMHF、OSLO、OpenText Secure Boot 和 tboot 等开源动态启动工具使用的引导阶段)不同,TrenchBoot 提供了通过关键执行启动内核升级的能力。然后,您可以启动一个完整性内核,它能够动态检查系统并在关机时将平台的完整性建立在一个无盘嵌入式环境中。请注意,新的中间阶段包括一个名为TrenchBoot Loader的中间加载程序,各种引导解决方案可以启动它。TrenchBoot Loader 包含TrenchBoot 安全引擎,它实现了完整性处理。请参阅以下图示:

图 3.17 – TrenchBoot 过程概述
Oracle 在 Oracle Linux 内核中添加了更多的 TrenchBoot 支持,以启用 Linux 内核的安全启动协议,适用于多个用例,如笔记本的双因素认证(2FA)或众包完整性处理;这个选项是最佳选择。
注意
您可以通过阅读 kernel.org 存档来了解 Oracle 的一些努力,链接为:lore.kernel.org/lkml/20230504145023.835096-1-ross.philipson@oracle.com/。
它是如何工作的…
TrenchBoot 引导程序由一些知名组件构成,如 Linux 和 u-root。让我们深入了解其中的主要组件:
-
启用 TrenchBoot 的内核,集成 TrenchBoot u-root initramfs
-
作为 u-root 扩展的集成 TrenchBoot 安全引擎
-
一个可以通过引导程序启动的新镜像
该构建过程如下图所示:

图 3.18 – TrenchBoot 镜像处理过程
使用 TrenchBoot 的主要优势如下:
-
安全启动:TrenchBoot 提供一个安全启动过程,确保系统上只执行可信的软件。这可以防止执行可能危及系统的恶意软件。
-
运行时完整性:TrenchBoot 通过在运行时验证软件和数据的完整性,确保系统在启动后仍然保持安全。它使用诸如 Intel SGX 和 AMD SEV 等技术来提供基于硬件的隔离和认证。
-
防御攻击:TrenchBoot 提供对各种类型攻击的防护,包括固件攻击、恶意软件和内核 rootkit。
-
平台无关性:TrenchBoot 是平台无关的,可以在不同的硬件平台上使用,包括 x86、Arm 和 RISC-V。
-
开源:TrenchBoot 是一个开源项目,任何人都可以检查其代码并为其开发做出贡献。这使得 TrenchBoot 更加透明和值得信赖。
移除 RHCK
在这个教程中,你将学习如何移除 RHCK 及其独特的软件包依赖关系,同时保留所有 UEK 依赖关系。记住,在安装 Oracle Linux 时,安装程序会自动安装 Oracle UEK 作为默认内核,但你可以为了兼容性目的安装 RHCK。
准备工作
旧版本的 Oracle Linux 需要一个叫做kernel-transition的工具来管理依赖关系。在新版本的 Oracle Linux 中,提供了一个更简便的过程。例如,在 Oracle Linux 8 中,这一要求已经过时。所有软件包都特别构建以避免与系统上运行的 UEK 或 RHCK 相关的任何依赖关系。这使得从系统中移除 UEK 或 RHCK 变得更加容易。
如何操作……
让我们来看看如何从系统中移除 RHCK:
- 首先,让我们使用
grubby命令检查系统中所有正在运行的内核:

图 3.19 – 检查内核
我们可以在前面的输出中看到,当前使用的默认内核是/boot/vmlinuz-5.15.0-8.91.4.1.el8uek.x86_64,这是一个 UEK;同时,我们也可以看到安装了几个 RHCK,/boot/vmlinuz-4.18.0-425.13.1.el8_7.x86_64和/boot/vmlinuz-4.18.0-425.3.1.el8.x86_64,这些我们可以安全地移除。
- 现在我们知道我们正在使用 UEK,可以安全地按照 Oracle Linux 手册中推荐的方式使用
dnf remove kernel命令来移除所需的 RHCK。它会检测未使用的内核并显示其中的依赖关系。

图 3.20 – dnf remove kernel
- 如你在上面的截图中看到的,系统中已检测到并删除了所有已安装的 RHCK。现在,让我们再次运行
grubby命令,查看 RHCK 是否真的从系统启动选项中移除。
警告
不要第二次运行dnf remove kernel。这样可能会意外地删除启动内核,导致系统无法启动。

图 3.21 – RHCK 已移除
很遗憾,两个内核仍然存在。RHCK 的 kernel-<version> 包仅仅是一个元数据包,不包含任何文件。它的作用是确保所有依赖的内核包都正确安装。换句话说,移除 "kernel-<version>.el8" RPM 并不会删除任何内核子包,其中包括更新 /boot 相关文件和启动加载器条目的包。
为了解决这个问题,我们需要移除包含 /boot/ 以及所有内核相关文件/目录的对应 kernel-core-<version> 包。
- 如下图所示,我们将使用
dnf erase kernel-core命令来删除所有相关的kernel-core包:

图 3.22 – dnf 删除 kernel-core
现在,让我们重新运行 grubby 命令,看看这次是否从系统中移除了 RHCK:

图 3.23 – 移除 RHCK 后的 grubby
如您所见,所有 RHCK 已从我们的系统中移除。
此外,如果您之后决定恢复已删除的 RHCK,您可以通过 dnf install kernel 命令快速恢复它们:

图 3.24 – 重新安装 RHCK
如您所见,在 Oracle Linux 上,切换内核是一项简单的任务,移除操作系统中的内核也是如此。您有机会时,可以比较 RHCK 和 UEK 之间的系统性能;您会惊讶地发现,UEK 在处理 I/O 等任务时要快得多。
第四章:创建和管理单实例文件系统
没有数据,系统就没有存在的意义,基于这一点,数据必须存储在某个地方。在本章中,我们将讨论两种最流行的文件系统,它们用于管理本地服务器上的数据:B 树文件系统(Btrfs,发音为Butter F S)和扩展文件系统(XFS,发音为X F S)。
这些是单实例文件系统,基本上是只在某一时刻挂载在单个服务器上的文件系统。也有多实例文件系统,可以同时挂载在多个系统上。常见的例子有Oracle 集群文件系统版本 2(OCFS2)和全局文件系统 2(GFS2)。所有这些例子都使用共享块存储作为底层存储。
此外,还有Ceph,它不是一个首字母缩略词,而是指头足类动物。这是因为 Ceph 是一种分布式架构,能够将数据存储在 Ceph 集群的所有节点上。这使得 Ceph 能够提供可扩展的存储,尽管它有一些额外的复杂性。Gluster是另一种分布式文件系统的例子。
注意
为什么不使用ZFS?因为 Btrfs 和 XFS 是内置在 Oracle Linux 的不可破坏企业内核(UEK)中的,而 ZFS 在第三方仓库之外无法使用。
我们将涵盖以下食谱,帮助你理解和管理本地文件系统:
-
关于本地文件系统,你需要知道的
-
Btrfs – 创建、调整大小和监控
-
Btrfs – 子卷、快照、配额等
-
使用 mdadm 保护数据 – 一种软件 RAID 解决方案
-
操作逻辑卷管理
-
XFS – 创建、修改等
技术要求
对于本篇,你需要一个Oracle Linux 8系统。像大多数这些食谱一样,推荐在桌面上使用如Oracle VirtualBox等桌面虚拟化产品的虚拟机。一个小型虚拟机,具有两个核心、2 GB 内存和几个空闲的磁盘空间就足够了。你还需要为虚拟机分配一些额外的磁盘,理想情况下至少五个大小相等的磁盘。理想情况下,在开始之前,先将系统补丁更新到最新版本。这个过程只需要几分钟,并且在解决由错误引起的问题时能节省大量时间。
本书中的许多食谱都提供了相关的配置文件,可以在 GitHub 上找到,地址为github.com/PacktPublishing/Oracle-Linux-Cookbook。
关于本地文件系统,你需要知道的
本篇将讨论本地文件系统与远程文件系统之间的区别,以及 Btrfs 和 ZFS 之间的核心差异。
操作系统(OS)的骨干是本地文件系统。它通过分层结构实现了计算机或服务器上文件和目录的高效存储和管理。这种结构使用户和程序可以轻松地在本地存储设备(如硬盘、固态硬盘以及来自本地存储区域网络(SAN)或云服务提供商的逻辑单元号(LUNs))上创建、修改和访问文件。这些文件系统专门设计用于文件和文件夹管理的高效性,能够保护文件免受意外删除或损坏。它们配备了文件权限、所有权和访问控制等功能,提供用户最高的安全性和隐私性。与远程文件系统相比,本地文件系统提供了更优的性能,尽管文件除非与远程文件系统技术配对,否则无法在其他系统上访问。Linux 本地文件系统的典型例子包括 Btrfs、XFS、ext4、fat32,甚至 ZFS。
注意
虽然 ZFS 是一个本地文件系统,但它没有包含在内核中,需要通过zfsonlinux.org提供的软件来添加。
远程文件系统使你能够通过网络访问远程服务器上的文件和目录。这个系统提供了便捷的方式,可以像本地存储一样访问和操作远程机器上的文件,从而消除了物理传输文件的需求。远程文件系统在分布式计算环境中被广泛使用,在这些环境中,多台计算机或服务器需要共享数据和资源。它们在云计算和网站托管环境中也非常有价值,因为数据存储在远程并通过互联网访问。然而,需要注意的是,在通过网络共享文件时,使用远程文件系统可能会影响性能,尤其是在多个服务器之间共享文件时。
远程文件系统的例子包括网络文件系统(NFS)、服务器消息块(SMB)和公共互联网文件系统(CIFS),这些在 Unix、Linux 和 Windows 环境中广泛使用。其他流行的远程文件系统还包括s3fs,它允许用户通过基于云的对象存储安全地访问文件。
在管理 MySQL、Postgres 和 Oracle 数据库时,建议使用本地文件系统而非网络文件系统,以确保最佳性能。这个策略也可以有效地应用于操作系统。
准备工作
你需要理解这两种文件系统的核心差异。XFS 文件系统比许多管理员意识到的要老得多。它最早起始于 1993 年,作为硅图形 IRIX操作系统的文件系统,并于 2001 年移植到 Linux。Btrfs 则要新得多,2007 年由 Oracle(作为开源项目)为 Linux 开发。Btrfs 不仅仅是一个文件系统,它还集成了卷管理器、数据冗余和文件系统功能于一体。
使用 XFS 时,您需要将其与逻辑卷管理器结合使用,以便动态管理卷,还需要使用 mdadm 命令来提供容错能力。
使用 Btrfs,您可以选择五种类型的 RAID 卷。选择哪种取决于您的使用案例,因为它是性能、所需磁盘空间和卷的可用容量之间的平衡。详细信息见下表:
| 类型 | 描述 | 性能 | 冗余性 | 容量 |
|---|---|---|---|---|
| RAID 0 | 跨磁盘条带化 | 最佳 | 无 | 100% |
| RAID 1 | 镜像两个磁盘 | 良好 | 1 个驱动器故障 | 50% |
| RAID 10 | 先镜像再条带化,最少 4 个磁盘 | 几乎最好 | 1 个驱动器故障 | 50% |
| RAID1C3 | 3 份元数据,最少 3 个磁盘 | 一般 | 2 个驱动器故障 | 66% |
| RAID1C4 | 4 份元数据,最少 4 个磁盘 | 最低 | 3 个驱动器故障 | 75% |
表 4.1 – Btrfs RAID 选项
两种系统的最大文件系统大小限制相同,都是 8 exabytes!但是,Btrfs 还增加了快照、透明压缩、基于校验和的数据完整性和回滚能力等功能。而 XFS 也不逊色,通过 I/O 线程和更高的带宽提供更高的性能,尽管在将 XFS 与 LVM 和 RAID 技术集成后,这些优势可能无法得到充分体现。另一个主要区别是 Btrfs 要求使用 UEK,而 XFS 则在 UEK 和红帽兼容内核(RHCK)下均能良好工作。
如何操作…
Oracle Linux 默认使用 XFS 文件系统,但在安装时,您可以选择使用 Btrfs 作为根文件系统。如果您想使用 XFS 作为启动文件系统,按常规方式安装即可。如果您想使用 Btrfs,则应继续进行。
注意
您的启动文件系统可以与服务器上的数据文件系统不同。您可以轻松地让根文件系统使用 XFS,而数据文件系统使用 Btrfs,或反之亦然。
运行 Btrfs 最简单的方法是在使用 UEK 启动盘进行安装时选择它。这样,您可以选择 Btrfs 作为目标文件系统。安装时,选择 安装目标,然后选择自定义存储配置。这时,您将获得手动分区选项,可以通过下拉菜单选择 Btrfs,如下面的截图所示:

图 4.1 – Btrfs 选择
在设置自定义配置时,可以为 /var 或 /var/tmp 添加额外的目录(这是安全技术实施指南(STIG)的要求)。这些实际上不仅仅是目录,而是主卷的子卷。因此,它们显示的可用空间相同:

图 4.2 – Btrfs 挂载点
这是因为使用 Btrfs 时,它们都使用相同的卷并具有相同的可用磁盘空间。我们可以稍后通过配额来限制这一点。
使用常规的网络和软件源设置完成安装,但需要注意的是,你可能需要将 安装源 设置为 URL 或本地网络共享。如果你使用的是 8.7 或更早版本,还需要添加 UEK 仓库。
系统启动后,你将看到它现在正在使用 Btrfs。系统启动后可以检查这一点。
它是如何工作的…
你可以通过几种方式检查文件系统,最简单的是检查 /etc/fstab 以查看文件系统是如何挂载的。如下图所示:

图 4.3 – Btrfs fstab 示例
你也可以使用带 T 选项的 df 命令来显示文件系统类型。运行以下命令将显示这些信息:
df -T
这将显示每个挂载文件的文件系统类型,如下图所示:

图 4.4 – 使用 Btrfs 文件系统的 df -T 输出
Btrfs – 创建、调整大小和监控
在本步骤中,我们将创建一个新的 RAID 磁盘阵列 Btrfs 卷和文件系统,使用多个磁盘实现容错存储。然后我们将添加新的 LUN,扩展文件系统。最后,我们将修改文件系统以压缩数据!
准备工作
首先,我向操作系统添加了五个 10 GB 的硬盘。它们将用于构建一个新的 RAID1C4 卷。可以通过使用 fdisk -l 命令并结合 grep 查找 GiB,使用以下命令来查看这些新设备:
fdisk -l | grep GiB
输出如图所示:

图 4.5 – fdisk 输出
在这里,我们可以看到这五个 10 GB 的设备分别是 sdb、sdc、sbd、sbe 和 sbf。我们将在创建 Btrfs 卷时使用这些信息。
如何操作…
现在我们已经知道了设备信息,接下来手动创建一个 RAID1C3 卷。我们将使用所有五个设备以 RAID1C3 配置,并将该卷命名为 data。
接下来,我们将使用以下命令来创建该卷:
mkfs.btrfs -L data -d raid1c3 -m raid1c3 /dev/sd[bcdef]
请参考以下图示查看输出:

图 4.6 – mkfs.btrfs 输出
注意
在挂载 Btrfs 卷时,通常使用卷中的第一个设备或 UUID。UUID 是在创建卷时由 mkfs.btrfs 报告的。
接下来,我们将它挂载到 /data 目录。首先创建 /data 目录,然后使用以下命令进行挂载:
mkdir /data
mount /dev/sdb /data
可选,但强烈推荐的是将其添加到 fstab 文件中。此示例中,我们使用的是卷的 UUID,并且由于数据没有子卷,subvol 参数已定义但留空:

图 4.7 – 使用 UUID 的 fstab 示例
它是如何工作的…
现在我们有了一个已挂载的卷,让我们对其进行一些操作!首先,我们可以使用 btrfs 命令来检查几件事情。首先是检查设备的健康状况,这对于查看 RAID 是否有任何失败设备非常有用。使用 btrfs stats /$DEVICE 命令来显示状态。不要忘记将 $DEVICE 替换为您正在检查的实际 Btrfs 设备:

图 4.8 – 健康设备
当设备开始故障时,您应该在此报告中看到错误。
接下来,我们将向卷中添加几个设备。又添加了四个 10 GB 的磁盘:sdg、sdh、sdi 和 sdj。
在添加设备之前,我们可以看到 /data 有 50 GB 可用的原始空间。使用以下命令可以看到:
btrfs filesystem usage /data
命令的输出显示在以下截图中:

图 4.9 – Btrfs 文件系统使用情况
这里我们可以看到统计数据,主要是 50 GB 的免费原始空间,以及其他指标,包括卷中每个设备分配的空间以及哪些设备具有元数据。
接下来,让我们添加四个新设备。这可以通过 btrfs device add 命令完成:
btrfs device add /dev/sdg /data
对于每个要添加到卷中的设备都要执行此操作,或者使用 /dev/sd[a-z] 批量添加它们,替换 a 和 z 为适当的范围。完成后,您可以使用使用选项检查使用情况,如以下示例所示:

图 4.10 – 添加的 Btrfs 设备
现在您将看到设备达到了 90 GB。现在,随着 /data 中的空间被消耗,您应该开始看到可用空间减少,以及数据分布在各个磁盘上的情况:

图 4.11 – Btrfs 使用空间
对于最后一个示例,我们将删除一个设备以释放空间,然后重新平衡数据。要删除物理设备,请使用 btrfs device delete 命令,并传递设备挂载点:
btrfs device delete /dev/sdj /data
这将移除设备:

图 4.12 – 设备移除
设备移除后,重新运行使用情况报告。现在您将看到剩余的设备以及哪些数据在哪个设备上:

图 4.13 – 不平衡使用情况
虽然这可能看起来是个小问题,但它有可能引起后续的复杂问题。幸运的是,解决方案很简单 – 系统重新平衡。这可以通过 btrfs 命令中的 balance 选项完成。以下命令将用于平衡 /data 文件系统:
btrfs filesystem balance /data
然后这个命令会重新平衡数据块,完成后,使用情况将显示数据均衡分布在各个磁盘上:

图 4.14 – 平衡使用情况
注意
为确保数据分布均衡,建议在添加或移除设备时始终对系统进行平衡操作,尽管可能会有轻微的变化。这一做法对于维持最佳性能的文件系统至关重要。ol8_developer 仓库中的 btrfsmaintenance 包是一个很好的工具,可以自动化所有必要的 Btrfs 维护任务。
Btrfs – 子卷、快照、配额及更多
Btrfs 比较旧的 XFS 技术能做的更多。这包括子卷、快照和配额。Btrfs 子卷是一种卓越的工具,允许用户在单一 Btrfs 文件系统内创建多个快照或子文件系统。这些子卷作为文件系统层次结构中的独立目录显示,但它们使用相同的存储空间,并且可以独立管理。
子卷的灵活性和多功能性使它们非常适合各种用途,例如创建备份或隔离文件系统的不同部分,以便更轻松地进行管理。快照特别有用,因为它们提供了在特定时间点的文件系统只读副本。通过快照,用户可以将文件或整个子卷恢复到以前的状态,或轻松创建可复制的备份,这些备份可以移动到另一台系统。
子卷还使用户能够更有效地管理磁盘空间。例如,用户可以为特定的应用程序或项目创建一个子卷,并将其磁盘使用量限制在一定范围内,以防止它占用过多的文件系统空间。此外,子卷还可以通过为不同的子卷分配不同的权限,或为不同的用户或组创建独立的子卷来实施访问控制。本教程将介绍如何做到这一点。
准备工作
本教程需要一个 Btrfs 文件系统,并将使用上一教程中创建的数据文件系统作为示例。
如何操作……
本教程中,我们将进行以下操作:
-
在
/data中创建子卷并挂载它。 -
设置子卷的配额。
-
创建快照。
-
启用压缩。
创建子卷很简单,只需使用 btrfs 命令并指定子卷的完整路径即可:
btrfs subvolume create /data/vol1
创建完成后,直接将其添加到 fstab 中,此时需要在第四列中声明子卷名称。以下截图显示了如何使用子卷 vol1 挂载 /data/vol1:

图 4.15 – fstab 中的子卷
现在我们已经挂载了子卷,让我们为其添加一个配额,将其限制为 5 GB。为此,首先需要启用该卷的配额。这可以通过以下命令完成:
btrfs quota enable /data
接下来,我们需要为子卷分配配额组限制。这将限制子卷的大小。可以使用 limit 选项来完成此操作,如下所示的命令所示:
btrfs qgroup limit 5g /data/vol1
使用 btrfs qgroup show 命令和 -reF 选项,可以查看卷中定义的配额:
btrfs qgroup show -reF /data/vol1
命令及其输出显示在以下屏幕截图中:

图 4.16 – 设置配额
现在我们已经设置了配额,让我们创建一个备份的快照。我们需要一个存放备份的位置,所以我们先创建一个子卷用来存放备份,使用以下命令:
btrfs subvolume create /data/backup
Btrfs 快照是非常有用的 Btrfs 文件系统副本,用于捕捉某一特定时间点。通过无缝的写时复制过程,这些快照将对文件系统所做的任何更改与快照本身分离开来。这使得它们非常适合用于不同的用途,例如创建备份、测试软件配置和提供一种轻松的方式来撤销系统更新。此外,备份可以快速创建且占用最小的存储空间,因为快照仅存储文件系统当前状态与快照拍摄时的状态之间的差异。要创建 Btrfs 快照,可以使用 btrfs subvolume snapshot 命令,指定要快照的子卷以及快照的名称和位置:
btrfs subvolume snapshot /data/vol1 /data/backup/vol1_backup1
此命令创建了 /data/vol1 子卷的只读快照,并将其作为一个单独的子卷保存在 /data/backup 目录下。
如果你已经创建了一个快照,不用担心——你可以通过强大的 Btrfs 回滚功能轻松地将文件系统恢复到当时的精确状态。通过 Btrfs 快照回滚,你只需选择一个快照,就可以将 Btrfs 文件系统恢复到先前的状态。回滚到快照会丢弃自快照创建以来对文件系统所做的所有更改,并将文件系统恢复到快照创建时的精确状态。
要回滚 Btrfs 快照,可以使用 btrfs subvolume snapshot 命令并加上 -r 选项,指定使用该快照进行回滚:
btrfs subvolume snapshot -r /data/backups/vol1_backup1 /data/vol1
此命令将 /data/vol1 回滚到 /data/backup/vol1_backlup1 快照创建时的状态。
需要注意的是,回滚快照会丢弃自快照创建以来对文件系统所做的任何更改。然而,当你想将文件系统完全恢复到先前的状态时,这一功能非常有用。Btrfs 快照提供了一个简单有效的数据管理和保护解决方案,使得备份创建变得轻松,并能够方便地恢复先前的文件系统版本。
注意
可以启用自动快照,使得 dnf 事务会创建一个快照。此操作由 dnf-plugin-snapper 工具完成。更多信息可以参见:docs.oracle.com/en/operating-systems/oracle-linux/8/fsadmin/fsadmin-ManagingtheBtrfsFileSystem.html#snapper-btrfs。
本节将介绍如何使用 Btrfs 文件系统启用压缩。Btrfs 压缩是一项强大的功能,可以在将数据写入文件系统的同时实时压缩数据。此功能可以显著减少存储空间,特别适合存储大量数据的文件系统,如媒体归档和备份系统。此外,它对于存储空间有限的系统(如移动设备和嵌入式系统)也很有帮助。
Btrfs 压缩在将数据写入文件系统时使用各种压缩算法。这些压缩数据会存储在磁盘上,并在访问时自动解压。这个过程对访问数据的应用程序是透明的,因此它们不需要关注压缩过程,Btrfs 会自动处理。Btrfs 支持三种压缩算法:zlib、lzo和zstd,每种算法都有其优缺点:
-
zlib:这是一种广泛使用的通用压缩算法,提供良好的压缩比,但在较高压缩级别下可能相对较慢。它适用于压缩通用数据和文本文件。 -
lzo:这是一种轻量级压缩算法,提供良好的压缩比,并且相对较快。它适用于压缩已经压缩过的数据,如媒体文件和归档文件。 -
zstd:这是一种较新的压缩算法,它在压缩比和速度之间提供了良好的平衡。它适用于压缩各种类型的数据,包括文本、媒体文件和归档文件。
压缩算法的选择取决于特定的使用场景和性能要求。
要在文件系统上启用压缩,可以使用btrfs property命令来设置文件系统的压缩:
btrfs property set /data/vol1 compression zstd
当启用压缩时,只有写入到文件系统的新增数据会被压缩。不过,你也可以使用defragment命令来压缩在启用压缩之前已经存在于文件系统中的数据。要在子卷上执行此操作,还需要使用-r选项递归运行命令,并配合-c选项来压缩数据:
btrfs filesystem defragment -rc /data/vol1
还有更多内容…
压缩效率会有所不同,取决于所使用的数据和算法。让我们首先使用以下命令检查剩余空间:
[root@btrfs vol1]# btrfs filesystem usage /data/vol1 | grep Data | grep Used
Data,RAID1C3: Size:1.00GiB, Used:0.00B (0.00%)
现在,让我们创建一个包含随机数据的 2 GB 文件:
head -c 2G </dev/urandom > /data/vol1/test1
接下来,我们可以使用df和du命令来比较已消耗的空间和已使用的空间:
df -h /data/vol1
du -hd0 /data/vol
这些命令的示例输出如下:
[root@btrfs vol1]# df -h /data/vol1
Filesystem Size Used Avail Use% Mounted on
/dev/sdb 30G 2G 28G 1% /data/vol1
[root@brtfs vol1]# du -hd0 /data/vol1
2.0G /data/vol1
[root@brtfs vol1]#
在这里,我们可以看到 2 GB 的空间已经被使用(通过du命令),而且实际上 2 GB 空间已经被消耗(通过df命令)。因此,对于这个随机数据文件,我们看到压缩并未带来任何好处。
现在让我们删除test1文件:
rm /data/vol1/test1
为了加速,我们来进行碎片整理和重新平衡。这是现在就释放已删除文件的空间所需要的,而不是等待:
[root@btrfs vol1]# btrfs filesystem defragment -rc /data/vol1
[root@brtfs vol1]# btrfs filesystem balance /data
Done, had to relocate 4 out of 4 chunks
[root@btrfs vol1]#
现在,使用一个包含大量重复数据的文件,我们将看到更多的压缩效果。要创建一个包含重复数据的 2 GB 文件,请运行以下命令:
yes "repeating text" | head -c 2G >test2
现在,我们重复之前的 du 和 df 命令,但将会看到非常不同的结果:
[root@brtfs vol1]# df -h /data/vol1
Filesystem Size Used Avail Use% Mounted on
/dev/sdb 30G 62M 29G 1% /data/vol1
[root@brtfs vol1]# du -hd0 /data/vol1
2.0G /data/vol1
[root@brtfs vol1]#
这里,我们看到分配了 4 GB,但实际上只使用了 62 MB!这就是压缩带来的巨大好处。
使用 mdadm 保护数据 – 一种软件 RAID 解决方案
现代计算系统依赖 RAID 技术以确保数据的完整性、可用性和性能。通过将数据分布在多个磁盘上并采用不同的配置,RAID 提供容错功能,使得即使一个或多个磁盘发生故障,系统仍能继续运行。这种冗余对于防止数据丢失和减少停机时间至关重要。
此外,RAID 配置,如条带化和镜像,可以通过允许从多个磁盘并行访问数据,显著提高读写性能。随着数据量和重要性在当今数字世界中的不断增加,RAID 在保护、优化和维护存储系统的可靠性方面发挥着至关重要的作用。在不使用 Btrfs 的 Oracle Linux 8 系统中,最简单的方式是使用一个名为 mdadm 的工具。
准备就绪
mdadm 是一个用于管理和配置 Linux 系统中软件 RAID 阵列的软件工具。它代表 多个设备管理,通常用于创建、管理、监控和维护 RAID 阵列。这些阵列利用一个名为 多个设备 (MD) 的内核驱动程序。mdadm 允许用户创建各种 RAID 级别,包括 RAID、RAID 0、RAID 1、RAID 5、RAID 6、RAID 0+1 和 RAID 10,通过结合多个物理磁盘:
| 类型 | 描述 | 备注 |
|---|---|---|
| RAID | 跨区 | 没有冗余或性能优势。 |
| RAID-0 | 条带化 | 没有冗余,但相较于 RAID 提供更好的性能。 |
| RAID-1 | 镜像 | 镜像冗余,但在写入工作负载中没有性能优势。读取工作负载可能有所改善。 |
| RAID-5 | 双重奇偶校验条带化 | 提供冗余和良好的性能。可以丢失一个磁盘而不丢失数据。建议至少使用四个磁盘。 |
| RAID-6 | 三重奇偶校验条带化 | 提供冗余和良好的性能。可以丢失两个磁盘而不丢失数据。建议至少使用五个磁盘。 |
| RAID 0+1 | 条带化磁盘的镜像 | 极好的性能,但恢复丢失的磁盘需要很长时间。需要至少四个磁盘。 |
| RAID 10 | 镜像磁盘条带化 | 最昂贵的选项,但通常被认为是最好的冗余、性能和重建时间解决方案。需要至少四个磁盘。 |
表 4.2 – MD RAID 选项
注意
将JBOD(仅为硬盘的盒子)外壳与 RAID 外壳混淆并不罕见。JBOD 是一种简单的磁盘外壳,没有硬件 RAID。RAID 磁盘外壳有一个硬件控制器,它会将外壳内所有磁盘的 RAID 逻辑卸载到硬件上。在此示例中,没有使用硬件 RAID,只有 JBOD。所有 RAID 逻辑由 Oracle Linux 执行。
mdadm 是管理员用来创建、修改和监控 RAID 阵列的重要工具。它允许用户从现有阵列中添加或移除磁盘,执行数据恢复操作,并配置诸如 RAID 级别和备用磁盘等各种参数。通过其命令行界面,mdadm 提供了灵活性来管理和维护磁盘冗余性和性能。它是一个可靠且强大的解决方案,优化了存储性能,确保了数据冗余,并保持了数据的高可用性。mdadm 通常在安装 Oracle Linux 时安装。
如何操作…
创建 MD 设备相当简单。但在创建设备之前,你需要提前规划一些事项:
-
你将使用什么类型的 RAID?如前所述,MD 内核驱动程序支持多种 RAID 算法。你需要在运行命令之前选择一种类型。这与
–level 选项对应。 -
你将使用多少个驱动器?大多数 RAID 类型使用偶数个磁盘,但你仍然需要知道用于数据的磁盘数量。这与
–raid-devices 选项对应。 -
你是否会配置一个热备份设备?热备份是一个很好的选择,当系统需要在设备故障时自动重建数据时。远程位置有许多热备份设备并不罕见。在选择热备份时,要平衡所需的空间与替换设备安装所需的时间。这与
–spare-devices 选项对应。 -
MD 设备的编号是多少?传统上,你从 0 开始,并逐渐增加,但要追踪这些编号,以免不小心使用了错误的设备。这与
/dev/md#对应。 -
你将使用的驱动器路径是什么?它们通常是
/dev/sd#、/dev/nvme#,甚至是/dev/vd#。
在以下示例中,我们将创建一个带有一个热备份的 RAID-5 阵列。所使用的设备是/dev/sd[bcdef],这将是/dev/md0设备:
mdadm --create /dev/md0 --level=5 --raid-devices=4 --spare-devices=1 /dev/sd[bcdef]
你可以通过查看/proc/mdstat文件来快速检查状态:

图 4.17 – /proc/mdstat
最后一步,虽然是可选的,但强烈推荐执行。它将当前的配置保存到 mdadm 配置文件中。这有助于内核在启动时组装阵列。使用以下命令可以完成此操作:
mdadm --examine --scan >> /etc/mdadm.conf
它是如何工作的…
现在,让我们看一下 MD 设备的一些细节。首先,如果我们使用lsblk命令,我们会看到 md0 使用的磁盘现在已被标识为 md0 的子设备。这是因为 md0 是实际磁盘的子设备:

图 4.18 – lsblk 命令输出
我们还可以通过 mdadm 命令的 -Q 选项来检查设备。只需将设备作为参数传递,命令会给出一个简短的总结:
mdadm -Q /dev/md0
输出如下:

图 4.19 – mdadm -Q
可选地,您可以传递 –-detail 选项,以获取关于阵列的更多信息:

图 4.20 – mdadm --detail
在这里,我们不仅可以看到阵列的健康状态,还可以看到其创建日期和一些底层指标,如块大小和布局。
一旦卷被创建,您现在可以将其用于文件系统或作为逻辑卷管理器的存储。
玩转逻辑卷管理
在谈到文件系统时,一个最大的问题是其在存储方面的局限性。在磁盘上创建一个卷意味着该空间会被锁定,进而也锁定了文件系统的大小。然而,逻辑卷管理器(LVM)为此问题提供了解决方案。LVM 是计算机存储管理领域中广泛使用的工具,它充当物理存储设备(如硬盘或 SSD)与操作系统之间的抽象层。这样可以灵活而高效地管理存储资源。LVM 尤其对于 Linux 系统来说非常有价值,因为它提供了一个灵活且可扩展的存储管理解决方案。
使用 LVM,管理员可以动态分配和调整存储卷的大小,无需重新分区磁盘或中断系统。这个灵活性在存储需求经常变化或需要高效资源分配的环境中尤为有用。此外,LVM 引入了卷组的概念,卷组作为物理存储设备的逻辑容器。通过在卷组中创建逻辑卷,管理员可以轻松分配和管理存储空间,从而简化了 Linux 系统中的存储资源管理,并使得存储资源的组织和利用变得更加高效。
在 LVM 中,存储有三个核心组件:
-
物理卷(PVs):这些是用于存储的块级磁盘设备。它们可以是物理磁盘、虚拟磁盘(例如在 mdadm 配方中创建的 MD 设备)或其他块级设备。
-
卷组(VGs):这些是由多个 PV 组合成的单一逻辑设备。它们可以一开始是一个单独的设备,后续可以添加新设备来增加容量。
-
逻辑卷(LVs):这些是内嵌在 VG 中的逻辑磁盘。它们用于创建文件系统,并可以根据需要动态调整大小。
LVM 中的 VG 是一个核心组件,充当一个或多个 PV 的逻辑容器。VG 是通过将物理存储设备(如硬盘或 SSD)组合成一个单一的存储池来创建的。
在本食谱中,我们将向你展示如何初始化 PV,创建 VG,然后添加 LV 供文件系统将来使用。我们还将展示一些基本的管理命令。
准备就绪
本食谱中的示例将使用在 mdadm 配方中创建的 /dev/md0 虚拟磁盘,以及一些额外的 LUN。LVM RPM 通常会在默认安装时自动安装。
如何操作…
第一步是确定我们可以使用哪些磁盘。这可以通过 lvmdiskscan 命令完成:

图 4.21 – lvmdiskscan
在这里,我们可以看到三个设备,md0、sda1 和 sda2。我们还可以看到 sda2 已经初始化为 PV。我们可以使用 pvs 命令显示系统上的 PV:

图 4.22 – pvs
在这里,我们可以看到 /dev/sda2 设备由 ol VG 使用。让我们继续使用 pvcreat 来初始化 /dev/md0。这是通过以下命令完成的:
pvcreate /dev/md0
现在设备已经初始化,我们可以创建一个 VG。这可以通过 vgcreate 命令完成。该命令使用第一个参数作为 VG 的名称,然后列出设备。在这种情况下,我们只使用 /dev/md0 来创建 DATA VG:
vgcreate DATA /dev/md0
如何运作…
我们可以使用 vgs 命令查看系统上的 VG 列表:

图 4.23 – vgs
在这里,我们可以看到两个 VG:新创建的 DATA VG 和已存在的 ol VG,其中安装了操作系统。接下来,我们将使用 VG 来创建 LV。这可以通过 lvcreate 命令完成。lvcreate 命令需要一些参数:-L 用来设置卷的大小,-n 用于命名,然后在最后指定卷所在的 VG。让我们在 DATA VG 中创建一个名为 xfs1 的 3 GB 卷:
lvcreate -L 2G -n xfs1 DATA
我们还可以告诉 lvcreate 使用所有可用空间。通过使用小写字母 l 和特殊的 100%FREE 选项来完成:
lvcreate -l 100%FREE -n xfs2 DATA
lvs 命令将显示服务器上的所有 LV:

图 4.24 – lvs
在这里,我们可以看到 xfs1 和 xfs2 卷及其大小。此外,我们还可以看到 ol 中的所有卷,Linux 就安装在这里。
让我们通过删除 xfs2 LV 来释放一些空间。这可以通过 lvremove 命令完成。在使用 lvremove 时,使用 VG/LV 来标识正在删除的 LV。以下命令将删除 xfs2 LV:
lvremove DATA/xfs2
你还需要确认删除操作:

图 4.25 – lvremove
最后的技巧是查看特定 LV 的详细信息。这可以通过 lvdisplay 命令完成。你可以单独运行该命令,这将显示服务器上所有 LV 的详细信息。你还可以使用该命令报告单个 LV,在本例中是 xfs1 LV:
lvdisplay /dev/DATA/xfs1
输出如下:

图 4.26 – lvdisplay
在这里,你可以看到卷的创建日期、UUID 和卷的大小。
一旦创建了逻辑卷(LV),有多种方式可以访问它们,但最常见的方法是使用其映射地址。在 Linux 中,/dev/mapper 目录用于访问设备映射器设备,设备映射器是一个内核级框架,允许创建和管理虚拟块设备。通过设备映射器,可以实现软件 RAID、加密和 LVM 等高级存储功能。使用 LVM 时,设备映射器会创建虚拟设备,并将它们作为设备映射器设备显示在 /dev/mapper 目录下,这些设备充当抽象层,并提供一个接口来访问和管理底层存储功能。
例如,使用 LVM 设置的逻辑卷会映射到 /dev/mapper 目录下的设备映射器设备。每个逻辑卷都有一个对应的设备映射器设备条目,可以像普通块设备一样与逻辑卷进行交互。访问路径为 /dev/mapper 后跟 VG-LV 名称。因此,DATA/xfs1 对应的路径为 /dev/mapper/DATA-xfs1。你可以使用 dmsetup ls 命令查看所有映射的设备:

图 4.27 – dmsetup ls
XFS – 创建、修改等
XFS 是一个高度先进且成熟的文件系统,具有多种优点和特性,使其成为广泛应用场景中的理想选择。XFS 旨在处理大容量存储,适用于数据需求较高的环境。它能够支持高达 8 exabytes 大小的文件系统和文件,从而管理大量数据。这种可扩展性使 XFS 特别适合大数据应用、企业存储系统和大规模存储部署。XFS 拥有出色的性能能力,采用了基于分配组的块映射、延迟分配和异步 I/O 等先进技术,优化了磁盘 I/O 操作,提高了整体吞吐量。XFS 在处理大文件和执行大量读写操作时特别高效。
XFS 集成了数据保护功能,以防止数据损坏。它采用了元数据和数据的校验和机制,使得文件系统能够检测并处理潜在的数据完整性问题。此外,XFS 支持写时复制(COW)快照,能够实现高效的时间点备份和数据恢复选项。XFS 还使用日志机制,在系统崩溃或电力故障时提供快速恢复。日志功能记录对文件系统元数据的修改,确保数据的一致性和完整性。这使得启动时间更快、可靠性更高,并减少了系统启动时进行文件系统检查所需的时间。
注意
Oracle 积极为许多 Linux 技术做出贡献。COW XFS 特性就是 Oracle 为社区做出的一个贡献示例,保持 Linux 的自由和开源。更多信息,请参阅 blogs.oracle.com/linux/post/xfs-data-block-sharing-reflink。
使用 XFS,管理员可以在文件系统挂载和使用时执行广泛的文件系统操作。这包括在线调整大小,实现对文件系统的无缝扩展或收缩,无需卸载或服务中断。这些在线管理功能使得 XFS 非常适合需要连续可用性和最小停机时间的环境。XFS 还提供了对扩展属性、访问控制列表(ACLs)和纳秒级时间戳的广泛支持。这些功能为管理文件元数据提供了灵活性,并支持复杂权限结构和自定义元数据方案的实现。
XFS 是 Linux 内核原生支持的文件系统,使其成为 Linux 发行版中一个良好集成和广泛采用的选择。它是 Oracle Linux 的默认文件系统,并继续由 Oracle 和 Linux 社区进行持续开发和改进。此外,XFS 提供了一套全面的文件系统管理和管理员工具,使其成为一个全面优秀的选择。
准备就绪
本示例中将使用先前创建的 xfs1 逻辑卷(LV)。XFS 文件系统可以在任何块设备上创建。
如何做到…
创建 XFS 文件系统最常见的方式是使用 mkfs.xfs 命令,并将数据和日志放置在同一设备上:
mkfs.xfs /dev/mapper/DATA-xfs1
此外,您可以使用额外的参数来获得更多控制:
| 选项 | 描述 | 示例 |
|---|---|---|
-L |
这将为文件系统添加一个标签。 | -L Test |
-b |
这将设置块大小。 | -b 8192 |
-f |
这是强制选项。 | -f |
-l |
这将设置日志的位置和大小,通常用于通过将日志置于快速设备上而将数据置于较慢设备上来调整性能。Size=20m /dev/$DEVICE |
-l 20m /dev/mapper/journal1 |
表 4.3 – XFS 选项
接下来,在 /etc/fstab 中添加条目信息。确保验证挂载点是否存在,并使用正确的 /dev/mapper 路径。更新后的文件如下截图所示:

图 4.28 – /etc/fstab
现在我们可以使用以下 mount 命令挂载文件系统:
mount /xfs1
我们可以清楚地看到文件系统现在已经挂载,如从 df 命令的输出所示:

图 4.29 – df -h
如何运作…
现在文件系统已挂载,我们可以对其进行一些操作。第一个任务是扩展文件系统,因为 2GB 对于该应用程序来说有些太小了。这个过程分几个步骤进行。首先,我们扩展包含文件系统的逻辑卷(LV),然后我们可以扩展文件系统。我们将其扩展到 10GB。
为了增加磁盘容量,我们将使用lvextend命令,并传递+选项来添加额外的 8GB:
lvextend -L +8G /dev/mapper/DATA-xfs1
输出结果如下图所示:

图 4.30 – lvextend
一旦逻辑卷(LV)扩展完成,我们需要扩展实际的文件系统。可以使用xfs_growfs命令来完成这个操作,传递映射路径:
xfs_growfs /dev/mapper/DATA-xfs1
根据文件系统的活动情况,扩展过程可能需要几分钟。xfs_growfs命令完成后,输出将显示文件系统的详细信息:

图 4.31 – xfs_growfs
你还可以使用xfs_info命令查看这些详细信息,传递文件系统的挂载点或映射路径。
如果在挂载xfs文件系统时遇到问题,可以使用xfs_repair命令行工具进行修复和恢复。然而,请记住,该命令必须在未挂载的文件系统上运行。xfs_repair的主要功能是修复由停电、系统崩溃或硬件问题引起的 XFS 分区中的不一致性和文件系统损坏。你也可以使用-n选项检查文件系统而不进行修复。例如,你可以使用以下命令检查xfs1文件系统而不进行修复:
xfs_repair -n /dev/mapper/DATA-xfs1
第五章:使用 DNF 进行软件管理
没有包,一个全新的 Linux 安装几乎和没有轮胎的汽车一样没用!你需要能够为系统添加软件,使它变得有用。这可以通过几种方式来完成。回到旧时光(嘿,我可是个真正的灰胡子 Unix/Linux 人),你曾经需要下载源文件,然后手动构建和安装。有时你可以获得预构建的包,但通常,所需的依赖关系需要花费数小时才能手动追踪下来。然后,在 1997 年,Red Hat Package Manager(RPM)文件问世了。它们简化了这个过程,因为你所需要做的就是找到安装应用程序所需的所有 RPM 文件,然后就能开始了。
然后,应用程序开始变得更加复杂;以 Apache HTTP 服务器为例——它的所有可选功能从 2-3 个 RPM 包增加到十多个,还有所有的依赖关系。追踪所有的 RPM 包及其依赖关系变得非常繁琐……由于版本不匹配,混乱迅速占据了主导地位。这一切在 2003 年 Yellowdog Updater, Modified(YUM)发布时戛然而止。现在,你可以为所有 RPM 包设置一个集中位置,轻松安装和修补这些包及所有依赖关系。Red Hat Enterprise Linux(RHEL)迁移到了 YUM,生活变得美好。
注意
YUM 替代了Yellowdog Update Program(YUP),后者是 Yellowdog Linux 使用的原始安装工具。Yellowdog Linux 是一款为 PlayStation 3 和 IBM 系统上的 POWER7 CPU 构建的 Linux 发行版,基于 CentOS/RHEL。尽管它在 2012 年停止更新,但它仍通过 YUM 继续存在。
Linux 发行版(如 RHEL 和 Oracle Linux)为特定的发行版在线维护 YUM 服务器,但如果你能够构建自己的 RPM 包并维护自己的 RPM 仓库呢?如果这些自定义 RPM 包可以用来部署内部构建的应用程序,并且进行所需的配置更改,使它们按预期运行呢?本章讲解了 RPM 文件的管理,从 yum 命令到 dnf 命令的过渡,管理 RPM 包,创建私人 RPM 仓库,并制作新的 RPM 包。
本章包含以下内容:
-
他们对 YUM 做了什么,转向 DNF?
-
使用 DNF 时间机器
-
从 ULN 构建 DNF/YUM 镜像
-
创建新的 RPM 包
他们对 YUM 做了什么,转向 DNF?
YUM 很好——它有效,且允许管理员轻松安装和修补软件。你甚至可以用它来回滚一个不良的安装。那么,发生了什么?为什么会发布 DNF?什么是 DNF,学习新工具会有多难?
首先,DNF 代表 Dandified YUM,是对 YUM 软件的重写。它在 2013 年的 Fedora 18 中发布,旨在解决 YUM 开始面临的许多问题。
YUM 的两个最常见问题是性能和内存使用:
-
性能差:YUM 存在性能问题。许多问题是由依赖关系解析引起的,这一过程将所有包及其依赖项组合在一起。这个过程可能需要长达 10 分钟。DNF 切换到 libsolv,大大减少了解决复杂依赖关系的时间。如今,这种情况越来越普遍,有些应用程序需要 30 个以上的 RPM。
-
高内存使用:YUM 使用大量内存;这个问题在 RHEL/CentOS 7 中变得尤为明显,较小的服务器在更新时经常会耗尽内存。
准备就绪
DNF 的变化不仅体现在性能上,还有一些行为上的关键差异。为了测试这些变化,你需要一个 Oracle Linux 8 系统,并访问至少免费的公共仓库,例如 yum.oracle.com。你还可以考虑在虚拟化环境中运行 Oracle Linux,这样可以利用快照在更改前后保留操作系统的副本。Oracle VM VirtualBox 是实现这一目标的好方法。
如何操作…
在大多数情况下,DNF 和 YUM 的工作方式相同:dnf install 和 yum install 看起来一样,但 DNF 更快。dnf upgrade 和 yum upgrade 也一样,所以你可能已经了解了基本的用法。
在 YUM 中,update 和 upgrade 有略微不同的行为,yum update 会从系统中删除旧版包。而在 DNF 中,update 和 upgrade 都会更新已安装的软件,但 upgrade 还会删除过时的包。此外,auto-remove 选项会删除系统中不再需要的包。
注意
从 Oracle Linux 8 开始,yum 命令变成了 dnf 命令。
在 DNF 的开发过程中,大多数命令都是一样的,但 DNF 确实有一些特别的功能,比如自动运行更新。
DNF 自动更新
你可以设置 DNS 使其自动运行。为此,安装 dnf-automatic 包,并通过以下命令启用该服务:
yum install dnf-automatic
systemctl enable dnf-automatic.timer
systemctl start dnf-automatic.timer
接下来,编辑 /etc/dnf/automatic.conf 文件。这个文件里有一些技巧。你可以通过将 apply_updates 参数设置为 yes 来覆盖是否在下载时应用补丁。这样,当任务运行时,补丁就会被强制应用。
别忘了设置 system_name 参数,这样电子邮件和通知中就会显示正确的名称。
你还可以设置系统,通过电子邮件报告安装了哪些内容。在 [email] 配置段中设置电子邮件。如果使用邮件中继,确保它不需要身份验证,或者如果需要,添加相应的配置。
最后的技巧是,你可以将 emit_via 参数从 stdio 更改为 motd。设置为 motd 时,系统的 motd 文件会更新,显示已安装的补丁内容。用户登录系统时,会看到已安装的补丁列表和安装时间,示例如下截图:

图 5.1 – 登录时的 MOTD
默认情况下,服务会在早上 6 点检查更新。你可以通过编辑/etc/systemd/system/timers.target.wants/dnf-automatic.timer文件来修改这个时间:

图 5.2 – dnf-automatic.timer 文件
在这个文件中,[Timer] 段控制时间以及随机延迟。要更改运行时间,只需将6:00替换为你想要的时间,使用 24 小时制格式。例如,如果你希望检查时间为晚上 10 点,那么时间应该是 22:00。
由于使用了标准的OnCalendar函数,你有更多的选择。OnCalendar是一个非常灵活的方法;以下是一些最常用的示例:
| OnCalendar 示例 | 描述 |
|---|---|
| DOW YYYY-MM-DD HH:MM:SS | 通用的时间格式方法。 |
| --* 2:00 | 每天凌晨 2 点运行。 |
| Weekly | 每周一的午夜。 |
| Sat --* 2:00 | 每周六凌晨 2 点运行。 |
| Sat | 每周六的午夜。 |
| Sun 2022-- | 2022 年每个星期日的午夜。 |
| --1,15 22:15 | 每月的 1 号和 15 号晚上 10:15 运行。 |
| *-05-03/2 | 每年五月的第三天运行,然后每隔一个月的第二天运行。每年都按照相同的周期运行。这个日期格式表达式使用了连字符来进行格式化。 |
表 5.1 – OnCalendar 示例日期规则
RandomizedDelaySec 也是一个重要的设置。它会给时钟增加一个随机的延迟,这在许多系统运行的企业环境中非常有用。比如,200 台服务器在早上 6 点访问 YUM 仓库时,可能会让服务器压力过大。在/etc/dnf/automatic.conf中加入一个随机延迟,比如 600 秒,可以将负载分散到几分钟内。
DNF 是 YUM 的升级版,具有一些增强功能。正如在本章节中所看到的,它确实有一些巧妙的技巧,但它仍然为管理员提供了一种简便的方式,用于在 Oracle Linux 系统上安装和修补软件。
使用 DNF 时间机器
DNF 内置了时间机器!这不仅仅是回顾宇宙的方式,它实际上允许你查看安装的历史记录,还能回滚某一项更改,或者回滚所有更改直到某个时间点。
准备工作
为此,你需要一台运行 Oracle Linux 8 并能够访问 RPM 仓库的测试系统。
如何操作…
当 DNF 安装软件时,它会保留所有执行操作的历史记录,包括软件的升级、已安装的软件和已删除的软件。dnf history 命令显示这个历史记录:

图 5.3 – dnf history 命令
有五列:ID、命令行、日期和时间、操作和修改:
-
ID:这是历史记录的标识符,用于在命令中显示信息、回滚、撤销或存储事务。 -
命令行: 这是在执行命令时传递给 DNF 的选项,已添加到事务历史中 -
日期和时间: 这是事务执行时的时间戳 -
Action(s): 这是执行的操作;在同一事务中可以执行多个操作:-
(
D)降级: 一个软件包被降级 -
(
E)删除: 一个软件包已被移除 -
(
I)安装: 一个软件包已安装 -
(
R)重新安装: 一个软件包已重新安装 -
(
O)废弃: 一个软件包被标记为废弃 -
(
U)更新: 一个软件包已更新
-
-
变更: 这是命令执行时所更改的软件包数量,并附带几个例外标志:-
E/EE: 事务已完成,但产生了输出。并非所有输出都是错误! -
P: 事务已完成,但在rpm数据库中存在问题。 -
s: 事务已完成,但由于启用了--skip-broken参数,一些软件包被跳过。 -
>: 事务执行后,rpm数据库在 DNF 外部被更改。 -
<: 事务执行前,rpm数据库在 DNF 外部被更改。 -
*: 事务在完成之前被中止。 -
#: 事务已完成,但返回了非零状态。
-
当出现错误代码时,可以使用 dnf history info {ID} 命令查看详细信息,如 图 5.4 所示:

图 5.4 – dnf history info 命令
在此示例中,输出更多的是信息性内容,没有实际错误。这并不罕见。
你还可以使用 dnf history 来卸载一个软件包。有两种方法可以做到这一点:rollback 或 undo。rollback 命令尝试从当前点回滚所有 DNF 事务,直到指定的事务 ID。undo 命令只是撤销指定 ID 中的事务。
在测试系统上,让我们使用 dnf history undo 34 命令撤销 2022 年 4 月 17 日安装的 Nmap,事务 ID 为 34:

图 5.5 – dnf history undo 命令
这是一个相对简单的撤销操作,Nmap 被卸载。当查看事务后的 DNF 历史时,会看到一个新的 ID 40,显示 undo 命令。

图 5.6 – 撤销后的 DNF 历史
现在,如果目标是回滚所有更改,比如回滚到 ID 37,那么命令将是 dnf history rollback 37。这将使系统回滚到事务 37 完成时的状态。

图 5.7 – DNF 回滚
rollback 命令会回滚事务,因此 Nmap 实际上会重新安装,而 oracle-cloud-agent RPM 会被降级。这将在新的历史摘要中反映为 ID 41(如下图所示),在 ID 41 中我们可以看到安装和降级操作:

图 5.8 – DNF 回滚后的历史记录
注意
虽然rollback和undo命令通常可以很好地工作,但保持使用虚拟化程序或云原生工具进行操作系统快照仍然是一个好的做法。你还可以使用 Btrfs 来创建快照。有时候,RPM 包中的rollback脚本无法撤销系统的所有更改。通过利用基于存储的快照,你可以减少由于此类问题带来的风险。
DNF 系统维护了所有事务的数据库,dnf history命令及其选项使你能够访问该数据库,检查发生了什么,并且能够撤销单个事务或从最新的事务回滚到历史中的某个特定 ID。这是管理员在需要撤销补丁和软件安装时非常有用的工具。
从 ULN 构建 DNF/YUM 镜像
对于运行在安全网络中的系统(如银行或政府网络),管理员常常不会启用互联网访问。Oracle 的不可破坏 Linux 网络(ULN)的本地镜像是一个极好的方式,允许系统访问补丁,而无需通过互联网进行远程访问。
准备工作
为此,你需要一台运行 Oracle Linux 8 的 YUM 服务器系统。该本地系统应具备互联网访问能力,以便能够通过直接访问或代理服务器连接到 ULN 服务器。只有同步到 ULN 的系统(通常称为 YUM 服务器)需要此访问权限;所有使用该系统的其他系统不需要访问互联网,它们将通过该系统来访问补丁。
该系统不会占用大量 CPU 或内存——通常 2 个核心和 4 GB 内存就足够了,但该系统会使用大量磁盘空间。你可以通过运行dnf repolist -v命令来检查所需的空间。
一个 TB 的空间可能会很快用完,这取决于服务器订阅了多少个仓库。关于空间的好消息是,性能高的存储并不是必需的。如果你在 Oracle 服务器上运行,还需要一个有效的 Oracle 支持合同,该合同已包含在硬件支持合同中。在我的本地仓库中,我将仓库保存在/var/www目录下,并将其作为逻辑卷管理(LVM)下的一个独立文件系统挂载。这样,当需要更多空间时,可以轻松地进行扩展。
此外,应该安装一个 HTTP 服务器,并且你必须确保防火墙端口已打开。如果你需要帮助,请回到第二章,使用与不使用自动化工具进行安装,该章节中涵盖了如何设置 HTTP 服务器。
如何操作…
要构建镜像,请按照以下步骤操作:
-
第一步是验证
/var/www中是否有足够的空间。即使是一个小型镜像,也建议从 600 GB 开始。要密切关注磁盘空间,因为未来可能需要更多空间。较大的镜像很容易消耗掉 2 TB 的空间。 -
接下来,使用
dnf install uln-yum-mirror -y命令安装uln-yum-mirror包。uln-yum-mirror包包括自动化复制 Oracle ULN 仓库到本地服务器的脚本。确保系统能够访问ol8_addons仓库:

图 5.9 – uln-yum-mirror 安装
- 这将安装来自 Oracle 的脚本。接下来,让我们使用
uln_register命令将系统注册到 ULN。你需要知道uln_register命令。从那里,你将看到主界面:

图 5.10 – uln_register 启动界面
- 点击 下一步 继续。在下一个界面中,你将被提示输入 Oracle SSO 凭据。CSI 是支持标识符。请使用与你的 Premier 硬件支持或 Oracle Linux 订阅关联的 CSI。不要使用 Oracle 数据库、WebLogic、E-Business Suite 等的 CSI。CSI 应该是针对 Oracle Linux 的。
注意
在生产环境中,你可能会考虑创建一个共享账户,直接使用 ULN 注册所有服务器。这将使得在员工进出时更容易管理服务器。

图 5.11 – uln_register 凭据
- 接下来,你需要为 ULN 确定服务器的身份。通常,你会使用服务器的 完全合格域名(FQDN),但选择权在你。你也可以选择上传硬件详细信息,但这是可选的。

图 5.12 – uln_register 系统名称
- 接下来,系统将更新 ULN 以同步服务器上安装的软件,这将使你能够通过 ULN 跟踪已安装的 RPM,但仅限直接注册到 ULN 的系统。当使用本地仓库时,你可能会考虑使用像 Oracle Linux Manager 这样的工具来跟踪未注册到 ULN 的系统上的软件:

图 5.13 – uln_register 初始包
- 服务器在 ULN 上的注册几乎完成。最后一步是将信息发送到 ULN 以注册服务器,这将在下一步自动完成:

图 5.14 – uln_register 发送
上传可能需要最多一分钟,具体取决于你的网络速度。
上传完成后,系统现在已在 ULN 中注册。下一步是可选的。它将为服务器设置 Ksplice。如果你不想使用 Ksplice,可以跳过此步骤。Ksplice 还要求你拥有 Oracle Linux Premier Support 订阅。这个订阅包含在 Oracle 硬件支持和 Oracle Cloud 虚拟机中。你也可以为第三方系统购买此订阅,通常价格比其他商业 Linux 发行版便宜。

图 5.15 – uln_register ksplice
- Ksplice 是一个快速步骤;只需查看设置,如下截图所示,然后点击确定:

图 5.16 – uln_register 设置
- 注册现已完成。您应该在继续之前使用
dnf -y update(工具推荐的命令)来修补服务器:

图 5.17 – 完成的 uln_register
-
接下来,使用
dnf update -y修补系统并重启系统。需要注意的是,-y选项的位置对命令没有影响。系统重启后,您需要登录linux.oracle.com/。虽然此服务器现在已注册到 ULN,但它还不是本地仓库!我们需要告诉 ULN 这是一个本地仓库,并选择我们需要镜像的仓库。为此,访问
linux.oracle.com并点击登录按钮:

图 5.18 – ULN 主页
在管理服务器时,使用与注册服务器时相同的登录信息。
- 登录 ULN 后,您将看到所有注册到您账户下的服务器。您还会看到最近更新和添加到系统中的通道:

图 5.19 – 管理的服务器
- 从这里开始,我们需要将服务器提升为 YUM 仓库。这将告诉 ULN 允许该服务器分配任何通道,从而使其能够下载不属于特定服务器所需的 RPM 包。这包括不同 Oracle Linux 主版本的补丁、不同 CPU 架构(如 AArch64)的补丁,以及针对 Exadata 等平台的特殊补丁。为此,点击服务器名称,然后点击编辑按钮:

图 5.20 – 编辑服务器
- 在此页面上,我们将更新服务器属性以使其成为 YUM 服务器。勾选Yum Server复选框,然后点击应用更改:

图 5.21 – 将其设为仓库
- 接下来,我们需要为服务器分配额外的通道。这将允许服务器提供它所订阅的任何通道。要管理包含相关 RPM 包的 RPM 通道,请点击管理 订阅按钮:

图 5.22 – 管理订阅
- 接下来,您将看到左侧是所有可用的频道,右侧是分配给服务器的频道。虽然您可以批量选择所有频道,但最好只选择您需要的频道。在此示例中,Oracle Linux 8 Addons x86_64 正在被添加。您还可以为不同的主版本号添加频道,例如 Oracle Linux 7。当选择频道时,请确保选择 < 或 > 符号来订阅或取消订阅本地服务器。如以下图中的第 2 步所示。另外,一旦完成选择,您必须点击 保存订阅 选项来更新订阅。如果在未保存订阅的情况下退出,所做的任何更改都将丢失。

图 5.23 – 添加更多仓库
注意
添加频道时,只添加您需要的频道,以节省空间和带宽。如果不小心,您可能会轻松下载几个 TB 的数据。另外,归档频道可能非常大,并且通常不适用于大多数站点,因为它们包含较旧的版本。如果开始在本地使用这些频道,预计会占用多个 TB 的磁盘空间。
- 确保您看到 订阅 已保存 消息:

图 5.24 – 保存配置
现在,我们终于完成了本地仓库的设置。接下来,作为 root 用户运行 uln-yum-mirror 命令,仓库将开始同步。这个过程可能需要几个小时,具体取决于您的互联网速度和您订阅的频道数量。系统也会每天自动运行,保持本地副本的最新状态。
注意
在进行第一次同步时,请密切关注磁盘空间。第一次时,您可能需要快速增加空间。如果发生这种情况,增加空间并手动重新启动 uln-yum-mirror 命令。
当您完成手动运行时,脚本会告诉您每个仓库复制了多少数据:

图 5.25 – 完成的镜像
配置完成后,系统将自动将本地仓库与 ULN 同步。随着您添加新的频道,它们将在 cron 作业运行时自动下载。
创建新的 RPM 包
虽然 Oracle 提供了大量的 RPM 文件,但有时您可能需要创建自定义的 RPM 包,以便轻松部署自己的软件。创建一个 RPM 文件是非常简单的!
准备工作
为了做到这一点,您将需要一个运行 Oracle Linux 8 的开发系统,并且可以访问 企业 Linux 的额外软件包 (EPEL) 频道。强烈建议使用专用系统来构建 RPM,而不是在生产系统上构建 RPM。您还需要一个系统来测试安装 RPM。
注意
根据构建的包,您可能需要额外的频道,如 CodeReady 或 Distro Builder。
在此之前,我们需要做一些准备工作——主要是安装 RPM 开发工具。为了做到这一点,我们还需要将 EPEL 仓库添加到系统中。
虽然本书中的大多数配方使用root用户进行大部分工作,但本配方仅在安装软件时使用 root。接下来的几步请使用root用户执行。
要添加 EPEL 仓库,请运行以下命令:
dnf install oracle-epel-release-el8
接下来,运行以下命令来启用 EPEL 以及codeready和distro_builder仓库。将所有这些工具安装到你的构建系统中,将来能更方便地利用更高级的构建工具,如 Mock:
dnf config-manager --enable ol8_developer_EPEL
dnf config-manager --enable ol8_codeready_builder
dnf config-manager --enable ol8_distro_builder
接下来,我们将安装构建rpm文件的基本工具。运行以下命令来安装这些工具:
dnf install -y rpm-build yum-utils rpmdevtools
如果你从 Git 拉取软件,可能需要安装git和git-lfs(gcc、make和python3-service-identity RPM 包也很常见。你可以使用以下命令安装所有这些:
dnf install -y git git-lfs make gcc python3-service-identity
如何操作……
现在我们已经安装了所有工具,切换到非 root 用户:
-
为 RPM 创建一个目录。在这里,我们将有一个软件源文件,以及所有将其制作成 RPM 所需的文件和目录。以我的情况为例,我将所有内容放在
/home/erik/中。 -
接下来,我们需要创建 RPM 目录树。可以通过运行
rpmdev-setuptree命令来完成此操作。运行该命令后,树状结构将在$HOME下的rpmbuild目录中创建:

图 5.26 – rpmbuild 目录
还会构建五个目录,每个目录都有特定的用途:
-
BUILD:这是编译后的二进制文件保存的地方。 -
RPMS:在这里创建 RPM,生成可以使用的rpm文件。这里会有针对不同 CPU 架构的子目录。 -
SOURCES:这是放置源代码的地方,通常是一个 tar 文件。 -
SPECS:这是.spec文件所在的目录。 -
SRPMS:源 RPM 文件将在这里构建——通常是包含软件源代码的包。
- 创建一个简单的 Bash 脚本,作为 RPM 发布。它将位于
rpmbuild目录下的xyzzy目录中。同时还创建了一个简单的 Bash 脚本:

图 5.27 – xyzzy.sh 脚本
-
接下来,创建一个包含
xyzzy目录内容的压缩 tar 文件:[erik@ol8 rpmbuild]$ tar -cvf SOURCES/xyzzy-1.0.tar.gz xyzzy xyzzy/ .spec file. The .spec file contains the name of the program, a description of the program, licensing information, project URL, build architecture, and more. The following command will create a default .spec file in the SPECS directory:rpmdev-newspec SPECS/xyzzy.spec
The skeleton is very sparse and will need information added.The sample skeleton is seen as follows:

图 5.28 – 基本.spec 文件
为了使其功能正常工作,需要做很多事情。
Version和Summary部分需要填写,另外还需要填写License信息和项目的 URL。此外,将构建架构设置为noarch,因为这将同时安装在 ARM 和 X64 系统上。重要的是确保包含Name、Epoch、Version、Release 和 Architecture(NEVRA)信息。这有助于确保正确的 RPM 安装到系统中。
已设置描述,并且更新了 %install 部分以反映脚本安装到正常的二进制目录中。
%files 部分显示了 /usr/bin/xyzzy.sh,因为所有 .sh 文件都被添加到安装程序中。未使用的部分也会被移除。
最终结果如下:

图 5.29 – 完成的 .spec 文件
rpm文件将通过rpmbuild命令构建,并传入.spec文件的路径。使用的命令是rpmbuild -bb -v SPECS/xyzzy.spec,其输出如下:

图 5.30 – rpmbuild 的输出
- RPM 文件现在位于
RPMS目录下的noarch目录中:

图 5.31 – RPM 文件
该 RPM 文件现在可以复制到其他系统上手动安装,或者添加到 YUM 仓库中。
- 安装后,您可以使用
rpm -qi xyzzy-1.0命令查看来自.spec文件的详细信息,例如许可证、描述等:

图 5.32 – RPM 文件详细信息
RPM 工具使您能够轻松构建自定义的 RPM 文件进行分发。这是通过 .spec 文件驱动的,该文件包含了所有的依赖关系、描述、文件位置,甚至是构建信息,用于创建 RPM 文件。
第六章:消除所有 SPOFs!冗余练习
在架构中确保冗余是至关重要的,以确保平稳的操作。消除单点故障(SPOFs)是实现这一目标的常见方法。实施高可用性(HA)技术是消除 SPOFs 的一种方式。HA 技术至关重要,因为它帮助企业保持运营连续性,提升性能,提高可靠性,促进灾难恢复(DR),建立客户信任,并遵守法规。通过 HA 技术,可以最小化停机时间并确保持续的服务可用性,从而为今天技术驱动的世界中的整体成功和竞争力做出贡献。
注释
那么灾难恢复呢?本章不涵盖数据中心故障的问题。话虽如此,灾难恢复的实施方法与 HA 非常不同。在云中运行时,可以寻找像 Oracle 全栈灾难恢复服务这样的服务,它们为整个技术堆栈自动化灾难恢复过程。
本章中的操作指南将帮助你消除环境中的 SPOFs。我们将首先概述 HA 和可用性,然后介绍如何为你的应用程序增加冗余的几个示例。帮助消除应用程序中的 SPOFs 的四种最常见技术是 HAProxy、Corosync、Pacemaker 和 GlusterFS。它们每个都提供了一套特定的功能来帮助使应用程序高度可用:
-
HAProxy:这是一个负载均衡器,允许你在服务器之间平衡 Web 工作负载
-
Corosync:这是一个通信系统,支持应用程序内部实现 HA 的通信。
-
Pacemaker:Pacemaker 是一个开源资源管理器,用于构建小型和大型集群。
-
GlusterFS:这是一种可扩展的网络文件系统,允许多个节点同时读取和写入同一存储中的数据。
以下的操作指南将帮助你实现这些常见的 HA 技术。这包括从负载均衡应用程序和集群应用系统到集群存储和冗余网络的一切内容:
-
获得 99.999% 的可用性及更高
-
网站的负载均衡
-
使用 Keepalived 使 HAProxy 高可用
-
使用 Corosync 和 Pacemaker 实现 HA 集群
-
在多个机器间共享文件系统——集群还是分布式?
-
生成、配置并监控通过 bond 的以太网流量
技术要求
对于这些大多数食谱,你需要一对 Oracle Linux 8 系统。与大多数这些食谱一样,建议在桌面上使用桌面虚拟化产品(如 Oracle VirtualBox)创建虚拟机。小型虚拟机就足够了,配有两个核心、2GB 内存和一些可用磁盘空间。你还需要为虚拟机分配一些额外的磁盘,最好至少有五个大小相等的磁盘。在开始之前,先将你的系统更新到最新的软件包。这样做只需要几分钟,但可以节省很多排除因错误导致问题的时间。
本书中的许多食谱相关配置文件可在 GitHub 上找到,链接:github.com/PacktPublishing/Oracle-Linux-Cookbook。
获得 99.999%及以上的可用性
本节将讨论灾难恢复(DR)和高可用性(HA)之间的区别,以及如何构建 HA 解决方案。在我们开始之前,先来澄清几个关键术语的定义:
-
高可用性,或HA:指的是防止单个组件故障的措施。可以将其理解为防止整个系统故障的保护措施。
-
灾难恢复,或DR:指的是数据中心或云区域的故障。
-
可用性九个:当提到可用性的九个时,它是通过指定正常运行时间百分比中的九个数字来量化系统的正常运行时间或可靠性。每个九个代表正常运行时间百分比中的一个小数位。
下面是最常用的nines及其对应的正常运行时间百分比的分解,假设 24x7x365 的运营模式:
| 九个 | 每年停机时间 | 每月停机时间 |
|---|---|---|
| 99 | 3 天 14 小时 56 分钟 18 秒 | 7 小时 14 分钟 41 秒 |
| 99.9 | 8 小时 41 分钟 38 秒 | 43 分钟 28 秒 |
| 99.99 | 52 分钟 10 秒 | 4 分钟 21 秒 |
| 99.999 | 5 分钟 13 秒 | 26 秒 |
| 99.9999 | 31 秒 | 2.6 秒 |
表 6.1 – 九个停机时间
在前面的表格中,正常运行时间百分比中每增加一个九个,意味着更高的可用性和更低的停机容忍度。实现更多的九个通常需要实施冗余系统、故障切换机制和严格的维护实践,以最小化停机时间并确保持续运行。此外,在设置服务级别协议(SLA)时,还可以定义在工作时间内的正常运行时间,并排除计划的维护。例如,使用每周一到周五、每天 12 小时工作、每年 10 个假期的工作计划时,矩阵会看起来非常不同!
| 九个 | 每年停机时间 | 每月停机时间 |
|---|---|---|
| 99 | 1 天 7 小时 2 分钟 58 秒 | 2 小时 35 分钟 14 秒 |
| 99.9 | 3 小时 6 分钟 18 秒 | 15 分钟 31 秒 |
| 99.99 | 18 分钟 38 秒 | 1 分钟 33 秒 |
| 99.999 | 1 分钟 52 秒 | 9 秒 |
| 99.9999 | 11 秒 | 1 秒 |
表 6.2 – 工作时间停机时间
注
在与业务部门设置 SLA 时,务必清楚理解在 SLA 中包括维护窗口和运营时间的区别。
准备工作
在设计 HA 系统时,需要考虑几个方面,以确保系统具有弹性并能够应对故障。以下是一些关键考虑因素:
-
冗余:在 HA 系统中实现冗余是必不可少的。这需要复制组件或整个系统,以消除潜在的单点故障(SPOF)。冗余可以在不同的层面实现,如硬件、软件和网络基础设施。为了最小化局部故障的影响,必须将冗余组件分布在不同的物理位置。
-
故障转移和负载均衡:HA 系统必须配备故障转移机制,使其在发生故障时能够自动切换到备份系统。实现这一点的一种方式是通过将数据和服务复制到多台服务器,并结合使用负载均衡技术,确保负载的均匀分配。通过负载均衡,流量可以在服务器故障时轻松地重定向到可用的服务器。
-
可扩展性:在设计高可用性(HA)系统时,确保系统能够处理增加的工作负载并能够轻松扩展非常重要。这可以通过水平扩展来实现,即添加更多的服务器以分配负载,或者通过垂直扩展来实现,即向现有服务器添加资源。此外,系统应能够根据需求动态调整资源分配,以防止过载。
-
数据复制和备份:维护数据的完整性和可用性对 HA 系统至关重要。为了确保在系统故障时仍能访问数据,必须将数据复制到多个存储系统或数据库中。此外,定期备份对于防范潜在的数据丢失或损坏至关重要。
-
容错性:用于高可用架构的系统应具备容错能力,这意味着即使特定组件或子系统发生故障,系统仍然能够正常运行。实现这一点需要构建一个能够轻松处理错误、自动恢复并确保服务连续性的系统。
-
灾难恢复:对于 HA 系统而言,拥有灾难恢复(DR)计划对于有效应对自然灾害或大规模停机等灾难性事件至关重要。该计划包括生成异地备份、设置备用数据中心以及依赖基于云的服务,确保即使在极端情况下也能保证业务连续性。
-
文档和测试:记录系统架构、配置和操作流程对于有效地排查故障和维护 HA 系统至关重要。定期测试,如故障转移测试、负载测试和灾难恢复演练,对于识别潜在问题并确保系统在各种场景中按预期运行起着重要作用。
-
成本和复杂性:设计、实施和维护高可用性系统可能既复杂又昂贵。重要的是仔细考虑可用预算,以及有效管理和监控系统所需的专业知识和资源。
通过解决这些考虑因素,您可以设计一个稳健且具有韧性的高可用性系统,确保高可用性、容错性和关键服务的连续性。
如何实现…
一般而言,您应选择适合的技术来应对合适的子系统和应用程序。
在旨在实现高可用性(HA)的 Web 应用程序中,第一步是将负载均衡器放置在 Web 服务器前面。这使得应用程序可以扩展,同时为这些系统提供一些容错能力。然而,还应关注数据层,可以通过对数据库进行集群化或根据数据库技术的限制构建一个能够运行数据库的集群来解决这一问题。
如果您使用的是如 Oracle 数据库这样的技术,您可以选择建立一个特定于数据库的集群,称为Oracle Real Application Clusters(Oracle RAC)。这个集群同时支持可扩展性和可用性。使用 RAC 时,只要一个节点在线,数据库就可以继续提供查询服务。虽然其他数据库可能会利用其独有的集群技术(例如 MySQL Cluster),您也可以选择使用通用的集群技术,如 Pacemaker 进行集群管理,使用 Corosync 进行集群间的通信。这种方法的优点是可以在 Linux 环境下使几乎任何技术实现高可用性。
您可以通过在整个集群上实现文件系统来实现存储的高可用性。Gluster 允许您在多个服务器之间挂载文件系统,同时在服务器之间复制存储。这在文件系统级别提供了可扩展性和可靠性。
最后,网络是常见的故障点,使用网络绑定技术可以实现高可用性以及一定的扩展能力。这通过将至少两个网络端口合并为一个虚拟端口来工作。
注意
最佳的高可用性架构将这些方法混合使用,覆盖整个技术栈。
网站负载均衡
如今,大多数应用程序都是基于 Web 的,无论是传统的 Web 界面还是 RESTful API。这一层通常会使用负载均衡器进行高可用性设置。负载均衡器是一个将传入的网络流量或工作负载分配到多个服务器或资源的系统。其主要目标是优化资源利用、提高性能,并确保应用程序或服务的可靠性和可用性。当多个服务器参与提供特定应用程序或服务时,负载均衡器充当客户端和服务器池之间的中介。它接收来自客户端的请求,并根据不同的算法(如轮询、最少连接数或加权分配等)智能地将请求分配到可用服务器上。
负载均衡器负责通过将流量从超负荷或有问题的服务器重定向到其他服务器,确保服务器的最佳健康和性能。这种工作负载的分配有助于防止任何一台服务器被过载,从而提高响应时间和整体系统的容量与可扩展性。
注意
虽然负载均衡器可以帮助分配工作负载,但实际的服务器负载是由其他因素决定的,因此不要期望所有服务器的 CPU、内存、网络等资源的利用率相同。
负载均衡器不仅分配流量,还提供一些高级功能,例如 SSL 终止、会话持久性、缓存和内容路由等。它们广泛应用于 web 应用、云服务以及其他需要高可用性和可扩展性的环境中。
最受欢迎的负载均衡器之一是 HAProxy。
HAProxy 是一个出色的开源负载均衡器选项。HAProxy 代表着 高可用性代理,因其卓越的性能以及提高应用程序可用性和可扩展性的能力而广泛应用。该软件工作在 OSI 模型的应用层(第 7 层),能够根据特定的应用层信息(例如 HTTP 头部和 Cookie)做出路由决策。与传统的网络层(第 4 层)负载均衡器相比,HAProxy 允许更先进的负载均衡和流量路由功能。
HAProxy 的一些关键特性和功能包括以下内容:
-
负载均衡:使用 HAProxy,传入的流量可以通过多种算法均匀分配到多个服务器上,例如轮询、最少连接数和源 IP 等。
-
高可用性:HAProxy 的一大优点是它支持主动-被动故障转移的设置。当活动服务器变得不可用时,备用服务器将接管。此外,它还能够监控服务器的健康状况,并通过添加或移除服务器自动调整负载均衡池。
-
代理:HAProxy 的主要功能之一是充当反向代理,它通过接收客户端请求并将其指向正确的后端服务器。此外,它还可以作为正向代理,拦截客户端请求并将其指向外部服务器。
-
SSL/TLS 终止:使用 HAProxy,SSL/TLS 加密和解密可以高效地管理,减轻后端服务器的负担。
-
会话保持:HAProxy 能够通过将来自客户端的后续请求路由到同一个后端服务器来保持会话亲和力,从而保证基于会话的应用程序的正常运行。
-
健康检查和监控:为了保证后端服务器的可用性和最佳性能,HAProxy 会进行定期的健康检查。它能够识别出失败的服务器并及时将其排除在负载均衡池之外。
-
日志记录和统计:通过 HAProxy,管理员可以有效地监控和分析流量模式、性能指标和错误状况。其详细的日志记录和统计功能使这一切成为可能。
HAProxy 可以部署在多种操作系统上,且常用于高流量的 Web 环境、云基础设施和容器化部署。它的多功能性和丰富的功能集使其成为管理和优化应用流量以及开源负载均衡器的强大工具。
在这个例子中,我们将把 HAProxy 安装在一台系统上(作为负载均衡器),然后再部署两台相同的 Web 服务器来平衡流量到:

图 6.1 – HAProxy 示例图
准备工作
要开始,首先我们需要三台服务器。在本练习中,我们将其命名为lb1、web1和web2。它们是相同的系统,每台有 8GB 内存、4 个 vCPU 和 100GB 硬盘空间。文件系统中,/有 50GB,/home有 5GB,交换空间为 8GB。剩余的磁盘空间为未分配。你还需要每台主机的 IP 地址。在本示例中,使用了以下 IP 地址:
| Host | IP |
|---|---|
| Web1 | 192.168.56.200 |
| Web2 | 192.168.56.201 |
| Lb1 | 192.168.56.202 |
表 6.3 – HAProxy IP 地址
一旦服务器搭建完成,使用以下命令将其更新到当前的软件版本:
dnf update -y
一旦软件打上补丁,重启系统。
Web 服务器
对于两个 Web 服务器,我们将安装 Apache,作为 root 用户,使用以下命令:
dnf install httpd -y
接下来,我们需要启用端口80通过防火墙,使用以下命令:
firewall-cmd --permanent --add-service=http; firewall-cmd --reload
然后我们需要启动服务器,并设置其开机启动。可以使用以下命令完成:
systemctl enable --now httpd
现在我们需要为该服务器设置一个基础的主页。
注意
根据你的环境,可能需要编辑 Apache 配置文件/etc/httpd/conf/httpd.conf来指定servername。在配置文件中,它将是单行条目,如下所示:
ServerName server.m57.local:80
这需要放入 /var/www/html/index.html。以下是一个示例文件。根据需要调整文本,使每个服务器都是唯一的。这样,你可以看到是哪台服务器被访问:
<!DOCTYPE html>
<html>
<body>
<h1> Running on web1</h1>
</body>
</html>
接下来,使用浏览器访问系统进行测试:

图 6.2 – 简单网站
接下来,重复在另一个 Web 服务器上的操作。一旦该系统启动,我们将设置负载均衡器。
注意
如果你在服务器上使用 httpd(TLS/SSL),别忘了在本地防火墙中启用 https。
负载均衡器
对于单一负载均衡系统,我们需要安装 HAProxy。这可以通过使用 dnf 命令以 root 用户身份完成:
dnf install -y haproxy
接下来,我们需要用以下命令在防火墙中打开 80 端口:
firewall-cmd --permanent --add-service=http; firewall-cmd --reload
接下来,我们需要编辑配置文件。配置文件位于 /etc/haproxy/haproxy.cfg。
配置文件有两个主要部分,global 和 defaults。配置文件中只能有一个 global 部分。这部分用于配置 TLS/SSL 数据、日志配置以及运行 haproxy 的用户和组设置。默认情况下,haproxy 作为用户 haproxy 和组 haproxy 运行。在大多数使用场景中,global 部分不需要更改。以下图示为例:

图 6.3 – HAProxy 全局设置
下一个部分叫做 defaults 部分,是你将进行大部分编辑的地方。它由三个子部分组成:frontend、backend 和 listen。
frontend 部分监听所有定义的 IP 地址和端口。这是用户将连接的部分。一个 HAProxy 服务器可以有多个 frontend 部分,但每个部分都需要一个唯一的名称和 IP/端口组合。
backend 部分定义了被负载均衡的服务器,定义了负载均衡方法以及流量发送到的服务器和端口。一个 HAProxy 服务器可以有多个 backend 部分,但每个部分都需要一个唯一的名称。
listen 部分用于定义如何监控负载均衡器,提供端口、URI 和监控 HAProxy 所需的认证信息。通常你只有一个 listen 部分。
对于同一个前端,我们将在 lb1 系统的 80 端口上监听,称为 www_app,并将定义这个 IP/端口组合使用 www_servers 后端。
frontend
HAProxy 配置文件的 frontend 部分提供了多种选项来管理传入流量的行为。这些选项可以用来控制前端流量的行为。以下是一些常用的前端选项:
-
bind:定义前端监听传入流量的 IP 地址和端口。例如,bind *:80表示在所有 IP 地址的80端口上监听。 -
mode: 指定前端的模式,例如http、tcp或ssl。对于 HTTP 流量,使用mode http。如果要负载均衡一个通用的 TCP 端口,请使用mode tcp。 -
option: 启用或禁用前端的特定选项。一些常用选项如下:-
option httplog: 启用 HTTP 请求/响应日志记录 -
option dontlognull: 防止记录缺失或空白用户代理字符串的请求 -
option forwardfor: 在使用 HTTP 代理模式时,将客户端的 IP 地址添加到 HTTP 请求头中 -
option http-server-close: 强制服务器在处理请求后关闭连接,而不是使用持久连接(keep-alive)
-
-
timeout: 配置前端的各种超时时间:-
timeout client: 设置客户端建立连接并发送数据的最大时间限制 -
timeout server: 设置服务器响应请求的最大时间限制 -
timeout connect: 设置等待连接后端服务器的最大时间
-
-
acl: 定义匹配特定条件的规则。ACL 与后端配置配合使用,根据不同标准控制流量路由。 -
use_backend: 指定用于处理符合特定 ACL 条件的流量的后端。它允许你根据特定条件将流量引导到不同的后端服务器。 -
default_backend: 定义当没有 ACL 条件匹配传入流量时使用的默认后端。 -
redirect: 在特定条件下执行 URL 重定向。例如,可以使用example.com重定向地址将 HTTP 流量重定向到 HTTPS。 -
http-request和http-response: 用于添加自定义 HTTP 请求/响应头,或根据 HTTP 请求/响应数据执行特定操作。 -
capture: 捕获请求或响应头的部分内容并将其保存到变量中。
对于示例前端,我们将前端定义为 www_app,绑定到负载均衡系统上所有 IP 的 80 端口。如下图所示:

图 6.4 – 示例前端
backend
使用 HAProxy 时,后端选项在配置后端服务器行为和流量路由方面起着至关重要的作用。这些选项专门在 HAProxy 配置文件的 backend 部分中指定。以下是一些常用的后端选项:
-
mode: 指定后端的模式,例如http、tcp或ssl。对于 HTTP 流量,请使用http模式。 -
balance: 定义负载均衡算法,用于将流量分配到后端服务器。常见的选项包括:-
balance roundrobin: 按照轮询方式依次将请求分配给每个服务器 -
balance leastconn: 将流量发送到活动连接数最少的服务器 -
balance source: 基于客户端的 IP 地址哈希,将流量一致地导向特定服务器。
-
-
server: 定义后端服务器及其地址、端口和可选参数。 -
timeout: 配置后端的各种超时:-
timeout server: 设置服务器响应请求的最大允许时间。 -
timeout tunnel: 配置建立隧道的最大时间(用于 TCP 模式)。
-
-
http-request和http-response: 类似于前端选项,主要用于添加自定义 HTTP 请求/响应头,或根据 HTTP 请求/响应数据执行特定操作。 -
cookie: 使用 Cookie 配置会话粘性。它允许根据客户端的特定 Cookie 值选择后端服务器。 -
check: 启用后端服务器的健康检查,以确定其可用性。如果服务器未通过健康检查,HAProxy 将停止向其发送流量,直到其恢复。 -
option: 启用或禁用后端的特定选项。一些常用的选项包括:-
option httpchk: 启用 HTTP 健康检查,替代 TCP 健康检查。 -
option redispatch: 允许 HAProxy 在连接到选定服务器失败时重新选择服务器。
-
-
errorfile: 指定用于作为自定义错误页面的文件,以应对后端服务器错误。
在示例后端中,它定义为 www_servers,并使用 roundrobin 负载均衡 web1 和 web2 服务器:

图 6.5 – HAProxy 示例后端
注意
强烈建议始终为您的服务器使用 check 选项。如果您没有运行检查,系统仍然会向服务器发送流量!
listen
在 HAProxy 中,listen 部分用于将前端和后端配置结合在一个块中,是一个便捷的组合方式。listen 部分允许您定义特定于监听套接字的选项以及如何处理传入流量。以下是 listen 部分常用的选项:
-
bind: 定义 HAProxy 用于监听传入流量的 IP 地址和端口。例如,bind *:80在端口80上监听所有 IP 地址。 -
stats: 启用 HAProxy 统计页面,用于监控和管理 HAProxy。 -
stats enable: 启用 HAProxy 的统计监控功能。 -
stats uri: 指定用于访问统计页面的 URI 路径。例如,stats uri /haproxy_stats将统计页面设置为可通过http://your-haproxy-ip/haproxy_stats访问。 -
stats realm: 设置访问统计页面时使用的 HTTP 基本身份验证的领域(认证领域)。此设置为防止未经授权的访问提供了一层安全保护。 -
stats auth: 配置访问统计页面时使用的 HTTP 基本身份验证的用户名和密码。格式为statsauth username:password。 -
stats hide-version:从统计页面隐藏 HAProxy 版本号,以增强安全性。 -
stats show-node:在统计页面上显示服务器节点名称。当使用动态服务器模板时,这非常有用。 -
stats refresh:设置统计页面自动刷新的间隔(以毫秒为单位)。例如,stats refresh 10s每 10 秒刷新一次页面。 -
stats admin:指定允许访问 HAProxy 统计信息的 IP 地址和端口。它允许通过统计页面远程管理 HAProxy。例如,localhost只允许来自本地计算机的访问。 -
stats maxconn:限制允许连接到统计页面的连接数。它有助于防止过载和潜在的拒绝服务攻击。 -
errorfile:指定用作前端错误的自定义错误页面的文件。
对于示例中的 listen 部分,我们将其定义为指标,允许从 192.168.56.1 访问管理员。用户将使用用户名 admin 和密码 passw0rd 进行登录。如下图所示:

图 6.6 – HAProxy listen 示例
由于状态页面运行在端口 8080,请别忘了将端口添加到防火墙中并重新加载防火墙。这可以通过以下命令完成:
firewall-cmd --permanent --add-port=8080/tcp; firewall-cmd --reload
它是如何工作的…
现在我们已经配置了两个 Web 服务器和负载均衡器,我们需要启动负载均衡器。可以使用 systemctl 来完成:
-
使用以下命令启动 HAProxy:
systemctl start haproxy -
使用以下命令检查状态:
systemctl status haproxy -
如果编辑了配置文件,请不要忘记使用以下命令重新加载 HAProxy:
systemctl reload haproxy
现在,将浏览器指向负载均衡器 IP 地址。你将看到 Web 服务器页面。如下图所示:

图 6.7 – 工作中的 HAProxy
由于规则是roundrobin,且我们将超时设置为一分钟,等待一分钟后再重新加载页面。你将看到一个新的服务器。

图 6.8 – 工作中的负载均衡
作为管理员,你还需要检查资源的健康状态。将浏览器指向统计页面的 URL,并输入已配置的用户名和密码。这将显示统计页面。在此示例中,URL 为 lb1.m57.local:8080/stats。你将在下图中看到一个示例:

图 6.9 – HAProxy 状态页面
在示例页面中,你将看到 web1 离线。你还可以看到每个前端和后端规则处理了多少流量,以及流量分别发送到了哪些服务器。
使用 Keepalived 使 HAProxy 高可用
在前面的配置中,我们使用 HAProxy 为我们的 Web 服务器提供了一些冗余。但这个解决方案的挑战在于,现在负载均衡器本身成了故障点。在高可用性架构中,您需要覆盖所有故障点,确保有冗余并避免单点故障(SPOF)。在本配置中,我们将使用 Keepalived 为我们的配置添加高可用性。Keepalived 是一款开源软件,专为基于 Linux 的系统设计。其主要功能是管理网络负载均衡和故障切换,确保 Web 服务的高可用性。Keepalived 通常与 HAProxy 一起使用。该软件主要使用虚拟路由冗余协议(VRRP)实现容错和负载均衡。Keepalived 使用以下功能来提供冗余:
-
高可用性:通过 Keepalived,您可以建立一个备份服务器集群,利用共享的虚拟 IP(VIP)地址。该配置确保即使主服务器发生故障,备用服务器也会自动接管并处理传入流量,从而实现最小的停机时间。
-
VRRP:VRRP 是一种常用协议,能够实现 IP 网络中的路由器自动故障切换。Keepalived 利用 VRRP 保持 VIP 地址的正常运行,可以根据需要将其分配给集群中的任何节点。
-
健康检查:Keepalived 的监控系统定期检查活动服务器的健康状况。如果服务器变得无响应,Keepalived 会将其从池中移除,并将流量重定向到健康的服务器。
-
通知机制:使用 Keepalived,可以为故障切换事件或超出某些阈值时设置通知。这些通知对于监控集群的整体健康状况非常有用。
在集群中,Keepalived 将一个节点指定为主节点,其他节点作为备份节点。主节点处理传入流量并响应 VIP 地址的 ARP 请求,而备份节点充当待命路由器并监视主节点的状态。节点之间使用 VRRP 协议进行通信,主节点定期发送 VRRP 广告以表明其正常运行。通常,VIP 被用来为终端用户访问提供单一的 IP 地址。下图展示了 Keepalived 管理两个 HAProxy 系统的正常操作。

图 6.10 – Keepalived 正常操作
如果备用节点停止接收广告或检测到主节点的问题,某个备用节点将接管成为新的主节点。Keepalived 使用 ICMP(ping)检查或第 4 层检查(例如,检查特定端口是否开放)等机制来检查服务器的健康状况,并将失败的服务器从池中移除。调整 VRRP 优先级以确保健康的备用服务器接管。这可以通过下图看到,用户连接的 VIP 已经迁移到第二个节点,而该节点现在使用 HAProxy 来管理工作负载。

图 6.11 – Keepalived 失败节点
准备工作
本教程扩展了前一个教程,添加了第二个负载均衡系统和 VIP。你需要搭建第二个负载均衡器并为 VIP 获取一个额外的 IP 地址。你的 IP 地址应该类似于以下:
| Host | IP |
|---|---|
| web1 | 192.168.56.200 |
| web2 | 192.168.56.201 |
| lb1 | 192.168.56.202 |
| lb2 | 192.168.56.203 |
| vip | 192.168.56.204 |
表 6.4 – Keepalived IP 地址
如何操作…
在开始配置 Keepalived 之前,你需要在第二台服务器上配置 HAProxy。你可以轻松安装 HAProxy,打开防火墙端口,并从现有系统中复制配置文件。
你可以通过简单地将浏览器指向第二个负载均衡器,查看应用服务器来进行测试。
接下来,我们将开始配置 Keepalived。
对于每个负载均衡器,你需要以 root 用户身份安装 Keepalived:
dnf -y install keepalived
接下来,我们需要编辑 Keepalived 配置文件。该文件位于 /etc/keepalived/keepalived.conf。需要编辑的主要部分有 global_defs 和 vrrp_instance。
global_defs 是 Keepalived 使用的全局定义。这些设置会被系统中配置的所有 vrrp_instance 类型使用。
有几个参数需要更新:
-
notification_email:这是一个电子邮件地址列表,当发生事件时会发送邮件。 -
notification_email_from_user:这是发送电子邮件的地址 -
smtp_server:这是 SMTP 中继服务器 -
router_id:这是该 Keepalived 集群的唯一名称
对于示例,此部分看起来如下:

图 6.12 – Keepalived 全局设置
下一节是 vrrp_instance。你可以在集群中拥有多个 vrrp_instance 类型,每个都支持不同的 VIP。
对于 vrrp_instance,你需要为每个实例分配一个唯一的名称。此外,还有几个参数需要更新:
-
state:实例的状态,通常主节点为 master,备用节点为 backup。 -
interface:集群中用于该主机的以太网接口。 -
virtual_router_id:该实例的唯一编号。其他实例不能使用相同的 ID。 -
authentication:此部分定义成员如何进行身份验证:auth_type:通常发送为 PASS,以允许节点作为此实例的成员进行身份验证。还有一种第二种支持类型,称为auth_pass:该实例的密码。
-
virtual_ipaddress:由此实例管理的 VIP 列表。
在我们的示例中,该部分将如下所示;

图 6.13 – Keepalived vrrp_instance
配置文件创建完成后,将其复制到第二个负载均衡器。不要忘记将第二个系统的状态更改为 BACKUP,并且如果该系统的接口不同,也要进行更新。
接下来,以 root 用户身份在两个节点上启动 Keepalived,使用以下命令:
systemctl enable --now keepalived
现在,你可以将浏览器指向 VIP!这在以下示例中可以看到。

图 6.14 – Keepalived VIP 使用中
你可以通过查看守护进程的日志条目来检查状态,使用以下命令:
journalctl -u keepalived
这将显示守护进程的所有活动。你应该能看到 Sending gratuitous ARP 消息,这是系统在检查健康状况。你还会看到一些关于状态的消息,比如 Entering MASTER STATE 或 Entering BACKUP STATE,当系统在 MASTER 和 BACKUP 之间切换时。
使用 Corosync 和 Pacemaker 为所有提供 HA 集群
在之前的配置中,我们通过在两个活跃的应用服务器之间分配流量来实现 HA。然而,这种方法仅对无状态应用有效,其中服务器或浏览器不包含特定的用户或会话数据。对于有状态应用或在复杂服务器上运行的应用,需要采用不同的 HA 方法。解决方案是通过使用 Pacemaker 和 Corosync 的组合,在不同的服务器上启动和停止应用组件。这两个开源软件项目协同工作,为基于 Linux 的系统提供 HA 集群。它们协调和管理集群中的多个节点,确保在硬件或软件故障期间,关键服务仍然可用。
Corosync 作为 HA 集群栈的通信层,允许节点之间进行可靠的通信。它利用成员资格和法定人数系统来监控集群的活动节点,并确保在任何时候只有一个节点作为主节点(或主控节点)运行。消息传递层对于共享有关集群状态、节点状态和资源条件的数据至关重要。Corosync 在集群的功能中发挥着至关重要的作用,提供以下关键功能:
-
集群通信:Corosync 使得节点能够可靠高效地交换消息,允许它们协调和同步各自的操作。
-
成员资格和法定人数:Corosync 是一个跟踪集群中活跃节点的工具,使用法定人数算法来确保有足够的节点可用来做出决策。这有助于避免脑裂场景,并确保只有一个节点处于活动状态。避免脑裂集群至关重要,因为脑裂会导致数据不一致、损坏和服务中断。脑裂场景发生在集群中的节点失去相互通信时,导致每个节点认为自己是唯一的活跃节点。这可能是由于网络问题、通信故障或配置错误引起的。
注意
当发生脑裂场景时,集群中的多个节点可能开始独立运行服务或使用共享资源,认为自己是唯一的活跃节点。这可能会导致冲突和数据不一致,因为每个节点独立操作而没有协调。如果可能,建议在集群中使用奇数个节点,或者启用法定人数保护。
Pacemaker 是一个集群资源管理器,它利用 Corosync 的消息传递和成员管理功能来管理集群资源和处理资源故障转移。它根据既定的策略和约束,决定集群中哪个节点应该运行特定的服务(资源)。Pacemaker 为集群带来了以下功能:
-
资源管理:使用 Pacemaker,管理员可以设置需要强大可用性的资源,如 IP 地址、服务、数据库和应用程序
-
资源监控:Pacemaker 持续监控资源和节点的状态,以检测集群中的故障或变化
-
资源故障转移:如果节点发生故障或出现资源问题,Pacemaker 将启动故障转移过程,将资源转移到正常运行的节点上,以确保不中断的可用性
-
资源约束:管理员可以为资源的放置和故障转移设置约束和规则,定义哪些节点适合或禁止用于特定资源
-
资源共址和顺序约束:Pacemaker 允许定义资源之间的关系,指定哪些资源必须在同一节点上一起运行,或按特定顺序运行
-
集群管理:Pacemaker 提供多种命令行工具和图形界面(如 Hawk)来管理和配置集群
准备工作
对于此配置,您将需要两台虚拟机,每台虚拟机至少有两个虚拟 CPU、8 GB 内存和 50 GB 磁盘空间。您应安装 Oracle Linux 8,并为浮动 VIP 配置一个第三个 IP 地址,以便由集群管理。两个 Web 服务器将更新到最新的软件版本。此示例将使用以下 IP 地址:
| 主机 | IP 地址 |
|---|---|
| Web1 | 192.168.56.200 |
| Web2 | 192.168.56.201 |
| vip | 192.168.56.204 |
表 6.5 – 高可用集群 IP 地址
在开始配置集群之前,您还需要在每台主机上设置一个httpd(Apache 2.4)服务器。这与其他食谱中设置其他主机的方法类似。
首先,在两个服务器上,以 root 身份安装 Apache web 服务器:
dnf -y install httpd
我们确实需要启用 Apache 的状态页面。这是资源检查的一种方式。为此,将以下行复制到/etc/httpd/conf.d/status.conf中:
<Location /server-status>
SetHandler server-status
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
</Location>
我们还需要一个简单的网页。为了测试目的,请将以下内容放入两个服务器的/var/www/html/index.html中。
注意
在设置像 Web 服务器这样的应用程序时,将您的内容目录(例如/var/www/html)放在 Gluster 文件系统上,可以更轻松地管理更新内容。这对于应用程序使用的其他数据(如临时状态数据)也同样有效。
接下来,在两个服务器上,使用以下命令将端口80添加到本地防火墙中:
firewall-cmd --permanent --add-service=http; firewall-cmd --reload
现在,为了测试目的,在两个节点上手动启动服务器。不要启用服务自动启动。稍后在配置 Pacemaker 时将会启用自动启动:
systemctl start httpd
现在,您应该能在两个服务器上看到一个基本页面,如下图所示:

图 6.15 – httpd 服务器测试
您还可以使用wget命令测试server-status页面:
wget localhost4/server-status
成功的示例输出如下截图所示。

图 6.16 – 服务器状态成功
现在,您已准备好安装和配置 Pacemaker 和 Corosync。
如何操作…
既然您已经安装了我们将要集群的 Apache httpd服务器,接下来让我们开始安装软件。首先,我们需要启用addons repo。可以在两个服务器上以 root 身份通过以下命令来完成:
首先,在两个节点上,以 root 身份使用以下命令启用 repo:
dnf config-manager --enable ol8_addons
然后,您将安装软件:
dnf install -y pacemaker pcs
安装这些软件包完成后,系统会添加一个名为hacluster的新用户。请注意,安装完成后该用户将无法进行远程登录。为了在其他节点上执行任务(例如同步配置或启动服务),必须在两个节点上为hacluster用户设置相同的密码。我们可以使用passwd命令设置密码:
passwd hacluster
接下来,我们需要启用pcs服务并启动它:
systemctl enable --now pcsd.service
接下来,我们需要为集群端口打开防火墙。可以通过以下命令来完成:
firewall-cmd --permanent --add-service=high-availability ; firewall-cmd --reload
现在,我们暂时完成了两个节点的配置。接下来的几个命令可以在任一节点上执行,但请注意,仍然需要是 root 用户。
接下来,我们需要将两个节点添加到集群中:
pcs host auth web1 web2 -u hacluster
注意
如果您的节点在 DNS 或/etc/hosts文件中不可解析,您可以选择在主机名后添加addr=$IPADDR。但强烈建议确保所有主机都能被解析。如果使用此选项,它将如下所示:
pcs host auth web1 addr=192.168.56.200 node2 addr=192.168.56.201 -****u hacluster
接下来,我们将创建集群:
pcs cluster setup webapp web1 web2
现在,我们可以启动集群:
pcs cluster start --all
要验证集群是否正常运行,我们可以使用pcs命令进行检查:
pcs cluster status
一个健康的集群应该返回类似以下示例的输出:

图 6.17 – 集群状态
在仅由两个节点组成的集群中,法定人数的运作方式与多节点集群不同。在这样的集群中,法定人数值设置为1,以确保主节点始终被认为是法定成员。如果由于网络故障两个节点都离线,它们会相互竞争以确定谁先成功“围栏”,先成功的节点赢得法定人数。为了增加优选节点赢得法定人数的机会,可以配置围栏代理赋予它优先权。这可以通过以下命令来完成:
pcs resource defaults update
最后一步是禁用STONITH,即击杀另一节点。这是一个高级围栏工具,要求根据您的环境进行特定配置。如果您想实验这个技术,请查看官方的 Oracle 文档:docs.oracle.com/en/operating-systems/oracle-linux/8/availability/availability-ConfiguringFencingstonith.html#ol-pacemaker-stonith:
pcs property set stonith-enabled=false
要设置集群,我们需要创建资源。资源代理名称由两个或三个字段组成,字段之间由冒号分隔。第一个字段是资源类,它表示资源代理遵循的标准,并帮助 Pacemaker 定位脚本。例如,IPaddr2 资源代理遵循开放集群框架(OCF)标准。第二个字段根据使用的标准而有所不同,OCF 资源使用它来表示 OCF 命名空间。第三个字段表示资源代理的名称。
资源可以使用元属性和实例属性。元属性不依赖于资源类型,而实例属性则特定于每个资源代理。
在集群中,资源操作是指可以对特定资源执行的操作,如启动、停止或监控它。这些操作通过op关键字来标识。为了确保资源保持健康,我们将添加一个间隔为 15 秒的监控操作。判断资源是否健康的标准取决于所使用的资源代理。这也是为什么我们在httpd服务器上启用了server-status页面,因为httpd代理使用该页面来帮助确定系统的健康状态。
所以,我们来添加 VIP 地址:
pcs resource create AppIP ocf:heartbeat:IPaddr2 ip=192.168.56.204 \
cidr_netmask=24 op monitor interval=15s
接下来,我们将添加httpd服务器:
pcs resource create AppWebServer ocf:heartbeat:apache \
configfile=/etc/httpd/conf/httpd.conf \
statusurl=http://127.0.0.1/server-status \
op monitor interval=15s
现在我们有了两个资源,我们还需要将它们绑定在一起,作为一个组。对于大多数应用,多个资源需要同时在同一台物理服务器上。这可以是 IP 地址、Tomcat 服务器、httpd服务器等。我们将这个组命名为WebApp,并将 VIP 和https服务器添加到其中。每个资源需要单独添加,因此需要运行两条命令:
pcs resource group add WebApp AppIP
pcs resource group add WebApp AppWebServer
现在,我们将使用pcs status命令检查配置:
pcs status
输出如下:

图 6.18 – pcs 状态
现在我们可以看到集群及其资源组WebApp,以及两个服务器的 VIP 地址。
它是如何工作的……
现在一切配置完成,让我们启动资源并进行管理。我们可以首先启动整个集群。这将使集群中的所有节点上线:
pcs cluster start --all
我们还可以通过以下命令设置集群在启动时自动启动:
systemctl enable --now corosync
systemctl enable --now pacemaker
你需要在两个节点上以 root 身份运行这两个命令。
接下来,让我们来看几个有用的命令。
有时,资源会出现故障;可能是配置文件有问题,或者你在集群控制之外启动了某个资源,导致集群混乱。一旦解决了问题,你可能需要刷新资源。这会告诉集群忘记故障并重新启动服务,清除所有错误:
pcs resource refresh AppWebServer
你还可以使用config选项检查资源的详细信息。如果你忘记了资源是如何配置的,这个功能非常有用。以下图所示为例:

图 6.19 – 资源配置
接下来,让我们将WebApp迁移到服务器web2:
pcs resource move WebApp web2
当你运行move时,你还可以通过检查约束来监控迁移情况。这比使用pcs status命令更清晰:
pcs constraint
输出如下:

图 6.20 – 集群约束
Pacemaker/Corosync 技术的强大之处在于它的灵活性。你几乎可以用它来集群任何东西,使它成为系统管理员的强大工具。
在多台机器之间共享文件系统——集群还是分布式?
当你开始使用负载均衡器和集群软件等技术时,你常常会遇到需要在多台服务器上拥有相同文件的情况。虽然你可以直接复制文件,但如果你能在每台服务器上挂载文件,并在系统间共享文件系统,而不引入 NFS 服务器所带来的单点故障(SPOF)呢?做到这一点最简单的方法之一是使用 Gluster。
Gluster,也称为GlusterFS,是一个开源分布式文件系统,提供可扩展和灵活的大数据存储解决方案。最初由 Gluster 公司开发,现在由开源社区维护。Gluster 采用分布式架构来创建一个统一的文件系统,可以跨多个服务器和存储设备扩展。这种方法允许你聚合多个服务器的存储容量,并将其作为一个单一、结构良好的文件系统提供给用户和应用程序。它具有广泛的应用场景,如数据存储、备份和内容分发。
Gluster 的关键特性和概念包括以下内容:
-
可扩展性:向集群中添加更多存储服务器可以使 Gluster 轻松适应日益增长的数据存储需求,同时实现横向扩展。
-
冗余:Gluster 通过将数据复制到多个节点来确保数据的可用性,从而提供冗余和故障容忍。
-
灵活性:Gluster 支持多种存储选项,包括本地磁盘、NAS 和云存储。它可以根据特定的使用场景和技术进行定制。
-
文件系统抽象:它为用户和应用程序提供了标准的文件系统接口,使得集成到现有系统中相对容易。
-
数据分布:数据以一种提高性能和可靠性的方式在集群中分布。数据可以均匀分布,也可以根据特定的标准进行分布。
-
自动修复:Gluster 具有自我修复功能,能够自动检测并修复数据不一致或损坏的文件。
Gluster 通常用于需要大规模分布式存储的环境,如网页服务器、云计算、大数据分析和媒体流服务。它提供了一种具有成本效益和灵活性的解决方案,用于管理网络中多个服务器和存储设备上的数据。
准备就绪
在本示例中,你将需要两个 Oracle Linux 8 系统,每个系统都能够访问 YUM 仓库。在本次练习中,我们将其称为gluster1和gluster2。它们是相同的系统,每个系统有 8 GB 的 RAM,4 个 vCPU,和 100 GB 的磁盘空间。文件系统的配置为:/分区 50 GB,/home分区 5 GB,swap 分区 8 GB。其余的磁盘空间尚未分配。此外,在这个例子中,每个节点将有一个 100 GB 的 LUN 用于存储 Gluster 数据。
警告
强烈建议在集群中至少使用三个节点,以避免发生脑裂(split-brain)现象。虽然可以使用两节点集群,但如果系统出现脑裂,将存在数据损坏的风险。脑裂集群在分布式计算环境中是不希望出现的,因为它们可能导致数据不一致、损坏和操作问题。脑裂发生在集群中的节点失去连接或相互通信时,导致集群分成多个孤立的节点。每个节点都认为自己是活动的或主要的集群,可能会导致冲突和数据不一致。
在每台服务器上,您需要执行以下准备工作:
-
在 100 GB LUN 上创建 XFS 文件系统。此空间将用于存储 Gluster 数据,称为砖块。在 Gluster 的上下文中,砖块指的是存储集群中的基本存储单元。一个集群由多个砖块组成,这些砖块本质上是存储服务器或设备上的目录,用于存储数据。每个砖块代表集群总存储容量的一部分。
-
由于我们将使用 Gluster 来管理存储,因此我们不会在文件系统上使用 LVM。在这些系统中,
/dev/sdb是 100 GB LUN。以下命令用于创建和挂载文件系统:mkfs.xfs -f -i size=512 -L glusterfs /dev/sdb mkdir -p /data/glusterfs/volumes/bricks echo 'LABEL=glusterfs /data/glusterfs/volumes/bricks xfs defaults 0 0' |sudo tee -a /etc/fstab df command to verify that the filesystem is mounted, as seen in the following example:

图 6.21 – 砖块已挂载
-
接下来,我们需要确保所有节点都在
/etc/hosts文件中。在这个示例中,gluster1、gluster2和gluster3都在文件中,使用了短名称和完全限定域名(FQDN)。可以在以下代码片段中看到:[root@gluster3 ~]# more /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.200.110 gluster1.m57.local gluster1 192.168.200.125 gluster2.m57.local gluster2 glusterfs and Gluster server software can be installed and started. This is done with the following commands:dnf -y install oracle-gluster-release-el8
dnf -y config-manager --enable ol8_gluster_appstream ol8_baseos_latest ol8_appstream
dnf -y module enable glusterfs
dnf -y install @glusterfs/server
systemctl status glusterd 命令。验证该服务是否处于活动状态并正在运行,如下例所示:

图 6.22 – Gluster 守护进程正在运行
-
接下来,让我们配置防火墙以允许
glusterfs端口,使用以下命令:firewall-cmd --permanent --add-service=glusterfs firewall-cmd --reload -
此外,为了提高安全性,我们将创建一个自签名密钥,以加密节点之间的通信:
openssl genrsa -out /etc/ssl/glusterfs.key 2048 .pem file, since this is a self-signed certificate, you will need to enter your contact info into the certificate; however, it will work with the defaults!
注意
在此示例中,我们使用的是自签名证书。在安全的生产环境中,您可能希望考虑使用商业签名的证书。
我们稍后将使用这些文件来加密通信。
如何操作…
现在,所有节点的准备工作已完成,我们将创建受信的存储池并加密通信。这将为创建卷做好准备,数据将在这些卷中存储和共享。
Gluster 中的受信存储池是指一组 Gluster 服务器集群,这些服务器被称为存储节点或对等节点,它们之间建立了信任关系,以便在存储集群中协同工作。通过受信存储池配置建立这种信任,通常涉及以下步骤:
-
身份验证:可以使用多种方法,如 SSH 密钥、证书或共享密钥,对受信存储池中的节点进行身份验证。这确保只有授权的服务器才能成为存储集群的一部分。
-
授权:节点通过身份验证后,它们授权彼此访问和操作 Gluster 存储集群中的特定数据。授权设置决定了哪些节点可以读取和写入集群中特定的卷或砖块。
-
通信:受信存储池中的成员通过安全网络进行通信,以复制数据、同步元数据并执行其他与集群相关的操作,确保存储集群的协同工作。
-
数据完整性:受信存储池通过在多个节点之间进行分布式复制,确保数据的完整性和冗余。
-
可扩展性:可以向受信池中添加更多的存储节点,从而增强存储容量和性能。受信池的特性使得新节点可以轻松加入集群并贡献其资源。
在 Gluster 中,受信存储池是一个关键元素,它为文件系统的容错和分布式特性奠定了基础。它保证集群中的所有节点可以无缝、安全地协同工作。以下步骤将指导您如何在两台主机上创建 GlusterFS。
-
要创建存储池,我们需要探测集群中的其他节点。在此示例中,我们将从
gluster1到gluster2使用gluster peer probegluster2命令进行探测:[root@gluster1 etc]# gluster peer probe gluster2 gluster pool list command to see what nodes are peered with the node where you ran the command from; in the following example, the command was run on gluster2:[root@gluster2 etc]# gluster pool list
UUID 主机名 状态
b13801f3-dcbd-487b-b3f3-2e95afa8b632 gluster1 已连接
gluster1 和 localhost 已连接,因为这是在 gluster2 上运行的。如果您从 gluster1 运行相同的命令,您将看到 gluster2 作为远程主机:
[root@gluster1 ~]# gluster pool list UUID Hostname State bc003cd0-f733-4a25-85fb-40a7c387d667 gluster2 Connected b13801f3-dcbd-487b-b3f3-2e95afa8b632 localhost Connected -
现在我们已经有了集群,让我们创建一个复制卷。该卷将在集群中重写砖块,提供对存储故障或节点故障的保护。
以下命令将创建该卷:
/mnt mount point:df 命令:

图 6.23 – data1 挂载在 /mnt
-
如果您想在其他节点上挂载此卷,您需要在每个节点上重复该命令,根据需要更新节点名称。以下示例显示了在
gluster1上的挂载:.pem files previously created and concatenate them into the /etc/ssl/glusterfs.ca file. This file should be placed on all nodes of the cluster. -
现在,我们需要启用加密。可以通过在每个节点上触摸 secure-access 文件来完成此操作,使用以下命令:
data1 volume that was just created:gluster volume set data1 client.ssl on
glusterd:
systemctl restart glusterd
现在,Gluster 通信已经为该卷加密。
它是如何工作的…
您可以通过 Gluster 做更多的事情。首先,在创建卷时,卷有多个选项,每个选项都提供复制和分布的选项:
-
分布式:使用分布式卷时,文件在卷中的砖块上随机分布。此类型的卷在需要扩展存储时非常有用,并且冗余不必要,或已由其他硬件或软件层提供。然而,需要注意的是,磁盘或服务器故障可能会导致显著的数据丢失,因为数据在卷中的砖块上是随机分布的。构建分布式卷的示例命令如下:
gluster volume create data1 gluster{1,2}:/data/glusterfs/volumes/bricks/data1 -
复制:文件在复制卷中跨砖块进行复制,以实现高可用性(HA)。构建复制卷的示例命令如下:
gluster volume create data1 replica 2 gluster{1,2}:/data/glusterfs/volumes/bricks/data1 -
分布式复制:将文件分布到卷中的复制砖块上,以提高读取性能、高可用性(HA)和可靠性。创建分布式复制卷时,节点的数量应为砖块数量的倍数。构建分布式复制卷的示例命令如下:
gluster volume create data1 replica 2 cluster{1,2,3,4}:/data/glusterfs/volumes/bricks/data1 -
分散:此卷类型利用纠删码高效地保护磁盘或服务器故障。它通过将文件的编码数据条带化,分布到卷中的多个砖块上,并添加冗余以确保可靠性。分散卷允许通过最小的空间浪费来自定义可靠性级别。分散卷必须至少有三个砖块。构建分散卷的示例命令如下:
gluster volume create data1 disperse 3 redundancy 1 \ cluster{1,2,3}:/data/glusterfs/volumes/bricks/data1 -
分布式分散:将数据分布到分散的砖块上,提供与分布式复制卷相同的好处,但使用的是分散存储。分散卷必须至少有六个砖块。构建分布式分散卷的示例命令如下:
gluster volume create data1 disperse 3 redundancy 1 \ cluster{1,2,3,4,5,6}:/data/glusterfs/volumes/bricks/data1
向任何卷中添加砖块时,您可以在同一 Gluster 节点上放置多个砖块。只需在命令中定义附加砖块即可。在此示例中,通过在每个节点上放置两个砖块来创建一个分布式分散卷:
gluster volume create data1 disperse 3 redundancy 1 \ cluster{1,2,3}:/data/glusterfs/volumes/bricks/data1 \ cluster{1,2,3}:/data/glusterfs/volumes/bricks/data2
可以使用gluster stop volume volumename命令停止卷。停止data1卷的示例如下:
gluster stop volume data1
您还可以向卷中添加砖块来扩展它。这可以在将新节点添加到集群后完成。在以下示例中,首先使用gluster node probe gluster3命令将gluster3添加到集群中。然后,使用以下命令扩展data1卷:
gluster volume add-brick data1 gluster3:/data/glusterfs/volumes/bricks/data1
注意
在向卷中添加砖块时,请确保添加所需数量的砖块。像分布式复制卷这样的卷类型需要添加多个砖块。
您还可以使用以下命令检查所有卷的状态:
gluster volume status
以下屏幕截图中可以看到示例:

图 6.24 – 卷状态
你可以通过将卷名称添加到命令中来查看单个卷的摘要。还可以通过添加 detail 选项来查看更多详细信息。这些可以组合使用,如下图所示:

图 6.25 – 卷详细信息
如果你想查看卷的性能信息,可以使用 top 选项。此命令将显示用于读/写操作的砖块,以及每个砖块的 I/O 吞吐量。基本命令是 gluster volume top volume_name option,其中 volume_name 是卷的名称,选项如下所示:
-
read:此命令显示每个砖块的最高读调用次数及其计数。 -
write:此命令显示每个砖块的最高写调用次数及其计数。 -
open:此命令显示哪些砖块有开放的文件描述符。 -
opendir:此命令显示每个目录上有哪些砖块有开放调用,以及它们的调用次数。 -
read-perf:此命令显示按砖块的读性能吞吐量。使用选项bs(块大小)1024和count 1024运行。 -
write-perf:此命令显示按砖块的写性能吞吐量。使用选项bs(块大小)1024和count 1024运行。
在下图中可以看到几个示例:

图 6.26 – 卷顶级示例
卷也可以被删除。使用命令 gluster volume delete volume_name 删除,其中 volume_name 是要删除的卷。需要注意的是,删除卷时,不要忘记使用 rm 命令删除存储中的砖块。
生成、配置和监控以太网流量通过 Bond
在使用裸机服务器作为专用主机或使用 KVM 虚拟化技术的 Linux 系统托管虚拟机时,网络可能成为一个薄弱环节。幸运的是,通过实现以太网绑定,也称为网络绑定或 网卡(NIC)绑定,可以解决此问题。它是 Linux 中的一项技术,允许将多个网卡组合成一个逻辑接口。这个逻辑接口被称为绑定接口(bonded interface),它提供了更高的网络带宽、容错性和负载均衡。具体如下:
-
负载均衡:绑定将网络流量分配到多个网卡,增加带宽。根据具体要求,可以使用多种算法,如轮询、活动备份和异或(XOR)。
-
容错性:在网卡或网络链路故障的情况下,以太网绑定可以自动将流量切换到另一个活动的网卡。这样可以提供冗余和容错性,确保即使一个网卡不可用,网络连接仍然可用。
-
链路聚合:绑定可以用于创建 链路聚合组(LAGs)或网卡团队,这可以增强带宽和在高可用性设置中的冗余性。
在本教程中,我们将配置绑定,然后展示一些常用的工具,这些工具可以让你监控并生成通过绑定接口的以太网流量。
此外,还有一些技术是你需要熟悉的。
MAC
媒体访问控制(MAC)地址是分配给网络接口(如以太网卡和 Wi-Fi 适配器)的硬件标识符,用于在本地网络上进行通信。它在制造过程中硬编码到网络硬件中,并用于 OSI 模型的数据链路层(第二层)。MAC 地址的一个重要特性是它们必须是唯一的。每个 MAC 地址应该是全局唯一的,制造商有责任确保没有两个网络接口具有相同的 MAC 地址,尽管在实际操作中,尤其是在虚拟化环境中,这可能是一项挑战。这可能会导致网络问题,因为任何网络上的 MAC 地址重复都会引发问题。此外,许多绑定模式依赖于 MAC 地址来进行流量负载均衡。
绑定模式
绑定模式是指通过 Linux 绑定驱动程序将多个物理网络接口聚合成一个绑定接口时,决定如何分配网络流量的各种策略或算法。这些模式控制绑定接口的负载均衡和故障转移行为。选择绑定模式取决于你的特定网络需求和目标。以下是一些常见的 Linux 绑定模式:
-
balance-rr:在此模式下,出站网络流量会均匀地分配到可用的网络接口上,采用轮询方式。这是一种简单的负载均衡模式,可以改善出站流量的性能,但不考虑接口的状态,这可能导致不均匀的入站流量分配。有时,这种模式在某些交换系统中可能无法正常工作。 -
active-backup:一种常用模式,通常被称为故障转移模式,该模式有一个主接口,其他接口处于待机状态。如果主接口出现故障,下一个可用接口会自动激活以确保连续性。此模式提供冗余性,是在任何环境中最容易使用的模式之一。 -
balance-xor:此模式利用简单的 XOR 运算来保持数据传输和接收之间的平衡。该过程根据源和目标的 MAC 地址分配流量,确保相同端点之间的包始终走相同的路径。此模式的主要目的是确保容错性。但有时,这种模式在某些交换系统中可能无法正常工作。 -
balance-tlb:在此模式下,外发流量根据各接口的当前负载在所有可用接口之间分配。然而,入站流量不会主动平衡,仅由活动接口接收。当交换机不支持链路聚合控制协议(LACP)时,此模式特别有用。偶尔,这种模式与某些交换系统配合不良。 -
balance-alb:该模式通过考虑每个接口的可用性和负载,积极地平衡进出流量。偶尔,这种模式与某些交换系统配合不良。
LACP
所有前述模式均可在不更改服务器连接的交换机设置的情况下运行。然而,还有一种更常用的模式,称为 LACP。LACP 是用于将多个网络连接(通常是以太网)聚合成一个高带宽链路的最复杂模式。这个过程通常被称为链路聚合、网卡团队或绑定。LACP 由 IEEE 802.3ad 标准定义,常用于企业和数据中心环境中,以提高网络性能、冗余性和容错能力。
然而,要使用 LACP,交换机必须配置为支持 LACP。作为管理员,必须明确传达配置要求,以确保交换机被配置为兼容模式。两端的配置必须匹配,LACP 才能正常工作。大多数企业级网络交换机和服务器网卡都提供 LACP 支持。LACP 的主要特点和功能包括以下几点:
-
聚合链路:LACP 允许将多个物理网络链路聚合成一个逻辑链路,该链路在网络设备上表现为一个单一接口。
-
带宽增加:通过 LACP 聚合多个链路可以提升带宽,适用于带宽密集型应用和服务器到交换机的连接。然而,每个 MAC 到 MAC 的连接通常受到聚合链路单一成员速度的限制。如果你有一个主机,主机上有两个 1 Gb/s 端口,可能无法在主机和客户端之间获得超过 1 Gb/s 的通信速度。
-
负载均衡:LACP 可以通过各种负载均衡算法将网络流量分配到聚合链路上,防止单一链路上的网络拥塞,同时优化网络利用率。
-
容错能力:除了提供更高的带宽,LACP 还提供冗余性和容错能力。如果一个物理链路发生故障,LACP 可以自动将流量重定向到剩余的活动链路,从而最小化停机时间并确保网络可用性。
-
动态协议:LACP 是一种动态协议,通过使用 LACP 帧动态协商并建立网络设备之间的链路聚合。
-
模式:LACP 支持两种操作模式:
-
主动模式:在此模式下,设备主动发送 LACP 帧以协商并建立链路聚合。
-
被动模式:在被动模式下,设备监听 LACP 帧,但不会主动发送。它依赖于另一端配置为主动模式来启动聚合。
-
LACP 通常用于对高可用性(HA)和网络性能要求较高的场景,例如服务器到交换机连接、交换机间连接和存储区域网络(SANs)连接。它允许组织高效利用可用的网络资源并提高网络可靠性。
准备工作
对于此操作,你需要三台 Oracle Linux 8 系统,每台系统可以访问 yum 仓库。我们将它们命名为networking、client1和client2。它们大致相同,每台系统有 8GB 内存、4 个 vCPU 和 100GB 的磁盘空间。不同之处在于networking应具有两个在同一网络上的网络接口。文件系统中,/有 50GB,/home有 5GB,交换分区为 8GB,其余磁盘空间未分配。
如何操作……
虽然也可以通过图形界面完成这项操作,但此方案将介绍如何通过命令行完成。需要注意的是,在处理服务器的主要网络连接时,最好使用系统控制台。如果通过 SSH 等远程连接进行操作,可能会导致你无法访问服务器。以下是配置冗余连接的步骤。
-
你需要做的第一件事是创建绑定。在本例中,我们将使用
balance-alb模式来最好地平衡进出流量:nmcli connection add type bond con-name "Bond 0" ifname bond0 bond.options "mode=balance-alb" -
接下来,我们将配置绑定使用 DHCP。在生产服务器上,通常会使用手动配置的 IP 地址:
enp0s3 and enp0s8:
注意
如果你要将端口添加到已经在使用的绑定中,你应该现在删除该端口。在本例中,enp0s3正在使用,所以用以下命令删除了它:
nmcli connection del enp0s3
nmcli connection add type ethernet slave-type bond con-name bond0-if1 ifname enp0s3 master bond0
nmcli connection add type ethernet slave-type bond con-name bond0-if2 ifname enp0s8 master bond0
-
现在,我们将启动连接并检查状态:
nmcli connection up "Bond 0" nmcli device command should look like the following:

图 6.27 – nmcli 设备输出,带有有效绑定
你可以看到bond0是设备,成员为enp0s3和enp0s8。
- 当你查看 IP 地址时,你会发现它现在位于
bond0设备上。可以通过ifconfig bond0命令来检查,输出如下:

图 6.28 – 来自 ifconfig bond0 的输出
现在你可以继续正常使用系统,但bond0是网络设备。
它是如何工作的……
现在我们已经有了一个正常工作的绑定,让我们看看进出流量。为此,我们需要安装iptraf-ng命令:
dnf -y install iptraf-ng
这个工具允许你监控服务器上的以太网流量。在本例中,我们将运行iptraf-ng命令。这将启动程序,你将看到主屏幕,截图如下所示:

图 6.29 – iptraf 主菜单
在这里,我们将按下S键查看一般接口统计,这将实时显示每个接口上的流量流动情况:

图 6.30 – 一般接口统计
你可以看到,进出流量在两个物理接口之间是平衡的。这是因为使用了balance-alb模式建立了链路聚合。为了生成这些流量,使用了client2系统的简单洪泛 ping 命令。具体命令如下:
ping -f 192.168.200.179
注意
使用-f选项时要小心,因为这会让网络充满流量,并且通常在生产网络上不接受这样做,除非事先与网络和安全团队协调。这可能会导致使用网络的系统出现性能问题。
不过,还有一种更好的方式来真正给网络施加压力。那就是使用一个能够生成接口最大支持的包数的工具。
iperf – 网络压力测试工具
我们将使用一个名为iperf的工具,它将生成接口可以支持的最大流量。要安装iperf,在所有系统上运行以下命令:
dnf –y install iperf3
我们还需要为系统打开一个 TCP 端口并重新加载防火墙。每个服务器实例只能处理一个客户端连接。我们将添加多个端口以启用运行多个服务器,每个服务器使用不同的端口。可以使用以下命令完成此操作:
firewall-cmd --permanent --add-port=8000-8010/tcp
firewall-cmd --reload
iperf采用客户端-服务器模式工作。要使用它,我们首先需要在网络系统上启动一个iperf服务器。在这个例子中,我们将设置服务器监听8001端口并使用 TCP 协议。可以使用以下命令启动服务器:
[root@networking ~]# iperf3 -s -p 8001
-----------------------------------------------------------
Server listening on 8001
-----------------------------------------------------------
我们将在另一个窗口中重复相同的命令,改为使用8002端口:
[root@networking ~]# iperf3 -s -p 8002
-----------------------------------------------------------
Server listening on 8002
-----------------------------------------------------------
现在,两个服务器都在运行,我们可以从client1进行测试。
测试使用以下命令运行:
iperf -c 192.168.200.179 -p 8001
测试开始后,几秒钟内会产生最大的流量,如以下输出所示:

图 6.31 – iperf 客户端输出
在测试运行时,我们可以通过iptraf命令监控性能,我们会看到大部分流量都集中在一个接口上。以下截图展示了这一点:

图 6.32 – 单客户端流量
所有这些流量都在enp0s8接口上。这是因为负载均衡算法使用了客户端的 MAC 地址,这限制了流量只通过链路聚合中的一个接口。
接下来,可以同时从client1和client2运行测试。不同之处在于client2将使用8002端口。结果显示在以下截图中:

图 6.33 – 使用两个不同客户端的测试
在这里,我们可以看到两个接口都在处理重负载的网络流量。这是因为每个客户端使用了不同的 MAC 地址。如果使用了第三个客户端,我们就会看到它与其中一个接口争夺流量,可能会导致问题。
这是一个重要的因素,特别是在需要来自多个客户端的高网络性能的环境中进行绑定时需要考虑的因素。当使用绑定时,如果遇到随机性能延迟问题,需要监控端口。你可能会面临一些争用。解决这个问题的一种方法是向绑定中添加额外的端口。你还可以升级接口,选择能够支持更多带宽的设备。
第七章:Oracle Linux 8 – 补丁安装不一定意味着重启
我这一生都在为补丁安装而重启,为什么现在要改变?
自 1991 年 Linux 发布以来,每当内核进行补丁更新时,您都必须重启系统。那时,即便是主导企业 IT 的 IBM 大型机,在进行补丁更新时也需要重启,因此对所有其他系统而言,补丁更新时重启是正常的。这个过程在接下来的 20 年里似乎运行良好,但变革的种子在 2005 年被播下,当时一位麻省理工学院(MIT)的学生提出了一个简单的问题。如果能在不重启系统的情况下打补丁会怎样? 他的团队在 2009 年找到了答案,发布了 Ksplice,使得在系统运行时也能进行 Linux 内核的补丁更新。
在本章中,我们将介绍为什么您应该开始使用 Ksplice,以及如何利用它来提升系统的安全性。
本章包含以下操作:
-
设置 Ksplice 以实现互联网访问
-
在没有互联网访问的情况下使用 Ksplice
-
安装并启用已知漏洞检测
设置 Ksplice 以实现互联网访问
在我们开始操作前,让我们了解一下关于 Ksplice 的讨论。
关于 Ksplice 为什么这么热议?
第一个问题是,为什么这对 IT 重要,更重要的是,对保护服务器上运行的应用程序有何意义? 在解答这个问题之前,您首先需要了解黑客入侵系统的过程。
基本流程包括三个主要阶段:侦察、获取访问权限和维持访问权限。一旦系统被攻破,该过程会在网络中的其他系统上重复进行:

图 7.1 – 安全生命周期
在第一阶段,侦察,黑客使用各种方法扫描系统以寻找漏洞。通常,针对服务器的攻击阶段始于黑客获得对具有访问权限的低级支持帐户的控制。一旦获得该权限,查看内核版本并识别内核易受的漏洞就变得轻而易举。Oracle 提供了一个免费的站点 (ksplice.oracle.com/inspector),让您可以轻松检查内核的漏洞。检查结果如 图 7.2 所示:

图 7.2 – Ksplice 检查器
注意
MITRE 公司是一家由美国联邦政府资助的非盈利组织,致力于研究改善多个行业安全性的方法,包括航空、医疗保健、国土安全、国防和网络安全。常见漏洞和暴露(CVE)项目于 1999 年启动,并迅速成为跟踪网络安全漏洞的首选平台。关于 CVE 项目的更多信息可以在 cve.org 查阅。
系统不仅会识别内核易受攻击的 CVE,还会链接到 MITRE 网站,提供 CVE 详细信息。在示例报告中,您可以看到内核易受几个 CVE 的影响,其中一些 CVE 允许攻击者获得 root 权限。令人惊讶的是,与其他类似技术不同,Ksplice 还通过其已知漏洞检测技术,帮助防御这一阶段的攻击。它能够检测到针对正在运行的内核的攻击,试图通过特权升级获取访问权限。这有效地将使用 Ksplice 的每个系统转变为一个免费的内核入侵检测系统。
在下一个阶段,即获取访问权限时,黑客利用漏洞,获取数据访问权限。这通常发生在初步发现阶段后的几周。黑客会慢慢进行操作,他们这样做是为了保持低调,并且他们知道大多数环境最多每季度才会打一次补丁。此外,许多攻击来自组织内部,这些人作为其正常职责的一部分,通常拥有有限的系统访问权限。Ksplice 打破了这一模式,使系统管理员能够轻松地进行每日打补丁,从而缩短了黑客攻击的机会窗口。
在最后阶段,黑客试图保持访问权限,通常会利用相同的漏洞不断从系统中挖取数据。Ksplice 还可以关闭这一过程,因为它不仅在补丁后关闭漏洞,还能在攻击进行时关闭漏洞。这是 Ksplice 的一项重要功能:能够在漏洞被利用时修补内核并关闭漏洞。这能够在漏洞利用进行中的过程中中断攻击,显著增强系统安全性。
关于补丁工作——最多每季度一次?内核补丁几乎每天都会发布,但系统可能会保持未打补丁的状态长达一个季度或更长时间。这为攻击者提供了一个巨大的入侵窗口。大多数关键任务系统不仅在安排补丁时面临挑战,而且补丁过程本身也非常耗时且需要大量劳动力。让我们来看一下为什么会这样。如下面的图示所示,打补丁需要经过多个步骤:

图 7.3 – 传统的补丁过程
以下是对这些步骤的简要描述:
-
阻止用户访问应用程序:禁用负载均衡器或禁用用户登录应用程序,以防止用户意外破坏数据。
-
关闭应用程序:关闭数据库、应用服务器、调度器、负载均衡器等。这是为了准备操作系统的重启。
-
对服务器进行正常重启:对服务器进行重启,且不做其他更改。目的是验证服务器是否能够顺利重启。在此步骤中,通常会对应用服务器进行快照。
-
重新启动应用程序:重新启动应用程序以验证其是否正常工作。这是为了验证重启的合理性。
-
测试重启后的合理性:通常,一些更改会对应用程序和/或其基础设施产生影响,从而导致应用程序出现问题。此步骤验证在应用补丁之前系统是否处于良好状态。
-
关闭应用程序:再次关闭所有内容以准备进行修补。
-
修补服务器:应用操作系统的修补。
-
修补后重启:重启以使修补生效。
-
重新启动应用程序:再次重新启动应用程序。
-
测试应用程序:测试应用程序,确认一切正常。
-
允许用户重新进入:允许用户重新进入应用程序。
注意
不是每个组织都遵循完整的流程,会跳过某些步骤以节省时间。虽然这可以在短期内节省一些时间,但只要有一个坏的修补周期,在修补周期之间对应用程序和/或其基础设施进行更改,就可能导致非常糟糕、漫长的夜晚,甚至更糟,变成漫长的几天。
如你所见,正确地修补需要花费大量时间,而且应用程序越复杂,每个修补周期所需的人力和时间也就越多。大部分的时间和精力都是由于需要重启而造成的。
当你避免重启时,修补过程会显著简化;如下图所示,只有两个步骤!

图 7.4 – Ksplice 修补过程
以下列表提供了这两个步骤的简短描述:
-
对服务器进行 Ksplice:使用 Ksplice 应用内核和用户空间的修补。
-
测试:测试应用程序
使用 Ksplice 后,你的团队可以节省大量时间,减少加班夜晚,并提高安全性。最棒的是,它易于设置和使用!
发现 Ksplice
Ksplice 配置起来很容易。在对你的服务器进行 Ksplice 之前,有一些概念和要点需要你理解:
-
如果你的服务器运行在Oracle Cloud Infrastructure(OCI)上,并使用 Oracle 的默认平台镜像,所有 Ksplice 的准备工作和访问 Ksplice 仓库的权限都已经完成,以支持在线使用 Ksplice。系统还需要有一条通路(通常是通过 NAT 网关)到 Ksplice 的端点。当使用虚拟云网络(VCN)向导时,这会自动设置好。
-
如果你在 OCI 上使用自主 Linux,你的系统已经在自动进行 Ksplice 操作。
-
Ksplice 有两个客户端:传统的 Uptrack 客户端和增强版客户端。
-
使用 Ksplice 时无需互联网访问;你可以使用特别构建的 Ksplice
.rpm文件来离线模式使用。这需要你在本地 YUM 服务器上镜像 ULN Ksplice 仓库。有关内容已在第五章中讲解。
增强版客户端和 Uptrack 客户端都允许您进行内核 Ksplice,但增强版客户端还提供了对用户空间库、KVM 虚拟机监控程序、基于 Arm 的系统的 Ksplice 支持,并且在 x86_64 平台上提供已知漏洞检测。大多数新用户应选择使用增强版客户端。
旧版的 Uptrack 客户端没有增强版客户端提供的优势,但它确实支持修补一些非 Oracle Linux 系统。
Ksplice 提供了两种不同的模式:在线模式和离线模式。在线模式要求每个系统注册到 Oracle ULN,但它提供了 Ksplice Web 界面、Ksplice Uptrack API,用于高级自动化,并且能够修补 Xen 虚拟机监控程序。然而,由于这要求每个系统不仅要在 ULN 上注册,还需要能够访问互联网,因此许多系统管理员选择使用离线模式。
离线模式允许系统在没有互联网访问的情况下使用 Ksplice。这通常用于企业和政府环境,其中所有服务器都没有互联网连接。在这些用例中,最常见的方法是设置一个 ULN 镜像,允许该系统访问互联网,本地的 Oracle Linux 服务器将从该镜像中拉取并使用 Ksplice:

图 7.5 – 使用 RPM 的 Ksplice 离线模式
在离线模式下,只有本地的 ULN 镜像需要能够通过 HTTPS 协议访问 Oracle ULN。这可以通过基础防火墙规则或更高级的代理服务器实现。一旦 ULN 镜像注册并从 ULN 同步,防火墙后面的服务器就可以通过 HTTP/HTTPS 从 ULN 镜像拉取 RPM。离线模式有几个优势:减少了互联网带宽的使用,并且并非每个客户端都需要注册。当然,由于没有 API,离线模式在更复杂的自动化方面有一些限制。
无论使用什么模式,客户端必须能够访问一些特定的 Ksplice 渠道。下表描述了在 Oracle Linux 中可用的 Ksplice 渠道:
| 渠道名称 | 增强版 客户端 | 渠道标签 | 描述 |
|---|---|---|---|
| Oracle Linux 7(x86_64)的 Ksplice | 可选 | ol7_x86_64_ksplice |
针对 x86_64 系统的 Oracle Linux 7 上的 Ksplice RPM |
| Oracle Linux 7(aarch64)的 Ksplice | 可选 | ol7_aarch64_ksplice |
针对 aarch64 系统的 Oracle Linux 7 上的 Ksplice RPM |
| Oracle Linux 8(x86_64)的 Ksplice | 可选 | ol8_x86_64_ksplice |
针对 x86_64 系统的 Oracle Linux 8 上的 Ksplice RPM |
| Oracle Linux 8(aarch64)的 Ksplice | 可选 | ol8_aarch64_ksplice |
针对 aarch64 系统的 Oracle Linux 8 上的 Ksplice RPM |
| Oracle Linux 7(x86_64)的 Ksplice 感知用户空间包 | 必需 | ol7_x86_64_userspace_ksplice |
针对 Oracle Linux 7(x86_64)的 Ksplice 感知用户空间包的最新 RPM |
| Oracle Linux 7(aarch64)Ksplice-aware 用户空间软件包 | 必需 | ol7_aarch64_userspace_ksplice |
Oracle Linux 7(aarch64)Ksplice-aware 用户空间软件包的最新 RPM |
| Oracle Linux 8(x86_64)Ksplice-aware 用户空间软件包 | 必需 | ol8_x86_64_userspace_ksplice |
Oracle Linux 8(x86_64)Ksplice-aware 用户空间软件包的最新 RPM |
| Oracle Linux 8(aarch64)Ksplice-aware 用户空间软件包 | 可选 | ol8_aarch64_userspace_ksplice |
Oracle Linux 8(aarch64)Ksplice-aware 用户空间软件包的最新 RPM |
表 7.1 – Ksplice 频道
注意
如果安装了 prelink,请将预链接的二进制文件恢复到其原始状态(prelink -au),然后卸载 prelink(dnf remove prelink -y)。虽然不常用,但 prelink 与 Ksplice 不兼容。
现在你已经理解了为什么需要使用 Ksplice 以及它的基本工作原理,接下来我们来看看具体的操作步骤。
使用 Ksplice 最简单的方式是让每个系统直接访问 Oracle Ksplice 服务,这称为在线模式。可以通过互联网代理、直接访问,或者将系统运行在 OCI 中来实现。
准备工作
为了执行此操作,你需要一台运行 Oracle Linux 8 且能够访问互联网的测试系统。
如何操作……
使用 Ksplice 时,确保操作系统版本和用户空间库相匹配。不要为 Oracle Linux 8 系统使用 Oracle Linux 9 的软件库。系统应如下图所示:

图 7.6 – 所需的频道
如果你使用互联网代理服务器,你需要导出一些环境变量来设置代理服务器:
sudo http_proxy=http://proxy_server_URL:http_port
sudo https_proxy=http://proxy_server_URL:https_port
sudo export http_proxy https_proxy
将 proxy_server_URL 设置为代理服务器,http_port 设置为代理服务器使用的端口。
接下来,Ksplice 将通过 dnf 安装。需要安装 ksplice 和 uptrack 包:
dnf install -y ksplice uptrack
安装完成后,请验证你的系统是否已出现在 ULN 中,并且 /etc/uptrack/uptrack.conf 中已填充访问密钥。
访问密钥应位于 [Auth] 部分,应该类似于以下内容:
[Auth]
accesskey = b3ag33k1746d141edb377f6f643344e23ad9638ae4d896ead4dcdddbb350a058b
完成后,执行正常的 dnf update 然后重启系统。第一次使用 Ksplice 时需要执行此 dnf update,以加载 Ksplice-aware 用户空间库。
一旦服务器重启,Ksplice 现在可以用于修补用户空间库和内核。
要查看内核有哪些更新可用,可以运行 Ksplice 的 kernel upgrade 命令,传递 -n 参数表示不执行任何操作:
ksplice -n kernel upgrade
此命令的输出如下图所示:

图 7.7 – 可用的 Ksplice 升级
在此系统中,只有一个更新可用,修补 CVE-2021-4034。要应用该修补程序,请运行相同的命令,将 -n 替换为 -y,以表示同意应用内核路径:

图 7.8 – Ksplice 更新内核
在这里,您可以看到 CVE 补丁已经在没有重启的情况下应用!
已经被修补的内核被称为有效内核。当您在 Ksplice 中使用ksplice kernel uname -r命令时,它会显示有效内核版本,该版本反映了基于已应用补丁的内核当前的安全状态。这个版本通常与初始启动的内核版本不同,旨在反映内核当前对于潜在安全威胁或重大问题的状况。
现在,您可以通过以下 Ksplice 命令验证您的有效内核:
ksplice kernel show
请注意,正在运行的内核版本和已安装的内核版本不会匹配!这是因为当 Ksplice 给内核打补丁时,它会将运行内核的 RAM 与新代码拼接。这修补了内核(和选定的用户空间库),但导致uname不再与有效内核匹配:

图 7.9 – Ksplice uname
在这里,已安装的内核是5.4.17-2136.302.7.2.1.el8uek.aarch64,但已经被 Ksplice 处理的有效内核是一个更新的内核,版本为5.4.17-2136.306.1.3.el8uek。这是 Ksplice 的正常行为。
用户空间库也可以以相同的方式进行补丁处理,将内核替换为用户空间。如果没有安装 Ksplice 用户空间库,首次运行该命令时,您会被提示将用户库升级到支持 Ksplice 的版本:

图 7.10 – 首次安装 Ksplice 用户库
注意
您还可以通过ksplice user show --available命令检查可用的 Ksplice 用户空间包,但是如果没有安装支持 Ksplice 的包,您将看到以下错误:
没有活动的用户空间 Ksplice 目标
您是否已经安装了支持 Ksplice 的库 并重启了系统?
您还可以检查当前运行的用户空间目标,并可以对其进行补丁处理。可以使用以下命令来完成此操作:
ksplice all list-targets
以下是示例输出的截图:

图 7.11 – Ksplice 目标
Ksplice 命令也可以用来回滚补丁。通过使用ksplice kernel show命令,您可以查看当前安装的所有补丁:

图 7.12 – 已安装的内核补丁
每个 Ksplice 补丁都有一个唯一的Ksplice 标识符(KID)。KID 还特定于某个内核版本和补丁,因此在比较不同内核的 KID 时,请小心。如果使用自动化工具来利用 KID,请确保将自动化限制在具有相同内核版本和架构的系统上。
这是已安装补丁列表中的第一列。如果你需要卸载特定的补丁,这是可能的。在这个示例中,KID qd1g4vxd(CVE-2021-4149:BTRFS 文件系统中的拒绝服务漏洞)将使用 Ksplice undo 命令卸载,并传递特定的 KID。你也可以使用 -v 参数查看详细信息。卸载后,检查已安装的 KID 列表,验证是否已成功移除该 KID:

图 7.13 – Ksplice 撤销
可选地,可以使用以下命令从运行中的系统中移除所有已安装的 KID:
ksplice kernel remove --all
这将从内存中的运行内核中移除所有 KID:

图 7.14 – Ksplice 移除
Ksplice 还允许自动更新。你可以通过简单地触摸一个文件或删除一个文件来启用或禁用自动更新。如果存在 /etc/uptrack/disable 文件,则在重启时,Ksplice 将不会自动更新系统。如果该文件不存在,Ksplice 将在重启时检查是否有新的 KID,并应用它们。你也可以通过更新 uptrack.conf 文件来修改此行为,本章后面会介绍。
它是如何工作的……
当你使用带有互联网连接的 Ksplice 时,Ksplice 客户端会连接到 Oracle ULN Ksplice 系统,下载并应用所需的补丁。
在没有互联网连接的情况下使用 Ksplice
并非所有系统都有互联网连接。没关系,因为可以使用 Ksplice 从本地补丁库进行操作。
准备工作
为此,你需要一台运行 Oracle Linux 8 的测试系统,并且可以访问网络中的本地 YUM 仓库。
如何操作……
安装客户端时,请确保你的服务器正在使用本地镜像的 RPM 仓库。安装 Ksplice 时,你必须选择使用在线客户端或离线客户端。提醒一下,在线客户端需要系统已注册到 ULN,而离线客户端则使用本地 RPM 仓库。
要安装在线客户端,请运行以下命令:
dnf install -y ksplice uptrack
要安装离线客户端,请运行以下命令:
dnf install -y ksplice ksplice-offline uptrack-offline
该命令的输出如下图所示:

图 7.15 – 离线安装 Ksplice
一旦安装了 Ksplice,你现在可以开始为服务器打补丁。
注意
由于 Uptrack 客户端在 Oracle Linux 8(或 Oracle Linux 7)中不再优于新客户端,因此我们将重点介绍增强版客户端。如果你使用的是较旧的操作系统,可能需要使用旧版的 Uptrack 客户端。
使用离线方式的 Ksplice 非常简单;只需使用 dnf 来打补丁:
dnf -y update
这将同时以常规方式和使用 Ksplice 对内核及用户库进行打补丁。如果你想禁用此行为,可以在 /etc/uptrack/uptrack.conf 中将 skip_apply_after_pkg_install 设置为 true。
在打补丁之前,请确保在 /etc/yum.repos.d 中添加了 Ksplice 条目。一个示例 Ksplice 条目可能如下所示:
[root@ol8 ~]# more /etc/yum.repos.d/Ksplice.repo
[Ksplice_ol8_local]
name=Ksplice for OL8
baseurl=http://yum.m57.local/yum/OracleLinux/OL8/Ksplice/x86_64/ol8_x86_64_Ksplice/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY
gpgcheck=1
enabled=1
[Ksplice_ol8_userspace]
name=Ksplice OL8 userspace
baseurl=http://yum.m57.local/yum/OracleLinux/OL8/userspace/Ksplice/x86_64/ol8_x86_64_userspace_Ksplice/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY
gpgcheck=1
enabled=1
它是如何工作的…
Ksplice 是一个工具,它允许 Linux 系统保持最新的安全修复和重要更新,而无需重启系统。这对于需要尽量减少停机时间的服务器和环境特别有益。值得注意的是,尽管 Ksplice 可以处理许多补丁,但某些更复杂的更改可能无法在实时环境中应用,这时将需要传统的基于重启的更新。
安装和启用已知漏洞检测
为了确保系统安全(更重要的是,保护系统中的数据),最关键的操作之一就是实现检测功能,以便发现坏人试图闯入。Ksplice 有一个独特的功能,称为 已知漏洞检测 (KED),它会报告针对内核的已知攻击。通常,只有那些允许黑客获得额外权限的漏洞才会被用于 KED,并且要触发这些漏洞,内核应该已经为该漏洞进行了拼接。
准备就绪
为此,你需要一台运行 Oracle Linux 8 且已设置 Ksplice 的测试系统。
如何操作…
这是通过 tripwire 代码完成的,当检测到特定事件时会触发。通常,只有那些使攻击者能够获得特权访问的事件才会被监控。此软件包在 x86 和 ARM 系统上都可用。
要启用此功能,首先必须使用以下命令安装该软件包:
dnf install -y ksplice-known-exploit-detection
无论安装是在 ARM 还是 x64 服务器上,安装过程几乎完全相同,主要的区别在于每个系统上已安装的软件。这让我想起一点:无论是 ARM 还是 x64,管理员的任务都是一样的。
注意
当安装了 KED 后,postfix 也会被安装,以启用作为通知系统一部分的邮件发送功能。
在基于 ARM 的系统上安装时的输出结果如下图所示:

图 7.16 – 在 ARM 上安装 KED
在基于 x86_64 系统上安装时的输出结果如下图所示:

图 7.17 – 在 x64 上安装 KED
安装完 KED 后,需要启用此功能。这可以通过将以下行添加到 /etc/uptrack/uptrack.conf 来完成:
[Known-Exploit-Detection]
enabled = yes
接下来,你需要通过 Ksplice 来启用运行中的内核中的此功能:
ksplice --yes kernel upgrade
安装后输出结果如下图所示:

图 7.18 – 在运行中的内核中启用 KED
需要注意的是,如果没有可用的 Ksplice 补丁,你将收到一个通知,表示内核是最新的,如前面的截图所示。但是,如果系统需要补丁,Ksplice 会在此时打补丁,同时启用 KED。
要验证 KED 是否启用,执行 cat /proc/sys/kernel/known_exploit_detection,并查找输出是否为 1。如果文件缺失或输出为零,说明 KED 没有启用,因此不会监控你的系统:

图 7.19 – 检查 KED 是否启用
KED 的通知由 /etc/log-known-exploit.conf 配置文件控制。以下截图显示了一个示例配置文件:

图 7.20 – KED 通知配置
在配置文件中,你可以控制以下操作:
-
[syslog]:大多数管理员将事件记录到 syslog,以便使用如 OCI Log Analytics 或 Splunk 等日志分析工具进行捕获和分析。enabled: 0设置将禁用记录到 syslog。 -
[email]:此部分允许在触发 tripwire 时发送电子邮件通知。根据需要添加收件人的电子邮件地址。此操作还要求系统能够发送电子邮件,可以通过云服务(如 OCI 邮件投递服务)或自己的 简单邮件传输协议 (SMTP) 中继来完成。 -
[actions]:你可以为特定的 CVE 禁用通知。如果系统上出现意外的误报,这会很有帮助。要禁用某个 CVE,只需添加一行包含 CVE 和ignore。default:参数设置所有 CVE 的默认行为。
注意
如果你启用了电子邮件通知,确保在启用来自 KED 的电子邮件之前,已经配置好了你的电子邮件子系统。
你还可以使用 log-known-exploit 命令测试系统。这将在内核中记录一条测试消息:
/usr/sbin/log-known-exploit -f -d ; tail /var/log/messages
测试事件在 /var/log/messages 中的显示如下:
Apr 22 23:01:02 ol8splice2 /log-known-exploit[4192]: exploit attempt detected; id=CVE-2012-1234 pid=1337 uid=1000 comm=./dummy-exploit lost=0
在日志中,你将看到时间、触发的 CVE,以及触发事件的进程和用户的 进程 ID (PID) 和 用户 ID (UID)。
它的工作原理是…
Ksplice 在内核中安装了特定漏洞的 tripwire 代码,用于检测是否有人试图利用该漏洞。这些触发器会启动通知子系统,让你知道何时发生攻击。
第八章:DevOps 自动化工具——Terraform、Ansible、Packer 等
如果操作系统不能满足开发者需求,那它又有什么用呢?毕竟,易于开发的操作系统往往比那些不适合开发的操作系统拥有更强大的生态系统。你会很高兴地知道,Oracle Linux 非常适合开发者使用,本章将介绍一些常见的开发工具,它们将使你在开展下一个项目时更加轻松。
有无数的开发工具在 Oracle Linux 上运行良好,但本章重点讨论的工具都与自动化相关。我们将讨论如何自动化云基础设施、自动化操作系统构建周期、自动化系统管理员任务以及自动化为开发目的启动虚拟机。
本章我们将介绍以下内容:
-
手动做一次——然后使用 Terraform 反复执行
-
为 Ansible 创建可移植角色
-
使用 Ansible Vault 管理机密
-
用 Vagrant 打造完美的实验环境
-
使用 Packer 修改源镜像
-
收拾好行囊,准备开始,呃,嗯……构建
技术要求
本章我们将涵盖很多技术。让我们准备好你的机器,这样你就可以方便地跟随教程进行操作。
Ansible
对于 Oracle Linux 8,我们可以通过利用Oracle Linux Automation Manager库来安装 Ansible,先安装该库,然后我们再安装 Ansible:
$ sudo dnf install -y oraclelinux-automation-manager-release-el8
$ sudo dnf install -y ansible
Packer、Vagrant 和 Terraform
Packer 是一个用于自动化创建机器镜像的工具,Vagrant 用于管理虚拟机的生命周期,而 Terraform 是一个基础设施即代码的工具。Packer、Vagrant 和 Terraform 都是 HashiCorp 的产品,但它们在 Oracle Linux 上表现良好。
我们将直接从 HashiCorp 安装 Packer、Vagrant 和 Terraform:
$ sudo dnf install -y dnf-plugins-core
$ sudo dnf config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
$ sudo dnf install -y packer vagrant terraform
完成后,我们继续安装Oracle VM VirtualBox,因为我们将与Packer和Vagrant一起使用 VirtualBox:
$ sudo dnf install -y oraclelinux-developer-release-el8
$ sudo dnf install -y VirtualBox-7.0
最后,除了 Terraform,我们还需要创建一个Oracle Cloud Infrastructure(OCI)账户。如果你愿意,可以选择使用其他云服务,但如果你希望直接跟随本教程,建议使用 OCI。
重要提示
一定要记住你的云账户名称,因为这是访问你的 OCI 账户时需要的一个重要细节。
下载源代码
本章的食谱源代码可以在github.com/PacktPublishing/Oracle-Linux-Cookbook/tree/main/ch8找到。
手动做一次——然后使用 Terraform 反复执行
Terraform 是一个 基础设施即代码 (IaC) 工具,它可以让你安全高效地构建、改变和版本化基础设施。本食谱将提供一个关于如何用 Terraform 自动化 繁琐 任务的技术概览。繁琐是什么意思?嗯,就是任何手动完成的任务。我们想要去掉这些手动步骤,尽可能地实现自动化。具体到 Terraform,这意味着我们将自动化云基础设施的部署。得益于 Terraform,我们不再需要通过数百个不同的菜单设置来点击操作。相反,我们将定义 基础设施即代码。这使得部署更快速、更一致。此外,由于所有内容都可以通过代码进行编辑,修改基础设施也变得更加容易。
开始使用
你将需要以下内容来完成本食谱:
-
Oracle Linux
-
Terraform
如果你需要帮助安装 Terraform,请参考本章开头的 技术要求 部分。
如何操作…
每当你开始自动化某件事时,最好先深入理解底层需要做什么。你能猜到这是什么意思吗?没错,你必须至少手动完成所有步骤一次,然后再尝试自动化。
首先,先手动操作一次…
本食谱的目标是使用 Terraform 在云中部署一个简单的虚拟机。这是一个足够简单的任务,但在我们跳入如何通过代码实现之前,通常最好先手动操作一次。所以,话虽如此,我们先通过 OCI 网页界面部署一台虚拟机:
- 登录到 Oracle 云基础设施控制台 (
cloud.oracle.com/)。

图 8.1 – OCI 控制台登录页面
- 点击左上角的汉堡菜单图标:

图 8.2 – OCI 控制台主屏幕
然后点击 计算 | 实例:

图 8.3 – OCI 云计算菜单
确认你在想要的 隔离区 中,最后点击 创建实例:

图 8.4 – OCI 云计算实例
信息
为了简洁,当需要点击多个菜单项时,管道符号(|)表示点击按钮/链接的顺序。
- 我们将使用默认的 Oracle Linux 镜像,但如果你想更改,可以进入 镜像和形状,然后点击 编辑。

图 8.5 – OCI 控制台计算镜像和形状
注意
只要你遵循所有始终免费适用的资源,就没有费用;然而,在写作时,存在一个错误,错误地显示了每月 $2.00 的启动卷费用。这个错误是因为启动卷使用的是块存储,而 OCI 为你提供最多 200 GB 的块存储是免费的。
在写作时,最新版本是Oracle Linux 8(镜像构建:2023.06.30-0)。
- 在添加 SSH 密钥下,选择为我生成一对密钥,然后点击保存私钥和保存公钥。
提示
选择一个容易记住的地方,因为你稍后需要在 SSH 连接到你的虚拟机时使用这个位置。
- 最后,点击创建。
注意
等待图像构建时,随时可以去喝杯咖啡。
现在,让我们使用 SSH 连接到实例:
-
在实例信息标签页中,点击公共 IP 地址旁边的复制按钮。
-
打开一个终端应用程序,使用
ssh命令连接。我们将使用-i(其中i代表身份文件)来引用我们在前面的步骤中保存的私钥。对于托管在 OCI 中的官方 Oracle Linux 实例,默认的用户名是opc,因此我们将指示ssh以opc身份连接。最后,输入你在前一步中获得的公共 IP 地址。你的命令应该看起来像这样:

图 8.6 – SSH 连接计算实例(失败)
- 哎呀!你注意到那个大警告以及最后的信息了吗?我们因为权限问题被拒绝访问。让我们通过使用
chmod命令,只为文件的所有者赋予访问密钥文件的权限来修复它:

图 8.7 – SSH 连接计算实例(成功)
太棒了!我们已经通过 SSH 连接到了机器。
现在我知道这并不难,但想象一下如果你需要做一百次该怎么办?为什么不使用 Terraform 自动化这个过程呢?
现在是时候使用 Terraform 反复操作了
这次我们将完成与之前描述的完全相同的操作——也就是,我们将再次在 OCI 中创建一个虚拟机。然而,这一次,我们将使用 Terraform 来定义我们的基础设施即代码(IaC):
-
首先,让我们在项目目录的根目录下创建三个新文件(我将这个文件命名为
terraform),使用你喜欢的代码编辑器,文件名如下:-
main.tf -
variables.tf -
terraform.tfvars
-
-
接下来,让我们前往 Terraform 注册表 (
registry.terraform.io/) 查找Oracle Cloud 基础设施(OCI)的提供者。 -
在 Terraform 注册表中,搜索
oci或oracle cloud infrastructure,然后选择oracle/oci。
注意
或者,你可以点击浏览提供者,然后点击Oracle Cloud Infrastructure 按钮。
- 点击
main.tf文件:

图 8.8 – Terraform OCI 提供者
-
注意
provider "oci"下的# 配置选项注释。这告诉我们可能需要提供一些配置选项才能使用该提供者。让我们看看如何做到这一点:
-
点击 文档 标签(它就在 使用提供者 旁边),然后找到 如何配置 提供者 的链接。
-
你会发现 OCI Terraform 提供者支持四种身份验证方法:
-
API 密钥 身份验证(默认)
-
实例 主体授权
-
资源 主体身份验证
-
安全性 令牌身份验证
-
-
对于本食谱,我将使用默认的身份验证方法;即 API 密钥身份验证。这种方法的限制最少,但根据你的使用情况,你可以选择最适合你需求的方法。
-
重要提示
提供身份验证信息没有快捷方式;但是,若需要一些帮助的指导,你可以参考与本食谱相关的 GitHub 仓库中的 oci-provider-conf.md 文件。如果你需要更多细节,我建议按照前面提到的 如何配置提供者 部分中描述的文档进行操作。
- 如果你决定在
main.tf文件中使用provider "oci":

图 8.9 – API 密钥身份验证详细信息
为了保持整洁,我们将引用这些值的变量。稍后我将在本食谱中提供更多有关如何定义/声明变量的详细信息。
注意
为了说明我们正在向文件中添加内容,我使用了三组省略号。这是为了表示我们在前面步骤中所做的操作的延续。
这是一个示例:
...
...
...
-
现在我们已经设置好了提供者,除非我们添加资源,否则它不会做太多工作。在这种情况下,我们想要添加一个
oci_core_instance。你还记得我们在手动过程中生成 SSH 密钥对时吗?现在,我们需要找出如何使用代码动态地做到这一点。以下指令是如何使用 Terraform 完成这一操作的。我们将创建一个
tls_private_key资源,并将其作为我们的ssh_authorized_keys引用到oci_core_instance资源的元数据中。我们从 SSH 密钥对开始,它是通过
tls_private_key资源创建的。有关此资源的详细信息,可以在 Terraform 注册表的hashicorp/tls提供者下找到。继续编辑main.tf文件,并添加以下内容:

图 8.10 – 使用 Terraform 定义 SSH 密钥对
- 你需要定义一个有效的可用域。实现这一点的一种方式是使用 Terraform 查询可用域列表,并引用该列表中的一个项,所以让我们将以下代码添加到
main.tf文件中:

图 8.11 – 使用 Terraform 获取可用域列表
- 最后,我们将添加一个
oci_core_instance资源。如果你查看 Terraform 注册表中的oracle/oci提供程序下的oci_core_instance资源,你会看到一个很长的参数列表,这些参数可以用来定义oci_core_instance资源;然而,并不是所有的参数都是必需的,因为很多参数前面都有#Optional标记。在这个示例中,我们将使用此资源所需的最少参数——大致应该是这样的:

图 8.12 – OCI 核心实例资源详细信息
- 一旦你完成了
oci_core_instance资源,你的整个main.tf文件应该像这样:

图 8.13 – main.tf 文件的内容
-
现在,我们需要声明在
main.tf文件中引用的所有变量。为了保持结构清晰,我们将它们放在variables.tf文件中。每个变量至少应包含一个类型;然而,我们还将添加描述以解释变量的用途。将以下内容输入到
variables.tf文件中:

图 8.14 – 在 variables.tf 文件中声明变量
- 最后,我们需要为变量分配值。为此,你可以使用
terraform.tfvars文件。它应该像这样:

图 8.15 – terraform.tfvars 文件的内容
注意
请参考以下指南,找到tenancy_ocid、compartment_ocid、user_ocid、fingerprint、subnet_ocid和private_key_path的ocid:docs.oracle.com/en-us/iaas/Content/API/SDKDocs/terraformproviderconfiguration.htm。
要获取 Oracle Linux 8 的 OCID,请访问以下链接:docs.oracle.com/en-us/iaas/images/oracle-linux-8x/ 此链接是区域特定的,也与架构有关,因此你需要找到适用于 x86 的最新 Oracle Linux 8 镜像(换句话说,查找镜像名称中没有aarch64文本的版本)。
警告
确保将terraform.tfvars文件添加到.gitignore列表中,以避免将任何敏感信息提交到版本控制中。
-
接下来,让我们运行 Terraform,看看我们是否做对了:
$ terraform init $ terraform plan terraform init command initializes the working directory containing your Terraform project files and this should always be the first command that you run after you write a new Terraform configuration. After this, it is a good idea to run terraform plan as this will give you a chance to preview/verify the plan. During this command, Terraform will compare your real infrastructure against your configuration. Finally, running terraform apply will display the plan again, but it will additionally give you the chance to enter yes to perform any actions proposed by the plan.When you see the prompt that asks you to `Enter a value`, go ahead and type `yes`, and then press *Enter*.
重要提示
如果遇到401-NotAuthenticated错误,请确保已将您的公钥添加到 OCI 控制台中。此公钥与API 密钥 认证方法下的private_key_path配对。
如果你需要帮助将公钥添加到 OCI 控制台,请访问 docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm#three。
-
如果一切顺利,你应该能够看到资源被创建的过程。一旦完成,你会看到类似这样的信息:
instances folder within your Terraform project.This is easy enough to do, but why not automate a bit more so we don’t need to check the OCI console for the public IP address? All we need to do is add a bit more code to our `main.tf` file and we can really start to take things to the next level.Go ahead and add the following code to your `main.tf` file:

图 8.16 – 输出连接详情的 Terraform 代码
-
现在我们已经完成了这部分,保存文件后,再次运行
terraform apply,看看它的作用:Enter a value prompt, go ahead and type yes, and then press *Enter*. -
Terraform 将按照它的方式执行,最后你会看到输出,其中提供了如何通过 SSH 连接到新创建的实例的说明。它的输出应该看起来像这样:

图 8.17 – “terraform apply” 的输出
我意识到我们刚才讨论的内容似乎有很多信息,但让我们来回顾一下我们所做的工作。我们实现了将实例自动部署到云端。每个参数都可以在我们的terraform.tfvars文件中轻松配置。最后,包括生成 SSH 密钥在内的琐碎步骤也被自动化处理,我们甚至在最后打印出一条信息,明确指导如何连接到新部署的实例。我希望你喜欢这个教程,并且开始看到IaC的真正价值!
这个教程的源代码可以在以下地址找到:github.com/PacktPublishing/Oracle-Linux-Cookbook/tree/main/ch8/terraform。
为 Ansible 创建可移植角色
在尝试跟随这个教程之前,我建议你具备一些关于 Ansible 的基础知识,以及如何编写 Ansible playbook。如果你从未编写过 Ansible playbook,我建议你参考官方 Ansible 文档中的创建 playbook指南。你可以在这里找到该指南:docs.ansible.com/ansible/latest/getting_started/get_started_playbook.html。
在这个教程中,你将学到使用Ansible 角色时,移动内容是多么的简单。当我第一次开始使用 Ansible 时,我只用任务来编写 playbook。对我来说,这种方法在当时看起来是合乎逻辑的,并且更像传统的脚本编写方式,因为所有的操作都是按时间顺序执行的。
以这种方式编写 playbook 的问题在于没有明确的依赖关系,并且任务与主机一起定义,都在同一个文件中。如果你想把某些内容移到另一个 playbook,你就得小心地为每个任务抓取正确的依赖项,而且你可能会不必要地重复自己,因为任务本身不可复用。当你的 playbook 变得更复杂和/或增大时,为了可管理性,你最终会希望有一些更便于迁移的东西。
根据 Red Hat 的说法,角色是设计成自包含的可移植自动化单元。
将任务组织成角色(roles)可以让您轻松地重复使用这些任务并与他人共享。事实上,如果您访问 Ansible Galaxy(galaxy.ansible.com/),您将会发现大量以预打包的工作单元(在 Ansible 中称为角色和集合)的形式存在的内容。因为这些角色是与其他 Ansible playbook 框架解耦的,所以将 Ansible 角色作为组织化的自动化单元进行重用和共享要容易得多。
如果您是程序员,可以把角色看作是函数或方法。很简单吧?让我们开始吧!
开始使用
对于这个教程,您需要以下内容:
-
Oracle Linux
-
Ansible
如果您需要帮助安装 Ansible,请参考本章开头的技术要求部分。
如何操作…
将一系列任务转换成角色并不困难,实际上只是将任务拆分并将其组织成代表角色的类别。这个教程旨在描述这个过程,并希望到最后,您能够很好地理解如何在自己的 playbook 中实现这一点。
原始 playbook
让我们首先来看一个不使用角色的 playbook,看看需要做什么。
一个典型的没有使用角色的 playbook 可能是这样的:

图 8.18 – 没有角色的长 playbook
注意
截图在最后消失是因为这是一个长 playbook,整个 playbook 的内容并不重要。
这个 playbook 自动化了几个任务。首先,如果标准用户不存在,它会创建一个,然后通过 container-tools AppStream 模块安装 Podman,接着启动一个 NGINX 容器,最后升级系统中的所有软件包,并检查系统是否需要重启。
如您所见,如果将所有任务直接写入一个 playbook,文件很快就会变得庞大而难以管理。不久之后,您会发现自己在文件中重复写入准备工作任务,并且很可能会在每行的开头添加注释符号,将不必要的任务标记为注释,从而让自动化引擎将它们视为注释而非代码——您甚至可能会在执行 playbook 时切换任务的启用与禁用,以便针对某个特定任务。这可能会让人感到不堪重负,如果不小心,您可能会删除一些代码,尽管有时您可能仍然需要它们。角色提供了一种更好的组织 playbook 的方式。事实上,您可以写尽可能多的角色,并将它们整齐地调用到 playbook 中——这样 playbook 会更易于阅读和维护。
创建角色
在 Ansible 中,角色是组织在 roles 目录下的。你在 roles 下创建一个文件夹,文件夹的名称将成为角色的名称。然后在该文件夹中,至少要创建一个名为 tasks 的文件夹,里面应包含一个定义该角色将执行的主要任务的 main.yml 文件:
-
让我们分解一下并通过在
roles目录中创建一个users文件夹来为用户创建一个角色。你的目录结构应该大致如下:
├── playbook.yml └── roles └── users ├── files │ └── wallpaper.jpg └── tasks └── main.yml -
现在,在
tasks目录中创建一个main.yml文件,将我们的用户相关任务迁移到该文件中。

图 8.19 – 用于配置用户的 Ansible 角色
-
现在我们有了角色的雏形。我们可以利用其他功能来便于预配置操作。以下是我最常用的两个功能——
files和meta:-
首先,你会注意到我们引用了一个
files目录。那是属于角色的一个特殊目录,包含与该角色相关的文件。 -
另一个是
meta目录,它用于声明依赖项。例如,由于users角色依赖于某些组的存在,最好先使该角色依赖于groups角色。为此,我们只需为groups创建一个角色,然后从meta目录中调用该角色。
-
-
groups角色可能如下所示。请注意目录结构以及附带的文件——这些都是构成角色的元素。你的目录结构应如下所示:├── playbook.yml └── roles └── groups └── tasks └── main.yml -
实际的任务应该写在
main.yml文件中,内容如下:

图 8.20 – 用于用户组的 Ansible 角色
-
现在,在
users角色的meta/main.yml文件中,我们只需要将groups角色作为依赖项调用:--- dependencies: - role: groups -
最后,使用以下命令运行剧本:
$ ansible-playbook playbook.yml你已经成功创建了一个 Ansible 角色。
-
接下来,重复这个过程,直到你将所有内容组织成角色。对我来说,最终我得到了以下的目录结构:
├── playbook.yml └── roles ├── base_software │ └── tasks │ └── main.yml ├── containers │ └── tasks │ └── main.yml ├── get_hostname │ └── tasks │ └── main.yml ├── groups │ └── tasks │ └── main.yml ├── update_packages │ ├── meta │ │ └── main.yml │ └── tasks │ └── main.yml ├── uptime │ └── tasks │ └── main.yml └── users ├── files │ └── wallpaper.jpg ├── meta │ └── main.yml └── tasks └── main.yml
更新版的剧本
至于实际的剧本,它现在可以简化为如下内容:

图 8.21 – 利用角色的 Ansible 剧本
注意
请注意,我们没有在剧本中列出 base_software 和 groups 角色,因为这些是我们在 meta 目录中定义的依赖项。
如你所见,我们现在不再引用 tasks,而是直接引用 roles。这种方式非常整洁有序,也更容易理解剧本的目的。如果你想了解某个特定角色的功能,只需进入 roles 目录,找到相应角色的名称,并查看该角色 tasks 文件夹中的 main.yml 文件。
当你准备好时,像往常一样运行剧本:
$ ansible-playbook playbook.yml
如果一切顺利,它应该已经完成了我们原本剧本中所做的所有工作;然而,这次我们使用的是 Ansible 角色,因此我们的剧本在未来将更容易维护。
本食谱的源代码可以在github.com/PacktPublishing/Oracle-Linux-Cookbook/tree/main/ch8/ansible-roles找到。
使用 Ansible Vault 管理机密
本食谱旨在提供关于如何利用Ansible Vault进行机密管理的指导。
在 Ansible 中存储机密有多种方法。刚开始时,你可能倾向于加密整个hosts文件。这种方法有效,并且在使用版本控制系统的上下文中保持所有内容安全,而不会泄露你的机密/密码;然而,它不可管理,也无法在版本控制系统中提供任何有用的信息,因为你剩下的只是一串长而毫无意义的加密字符。
入门
你需要以下内容来完成这个操作:
-
Oracle Linux
-
Ansible
如果你需要帮助安装 Ansible,请参考本章开头的技术要求部分。
如何操作…
首先,让我们看看整个文件加密。首先,我们需要在明文中定义我们的 Ansible 主机文件。
整个文件加密
通常,Ansible 主机文件看起来像这样:
# hosts
[host1]
192.168.2.70
[host1:vars]
ansible_user=admin
ansible_password=B@by-Y0dA
ansible_connection=ssh
ansible_shell_type=powershell
[host2]
192.168.2.71
[host2:vars]
ansible_user=admin
ansible_password=B@by-Y0dA
ansible_connection=ssh
ansible_shell_type=powershell
你可以通过在终端/控制台中运行以下命令来加密文件:
$ ansible-vault encrypt hosts --ask-vault-pass
New Vault password:
Confirm New Vault password:
Encryption successful
我正在使用一个随机生成的字符串作为我的 vault 密码。
加密文件的另一种方式是使用vault_password,并将密码粘贴到其中。
注意
最好将vault_password文件的权限设置为0600(可以通过运行chmod 0600 ./vault_password来实现),以保护它不被其他用户访问。
现在,不再使用--ask-vault-pass,你可以使用以下命令:
$ ansible-vault encrypt hosts --vault-password-file vault_password
Encryption successful
很棒!只要确保将vault_password文件添加到.gitignore列表中,以避免将其提交到版本控制中。
现在,如果你cat你的hosts文件,你会看到内容已被加密:

图 8.22 – 加密“hosts”文件的内容
这很好,但每当你需要修改hosts文件时,你面临两种选择:
-
解密
hosts文件,进行更改,然后再次加密 -
使用
ansible-vault edit hosts来利用 ansible-vault 的vim模式编辑文件
这些选项并不糟糕,但实际上这可能会变得很繁琐。我建议一种更好的方法,即在 Ansible Vault 中使用encrypt_string方法,仅加密敏感数据,并使用变量代替密码/密钥来引用这些加密的字符串。
将密码公然隐藏
将密码明文隐藏在明处与我们之前描述的整个文件加密直接相反。我们仍将加密我们的敏感数据,但这一次我们将仅加密敏感数据,而将其他所有内容保留在明文未加密状态:
-
我们将使用
encrypt_string方法。在本示例中,我们要加密的密码是B@by-Y0dA,我们将使用标识此密码的变量命名为admin_password。'B@by-Y0dA' looks like once encrypted:

图 8.23 – 加密密码
-
接下来,我们需要将其输出到
secrets.yml文件中(您可以简单地将>> secrets.yml追加到之前输入的命令中,以自动将输出复制到文件中)。这是一个示例:secrets.yml file should look something like this:

图 8.24 – secrets.yml 文件内容
重要提示
每次运行命令时,您可能会注意到加密后的值都不相同,即使使用相同的密码加密相同的值也是如此。每次加密时会改变随机盐;这是有意设计的,目的是确保最终加密输出永远不相同(即使使用相同内容)。
-
现在您已加密,可以将主机文件中的
ansible_password值替换为引用密码的变量名称(在本例中为admin_password):# hosts [host1] 192.168.2.70 [host1:vars] ansible_user=admin ansible_password={{ admin_password }} ansible_connection=ssh ansible_shell_type=powershell [host2] 192.168.2.71 [host2:vars] ansible_user=admin ansible_password={{ admin_password }} ansible_connection=ssh ansible_shell_type=powershell
注意
变量级加密的优点在于文件仍然可以轻松阅读和理解,因为在加密变量旁边会有明文混合存在。
此配方的源代码可在 github.com/PacktPublishing/Oracle-Linux-Cookbook/tree/main/ch8/ansible-vault 找到。
用 Vagrant 打造完美的实验环境
最近在工作中,我被要求准备一个 Oracle Linux Manager 的演示,并展示软件的几个特性。这本来是一件容易的事情,但在您访问 Oracle Linux Manager 的 Web GUI 之前,有几个入门障碍需要克服。
首先,Oracle Linux Manager 需要 Oracle Linux 7;它尚未在 Oracle Linux 8 上认证。因此,我开始下载 Oracle Linux 7 的 ISO 并在 VirtualBox 中创建虚拟机并安装操作系统。然后我想要 SSH 进入该虚拟机,因此我不得不进入虚拟机的设置菜单,并配置主机到客户机的端口转发。此时,我能够成功 SSH 登录,并按照 Oracle Linux Manager 的安装说明进行操作。设置起来并不是太糟糕,但中途出现了几个阻碍。例如,我需要决定使用哪个数据库。Oracle 仅支持将 Oracle 数据库与 Oracle Linux Manager 配合使用,但为了简洁起见(并且因为这只是 Oracle Linux Manager 的实验演示),我决定使用 PostgreSQL。
由于手动步骤繁多,我倾向于把我新创建的虚拟机当做宠物来照顾。人们常说容器像牛群,虚拟机像宠物。也就是说,直到你开始使用像 Vagrant 这样的工具。Vagrant 做得很好,它让你的虚拟机和牛群融合在一起——感谢 Vagrant 让你能够轻松地重建虚拟机,你不再需要像以前那样照顾它们,尤其是当你不使用 Vagrant 时。
本教程将指导你创建一个使用Vagrant的实验环境。
准备工作
你将需要以下内容来完成本教程:
-
Oracle Linux
-
Oracle VM VirtualBox
-
Vagrant
如果你需要帮助安装 Oracle VM VirtualBox 和 Vagrant,请参阅本章开始的技术要求部分。
如何操作……
Vagrant 是一个用于管理虚拟机生命周期的工具。在本指南中,我们将创建一个 Vagrant 盒子,它会自动安装并配置 Oracle Linux Manager。Oracle Linux Manager 需要 Oracle Linux 7。在这种情况下,我们可以使用官方的Oracle Linux 7 Vagrant Box作为基础:
$ vagrant init oraclelinux/7 https://oracle.github.io/vagrant-projects/boxes/oraclelinux/7.json
很好,这已经为我们拉取了一个不错的基础文件。让我们看看Vagrantfile文件,看看里面有什么:
# Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "oraclelinux/7"
config.vm.box_url = "https://oracle.github.io/vagrant-projects/boxes/oraclelinux/7.json"
end
实际上,由init命令生成的Vagrantfile包含 69 行代码,但其中 65 行是注释,因此我将它们移除,以帮助使这篇指南更容易理解。
正如我们从这个Vagrantfile中看到的,启动 Oracle Linux 7 实例只需要这四行命令,当它启动并运行时,你只需输入vagrant ssh命令即可访问虚拟机并查看它如何工作。完成后,输入vagrant destroy命令以销毁虚拟机。现在,让我们深入研究如何使这更有用;因为我希望能够输入vagrant up,不仅启动一个 Oracle Linux 虚拟机,还希望同样的命令启动一个可以工作的 Oracle Linux Manager 副本。
首先,让我们回顾一下 Oracle Linux Manager 的安装和配置说明——这些可以在docs.oracle.com/en/operating-systems/oracle-linux-manager/2.10/install/#Oracle-Linux-Manager找到。由于我们不使用 Oracle 数据库,我们将稍微偏离这些说明——这意味着我们将跳过与 Oracle 数据库相关的内容(例如,我们不需要 Oracle Instant Client 和SQLPlus*包)。
为了说明我们将要做的事情,我将列出指南中的所有步骤,并将我们要保留的步骤用粗体标出。那些没有加粗的步骤将被跳过:
-
sudo yum installoracle-instantclient18.5-basic-18.5.0.0.0-3.x86_64.rpm oracle-instantclient18.5-sqlplus-18.5.0.0.0-3.x86_64.rpm -
echo "/usr/lib/oracle/18.5/client64/lib" | sudotee /etc/ld.so.conf.d/oracle-instantclient18.5.conf -
sudo ldconfig -
sudo yum list installed | grep jta
-
sudo yum remove jta
-
echo «exclude=jta» >> /***etc/yum.conf
-
sudo yum-config-manager –****disable ol7_addons
-
sudo firewall-cmd --``permanent --add-port=69/udp -
sudo firewall-cmd --``permanent --add-port=80/tcp -
sudo firewall-cmd --``permanent --add-port=443/tcp -
sudo firewall-cmd --``permanent --add-port=5222/tcp -
sudo firewall-cmd --``permanent --add-port=5269/tcp -
sudo systemctlreload firewalld -
sudo yum install oracle-release-el7
-
sudo yum install oracle-linux-manager-server-release-el7
-
sudo yum-config-manager --****enable ol7_optional_latest
-
spacewalk-oraclespacecmd spacewalk-utils -
sudospacewalk-setup --external-oracle
就这些了。以下是我们需要做出的其他更改,以便将 Oracle Linux Manager 与 PostgreSQL 一起使用:
sudo yum install spacewalk-setup-postgresql spacewalk-postgresql
最后,我们需要提供一个答案文件,因为我们在 Vagrant 中进行的自动化不能进行交互式操作:
sudo spacewalk-setup --non-interactive --answer-file=/tmp/answer-file.txt
创建一个名为answer-file.txt的文件,并将以下内容放入该文件:
admin-email = root@localhost
ssl-set-cnames = spacewalk
ssl-set-org = Oracle
ssl-set-org-unit = OLM
ssl-set-city = Raleigh
ssl-set-state = NC
ssl-set-country = US
ssl-password = Password1
ssl-set-email = root@localhost
ssl-config-sslvhost = Y
db-backend = postgresql
db-name = spaceschema
db-user = spaceuser
db-password = Password1
db-host = localhost
db-port = 5432
enable-tftp = Y
这总结了大部分安装和配置步骤。接下来,为了使这些操作能够正常工作,以便我们可以通过 Vagrant 自动部署和配置 Oracle Linux Manager,我们需要进行一些非常简单的修改。我们真正需要做的就是将这些步骤粘贴到一个Bash shell 脚本文件中,并告诉 Vagrant 使用一个提供者在虚拟机上运行这些命令。同样,由于自动化不能进行交互操作,我们只需要在所有yum命令中添加-y。
因此,为了清理并为 Vagrant 做好准备,我们的 Bash 脚本将类似于以下内容:
#!/bin/bash
yum remove jta -y
echo "exclude=jta*" >> /etc/yum.conf
yum-config-manager --disable ol7_addons
yum install oracle-release-el7 -y
yum install oracle-linux-manager-server-release-el7 -y
yum-config-manager --enable ol7_optional_latest -y
yum install spacewalk-schema-2.10.14-1.el7 spacewalk-setup-postgresql spacewalk-postgresql spacecmd spacewalk-utils -y
spacewalk-setup --non-interactive --answer-file=/tmp/answer-file.txt
注意
在编写本食谱的过程中,spacewalk-schema 包做出了更新,导致其不再与 PostgreSQL 兼容。通过将 spacewalk-schema 包固定到spacewalk-schema-2.10.14-1.el7,如前面的代码片段所示,可以解决这个问题。
我删除了每个步骤中的sudo调用,因为在 Vagrant 的配置阶段,一切都以 root 身份运行。
现在,对于Vagrantfile,我们添加几行代码,以便 Vagrant 可以将answer-file.txt文件复制到虚拟机上,然后告诉 Vagrant 执行我们刚刚编写的脚本。我们还将创建一个私有网络,允许通过特定的 IP 进行主机仅访问(这将使我们可以通过网页浏览器轻松访问 Oracle Linux Manager):

图 8.25 – 用于部署 OLM 的 Vagrant 文件
注意
在 Linux/Unix 系统上,VirtualBox 只允许将192.168.56.0/21范围内的 IP 地址分配给主机专用适配器。这允许从192.168.56.1开始的 IP 地址,直到192.168.63.254。
现在,我们可以查看我们的目录应该是什么样子的:
└── oracle-linux-manager
├── answer-file.txt
├── provision.sh
└── Vagrantfile
我们准备好启动了:
$ vagrant up
…
…
…
--> default: Running provisioner: shell…
default: Running: inline script
default: Access Oracle Linux Manager at https://192.168.56.10
你将看到配置脚本安装并配置 Oracle Linux Manager,并且在短短几分钟内,你就能够通过浏览器访问虚拟机所定义的 IP 地址来访问 Oracle Linux Manager。最棒的是,这一切都是以代码形式定义的。我们在本教程中创建的一切总共仅有 6 KB 大小!Vagrant 在解决经典的“它在我的机器上能用”问题方面做得非常出色。你可以将这 6 KB 的代码部署到任何机器上(Mac、Windows、Linux 等)——所需要的只是 Vagrant 和 Oracle VM VirtualBox。
我们可以将这个自动化过程更进一步,使其更加有用。例如,我们可以自动化为 Oracle Linux Manager 创建第一个用户,自动创建频道、仓库和激活密钥,然后为 OLM 创建客户端并自动连接它们。深入讨论这些细节超出了本教程的范围,但如果你有兴趣了解如何实现,我已经将解决方案发布在 GitHub 上——你可以在这里找到:github.com/PacktPublishing/Oracle-Linux-Cookbook/tree/main/ch8/vagrant。
使用 Packer 修改源镜像
Packer 是一个用于自动化创建机器镜像的工具。在本教程中,我们将使用 Packer 引用一个Oracle Linux 8平台镜像作为源,使用配置器安装某些内容,并将这些更改推送到 OCI 中,创建一个新的 OCID 镜像。
注意
尽管 OCI 提供了一个包含“永久免费”资源的免费层,但这不包括存储镜像的能力。如果你希望跟随本教程,你需要使用一个付费账户。
准备工作
本教程需要以下内容:
-
Oracle Linux
-
Packer
如果你需要帮助安装 Packer,请参考本章开头的技术要求部分。
如何操作…
Packer 常常被忽视,因为它看起来非常简单;然而,不要让这种简单性愚弄了你——Packer 非常强大且有用。在本教程中,我们将使用 Packer 引用某个版本的 Oracle Linux 8 作为基础镜像,使用一个配置器安装某些内容,并将这些更改推送到 OCI 中,创建一个新的 OCID 镜像:
- 首先,我们将指定一个提供名为
oracle-oci的构建器的 Packer 插件,该构建器使 Packer 能够为 OCI 创建机器镜像。我们可以在名为oracle-oci.pkr.hcl的文件中完成此操作。在文件开头输入以下内容:

图 8.26 – Packer OCI 构建器插件
-
接下来,我们将使用
oracle-oci构建器指定的配置选项来配置我们的 OCI 认证。有关配置oracle-oci构建器的详细信息,可以查看developer.hashicorp.com/packer/plugins/builders/oracle/oci:- 有许多方法可以做到这一点。一种方法是直接在你的
*.pkr.hcl文件中引用用于认证的变量,像这样:
- 有许多方法可以做到这一点。一种方法是直接在你的

图 8.27 – 在 Packer 中引用变量
- 然后,我们需要在名为
variables.pkr.hcl的文件中声明所有这些变量。在这个文件中,我们声明变量并指定类型,同时提供一个描述来解释变量的目的。将以下内容输入到你的variables.pkr.hcl文件中:

图 8.28 – 在 Packer 中声明变量
- 最后,我们要为变量分配值。我们将它们放在名为
variables.auto.pkrvars.hcl的文件中。它应该看起来像这样:

图 8.29 – 在 Packer 中分配变量
-
另一种方法是配置你的 OCI CLI,在
~/.oci/config文件中。这看起来像这样:[DEFAULT] user=ocid1.user.oc1..<unique_ID> fingerprint=<your_fingerprint> key_file=~/.oci/oci_api_key.pem tenancy=ocid1.tenancy.oc1..<unique_ID> region=us-ashburn-1 [ADMIN_USER] user=ocid1.user.oc1..<unique_ID> fingerprint=<your_fingerprint> key_file=keys/admin_key.pem pass_phrase=<your_passphrase>
注意
关于配置 OCI CLI 的完整详细信息可以在这里找到:docs.oracle.com/en-us/iaas/Content/API/Concepts/sdkconfig.htm
- 一旦你配置了认证,你可以开始定义基础镜像。它应该看起来像下面这样:

图 8.30 – 在 Packer 中定义基础镜像
注意
要获取 Oracle Linux 8 的 OCID,请访问以下网址:docs.oracle.com/en-us/iaas/images/oracle-linux-8x/。这不仅与区域相关,还与架构相关,因此你需要查找适用于 x86 的最新 Oracle Linux 8 镜像(换句话说,寻找镜像名称中没有 aarch64 的版本)。
- 一旦你定义了源,你可以开始指导 Packer 在构建过程中该做什么。在这种情况下,我们将调用一个 provisioner,这样我们就可以运行一个 shell 命令来安装 Git:

图 8.31 – Packer 的 provisioners
- 到此为止,我们已经告诉 Packer 我们要使用什么源,并描述了我们在构建时希望做什么。你的完整文件应该像这样:

图 8.32 – 完整的 Packer 文件用于修改基础镜像
注意
在最终文件中,我将 example 替换为 ol8u8,以便更清楚地描述我正在处理的内容。这只是良好的自我文档化方式。
-
接下来,我们将运行
packer init来下载外部插件:$ packer init . -
最后,让我们继续构建 OCID 镜像:
sudo dnf install -y git to install Git on the instance.

图 8.33 – 运行 packer build 后的初始输出
安装 Git 后,它将对实例进行快照,并将其导出为新的 OCID 镜像,为所有未来的实例提供一个新的起点。

图 8.34 – Packer 完成构建过程后的输出
当 Packer 完成时,您可以通过在 OCI 控制台中导航到 计算 | 自定义镜像 来查看新发布的镜像。以下是该界面的示例:

图 8.35 – 查看最近发布的自定义镜像
本食谱的源代码可以在 github.com/PacktPublishing/Oracle-Linux-Cookbook/tree/main/ch8/packer-cloud 找到。
打包它,收起它,让我开始,嗯,呃……构建
在本食谱中,我们将使用 Packer 从源媒体(如 ISO 文件)开始,从头创建我们的 Vagrant box。
开始
本食谱需要以下内容:
-
Oracle Linux
-
Oracle VM VirtualBox
-
Packer
如果需要帮助安装 Oracle VM VirtualBox 和 Packer,请参阅本章开头的 技术要求 部分。
如何操作……
更常见的是,您可以在 Vagrant 目录中搜索并找到包含所需操作系统的预制 Vagrantfiles。但是如果您需要的内容没有呢?或者也许您不信任 Vagrantfile 的作者和/或您更倾向于自己创建一个。您可以手动完成此操作,或者可以完全通过代码来实现,使用 Packer。在本食谱中,我们将使用 Packer 从 Oracle Linux 8.8 源 ISO 创建一个全新的 Vagrant box。从高层次来看,Packer 将下载我们希望使用的操作系统的 ISO 镜像,然后使用 Oracle VM VirtualBox 启动一个虚拟机并安装它。之后,它会将虚拟机导出为 开放虚拟化格式(OVF)。最后,它将压缩此文件并将其转换为 Vagrant box 文件。
Oracle Linux 8 kickstart 文件
-
为了让这项操作生效,您需要提供一个 kickstart 文件来自动化 ISO 的安装。您可以自己创建一个,或者使用 Oracle Linux Image Tools 中的一个文件,该文件可以在 GitHub 上的官方 Oracle Linux 仓库中找到。在本食谱中,我将使用来自 Oracle Linux Image Tools 的一个文件:
https://github.com/oracle/oracle-linux/blob/main/oracle-linux-image-tools/distr/ol8-slim/ol8-ks.cfg
-
现在,为了开始使用这个配置,我们将创建一个名为
ol8-vagrant的新目录。在该目录下,创建一个 Packer 文件,并命名为vagrant-ol8.pkr.hcl,然后创建一个名为http的文件夹,并将 kickstart 文件放在其中。完成后,您的文件结构应如下所示:└── vagrant-ol8 ├── http │ └── ol8-ks.cfg └── vagrant-ol8.pkr.hcl -
在我们的 kickstart 文件中,我们只需要设置 root 用户的密码。因此,在这种情况下,我们将
rootpw --lock这一行修改为rootpw --``plaintext vagrant。 -
接下来,我们将继续处理
vagrant-ol8.pkr.hcl文件。首先,我们需要指定我们需要的插件。由于我们想从 ISO 镜像创建虚拟机,所以使用 VirtualBox Builder,另外由于我们要将 OVF 文件转换为 Vagrant box 文件,因此使用 Vagrant Builder。可以通过在 Packer 配置文件中添加以下代码来完成这些设置:

图 8.36 – Packer VirtualBox 和 Vagrant 构建插件
信息:
有关 Packer VirtualBox 插件的更多信息,请访问:www.packer.io/plugins/builders/virtualbox。
- 现在我们需要定义一个源。在这种情况下,我们希望使用 Oracle Linux 8.8 的 ISO。请将以下内容添加到
vagrant-ol8.pkr.hcl文件中:

图 8.37 – 用于构建 Vagrant box 的 Packer 文件
重要提示
注意 modifyvm 命令,它将 --nat-localhostreachable1 设置为 on。这是一个新的设置,在 Oracle VM VirtualBox 7 中默认是 off。将此值设置为 on 可以解决一个网络问题,防止 Packer 将 kickstart 文件发送到虚拟机。换句话说,如果你正在使用 VirtualBox 7 来构建虚拟机,务必包含此设置,但如果你使用的是 VirtualBox 6,则需要移除此行,否则构建将失败。
- 在前面的代码中,我们将
guest_os_type指定为"Oracle_64",因为我们是从 Oracle Linux ISO 构建虚拟机的。接下来,我们输入 ISO 的 URL 以及校验和。对于ssh_username,我们使用"root",对于ssh_password,我们使用"vagrant",因为这些是 Vagrant 默认的设置,旨在简化操作,特别是如果你计划公开发布你的 box。如果你打算将 box 保留为私人使用,最好使用不同的值,这样可以提高安全性。
信息
有关 Vagrant 用户名和密码的更多信息,请访问:www.vagrantup.com/docs/boxes/base#vagrant-user。
-
我们将
headless设置为"true",以防止虚拟机启动 VirtualBox GUI。我们将ssh_wait_timeout的时间增加,以给操作系统足够的时间进行安装并启动。一切都不言自明,直到我们遇到http_directory设置。 -
你需要知道的就是,我们将利用
http_directory选项作为一种便捷的方式,通过 HTTP 服务器提供一个目录。这样做是为了让引导命令能够指向一个 kickstart 文件——我们已经将它放置在http目录中。http://{{ .HTTPIP }}:{{ .HTTPPort }}/ol8-ks.cfg会告诉操作系统如何找到这个 kickstart 文件。你不需要担心{{ .HTTPIP }}和{{ .HTTPPort }}的语法,这些只是由 Packer 模板引擎处理的模板变量。 -
对于
nic_type,默认值是82540EM,它等同于 Intel PRO/1000 MT 桌面版。这是一个安全的选择,非常适合运行旧操作系统,但 Oracle Linux 8 是一个现代操作系统,所以我们将其设置为virtio。VirtIO 是一个准虚拟化驱动程序,它能为虚拟机提供更好的网络性能。 -
现在,我们来看看
boot_command。基本上,我们需要弄清楚,在启动时,操作系统接收引导命令所需的按键序列。对于 Oracle Linux 8,我们发送up和Tab键,然后发送指令以告知从哪里找到 kickstart 文件,最后我们告诉它按Enter键开始安装操作系统。 -
对于
vboxmanage,我发现默认情况下,Packer 尝试以仅 512MB 内存启动我的虚拟机,这导致在操作系统安装时发生错误。为了解决这个问题,我将内存增加到2048。为了安全起见,我还为虚拟机分配了两个 CPU。 -
最后,使用
shutdown_command,我们只需告诉 Packer 如何在所有配置完成后优雅地关闭系统。如果我们留空此项,Packer 会强制关闭机器。
信息
要查看可用配置选项的完整概述,请参阅www.packer.io/plugins/builders/virtualbox/iso。
-
到目前为止,我们已经完成了自动安装操作系统所需的步骤,但还需要做一些事情来准备虚拟机以适应 Vagrant。具体来说,我们需要添加一个名为
vagrant的用户,为该用户填充已知的公共密钥,最后我们还需要安装 VirtualBox Guest Additions。对于这些任务,我们将使用一个提供程序来执行一个 shell 脚本。这个任务发生在操作系统安装完成后,并且虚拟机仍在运行时。这是我们在关闭系统并将其转换为 Vagrant box 之前需要做的最后一件事。
接下来,请将以下内容添加到
vagrant-ol8.pkr.hcl文件中:

图 8.38 – 用于构建 Vagrant 盒子的 Packer 文件(续)
信息
有关后处理程序的更多信息,请参阅:www.packer.io/plugins/post-processors/vagrant/vagrant#virtualbox。
-
从上面的截图可以看到,我们将创建一个名为
scripts的新文件夹,并将 shell 脚本放入其中:└── ol8-vagrant ├── http │ └── ol8-ks.ks ├── scripts │ └── vagrant-base-box.sh └── vagrant-ol8.pkr.hcl -
现在,在
vagrant-base-box.sh脚本中,我们将添加以下内容:

图 8.39 – vagrant-base-box.sh 脚本的内容
-
接下来,我们将运行
packer init来下载外部插件:$ packer init . -
现在我们准备好构建 Vagrant box 了。这部分很简单,只需运行以下命令:
$ packer build .输入命令后,你将看到如下内容:

图 8.40 – “packer build” 命令的输出
这将需要一些时间,因为实际上这里有很多操作。记住我们之前讨论过的高层次内容:Packer 将下载 ISO 文件,创建虚拟机,安装操作系统,之后它将运行你刚才定义的所有脚本,但一旦这些完成,你将得到一个整洁的 .box 文件(这正是我们需要用于 Vagrant 的)。
如果你切换到 VirtualBox,你将最终看到一个由 Packer 创建的新虚拟机。你可以不管它,让 Packer 自行操作,但了解这个细节能让你知道背后的过程发生了什么。

图 8.41 – 使用 Packer 构建并配置虚拟机的截图
构建完成后,你应该会看到类似以下内容的输出:

图 8.42 – 完成构建的 Vagrant box 截图
注意
Oracle Linux ISO 文件有几个 GB,因此这可能需要一些时间。现在或许是休息一下,喝杯咖啡的好时机。😉
-
现在是时候准备我们的 Vagrant box 以便与 Vagrant 一起使用了。我们将运行
vagrant init来构建 Vagrantfile:$ vagrant init ol8-x64-virtualbox.box输出如下所示:

图 8.43 – 初始化 Vagrant box
有用的提示
你可以运行 vagrant init 和 vagrant init .,但最好指定 box 的文件名。这样,Vagrant 会自动在 Vagrantfile 中指定正确的 box 值。正因如此,在这个食谱中,我们运行的是 vagrant init ol8-x64-virtualbox.box。
-
最后,是时候通过运行
vagrant up来测试我们的新 Vagrant box 了:$ vagrant up这个命令的输出如下所示:

图 8.44 – “vagrant up” 命令的输出
就这样。几分钟后,你的虚拟机将启动并运行,你可以使用 Vagrant 提供的便捷命令与之交互。
本食谱的源代码可以在github.com/PacktPublishing/Oracle-Linux-Cookbook/tree/main/ch8/packer-vagrant找到。
重要提示
如果你还在开发你的 Vagrant 盒子,并且需要在每次构建后进行测试,你会希望确保你正在测试最新构建的盒子。我曾经遇到过一个问题,认为我的更改没有保存,直到我意识到 Vagrant 正在使用之前构建的缓存盒子。你可以使用vagrant box remove ol8-x64-virtualbox.box命令来删除旧盒子。
第九章:保持数据安全 – 保护系统
没有人希望成为头条新闻,尤其是在他们的数据被盗时。保护数据的最佳方式之一是确保操作系统及其服务的安全。安全通常被比作洋葱,因为它有多层防护,很难被剥开,每一层都能提供对恶意行为者的防御。当恶意行为者攻击你的数据时,目的并不仅仅是窃取数据;他们往往也会修改数据。更糟的是,当你迁移到云端时,你不仅要保护系统免受内部威胁(如不良承包商或员工)和外部威胁(如黑客攻击),还要保护你的数据免受云服务提供商的威胁。在安全领域,你永远不知道谁是恶意行为者!
这不仅仅是保护你的系统免受恶意行为者的攻击;许多行业也要求有强大的安全措施。尤其在医疗行业,通常需要实施安全控制,以符合健康保险流通与责任法案(HIPAA)的要求。处理信用卡的企业必须遵守支付卡行业数据安全标准(PCI-DSS)的原则,许多政府机构也必须实施安全标准,以符合联邦风险与授权管理计划(FedRAMP)的要求,确保其云端工作负载的合规性。
注意
安全团队有自己的术语!“恶意行为者”指的是黑客——那些试图修改或窃取数据的人。他们通过攻击系统的攻击面、基本的系统组件和可以被恶意行为者接触到的服务来实现这一目的。
当你保护系统时,必须涵盖不止一个攻击面。这些攻击面可能是静态数据、动态数据、像 HTTP 这样的服务,甚至是 Linux 内核。你还需要使用可以帮助识别系统配置的工具,以最佳方式保护数据。在本章中,目标是为你提供几个方法,帮助你识别风险并保护你的数据。
本章将涵盖以下主要方法:
-
使用 GPG 签名 Git 提交
-
加密所有 Web 流量
-
加密所有静态数据
-
验证是否遵守合规政策
-
端口保护和限制网络访问
-
保持 SELinux 活跃
技术要求
对于这个方法,你需要一台 Oracle Linux 8 系统。和大多数方法一样,推荐使用桌面虚拟化产品(如 Oracle VirtualBox)在桌面上运行虚拟机。一个拥有 2 个核心、2GB 内存和几个可用 GB 磁盘空间的小型虚拟机就足够了。理想情况下,在开始之前,你应该将系统更新到最新的可用包。这只需几分钟,并且在排除由于错误导致的问题时能节省大量时间。
本书中的许多食谱相关的配置文件可以在 GitHub 上的github.com/PacktPublishing/Oracle-Linux-Cookbook找到。
使用 GPG 签署 Git 提交
本食谱将展示如何使用GNU 隐私保护(GPG)密钥对来为 Git 提交和 RPM 包进行数字签名。一个 GPG 密钥对由两部分组成:公钥和私钥。
这是通过创建一个 GPG 密钥对并使用它来签署 Git 提交和 RPM 包完成的。
准备工作
为了使用 GPG 和 Git,首先需要安装一些软件包。通常,当安装gnupg2包时,GPG 会默认安装。
Git 应使用dnf install git -y命令安装。
如何操作...
第一步是创建一个 GPG 密钥,如果你还没有的话。这个密钥将用于签署你的 Git 提交和 RPM 包。你可以使用gpg或gpg2命令来操作 GPG 密钥;这两个命令是相同的,因为gpg链接到gpg2。
GPG 密钥是通过命令行创建的:
[erik@ol8 ~]$ gpg2 --gen-key
该命令会要求输入一些信息,主要是你的真实姓名和电子邮件地址。输入信息并继续后,它会要求你设置一个密码短语以保护密钥。不要忘记密码短语!如果忘记了,密钥将无法使用,所有用该密钥加密的数据将丢失。你可以选择不使用密码短语,但如果这样做,你会多次被要求验证。密钥创建的输出应该类似于以下截图:

图 9.1 – 创建的 GPG 密钥
可选地,你可以使用--full-generate-key选项,它可用于创建存储在硬件设备上的密钥等用途。
一旦密钥被创建,它会被放入你的密钥环中,也就是位于你的主目录中的.gnupg目录下的pubring.kbx文件。要查看文件中的所有密钥,运行命令gpg2 --list-keys --keyid-format=long。
gpg --list-secret-keys命令用于列出存储在 GPG 密钥环中的私密密钥(即私钥)。运行该命令会显示类似于以下图示的 GPG 密钥输出:

图 9.2 – GPG 密钥
输出会显示每个密钥的多个信息列:
-
sec:这一列表示该密钥是一个私密密钥。 -
rsa2048/4096/...:这一列显示密钥所使用的算法和密钥长度。例如,rsa2048表示密钥使用 RSA 算法,密钥长度为 2048 位。如果使用长格式,它还会在密钥长度后显示密钥指纹。 -
[创建日期]:这一列显示密钥创建的日期。 -
[过期日期]:如果密钥设置了过期日期,这一列会显示该日期。如果没有设置,则该列为空。 -
[用户 ID]:这一列显示与密钥相关的用户 ID,通常是密钥拥有者的名字和电子邮件地址。 -
[ssb]:此列表示该密钥有一个对应的子密钥(即用于加密、签名或认证的独立密钥)。 -
[expires]:如果子密钥设置了过期日期,它将在此列显示。如果没有设置,则此列将为空。
密钥指纹是密钥的简化数字表示。它允许其他人验证您的公钥在传输过程中没有被篡改。GPG 命令的长密钥 ID 格式是一个 16 个字符的十六进制字符串,用于唯一标识 GPG 中的公钥或私钥。在与 GPG 一起工作时,它通常用于引用特定的密钥。
长密钥 ID 是从密钥的完整 40 字符指纹派生的。指纹是密钥公钥材料的加密哈希值,用于验证密钥的真实性。长密钥 ID 是指纹的最后 16 个字符。
现在你已经有了密钥,我们需要将其导入到 Git 中。在以下示例中,我们将使用密钥E921BF9E922221B6。要导入密钥,我们将使用以下命令:
git config --global user.signingkey E921BF9E922221B6
然后,我们可以使用以下命令设置 Git 默认签署所有提交:
git config --global commit.gpgsign true
它是如何工作的……
Git 可以使用 GPG 密钥签署提交和标签。但要小心使用 Git,因为它并不一致。git tag 使用 -s 来签署标签,而 git commit 使用 -s 添加 -S,实际上是使用 GPG 签署提交。
要设置一个新的标签,我们将使用 Git 标签命令 -s $TAG -m $TAG_DESCRIPTION:
$ git tag -s v1.0 -m 'Version 1.0 tag'
You need a passphrase to unlock the secret key for
user: "Erik Benner <erik@talesfromthedatacenter.com>"
2048-bit RSA key, ID 922221B6, created 2024-04-01
注意
您还可以全局或针对每个仓库设置tag.gpgsign,以确保所有标签自动签署。
接下来,我们可以使用 git show v1.0 显示标签:
$ git show v1.0
tag v1.0
Tagger: Erik Benner <erik@talesformthedatacenter.com >
Date: Sun April 2 215:24:41 2023 -2300
Version 1.0 tag
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
JHGSksdhj847yskKJHSnd874tlKJAHGS32674GJHSAD784ghsjkd7*&^ADDXGFdgj3kjj hde018GDKjskhdh8737ybdhajkjkjhsadfs7892987812mmxnbcbsd8JASJ74845jfhHA SHDepkjahZXkjs83828732ZMKDjh92yaskjagZKDSJHGHHD&=7213kj4ha,,jhsad10al qpdif9839928hdkask
=EFTF
-----END PGP SIGNATURE-----
commit 7fhs49185hflvmsgd742825hhabzb182ufnc8
Author: Erik Benner <erik@talesformthedatcenter.com>
Date: Sun Apr 2 12:52:11 2023 -2300
Change version number
之后,当我们使用 Git 检查代码时,添加-S选项到命令中,以自动使用标签签署提交:
git comit -a -S -m "comment goes here"
注意
如果全局或在当前 Git 仓库中设置了commit.gpgsign=true,则无需此操作。
加密所有的网络流量
加密与您的 Web 服务器之间的通信非常重要。即使是一个没有登录功能的简单博客或公司网站,进行加密也有很多优势:
-
维护用户信任:使用 HTTPS 加密您的网页有助于建立您网站与用户之间的信任。当用户看到浏览器中的锁形图标,表示连接是安全的时,他们可以更加放心地认为他们的数据是安全传输的。浏览器会显示未加密的网站。Chrome 和 Edge 浏览器会在 URL 旁边显示 不安全,或者像 Mozilla 浏览器一样显示红色斜线的锁图标。
-
SEO 好处:谷歌曾表示 HTTPS 是其搜索算法中的一个排名因素。这意味着使用 HTTPS 的网站可能在搜索结果中排名高于不使用 HTTPS 的网站。
-
浏览器警告:现代 Web 浏览器(如 Chrome 和 Firefox)现在会在用户访问收集敏感信息的非 HTTPS 网站时显示警告信息。这可能会阻止用户使用您的网站,从而对您的业务产生负面影响。
-
合规性:如果你的网站需要遵守某些法规或标准,如 PCI DSS 或 HIPAA,则可能需要通过 HTTPS 加密网页,以遵守这些法规。
注意
虽然 SSL 是一个常用的术语,但现代系统实际上使用传输层安全性(TLS)作为加密技术。SSL 作为一种较旧的技术存在一些安全漏洞,这也是 TLS 作为 SSL 的升级版被开发出来的原因。TLS 解决了 SSL 存在的漏洞,使其成为一个更安全的选择。
总体而言,使用 HTTPS 加密网页对于保护敏感数据、维护用户信任、遵守法规和标准非常重要。它对 SEO 也越来越重要,可以避免浏览器警告,这些警告可能会对你的网站声誉产生负面影响。而且通过像 Let’s Encrypt(letsencrypt.org/)和 ZeroSSL(zerossl.com/)这样的服务来实现这一点既简单又免费。
Let’s Encrypt 和 ZeroSSL 都提供免费的安全证书,包括用于加密 HTTP 流量的 SSL/TLS 证书。SSL/TLS 证书用于加密 Web 流量,允许 Web 服务器和 Web 浏览器之间进行加密通信。Let’s Encrypt 的创建旨在让网站所有者更容易获得 SSL/TLS 证书并在他们的网站上启用 HTTPS。在 Let’s Encrypt 出现之前,获取 SSL/TLS 证书通常是一个复杂且昂贵的过程,需要手动验证并支付证书颁发机构的费用。Let’s Encrypt 通过自动化验证过程并提供免费的证书,简化了这一过程。
Let’s Encrypt 证书被所有主流浏览器和操作系统信任。它们的有效期为 90 天,并可以通过自动客户端软件自动续期。Let’s Encrypt 还提供了一个自动证书管理环境(ACME)协议,允许 Web 服务器自动化获取、续期和吊销证书的过程。
准备工作
对于本示例,你需要一台运行 Oracle Linux 的 Web 服务器。该服务器需要能够通过互联网访问,以便 Let’s Encrypt 系统能够验证 URL。在这个示例中,我将使用 Oracle Cloud 上的虚拟机,并使用他们的免费服务层。这台虚拟机运行在一颗基于 Arm 架构的 CPU 上,拥有 2 个核心和 12GB 内存。80和443端口都已开放给这台服务器。无论处理器类型或云平台如何,这个过程都相同。系统运行的是带有最新补丁的 Oracle Linux 8。
如何操作…
为了实现这一目标,我们需要做一些事情:
-
安装带有
mod_ssl的 Apache 及其所有依赖项。 -
从 Git 获取
acme.sh。 -
使用 webroot 模式创建证书。Webroot 模式要求站点可以通过
80和443端口从互联网访问。虽然这种方法易于实现,但还有另一种使用 DNS 的验证方法。有关不同挑战类型的更多信息,请参阅letsencrypt.org/docs/challenge-types/。 -
进行测试。
安装 Apache 并配置 mod_ssl 及其所有依赖项
-
所以我们作为 root 用户开始吧。首先,我们需要安装一些软件包:
-
httpd– Apache Web 服务器 -
mod_ssl– 在 Apache 上启用 SSL
您可以使用以下命令来执行此操作:
80 and 443 to the firewall. This is done as the root with the following commands:firewall-cmd --zone=public --permanent --add-service=http
firewall-cmd --zone=public --permanent --add-service=https
ssltest.talesfromthedatacenter.com。这样,我们可以为这个虚拟服务器单独添加 SSL 证书。作为 root 用户,让我们为文件创建一个目录,并将其所有权更改为 apache 用户:
mkdir -p /var/www/ssltest ssltest.conf in /etc/httpd/conf.d:<VirtualHost *:80>
将此内容放入 /etc/httpd/conf.d/ssltest.conf
Alias /.well-known/acme-challenge/ /var/www/ssltest/.well-known/acme-challenge/
<Directory "/var/www/ssltest/.well-known/acme-challenge/">
Options None
AllowOverride None
ForceType text/plain
RedirectMatch 404 "^(?!/.well-known/acme-challenge/[\w-]{43}$)"
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge [NC]
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
-
-
保存文件后,运行
apachctl configtest。每次修改配置文件时,最好始终运行此测试。apachectl configtest enable option will restart the web server when the system starts. The --now option will start the server now:80。您应该看到默认的 Apache 页面。注意,左上角显示“未加密”标志!站点未使用 SSL:

图 9.3 – 没有 SSL 的 Apache 测试页面
从 Git 获取 acme.sh
现在,我们需要从 Git 获取 acme.sh 脚本:
-
首先,我们需要使用以下命令安装 Git:
acme:mkdir acme
-
现在,我们可以使用以下命令从官方 Git 网站克隆(
github.com/acmesh-official/acme.sh):git clone https://github.com/acmesh-official/acme.sh.git
然后运行安装程序,根据需要更新您的目录和电子邮件地址。
/root/acme/acme.sh --install -m my@email.com
使用 webroot 模式创建证书
-
接下来,让我们注册一个账户,传递一个电子邮件地址作为变量:
/root/acme/acme.sh/acme.sh --register-account -m erik@talesfromthedatacenter.com [Sun Apr 2 22:02:01 GMT 2023] No EAB credentials found for ZeroSSL, let's get one [Sun Apr 2 22:02:02 GMT 2023] Registering account: https://acme.zerossl.com/v2/DV90 [Sun Apr 2 22:02:03 GMT 2023] Registered ACCOUNT_THUMBPRINT for future use. This is also saved in ./ca/acme.zerossl.com/v2/DV90/ca.conf. -
现在,我们可以运行脚本,传递 URL 和站点的
apache主目录:./acme.sh --issue -d ssltest.talesfromthedatacenter.com --log以下图显示了脚本安装新证书时运行的命令。

图 9.4 – 待安装证书
脚本将重启 Apache。
测试
- 现在,您可以通过 HTTPS 访问该站点。您会在地址栏的左侧看到一个锁形图标,表示站点已加密安全。下图显示了这一点:

图 9.5 – 安装的 SSL 密钥
它的工作原理…
这个过程的工作原理是,acme.sh 脚本生成一个临时密钥文件,并将其放置在 .well-know/acme-challenge 目录中。系统然后从互联网查询服务器以获取该文件。如果能获取到该文件,则测试通过,新的密钥会被发放。需要注意的是,要监控这一过程,因为第三方安全软件或 SELinux 可能会影响你获取临时密钥文件的能力。
现在证书已经设置完毕,还有一项任务需要做,以使其定期更新。你可以通过添加以下 cron 任务,轻松地让系统每天检查一次新证书。需要注意的是,你需要根据实际安装位置调整脚本路径。在本例中,脚本安装在 /home/acme/.acme.sh:
0 0 * * * /home/acme/.acme.sh/acme.sh --cron --home /home/acme/.acme.sh > /dev/null
注意
当使用自动更新的密钥时,强烈建议定期监控你的网站是否出现 SSL 错误。理想情况下,你应该每小时检查一次 SSL 错误,以防万一出现问题。查看 Web 服务器的 SSL 日志,并使用如 wget 或 curl 等工具进行检查,确保网站正常运行。如果 SSL 密钥无效,wget 和 curl 会因为错误而失败。
加密所有静态数据
加密传输中的数据很重要,但你也需要加密静态数据。这一点在云环境中尤为重要,因为你与许多其他用户共享存储空间。尽管云服务提供商可能提供自动加密功能,但需要记住的是,如果他们可以自动解密数据,那么他们也可以访问密钥。为了真正保护数据,你需要使用云服务无法访问的密钥进行加密。这可以通过Linux 统一密钥设置(LUKS)轻松实现。大型组织还可以使用Clevis,它能够从由 Tang 服务器管理的密钥中自动解密数据。Tang 服务器用于存储和管理加密密钥。在云环境中,这使你能够管理启动加密,而无需让云服务提供商访问你的密钥。这个过程被称为网络绑定磁盘加密(NBDE)。
NBDE 是 Oracle Linux 中的一项安全功能,在启动过程中提供磁盘加密密钥。NBDE 是常规磁盘加密的扩展,它使用网络服务器来存储并提供加密密钥,而不是本地机器。结合 NUKS,这使得可以使用本地密钥(需要手动输入密码短语)和来自 Tang 服务器的自动密钥解密启动驱动器。这提供了简化的安全自动启动,但在紧急情况下,你仍然可以在没有 Tang 服务器的情况下启动。
准备工作
与其他教程不同,本教程需要至少两台虚拟机:一台作为 Tang 服务器,另一台作为客户端。两台系统应更新到最新的软件版本。
如何操作……
在本教程中,我们将执行以下操作:
-
创建名为
tang的服务器:- 安装并配置 Tang 服务器
-
构建另一个名为
clevis的服务器:-
安装并配置 Clevis
-
配置 LUKS 与 Clevis 一起加密数据卷
-
配置 Tang 服务器
Tang 服务器由 Oracle Linux 使用,在启动过程中提供加密密钥。以下是它的基本工作原理:
-
在启动过程中,远程系统会联系 Tang 服务器并请求加密密钥。
-
Tang 服务器生成一个随机加密密钥并将其发送回远程系统。
-
远程系统使用加密密钥解锁其加密磁盘,从而能够启动。
-
Tang 服务器丢弃加密密钥,以使其无法再次使用。
使用 Tang 服务器的一个关键好处是,即使主加密密钥被泄露,它仍然可以为远程系统提供加密密钥。这可以通过限制主加密密钥泄露后的损害来提高系统的安全性。
-
要安装 Tang 服务器,我们只需要使用
dnf安装软件,打开防火墙端口,并设置服务器运行。这些操作都以 root 用户身份完成。通过
dnf安装非常简单;只需运行以下命令:192.168.56.0/24 is my boot subnet. Don’t forget to update the subnet to your subnet when running the following firewall commands:firewall-cmd --zone=trusted --add-source=192.168.56.0/24
firewall-cmd --zone=trusted --add-service=http
firewall-cmd --runtime-to-permanent
-
使用以下命令配置服务在启动时自动启动,并立即启动:
systemctl enable --now tangd.socket您可以使用以下命令验证服务是否正在运行:
systeemctl status tangd command; # systemctl status tangd.socket ● tangd.socket - Tang Server socket Loaded: loaded (/usr/lib/systemd/system/tangd.socket; enabled; vendor preset: disabled) Active: active (listening) since Mon 2023-07-17 13:52:58 EDT; 2min 46s ago Listen: [::]:80 (Stream) Accepted: 0; Connected: 0; Tasks: 0 (limit: 48611) Memory: 0B CGroup: /system.slice/tangd.socket /var/db/tang. You can also run the command tang-show-keys. This will show all of the thumbprints of the keys in the system:[root@tang ~]# tang-show-keys
RxdbjAY7_N19UEYBO6XIUVosv0s
[root@tang ~]#
接下来,让我们使用 LUKS 设置客户端系统,以加密数据磁盘。
设置 LUKS
-
首先,使用以下
dnf命令安装所需的包:/dev/sdb, which is a small 20 GB device. You can see by checking all the block devices with the lsblk command:[root@clevis ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 100G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 72.9G 0 part
├─ol-root 252:0 0 50G 0 lvm /
├─ol-swap 252:1 0 7.9G 0 lvm [SWAP]
├─ol-var 252:2 0 5G 0 lvm /var
├─ol-home 252:3 0 5G 0 lvm /home
└─ol-var_log 252:4 0 5G 0 lvm /var/log
sdb 8:16 0 20G 0 disk
使用以下命令操作 /dev/sdb:
cryptsetup luksFormat --type luks2 --cipher aes-xts-plain64 \ --key-size 512 --hash sha256 --use-random --force-password /dev/sdb警告:执行此操作将删除设备上的所有数据,包括任何分区:

图 9.6 – 加密磁盘
执行命令时,系统还会提示输入密码短语。请不要丢失此密码,否则您将无法手动解密磁盘。
-
接下来,使用之前保存的密码短语手动解锁磁盘,命令如下:
/dev/mapper:[root@clevis ~]# ls /dev/mapper/datadisk1
/dev/mapper/datadisk1 就像任何正常的磁盘一样。在本例中,我们将在 /dev/mapper/datadisk1 上创建一个 xfs 文件系统:
/data:blkid 命令。UUID 将用于标识磁盘,以便稍后解密:
[root@clevis ~]# blkid -s UUID /dev/mapper/datadisk1 fstab entry with the following command:echo "UUID=58c9f051-f243-4c42-af4f-62d2e3e3b90f /data xfs defaults 0 0" | sudo tee -a /etc/fstab
-
现在我们可以使用以下命令挂载磁盘:
mount /data -
接下来,我们需要使用 Clevis 通过以下命令将 Tang 密钥绑定到设备。我们将通过以下命令行传递设备和 Tang 服务器的信息。您需要使用现有的 LUKS 密码将密钥添加到 Tang:
[root@clevis ~]# clevis luks bind -d /dev/sdb tang '{"url":"http://tang.m57.local"}' Warning: Value 512 is outside of the allowed entropy range, adjusting it. The advertisement contains the following signing keys: RxdbjAY7_N19UEYBO6XIUVosv0s Do you wish to trust these keys? [ynYN] Y 1: is populated with a key:

图 9.7 – 使用第二个插槽的 LUKS
-
接下来,我们需要配置磁盘,以便在启动时自动解密该驱动器。我们首先需要获取加密驱动器的新 UUID:
[root@clevis ~]# blkid -s UUID /dev/sdb /dev/sdb: UUID="218ec8bc-2508-4e34-a569-1e8d3783874e" -
接下来,启用 Clevis 服务:
/etc/crypttab file. The crypttab file contains a list of all encrypted drives:/etc/fstab 文件用于文件系统,将默认设置更改为 _netdev。这将允许设备在其他非加密文件系统后进行挂载。
-
/etc/fstab应该类似于以下截图,其中加密驱动器的 UUID 作为_netdev挂载:

图 9.8 – fstab
工作原理…
Clevis 和 Tang 都是软件工具,用于在 Linux 系统的启动过程中自动解锁和解密磁盘。
这里简要概述了它们的工作原理:
-
在启动过程中,系统会提示用户输入密码短语以解锁和解密磁盘。
-
使用 Clevis 和 Tang 后,系统提示会被一个自动化过程所取代,通过基于网络的密钥服务器解锁并解密磁盘。
-
Clevis 和 Tang 协同工作,创建一个加密磁盘与密钥服务器之间的绑定。这个绑定基于一个策略,该策略指定了解锁磁盘的条件。
-
当系统启动时,它会联系密钥服务器,并请求加密磁盘的解密密钥。密钥服务器检查策略,以确定是否满足解锁磁盘的条件。
-
如果符合政策条件,密钥服务器会向系统发送解密密钥,系统随后使用该密钥解锁并解密磁盘。
-
如果不符合政策条件,密钥服务器会拒绝解密密钥请求,磁盘将保持加锁状态。
还有更多…
可选地,您还可以修改系统,以允许管理员在系统启动时手动输入初始密码。为此,请安装 clevis-dracut:
dnf install -y clevis-dracut
然后,重新构建启动文件:
dracut -fv
当系统启动时,您将有机会手动输入密码:

图 9.9 – 手动输入密码短语
现在,您已经有了一个加密的文件系统,并且具备自动解密的方法,同时还提供了应急情况下使用的手动解密方法。
验证是否遵守合规性政策
系统安全不仅仅是加密静态数据或传输中的数据。许多配置文件和其他常见的安全设置也应当检查。这可以通过使用安全内容自动化协议(SCAP)文件自动完成。SCAP 是一个标准化框架,用于自动化维护计算机系统安全的过程。它是一套规范,提供了一种标准化的安全自动化方法,使组织能够在其 IT 基础设施中实施一致且可重复的安全实践。
SCAP 定义了一种用于传递与安全相关的信息的通用语言,使得来自不同厂商的安全工具和产品可以无缝协同工作。它包括一套标准和指南,用于创建和共享安全内容,如漏洞数据、安全检查表和配置基线。SCAP 的一些关键组件包括常见漏洞和暴露(CVE)数据库,用于识别和追踪已知的安全漏洞,以及常见配置枚举(CCE)数据库,提供一种标准化方法来识别与安全相关的配置设置。
最简单的方法是使用一个名为 OpenSCAP 的工具,它附带 Oracle Linux。
准备就绪
与其他测试一样,我们需要一个 Oracle Linux 系统来进行操作。只需要该系统能够访问dnf仓库以安装附加软件包。
如何操作…
第一步是安装 OpenSCAP,通常通过安装整个工具套件来完成:
-
scap-workbench:图形界面 -
openscap-scanner:扫描系统 -
openscap:OpenSCAP 核心 -
openscap-utils:几个用于扫描系统和容器的命令行工具 -
scap-security-guide:常用 SCAP 文件
通过以下命令使用dnf来完成此操作:
dnf install -y scap-workbench
一旦安装了 OpenSCAP,你可以通过两种方式运行该工具:通过图形界面(GUI)或使用命令行。要启动图形界面,运行scap-workbench。这将启动一个易于使用的 GUI,允许你运行扫描。
注意
如果你安装了scap-workbench且没有安装 X11,dnf将会安装它。如果你的服务器上不使用 X11,可以考虑在 WSL Oracle Linux 系统或安装了 X11 的系统上安装scap-workbench。你也可以在 Windows 桌面上安装 SCAP Workbench。Windows 版本的下载可以在 Open SCAP 网站找到,www.open-scap.org/。
它是如何工作的……
虽然许多用户使用图形界面(GUI),但你也可以使用命令行。
当图形界面启动时,你需要选择你希望扫描的系统类型。在这里,使用的是 OL8:

图 9.10 – 工作台启动
接下来,选择你希望用于扫描的配置文件。配置文件是你要进行对比的标准。你必须选择其中一个配置文件才能继续:

图 9.11 – SCAP 配置文件
所包含的配置文件类别如下:
-
ANSSI-BP:ANSSI-BP 是由法国国家信息系统安全局(ANSSI)制定的一套安全建议,旨在为信息系统的安全提供指导。ANSSI-BP 建议涵盖了广泛的主题,包括网络安全、安全软件开发、访问控制、加密技术、事件响应和安全监控。
-
CJIS:犯罪司法信息服务(CJIS)是美国联邦调查局(FBI)的一个部门。CJIS 部门负责向执法机构提供对刑事司法信息系统的访问,包括犯罪记录、指纹和其他相关信息的数据库。CJIS 部门成立于 1992 年,向美国超过 18,000 个执法机构提供服务。其使命是为执法官员提供准确及时的信息,帮助他们解决和预防犯罪,同时确保信息的隐私和安全。
-
NIST-800:NIST-800 是由美国国家标准与技术研究院(NIST)制定的一系列信息安全指南和标准。NIST-800 系列包括一套出版物,提供有关信息安全的各个方面的指导,如风险管理、安全控制和事件响应。NIST-800 系列被政府机构、私营部门组织和其他实体广泛使用,以提高其信息系统的安全性。该系列的出版物会定期更新,以反映威胁环境的变化和安全技术的进步。
-
ACSC:澳大利亚网络安全中心(ACSC)是一个政府机构,负责提升澳大利亚政府、企业和社区的网络安全能力和韧性。ACSC 成立于 2014 年,是澳大利亚信号局(ASD)的一部分。
-
HIPAA:健康保险可携带性和责任法案(HIPAA)是美国的一部联邦法律,旨在保护医疗健康信息。该法律建立了保护个人健康相关信息的隐私和安全的标准。HIPAA 包括针对电子受保护健康信息(ePHI)的具体要求,ePHI 是指存储或传输的电子健康信息。
-
PCS-DSS:支付卡行业数据安全标准(PCI-DSS)是一套由主要信用卡公司制定的安全标准,确保有权访问信用卡信息的组织保护持卡人数据的机密性和完整性。PCI-DSS 旨在减少数据泄露和信用卡欺诈的风险。
-
STIG:STIG 代表 安全技术实施指南,是一套由美国 国防信息系统局(DISA)为保障 国防部(DoD)使用的信息系统和软件安全而制定的指南。STIG 提供了有关如何配置和维护各种技术,以满足 DoD 安全要求并确保系统对抗网络攻击的详细信息。
在选择标准时,你可以使用默认的通用标准(例如,Oracle Linux 8 的标准系统安全配置文件,可在 static.open-scap.org/ssg-guides/ssg-ol8-guide-standard.html 查找),或者选择与工作负载相符的标准。例如,对于医疗行业,HIPAA 可能是合适的标准。如果你在美国联邦政府生态系统中,STIG 标准在国防部以外的地方也被广泛使用。一旦选择了标准,你将有几个额外选项,如下图所示。你可以选择本地或远程机器,以及修复角色。修复角色允许系统在可能的情况下自动解决问题,但任何管理员在使用时都应该小心。因为许多标准可能会破坏系统功能。在自动修复问题时,尤其是在更严格的标准(如 STIG 和 CJIS)下,务必小心。

图 9.12 – 扫描设置
一旦做出选择,点击扫描。
根据所使用的标准,扫描可以在几秒钟内完成,或者可能需要超过 20 分钟。扫描完成后,你可以使用图形界面(GUI)查看结果:

图 9.13 – 扫描结果
并非所有修复都仅涉及更改简单的设置。有些可能需要额外的文件系统或内核设置。要查看某项发现的详细信息,只需展开结果,如下图所示:

图 9.14 – 结果详情
在总结的底部,你有几个选项:

图 9.15 – 报告选项
这些选项如下:
-
保存结果:将结果保存为 HTML 文件、资产报告文件(ARF)文件或可扩展配置检查清单描述格式(XCDDF)文件
-
生成修复角色:生成 bash、Ansible 或 Puppet 格式的脚本,以自动修复服务器问题
-
显示报告:在浏览器中打开 HTML 格式的报告
端口保护和限制网络访问
Oracle Linux 系统内置了一个防火墙。这个防火墙叫做 firewalld,即 防火墙守护进程 的简称。firewalld 是一个动态防火墙管理工具,广泛用于 Linux 系统,提供了一种简单而一致的方式来管理不同发行版上的防火墙规则。它的设计旨在使管理员能够灵活、高效地管理防火墙规则。
准备就绪
与其他测试一样,我们需要一个 Oracle Linux 系统进行实验。其他没有特别要求。该系统在大多数安装中默认启用。要检查守护进程的状态,可以使用 systemctl 命令,如下所示:
systemctl status firewalld
输出显示在以下截图中:

图 9.16 – firewalld 状态
如何做…
您可以使用带有 --list-all 选项的 firewall-cmd 来查看当前配置:
[root@ol8 ~]# firewall-cmd --list-all
将显示以下信息:

图 9.17 – firewall-cmd --list-all
上述命令的输出显示了由 firewalld 管理的 Linux 系统上活动防火墙规则和配置的综合摘要。输出被组织成多个部分:
-
public(活动):此行显示活动防火墙区域的名称,在此示例中为公共区域。当出现Target:default时,表示这是默认区域,并且当前处于活动状态。 -
interfaces: enp0s3 enp0s8:此行显示分配给活动防火墙区域的网络接口。在此示例中,enp0s3和enp0s8两个接口都分配给了公共区域。 -
sources:此行显示允许访问防火墙区域的 IP 地址或网络范围。如果没有定义源,这一行将为空。 -
services: cockpit dhcpv6-client ssh:此行列出了允许访问防火墙区域的服务。在此示例中,允许来自 cockpit、dhcpv6-client和ssh服务的传入流量。 -
ports:此行显示允许访问防火墙区域的 TCP 和 UDP 端口。如果没有定义端口,这一行将为空。 -
protocols:此行显示以协议级别管理的协议,如 TCP/UDP/ICMP。 -
forward:显示是否启用了区域转发。 -
masquerade: no:此行指示防火墙区域是否启用了或禁用了伪装。伪装允许一个网络的包看起来像是来自另一个网络。 -
forward-ports:此行显示为防火墙区域定义的任何转发端口。转发端口允许将特定端口上的传入流量重定向到另一个端口或 IP 地址。 -
source-ports:此行显示为防火墙区域定义的任何源端口。源端口允许将来自特定端口的传入流量重定向到不同的端口或 IP 地址。 -
icmp-blocks:此行显示防火墙阻止的任何互联网控制消息协议(ICMP)数据包。ICMP 数据包用于网络诊断和故障排除。 -
rich rules:此行显示为防火墙区域定义的任何丰富规则。丰富规则允许使用类似于iptables语法的语法定义更复杂的规则。
添加新规则很容易做到。可以使用服务名称(在/etc/services文件中找到)或端口号来添加规则。最常见的任务是添加一个常见的用户服务,如http或mysql。这可以通过向命令中添加--add-service选项来完成。当服务添加后,除非添加了--permanent选项,否则配置不会在重启后保存。一些常见的示例如下:
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=imap
firewall-cmd --permanent --add-service=pop
firewall-cmd --permanent --add-service=mysql
可选地,你可以指定协议和端口来允许该服务。以下是添加 TCP 或 UDP 端口的示例:
firewall-cmd --permanent --add-port=1521/TCP
firewall-cmd --permanent --add-port=6900/UDP
你还可以使用--remove-port或--remove-service选项来移除端口或服务:
firewall-cmd --permanent --remove-service=pop
firewall-cmd --permanent --remove-port=6900/UDP
完成修改后,你需要重新加载防火墙规则。这可以通过--reload选项完成:
firewall-cmd --reload
它是如何工作的…
firewalld 基于 netfilter 框架,netfilter 是一组钩子,允许网络数据包由内核进行过滤。这个框架用于在许多 Linux 系统上实现 iptables 防火墙。firewalld 提供了 netfilter 框架的更高级抽象,允许管理员通过服务、端口和协议来定义规则,而不是直接操作 iptables 规则。firewalld 的一个关键优势是能够定义匹配多个属性的防火墙规则。例如,管理员可以定义一个规则,匹配源 IP 地址、目标 IP 地址、协议和端口号。这允许更精细地控制网络流量,并使得定义复杂的防火墙策略变得更加容易。
firewalld 还允许管理员根据网络区域定义防火墙规则。区域是被分配特定信任级别的一组网络接口。例如,管理员可能会为暴露在互联网的网络接口定义一个公共区域,为仅能从可信内部网络访问的网络接口定义一个受信任区域。每个区域可以有自己的一组防火墙规则,允许管理员对不同的网络接口应用不同的策略。
保持 SELinux 活跃
SELinux,或称为安全增强型 Linux,是一个提供 强制访问控制(MAC)策略的安全模块,运行在 Linux 内核中。它之所以必要,是因为它通过对系统上进程和用户可以执行的操作实施严格的规则,提供了更高等级的安全性。默认情况下,Linux 使用 自主访问控制(DAC),这意味着任何用户或进程只要拥有适当的权限,就可以访问任何文件或资源。这可能导致安全漏洞,因为任何被攻破的进程或用户都可能访问和修改敏感数据或系统文件。
SELinux 通过强制实施强制访问控制策略,增加了一层额外的安全性,这些策略根据进程或用户的安全上下文限制对文件和资源的访问。这意味着即使一个进程或用户具有适当的权限,他们也只能访问 SELinux 策略明确允许的资源。
本教程将介绍如何创建自定义 SELinux 策略,而不是禁用它,并且如何允许服务执行诸如绑定低端口(<1024)之类的操作。
准备工作
和其他测试一样,我们将需要一个 Oracle Linux 系统来进行操作。其他没有特别的要求。大多数安装默认启用了该系统。要查看 SELinux 的状态,可以使用命令 getenforce。该命令会返回当前的活动状态。状态有三种:
-
enforcing– SELinux 处于活动状态,并且阻止不允许的操作 -
permissive– SELinux 已启用,但不会阻止任何活动 -
disabled– SELinux 已禁用
如果你安装了 setools,可以使用 dnf 来获得其他命令:
dnf install -y setools-console
你还可以使用命令 sestatus 来获取有关 SELinux 的更多信息:
[root@ol8 ~]# sestatus
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Memory protection checking: actual (secure)
Max kernel policy version: 31
你还可以使用 SELinux 类型来管理资源。SELinux 类型是用于对 Linux 系统中各种资源进行分类的标签,例如进程、文件、目录和网络端口。SELinux 类型是 SELinux 安全策略的重要组成部分,因为它们决定了哪些进程和用户可以访问系统上的特定资源。
有几种类型的 SELinux 类型,包括以下几种:
-
用户类型:用户类型用于定义用户的安全上下文。它们还用于将用户的操作限制在系统上特定资源的集合内。
-
角色类型:角色类型用于定义角色的安全上下文。它们还用于将用户的操作限制在系统上特定资源的集合内。
-
域类型:域类型用于定义进程的安全上下文。系统上的每个进程都会被分配一个唯一的域类型,该类型决定了进程可以访问哪些资源。
-
类型强制类型:类型强制类型用于定义文件或目录的安全上下文,并将进程的操作限制在系统上特定资源的集合内。
-
网络端口类型:网络端口类型用于定义网络端口的安全上下文。网络端口类型用于限制系统上特定端口或服务的网络访问。
除了这些类型外,SELinux 还有几个特殊类型,例如 unconfined_t 类型,用于没有被 SELinux 限制的进程,和 system_u 与 root_t 类型,分别用于系统资源和进程。
如何操作…
可以使用命令 setenforce 配合参数 1 或 0 动态更改 SELinux 的状态。使用 1 会将 SELinux 设置为 enforcing 模式,而 0 会将其设置为 permissive 模式。
此外,你可以编辑配置文件 /etc/selinux/config,并将 SELinux 字段设置为三种状态之一。这也是禁用 SELinux 的唯一方法。
虽然许多管理员都倾向于禁用 SELinux,但它可以轻松地更新以允许所需的行为。
SELinux 默认情况下还会将日志记录到 /var/log/audit/audit.log 文件中。
它是如何工作的…
SELinux 有多个安全层次,用于管理文件、端口和内核模块。它们都由 semanage 命令管理。
semanage
semanage 是一个命令行工具,用于管理 Linux 系统中的 SELinux 策略。它用于创建、修改或删除 SELinux 策略,还可以管理文件上下文和网络端口。以下是 semanage 命令的一些常见用途:
-
semanage可用于创建、修改或删除策略模块。例如,你可以使用以下命令创建一个新的策略模块:kernelmodule.pp to the SELinux policy. -
semanage可用于管理文件上下文,包括添加或修改特定文件或目录的上下文。例如,你可以使用以下命令添加一个新的文件上下文:/var/www/html. -
semanage可用于管理网络端口和服务,包括添加或修改端口类型和策略。例如,你可以使用以下命令定义一个新的端口类型:www2 for TCP port 8080. -
setsebool:SELinux 有布尔变量,可以启用或禁用,以控制特定的安全策略。要更改这些变量的值,可以使用setsebool命令启用或禁用某些 SELinux 策略。一个有用的示例是,当你将httpd_can_network_connect设置为 true 来允许 Web 服务器时:getsebool: To view the status of SELinux policies, you can use the getsebool command. This command displays Boolean variables that can enable or disable certain policies. To view all values, use the -a option. Alternatively, you can pass a specific value to check, as shown in this example:getsebool httpd_can_network_connect
httpd_can_network_connect --> off
SELinux fixfiles
SELinux fixfiles 是一个命令行工具,用于恢复文件和目录的 SELinux 文件上下文。SELinux 使用文件上下文来确定哪些进程和用户可以访问系统中的特定文件或目录。当文件上下文被更改或损坏时,可能会导致系统功能或安全问题。fixfiles 命令用于将文件上下文恢复为默认值。这在遇到文件访问或 SELinux 相关错误时非常有用。以下是一些常见的 fixfiles 命令使用方式:
-
恢复目录的默认文件上下文:要恢复特定目录的默认文件上下文,可以使用以下命令:
fixfiles restore /directory_to_fix这将递归地恢复指定目录内所有文件和目录的默认文件上下文。
-
恢复整个系统的默认文件上下文:要恢复整个系统的默认文件上下文,请运行以下命令:
fixfiles restore这将恢复系统中所有文件和目录的默认文件上下文。请注意,这可能需要一些时间才能完成,并且可能会导致系统功能的暂时中断。
-
验证文件上下文:您可以使用以下命令验证特定文件或目录的文件上下文:
fixfiles command to restore the default context.
注意
如果 SELinux 曾在某段时间内被禁用,那么在其未运行期间,这些上下文将未被设置。可以使用一个快捷方式让 SELinux 重新标记整个文件系统层次结构:# touch /.autorelabel
现在重启机器。随着 SELinux 的启动,它将为每种类型和位置的文件和安全上下文设置默认值。
SELinux 用户
SELinux 用户是用来分类 Linux 系统中不同类型用户的标签。SELinux 用户是 SELinux 安全策略的重要组成部分,因为它们用于将用户的操作限制在系统中一组特定的资源上。
有几种类型的 SELinux 用户:
-
系统用户:系统用户是由系统定义的用户,用于运行系统服务或守护进程。这些用户通常会被分配一个独特的 SELinux 用户标签,用于将用户的操作限制在系统中一组特定的资源上。
-
登录用户:登录用户是由系统定义的用户,用于登录系统。这些用户通常会被分配一个独特的 SELinux 用户标签,用于将用户的操作限制在系统中一组特定的资源上。
-
工作人员用户:工作人员用户是由系统定义的用户,由工作人员用于执行他们的工作。这些用户通常会被分配一个独特的 SELinux 用户标签,用于将用户的操作限制在系统中一组特定的资源上。
-
用户定义的用户:用户定义的用户是由系统管理员定义的用户。这些用户通常会被分配一个独特的 SELinux 用户标签,用于将用户的操作限制在系统中一组特定的资源上。
下面是一些常用的 SELinux 用户命令:
-
semanage user:此命令用于管理 SELinux 用户及其属性。例如,要创建一个新的 SELinux 用户,可以使用命令semanage user -a -R "s0-s0:c0.c1023" -r s0 -L s0:c0.c1023 -P user -n username。 -
semanage login:此命令用于管理 SELinux 登录映射,它将系统用户映射到 SELinux 用户。例如,要创建一个新的登录映射,可以使用命令semanage login -a -s user_u -r s0 username。 -
semanage staff:此命令用于管理 SELinux 员工映射,它将员工用户映射到 SELinux 用户。例如,要创建一个新的员工映射,可以使用命令semanage staff -a -s user_u -r s0 username。 -
semanage sudo:此命令用于管理 SELinux sudo 映射,它将 sudo 用户映射到 SELinux 用户。例如,要创建一个新的 sudo 映射,可以使用命令semanage sudo -a -r s0 -R "s0-s0:c0.c1023" -L s0:c0.c1023 -U username。 -
semanage port:此命令用于管理 SELinux 端口映射,它将端口映射到 SELinux 类型。例如,要创建一个新的端口映射,可以使用命令semanage port -a -t http_port_t -p tcp 80。
第十章:重新回顾模块和 AppStreams
在本章中,我们将进一步了解模块和应用流(AppStreams)。我们在第五章《使用 DNF 进行软件管理》中讨论了新的仓库组织结构和模块化概念,但现在我们将通过以下教程深入探索 AppStreams 的真正功能:
-
搜索和列出 AppStream 模块
-
通过 AppStream 安装应用程序和开发工具
-
使用 AppStreams 安装不同版本的软件
-
通过 AppStream 移除软件包
技术要求
AppStreams 的概念是新的,并且是在 Oracle Linux 8 中引入的。也就是说,只要你使用的是 Oracle Linux 8,你就能拥有在本章中跟随操作所需的所有条件。
搜索和列出 AppStream 模块
首先,让我们回顾一下与模块相关的命令列表:
-
disable:禁用一个模块及其所有流 -
enable:启用一个模块流 -
info:打印关于模块的详细信息 -
install:安装一个模块配置文件及其包 -
list:列出所有模块流、配置文件和状态 -
provides:列出模块化包 -
remove:移除已安装的模块配置文件及其包 -
repoquery:列出属于某个模块的包 -
reset:重置模块 -
switch-to:将模块切换到某个流并进行distrosync RPM 包同步 -
update:更新与活动流相关的包
如何操作…
AppStreams 非常易于使用。要开始使用,通常最好先检查可用模块的列表。你可以通过在终端/控制台输入一个简单的命令dnf module list来完成此操作:

图 10.1 – dnf module list 的输出
输出继续显示一个相当长的模块列表,最后你将看到不同字母含义的键映射:

图 10.2 – 通过提示查看模块键映射
以下是几个我立刻注意到的模块:container-tools、gimp、go-tools、inkscape、mariadb、mysql、nginx、nodejs、python和php。这些是模块,但你会发现每个模块都有一个流,而每个流包含一个配置文件。如果我们将其可视化成图表,它可能看起来像这样:

图 10.3 – 可视化 AppStreams
现在,假设我们想要获取某个特定模块的更多信息。以nodejs为例。首先,我们需要在请求列表时指定nodejs。我们可以通过将模块名称添加到list命令后面来做到这一点,如下所示:

图 10.4 – dnf module list nodejs 的输出
在列表的底部,你将看到以下内容:
Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled
从中我们可以看到,流 10 被标记为 nodejs 的默认(d)。这到底是什么意思?基本上,如果我们运行 dnf module install nodejs,我们将得到流 10 中的最新版本 Node.js(是的,流 10 对应的是 Node.js 10)。
注意
在写作时,Node.js 10 系列流的最新版本是nodejs-1:10.24.0-1.module+el8.3.0+9671+154373c8.x86_64。
我们可以进一步探索并通过输入以下命令来了解更多有关此特定 AppStream 的信息:
# dnf module info nodejs:10
该命令的输出将显示 10 系列流中每个可用的 Node.js 版本。虽然有很多,但为了简洁起见,我只粘贴了列表中的最后两个版本:

图 10.5 – dnf module info nodejs:10 的输出
有趣的是,10 系列中的每个流都被标记为[d][a](默认和活动);这是因为 Stream 项是指流本身,而不是流中的任何特定版本。
通过 AppStream 安装应用程序和开发工具
从之前的食谱中,我们已经熟悉了如何在 AppStream 中搜索和列出应用程序;现在让我们深入了解通过 AppStream 安装应用程序和开发工具。
如何做...
基于上一个食谱,我们研究了nodejs,现在让我们继续安装它。安装它的方法有不止一种。你可以启用该模块,然后使用标准的dnf install [package(s)]命令来安装软件包:
# dnf module enable nodejs
# dnf install nodejs npm
你也可以使用标准的 dnf 命令而不指定模块,默认模块将在事务中启用:
# dnf install nodejs npm
或者,更推荐的方式是直接使用新的 dnf module 命令集,简单地运行 dnf module install [module name(s)]:
# dnf module install nodejs
输出如下面的截图所示:

图 10.6 – dnf module install nodejs 的输出
你得到的是默认 AppStream 中的最新版本(如果没有启用任何模块),但是如果出于某种原因你希望获取流中的旧版本,你可以通过在命令末尾加上冒号和版本号来选择。例如,如果我不想要最新版本,而是想要它之前的版本,我会输入以下命令:
# dnf module install nodejs:10:8030020210118191659
输出如下面的截图所示:

图 10.7 – dnf module install nodejs:10:8030020210118191659 的输出
这将指示 DNF 安装与指定版本相关的 Node.js(以及相关组件)发行版。
另一个需要注意的点是,默认情况下,只会安装common配置文件。如果我们想安装其他配置文件(例如,development配置文件),可以通过在命令末尾加上斜杠和配置文件名称来指定:
# dnf module install nodejs:10/development
输出如下面的截图所示:

图 10.8 – 执行 dnf module install nodejs:10/development 的输出
您甚至可以指定多个配置文件,像这样:
# dnf module install nodejs:10/development nodejs:10/s2i
输出显示在下面的截图中:

图 10.9 – 执行 dnf module install nodejs:10/development nodejs:10/s2i 的输出
或者,如果您希望安装所有配置文件,只需使用星号表示通配符选择:
# dnf module install nodejs:10/*
输出显示在下面的截图中:

图 10.10 – 执行 dnf module install nodejs:10/* 的输出
使用 AppStreams 安装不同版本的软件
现在,我们将进一步了解 AppStreams,并且不再从默认模块流安装应用程序,而是指定一个不同的流。
如何操作…
有多种方法可以做到这一点:只需指定安装不同的流即可,或者您可以先手动启用不同的版本。我的偏好是在安装时指定版本,因为这样,AppStream 会自动启用该版本:
# dnf module install nodejs:16
注意
如果您已经安装了某个版本的 AppStream,最好在重置并安装不同版本之前移除旧版本。稍后会讲解这个过程。
输出显示在下面的截图中:

图 10.11 – 执行 dnf module install nodejs:16 的输出
您会看到从输出中 nodejs 16 的模块流将被启用。现在,如果我们列出 nodejs 的模块流,我们将看到以下内容:

图 10.12 – 执行 dnf module list nodejs 的输出
如您所见,10 仍然是默认版本,但 16 已启用(e)。AppStreams 维护一个默认流,以允许 dnf 正常工作,无需用户了解 AppStreams 的任何信息。此外,如果我们重置模块,它将恢复到原始设置——也就是说,10 将成为唯一的默认并启用版本,而版本 16 将不再启用。值得注意的是,任何时候只能启用一个流。总结一下,默认流在没有启用其他流时会默认启用。如果启用其他流,它将成为唯一可以安装的流,但很容易重置并切换到另一个。要这样做,只需按照以下步骤操作:
# dnf module remove nodejs
# dnf module reset nodejs
您将看到关于模块已重置的确认信息:
Disabling module profiles:
nodejs/common
Resetting modules:
nodejs
到此为止,我们可以安装不同的版本了。这次我们选择安装 Node.js 14:
# dnf module install nodejs:14
您将看到关于包管理器计划执行的操作的确认信息:

图 10.13 – dnf module install nodejs:14 的输出
你可能会注意到你正在降级。正如你可能猜到的那样,如果没有安装任何模块,它会显示 Installing;如果安装的版本号大于当前安装的版本,它会显示 Upgrading;如果安装的版本号小于当前安装的版本,它会显示 Downgrading。不管包管理器显示的是在做什么,最终你将得到你请求的版本——就这么简单。
你应该知道其实还有另一种切换到不同流的方法。你可以通过使用 switch-to 来一步完成,而不是先使用 remove、reset 然后再 install:

图 10.14 – dnf module switch-to nodejs:16 的输出
这是推荐的切换流版本的方法,因为它只需一步即可完成切换,而且能清晰地打印出正在进行的操作。它的状态是 Upgrading,并且正在从 14 -> 16。
注意
其实还有一种方法可以动态切换模块。如果你在 /etc/dnf/dnf.conf 中将 module_stream_switch 设置为 True,那么你可以在不使用 switch-to 语法的情况下安装不同的模块。
下面是一个例子:
echo “module_stream_switch=True” >> /****etc/dnf/dnf.conf
那 Python 呢?
如果你查看模块列表,可能会注意到 Python 包含多个模块,而不是一个包含多个 AppStream 的单一模块:
# dnf module list python*
输出可以在以下屏幕截图中看到:

图 10.15 – dnf module list python* 的输出
一开始看起来有点奇怪,但考虑到 Python 是 Oracle Linux 操作系统的一个重要组成部分,每个 Oracle Linux 版本都附带一个平台 Python 版本。每个 Oracle Linux 版本的特定平台 Python 版本可能不同,并且每个版本的相应平台 Python 版本将在该版本的整个生命周期内得到支持。对于 Oracle Linux 7,平台 Python 版本是 2.7,并始终安装;而对于 Oracle Linux 8,平台 Python 版本是 3.6。换句话说,Python 2.7 在 Oracle Linux 7 的整个生命周期内得到支持,而 Python 3.6 在 Oracle Linux 8 的整个生命周期内得到支持。在 Oracle Linux 8 上,平台 Python 专门供系统工具(如 Yum 和 DNF)使用。对于一般用途的 Python,不会在 Oracle Linux 8 上默认安装,因此这时 AppStream 模块就发挥了作用。
你可以通过指定与所需 Python 版本相对应的模块,在 Oracle Linux 8 上安装多个版本的 Python。所有 Python 模块可以同时安装并在同一台机器上使用,你可以通过输入版本号来指定希望使用的安装版本——例如,python3.6 --version,python3.8 --version,等等。
默认情况下,如果系统上安装了python3,它总是别名为 Python 3.6,这是因为 Python 3.6 是 Oracle Linux 8 上的平台 Python 版本。
通过 AppStream 移除包
通过 AppStream 移除包非常简单。通常,你只需指示包管理器执行移除操作,而不是安装操作。如果包管理器找到一个匹配的模块,它将继续移除相关的包。
如何操作……
参考前一个示例中的内容,我们通过运行dnf module remove nodejs命令来移除 Node.js 模块:

图 10.16 – 执行 dnf 模块移除 nodejs 的输出
从这条信息中,你可以看到 NPM 将被卸载,但考虑到 Node.js 模块不仅仅安装了 NPM,你可能会有些困惑。如果你想移除与该模块相关的所有内容,你需要添加--all标志,像这样:
# dnf module remove nodejs --all
这次,你将看到所有相关的包都排队等待移除:

图 10.17 – 执行 dnf 模块移除 nodejs --all 的输出
现在这就对了。输入y并按Enter,模块将被移除。
还有更多内容……
所以,既然我们已经讨论了 AppStreams 的使用,你可能会问自己,“我们之前不是已经通过软件集合实现了类似的功能吗?” 答案是肯定的,但软件集合和 AppStreams 之间有一个很大的区别。
软件集合提供了平行可用性和平行可安装性,而 AppStreams 仅提供平行可用性。
根据 Fedora 文档,"平行可用性意味着可以安装多个流行软件项目的主要版本。” 以及“平行可安装性意味着同一用户空间中可以安装多个主要版本的一个软件项目。”
现在你可能会问,“等一下,你是说 AppStreams 不如我们之前使用的那种好吗?” 好吧,答案并不完全是这样。事实上,平行可安装性并没有想象中那么好。虽然表面上看,能够在同一系统上安装多个版本的软件似乎很不错,但实际上,它存在一些复杂问题,需要用户知道自己需要做额外的操作才能真正使用已安装的软件和/或备用版本。例如,如果你想安装多个版本的 Node.js,你首先需要启用你想要的 Node.js 软件集合,然后你还需要知道在哪里查找并激活你想使用的特定版本。换句话说,你不能像正常使用软件那样直接使用备用版本,因为这些包会被安装到非标准位置。
AppStreams 解决了这个问题,因为它不允许并行安装性,而是提供并行可用性的能力。换句话说,你一次只安装一个包,然后像平常一样使用它。如果你想要不同的版本,那么你只需启用不同的流。
作为一个奖励,AppStreams 在设计上用于创建单次使用的容器时特别有用。拥有 AppStreams 意味着每个容器镜像都配置有正确版本的模块,然后在容器内部全局可用。如果需要多个版本,只需运行多个容器。
AppStreams 大大简化了安装不同版本软件的过程,而且最棒的是,即使你对 AppStreams 一无所知,你仍然可以像以往一样使用 DNF 安装基本应用程序。
第十一章:狮子、老虎和容器——哎呀!Podman 和朋友们
如今,一切都与容器有关。Docker 使容器变得酷并带入主流,而 Podman 作为一个开源的容器运行时,向所有人开放并准备救援。Oracle Linux 7 包括 Oracle Container Runtime for Docker,而 Oracle Linux 8 及以后的版本包括 Podman、Buildah 和 Skopeo。
随着每次新版本的发布,Podman 正在缩小与 Docker 之间的差距。随着 Podman v2.0 的发布,它开始提供一个完全兼容的构建,使得 docker-compose 等技术能够与 Podman 互换使用。随着 Podman v4.1.0 的发布,现在可以无缝地将主机机器的 home 目录挂载到 Podman 虚拟机中,使其在容器卷挂载中可用。本章主要面向有一定 Docker 基础的用户,帮助他们理解 Docker 和 Podman 之间的差异,以便成功地将工作负载迁移到这一“即插即用替代品”。如果你不熟悉 Docker 或容器概念,可以查阅 Docker 的入门指南,链接如下:docs.docker.com/get-started/。
在本章中,我们将涵盖以下食谱:
-
使用 Podman 驱除守护进程(呃,那个……守护进程)
-
给你的容器做根管治疗
-
创建便捷的实用容器
-
使用 Podman 进行 Docker Compose
-
使用 Pod 管理堆栈
-
容器化数据库
-
Buildah 和 Skopeo – Podman 的得力助手
技术要求
Podman、Buildah 和 Skopeo 都包含在 container-tools 模块中,来自应用流:
$ sudo dnf module install container-tools
本章中食谱的源代码可以在 github.com/PacktPublishing/Oracle-Linux-Cookbook 找到。
使用 Podman 驱除守护进程(呃,那个……守护进程)
Docker 和 Podman 都是旨在简化在主机上运行和管理容器的工具。由于 Podman 是新兴工具,你可能会想知道如何将 Docker 切换到 Podman。虽然技术上可以在同一系统上同时运行 Docker 和 Podman,但实际上几乎没有必要这样做。因为这两个工具提供相同的核心功能,我建议你选择其中一个。
切换到 Podman 的一个主要好处是你将不再使用 Docker 背后潜藏的守护进程。你看,Docker 依赖于一个守护进程,它负责管理容器的所有繁重工作。乍看之下,这似乎没什么问题,但在这种架构下,有些问题是需要注意的。
首先,后台有一个额外的守护进程运行意味着系统会有更多的故障点。如果专门为 Docker 运行的守护进程崩溃,你的所有容器都会丢失。额外的守护进程还会增加攻击面,因为 Docker 守护进程具有 root 访问权限,任何对 Docker 守护进程的攻击都会使系统面临更大风险。
这个方案旨在驱逐那些“恶魔”——呃,嗯——停止使用 Docker 守护进程。最好的部分是,如果你没有使用 Docker,且只安装了 Podman,那么你无需担心任何问题——因为 Podman 默认是无根的,并且它利用 systemd 来管理你的容器。systemd 是一个经过验证的系统级守护进程,提供了一系列系统组件,包括系统和服务管理器、并行化功能、日志记录,以及用于管理和维护系统配置的工具。
另一方面,如果你之前使用的是 Docker,我们将向你展示如何切换。其实非常简单——你只需移除 Docker 并安装 Podman。
准备工作
我使用的是 x86-64 位架构,但 Oracle Linux 和 Podman 也可以在 Arm 上运行。不过,需要注意的是,并不是所有的容器都在 Arm 上编译,反之亦然。话虽如此,使用 x86-64 位 CPU 跟随本指南可能会更容易:
-
Oracle Linux
-
Podman
如何操作……
-
通过运行以下命令来移除 Docker:
$ sudo dnf remove -y docker-ce docker-ce-cli containerd.io docker-compose-plugin -
完成后,你将能够通过以下方式安装 Podman:
docker group, you may go ahead and delete that group because it is no longer needed:$ sudo groupdel docker
现在你已经在没有 Docker 守护进程的情况下运行容器,默认情况下,使用 Podman 时,你是无根用户。
给你的容器做个根管治疗
根据 Docker 文档,你会发现“Docker 守护进程绑定到一个 Unix 套接字,而不是 TCP 端口。默认情况下,这个 Unix 套接字归 root 用户所有,其他用户只能使用 sudo 访问它。Docker 守护进程始终以 root 用户身份运行。”
文档接着指导你将用户添加到 docker 组,以便在不使用 sudo 的情况下使用 Docker。听起来很不错,对吧?不过,问题是,docker 组赋予的权限相当于 root 用户的权限。这可能会带来严重后果。例如,宿主文件系统上的任何位置都可以挂载到容器中——我说的“任何”都是真的!这甚至包括 /(根)目录,容器可以在没有任何限制的情况下更改你的宿主文件系统。由于这种架构,存在许多其他安全漏洞,但你应该明白了。
Podman 与其他工具不同之处在于,默认情况下,它是以无 root 权限的方式运行;换句话说,你可以在没有 root 权限的情况下使用 Podman 运行容器。当我第一次听到这一点时,我以为这意味着容器中的用户不是 root,但事实并非如此。Rootless 容器的含义仅仅是启动容器的用户没有 root 权限。关于在没有 root 权限的情况下运行容器,有一些需要了解的事项,本指南将教你如何运行 rootless 容器,同时解释 rootless 和 rootful 之间的区别。
准备工作
-
Oracle Linux
-
Podman
如何操作…
要运行 rootless 容器,只需以无 root 权限的用户身份使用 Podman。并且,千万不要在任何 Podman 命令前加上 sudo,因为如果加了 sudo,那么你实际上是在以 root 用户身份运行容器。
Rootless 容器有什么不同?
网络模式
Podman 支持三种常见的网络模式:
-
桥接
-
macvlan
-
slirp4netns
首先,桥接网络是 rootful Podman 默认使用的网络模式。桥接网络在主机上创建一个网络接口,并将该接口专门分配给容器。另一种网络模式是macvlan,它是一个虚拟局域网,基本上将整个网络接口从主机转发到容器。最后,还有slirp4netns,它允许你以完全无特权的方式将一个网络命名空间连接到互联网。Rootless Podman 利用slirp4netns,因为无特权用户无法在主机上创建网络接口。为了绕过这一限制,slirp4netns会在主机和容器之间创建一个隧道,以转发流量。
网络端口
当你以非 root 用户身份运行容器时,可能会遇到暴露某些网络端口的问题。例如,用户在运行容器时通常会暴露80端口和/或443端口;然而,如果你在运行 rootless 容器时尝试这样做,你将看到类似下面的消息:
Error response from daemon: rootlessport cannot expose privileged port 80, you can add 'net.ipv4.ip_unprivileged_port_start=80' to /etc/sysctl.conf (currently 1024), or choose a larger port number (>= 1024): listen tcp 0.0.0.0:80: bind: permission denied
Rootless Podman 限制只能暴露 1024 以上的端口。如果你想暴露更低的端口,首先需要以 root 身份进行配置,以允许无特权用户暴露较低的端口号。
假设你想让 rootless Podman 暴露标准的 HTTP Web 端口(端口 80)。在这种情况下,你可以运行以下命令:
sudo sysctl net.ipv4.ip_unprivileged_port_start=80
如果你希望这些设置保持不变,只需按照之前收到的错误信息的指引操作。也就是说,编辑 /etc/sysctl.conf 文件,并添加 net.ipv4.ip_unprivileged_port_start=80。
创建实用的工具容器
本指南展示了如何使用 Podman 快速启动一个容器,以完成有用的任务。
本教程将引导你通过使用容器创建超级实用工具的过程。容器的基本原则鼓励我们将容器设计为只做一件事——也就是说,提供某种形式的工具功能,其他的都不做。你不应创建一个功能过多的容器。话虽如此,大多数容器镜像已经存在,用于提供有用的工具。在本教程中,我们将查看一些有用的容器示例,并探索如何利用它们。
准备工作
我们将需要以下工具:
-
Oracle Linux
-
Podman
如何操作……
本教程的主要目的是展示如何使用容器实现功能,而无需在本地机器上安装额外的包。一旦在本地机器上安装了 Podman,你可以访问整个有用的包和工具生态系统,而无需安装更多的包——你只需运行一个包含所需包的容器镜像,或者,你可以创建一个新的容器并在那里安装所需的包。
为什么有人会选择这样做?首先,这可以帮助你最小化在主机上安装的包和依赖项的数量。通过减少包的数量,你可以降低安全方面的攻击面。此外,你的操作系统的仓库可能会限制某些包的访问,或者可能无法访问最新版本。与其通过添加可能不受信任的仓库来安装所需的包,不如直接启动一个包含所有你需要的功能的容器呢?
在我们尝试挖掘容器的真正潜力之前,首先需要讨论一些重要的概念,这些概念将使这个过程变得更加简便。
入口点
容器的入口点定义了容器默认运行的命令。你可以通过指定 inspect 命令并将其结果传输到 jq 来提取入口点。
首先,如果系统中没有该镜像,请拉取镜像:
$ podman pull docker.io/pandoc/core
现在,让我们检查镜像并运行 jq 查询入口点:
$ podman image inspect pandoc/core | jq -r '.[].Config.Entrypoint[0]'
在我们的计算机上安装 jq。在这种情况下,我们可以将 inspect 的输出传输到一个包含 jq 的容器中:
$ podman image inspect pandoc/core | podman run -i --rm stedolan/jq -r '.[].Config.Entrypoint[]'
无论哪种情况,这个命令的输出将是 /usr/local/bin/pandoc。
这告诉我们,当我们运行 pandoc/core 容器时,默认执行的命令将是 /usr/local/bin/pandoc。
有时,容器的入口点可能是一个脚本。例如,你可能检查入口点并发现入口点是 docker-entrypoint.sh。你可以通过重写入口点并使用 cat 查看文件内容,从而揭示更多关于该文件的信息。例如,假设我们要检查 node 容器镜像:
$ podman image inspect node | jq -r '.[].Config.Entrypoint[]'
我们会发现入口点是 docker-entrypoint.sh。
现在,让我们覆盖入口点来检查这个文件的内容:
$ podman run --rm --entrypoint=/bin/bash node -c 'cat docker-entrypoint.sh'
在这种情况下,输出如下:
cat: docker-entrypoint.sh: No such file or directory
这是因为在node镜像的情况下,docker-entrypoint.sh文件不在工作目录中;相反,它位于路径中。所以,我们将尝试另一种方法来检查这个文件:
$ podman run --rm --entrypoint=/bin/bash node -c 'cat $(which docker-entrypoint.sh)'
输出结果如下:

图 11.1 – docker-entrypoint.sh 的输出
现在我们了解了默认入口点,我们可以利用这一点来决定我们将如何使用这个容器。有时我们可能希望按预期使用默认入口点,而其他时候,我们可能从覆盖默认入口点来使用容器内的其他可用包中受益——这完全取决于我们想要做什么。
工作目录
你通常需要指定容器内部的工作目录,因为默认情况下,容器被配置为在该目录中执行其工作。要获取容器的工作目录,你可以运行以下命令:
$ podman image inspect pandoc/core | jq -r '.[].Config.WorkingDir'
再次提醒,如果你能在不安装jq的情况下通过运行以下命令来实现,你将获得额外的奖励:
$ podman image inspect pandoc/core | podman run -i --rm stedolan/jq -r '.[].Config.WorkingDir'
无论哪种情况,执行此命令的输出将是/data。
这告诉我们,当我们运行pandoc/core容器时,容器内的默认工作目录是/data。
卷挂载
为了利用一个在本地机器上对文件执行任务的容器,你首先需要将一个卷挂载到容器中。一种简单的方法是通过指定$(pwd)来指定当前工作目录。另一种方法是指定./。执行此操作的顺序是先声明主机机器的目录,再声明容器的目录。
例如,如果你想将主机机器的当前工作目录挂载到容器的工作目录中,你可以运行-v $(pwd):/data。在这个例子中,我们是想让主机机器的当前工作目录在容器内的/data路径下可访问。记住,当我们使用podman inspect命令时,我们已经找到了容器的工作目录。
超级实用的容器工具
现在我们已经讨论了一些重要概念,我将列出我在容器中找到的有用工具的示例,并扩展利用容器执行这些功能的实际性。
使用 pandoc 将 Markdown 文件转换为 docx
在这个例子中,假设我们有一个文档,想要将其转换为另一种类型。我们可以利用许多工具来实现这一点,但有一个工具是 pandoc。与其在本地机器上安装 pandoc,不如直接运行已经预安装了 pandoc 的pandoc/core容器。pandoc容器的入口点是/bash/pandoc。这意味着,在指定容器镜像后,任何内容都会自动附加到容器内的pandoc命令。
我们可以在pandoc/core命令后加上--help来了解如何使用该工具,例如:
$ podman run --rm pandoc/core --help
从这个(你也可以查看这里维护的手册页:linux.die.net/man/1/pandoc),我现在对如何使用 pandoc 有了一些了解。在这种情况下,我可以通过将当前工作目录挂载到容器中,并指定我的源文档和输出内容,来在容器中使用pandoc命令,例如:
$ podman run --rm -v $(pwd)/:/data pandoc/core -s input.md -o output.docx
由于容器内的工作目录是/data,并且我已经将该目录挂载到我的主机系统上,如果容器在该目录中创建了新文件,我将能够在我的主机系统上找到输出结果。很酷!
使用 FFMPEG 对图像或视频文件进行修改
在这个示例中,我们将以与之前使用 pandoc 容器相同的方式,在容器中使用 FFMPEG。使用 FFMPEG 容器特别方便,因为 FFMPEG 通常依赖许多我不希望安装在本地计算机上的依赖项。此外,官方的 FFMPEG 容器自带最新版本,运行起来也很棒!
就像之前的示例一样,我们可以在ghcr.io/linuxserver/ffmpeg命令后加上--help来了解如何使用 FFMPEG,例如:
$ podman run --rm ghcr.io/linuxserver/ffmpeg --help
从输出结果来看(你也可以查看这里维护的手册页:linux.die.net/man/1/ffmpeg),我可以看到许多选项,但为了简洁起见,我将简单展示如何从容器中使用ffmpeg来转换容器内的视频,例如:
$ podman run --rm -it -v $(pwd):/config \
ghcr.io/linuxserver/ffmpeg \
-ss 00:00:30 -t 5 -i /config/input.mkv \
-vcodec libx265 -crf 30 /config/output.mp4
这个命令会从视频的 00 小时 00 分钟 30 秒(由-ss指定)开始,并录制 5 秒钟(由-t指定)。然后,它会转换视频,输出结果可以在./config/output.mp4找到。
在容器中使用 Node.js
假设我们需要构建一个 Node.js 应用程序。为此,我们需要使用 Node 和 npm。在第十章中,我们讨论了应用流的有用性,以及如何利用应用流安装不同版本的 Node.js。好吧,就像生活中的其他事情一样,有多种方式可以解决问题。
为什么不直接在容器中使用 Node.js,而不是在主机系统上安装 Node.js 呢?node容器包含了 Node 和 npm。默认情况下,当你运行node容器时,你是在执行node命令,因为这是默认的入口点(就像我们之前讨论入口点时提到的那样)。
假设我们想使用npm命令——我们可以通过覆盖入口点来实现这一点。到此为止,我们知道可以通过利用 bash 并在末尾添加命令来覆盖入口点,但我们还需要知道如何挂载我们的主机系统:
$ podman image inspect node | podman run -i --rm stedolan/jq -r '.[].Config.WorkingDir'
从中我们可以看到,容器内的默认工作目录是 null。这是否意味着我们不能按照自己的方式使用容器?当然不是,因为我们可以简单地覆盖入口点,自己来操作。在这种情况下,我会将主机系统中的当前工作目录挂载到 /app 目录,并将入口点覆盖为 bash,这样我就可以指示容器在运行 npm 命令构建我的 Node.js 应用程序之前,先切换到 /app 目录。以下是实现方法:
$ podman run --rm -v $(pwd):/app --entrypoint bash node -c 'cd /app && npm run build'
一旦 NPM 完成构建,你将在主机机器上找到名为 ./build 的目录,其中包含你的应用程序二进制文件。
但等等,正如我之前提到的,有很多种方法可以解决同一个问题。一种更优雅的方法可能是直接告诉 Podman 你希望工作目录在哪里。如果我们这样做,我们甚至不需要将 bash 设置为入口点——相反,我们可以直接跳到 npm。可以使用 -w(或 --workdir)命令来实现,方法如下:
$ podman run --rm -v $(pwd):/app --workdir /app --entrypoint npm node run build
在我看来,第二种方法更简洁,但最终结果是一样的。
运行一个轻量级的 NGINX 网络服务器以在本地预览网页
在这个示例中,我们可以继续上一个练习,在那里我们构建了一个 Node.js 应用程序。现在我们已经构建/编译了 Node.js 应用程序,接下来让我们将其托管在 NGINX 容器中。我们可以通过简单地将构建目录挂载到 NGINX 容器内的 /user/share/nginx/html 目录来实现这一点。
我是怎么知道要把它托管在这个特定目录里的呢?在这种情况下,我不得不查阅 NGINX 容器的 NGINX 文档。你通常可以在任何托管你要运行的容器的容器注册表中找到这类文档。
托管我们的构建目录的命令如下:
$ podman run --rm --name ol8cookbook -p 80:80 -v ${pwd}/build:/usr/share/nginx/html:ro -d nginx
使用 Podman 时,rootless 端口的默认设置不能暴露特权端口 80。如果你没有更改此设置,你将看到如下信息:
Error: rootlessport cannot expose privileged port 80, you can add 'net.ipv4.ip_unprivileged_port_start=80' to /etc/sysctl.conf (currently 1024), or choose a larger port number (>= 1024): listen tcp 0.0.0.0:80: bind: permission denied
如果你具有 root 权限,可以通过以下方式覆盖此设置:
$ sudo sysctl net.ipv4.ip_unprivileged_port_start=80
另外,你可以选择使用 1024 或更高的端口号。一旦容器运行起来,你可以通过导航到 http://localhost(如果你使用的是端口 80)或 http://localhost:8080(如果你没有选择端口 80,则是你分配的端口)来预览本地网站。
使用 Podman 的 Docker Compose
Podman 是一个强大的容器引擎,通常通过 docker-compose.yml 文件进行访问。
虽然 Docker Compose 是一个很棒的工具,可以将容器配置为代码,但重要的是要知道 Docker Compose 设计时是为了与 Docker 一起使用的。因此,在使用 Docker Compose 与 Podman 时,有几个需要注意的事项。
准备工作
我们需要以下内容:
-
Oracle Linux
-
Podman
-
Docker Compose
如何操作…
在本教程中,我们将讨论如何将 Docker Compose 与 Podman 一起使用。
由于 Compose 文件通常涉及多个容器和应用程序之间的通信,我建议使用基于 Netavark 和 Aardvark 的网络堆栈,而不是基于 CNI 的堆栈。Netavark 和 Aardvark 是 Podman 4.0 中的新特性,提供了更低的开销和显著的性能提升。此外,我在使用默认的 CNI 堆栈时遇到了一些问题,而切换到 Netavark 和 Aardvark 后,容器之间能够按预期相互通信:
-
要切换网络堆栈,只需在
/usr/share/containers/containers.conf文件中指定netavark作为网络后端。您可以通过运行以下sed命令快速完成此操作:sudo sed -i 's/network_backend = "cni"/network_backend = "netavark"/g' /usr/share/containers/containers.conf sudo podman info | grep networkBackend
注意
如果您已经在系统上运行容器,您需要运行 sudo podman system reset 才能完全切换到基于 Netavark 和 Aardvark 的网络堆栈,但请注意,此命令将删除所有现有的镜像、容器、Pod、网络和卷。
-
既然这部分已经处理完了,我们来开始安装 Docker Compose:
sudo curl -SL https://github.com/docker/compose/releases/download/v2.20.3/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose podman-docker package to ensure Podman is called anytime a reference to Docker is being made:sudo dnf install podman-docker
-
接下来,我们需要启用 Podman 套接字:
-
要以无 root 用户身份使用 Docker Compose,请使用以下命令:
systemctl --user enable --now podman.socket export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock echo 'export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock' >> ~/.bash_profile -
要以 root 用户身份使用 Docker Compose,请使用以下命令:
sudo systemctl enable --now podman.socket sudo export DOCKER_HOST=unix:///run/podman/podman.sock sudo echo 'export DOCKER_HOST=unix:///run/podman/podman.sock' >> /root/.bash_profile
-
-
现在 Docker Compose 准备就绪,我们需要一个 Compose 文件来进行测试。让我们首先查看一个 Compose 文件:

图 11.2 – Portainer 的 Compose 文件
在 docker-compose.yml 文件中,我们定义了如何希望 Docker(或在本例中为 Podman)运行多容器应用程序。在这个 docker-compose.yml 文件中,我们定义了 Podman 要创建的服务和卷,并根据我们的喜好配置了服务的各项参数。
信息
要全面了解整个 Compose 规范,请参见 docs.docker.com/compose/compose-file/。
-
现在,让我们测试一下,看看 Docker Compose 是否可以正常工作。将 Compose 文件的内容保存到名为
docker-compose.yml的文件中。 -
使用终端,将当前目录切换到保存
docker-compose.yml文件的目录,然后运行以下命令:http://127.0.0.1:9000.
恭喜,您现在正在使用 Podman 和 Docker Compose。
使用 Pod 管理堆栈
通过堆栈管理保持一切有序,并为 Kubernetes 做准备。
Podman 支持 Docker 中不存在的概念。一个重要的概念是 Pod——我想这也是 Podman 这个名字的来源... Podman = Pod 管理器。在本教程中,您将学习如何通过使用 Pod 管理堆栈来保持一切有序。我们将通过使用 Pod 来实现这一功能。Pod 由一个或多个容器组成。由于 Pod 是您可以在 Kubernetes 中创建和管理的最小可部署单元,因此熟悉 Pod 将帮助您弥合容器和 Kubernetes 之间的差距。
准备中
我们需要以下内容:
-
Oracle Linux
-
Podman
-
Docker Compose
如何操作...
在我们跳入食谱之前,我们首先应该多讨论一下 pods。如前所述,pods 由一个或多个容器组成。pods 将始终包含一个infra容器,默认情况下基于k8s.gcr.io/pause镜像。infra容器基本上什么也不做,只是睡眠——这确保即使在空闲时,容器仍然运行,并且它持有来自内核的端口绑定、命名空间和 cgroups。一旦 pod 创建,分配给infra容器的属性就不能更改。重要的是要记住,任何需要暴露的端口必须在 pod 初次创建时完成。
在 pod 外部存在一个conmon(容器监控)实例,负责监视容器的主进程。每个容器都有自己独立的 conmon 实例。
下图提供了构成 pod 的架构概述。

图 11.3 – pod 的架构概述
下面是与 pods 相关的 Podman 命令:
Manage pods
Description:
Pods are a group of one or more containers sharing the same network, pid and ipc namespaces.
Usage:
podman pod [command]
Available Commands:
clone Clone an existing pod
create Create a new empty pod
exists Check if a pod exists in local storage
inspect Displays a pod configuration
kill Send the specified signal or SIGKILL to containers in pod
logs Fetch logs for pod with one or more containers
pause Pause one or more pods
prune Remove all stopped pods and their containers
ps List pods
restart Restart one or more pods
rm Remove one or more pods
start Start one or more pods
stats Display a live stream of resource usage statistics for the containers in one or more pods
stop Stop one or more pods
top Display the running processes of containers in a pod
unpause Unpause one or more pods
从前面的命令可以看到,你可以使用 Podman CLI 来创建 pod 并在 pod 内运行你的容器。
手动创建 pod
假设我们想要在 pod 内部署 Wiki.js。Wiki.js 是一个开源的 Wiki 软件,建立在 Node.js 上,并依赖于数据库后端。换句话说,我们希望 pod 看起来像这样:

图 11.4 – Wiki.js pod 的架构
我们可以按照以下步骤手动构建这个 pod:
-
第一步是创建一个 pod。在我们这样做时,需要确保配置端口映射,以允许进入端口
3000。我们将使用podmanpod命令来实现:--pod tag:--pod 标签确保该容器在与数据库相同的 pod 内运行:
http://127.0.0.1:3000/.
自动创建 pod
Podman 允许你通过命令行界面手动创建 pods,但 Podman 的另一个酷功能是它原生支持 Kubernetes 清单。由于 pods 是你可以在 Kubernetes 中创建和管理的最小可部署单元,这意味着在 Podman 中部署 Kubernetes 清单将默认创建 pods。
编写完整的 Kubernetes 清单超出了本食谱的范围,但我将向你展示如何使用 Podman 自动生成 Kubernetes 清单,并随后使用该清单将容器部署到 pods 中。由于我们在前面的食谱中刚刚学习了如何使用 Compose 文件,所以我们将在这里再次利用它们,然后通过将它们转换为 Kubernetes 清单来增强它们:
- 首先要做的是从 Compose 文件部署容器。对于本食谱,我们将从 Wiki.js 的 Compose 文件开始。

图 11.5 – Wiki.js 的 Compose 文件
Wiki.js 需要两个容器,一个用于应用程序本身,另一个是 PostgreSQL 数据库。
-
现在我们有了 Compose 文件,接下来我们使用 Docker Compose 部署容器:
wikijs to change to Started. -
一旦容器运行,验证一切是否正常,可以通过浏览器访问 http://127.0.0.1:3000 进行检查。
-
如果你看到了 Wiki.js 设置界面,说明一切正常。此时,我们将从刚刚启动的两个容器生成一个 Kubernetes 清单(名为
wikijs.yaml):Podman generate kube -s -f wikijs.yaml wikijs wikijs-db -
现在 Kubernetes 清单已生成,让我们关闭刚刚启动的容器:
Docker-compose down podman play kube to bring up the containers in a pod using the Kubernetes manifest, but before we do that, we need to fix one of the hostnames specified in the environment variables.The reason we need to do that is the name of the pod is appended to the name of every container running within the pod. So instead of our database container being called `wikijs-db`, it will be called `wikijs-pod-wikijs-db`. If you look at the manifest, you’ll see that `wikijs` is configured to hook up to a database container called `wikijs-db`, so we need to update the value of `DB_HOST` and change it to `wikijs-pod-wikijs-db`.You can do this reliably by using the `yq` command. If you don’t have `yq` installed on your computer, no worries, just use a `yq` container:Podman run –rm -v ${PWD}:/workdir docker.io/mikefarah/yq e -i '(select(.kind == "Pod").spec.containers[] | select(.name == "wikijs" ).env[] | select(.name == "DB_HOST")).value = "wikijs-pod-wikijs-db"' wikijs.yaml
注意
请参考创建方便实用的工具容器一节,了解如何将容器用作工具。
-
一旦你修正了
DB_HOST值,运行以下命令:podman play kube wikijs.yaml -
验证 Pod 是否正在运行:
podman pod ls podman ps -ap最后,继续访问 http://127.0.0.1:3000。
容器化数据库
本节讨论了使用容器化数据库的最佳实践。
准备工作
我们将需要以下资源:
-
Oracle Linux
-
Podman
如何执行…
容器使数据库成为日常应用部署中更容易接受的部分。本节讨论的内容不多,但有一些关于容器化数据库的最佳实践,了解这些将非常有帮助。
做一件事,只做一件事
正如容器的核心原则是“做一件事,只做一件事”,同样的原则也适用于容器化数据库。这是什么意思呢?首先,你可能会倾向于启动一个容器化数据库,然后在该数据库中创建多个模式和/或多个数据库。假设你有几个需要 MySQL 数据库的应用程序,那么让一个单独的 MySQL 数据库容器包含每个容器化应用程序的不同数据库模式似乎是个好主意……像这样:

图 11.6 – 使用容器化数据库时不应做的事
这种架构的问题在于它没有很好地遵循“做一件事,只做一件事”的原则。相反,我建议为每个应用所需的数据库启动一个独立的容器。为容器命名时,使其与应用程序相辅相成——像这样:

图 11.7 – 更好的使用容器化数据库的方法
例如,假设你有一个需要数据库的 WordPress 容器。在这种情况下,如果你将你的 WordPress 容器命名为 wordpress01,那么你应该将 MySQL 容器命名为 wordpress01-db。为每个要运行的数据库设置单独的容器会使排查问题变得更容易,而且这种做法还会作为你部署应用程序时更可靠的架构模型。如果你需要停用一个容器化的数据库,那么你只会影响一个应用程序,而不是所有应用程序(如果你选择将多个数据库运行在同一个容器中)。
数据存储
持久化数据是你在容器中运行数据库时需要处理的一个问题。在 Podman 中,你有两个主要选项:卷(volumes)和绑定挂载(bind mounts)。使用卷时,Podman 会通过其内部的卷管理系统将数据写入磁盘,从而管理数据库的存储。而使用绑定挂载时,你需要指定主机系统上的位置,并将其挂载到容器中。两种选择都可以,通常来说,卷更容易一些,因为用户的配置要求较少,但缺点是数据可能在主机系统中更难找到。此外,卷有可能会因不小心使用 podman volume prune 命令而被删除。因此,对于演示或快速测试,我喜欢使用卷,但对于真正重要的持久化数据,我更倾向于使用绑定挂载。
创建卷非常简单。Podman 提供了几种创建卷的方式。你可以通过 podman volume create [NAME] 命令从命令行手动创建卷。你也可以让 Podman 自动为你创建卷,因为它在创建容器时可以自动创建卷。如果你指定名称,Podman 可以创建一个命名卷;例如,运行 podman run -v my_data:/var/lib/mysql mysql:8-oracle 将会创建一个名为 my_data 的卷。如果你省略了 -v my_data:/data 参数,而运行 podman run -it oraclelinux:8,Podman 也会创建一个匿名卷。
如果你想使用绑定挂载,只需要指定挂载在主机系统上的位置。例如,如果你希望将数据存储在 /mnt/hdd/podman/volumes/ 目录中,只需将该目录指定为源位置。我更倾向于将我的卷位置设置为名为 VOLUME_DIR 的环境变量,这样我可以通过 ${VOLUME_DIR} 来引用它。然后,在我指定在容器中创建绑定挂载时,只需使用 podman run -v ${VOLUME_DIR}/wordpress:/var/lib/mysql mysql:8-oracle。这将确保我的所有数据都存储在系统上一个可预测的位置,并且每个容器在该路径中都有自己的专用文件夹。
初始化脚本
大多数容器化的数据库都提供了一种便捷的方式来执行初始化设置后的脚本,这非常实用。这通常是通过允许用户将包含 .sql 和/或 .sh 文件的主机目录挂载到容器的 /docker-entrypoint-initdb.d 目录来实现的。脚本通常按字母顺序执行,因此可以通过添加带数字前缀的文件名来轻松控制顺序,例如:01_users.sql,02_permissions.sql,03_hostname.sh 等等:
-
MySQL 数据库:
MySQL 数据库支持在以下挂载点运行
*.sh和*.sql脚本:*.sh, *.sql, and *.sql.gz scripts in the following mount points:*.sh 和 *.js 脚本位于以下挂载点:
*.sh and *.sql scripts in the following mount points:* `/opt/oracle/scripts/setup`: Post-setup scripts* `/opt/oracle/scripts/startup`: Post-startup scripts* `/docker-entrypoint-initdb.d`: Symbolic link representing the aforementioned directories
控制启动顺序
使用 Compose 文件,您可以通过使用条件属性来控制容器的启动顺序。一种确保数据库启动并正常运行(并且准备好接受连接)的好方法是配置数据库的健康检查。一旦健康检查成功,数据库容器将变为健康状态。需要数据库的应用程序可以配置为在数据库容器进入健康状态之前不会启动。这可以通过使用 depends_on 选项来实现。
如果您想为 PostgreSQL 数据库添加健康检查,您可以使用以下配置:
healthcheck:
test: pg_isready
start_period: 5s
interval: 5s
timeout: 5s
retries: 55
然后,对于应用程序,您只需指定服务名称(在此示例中为 wikijs-db):
depends_on:
wikijs-db:
condition: service_healthy
当这些选项配置正确时,您将不再看到应用程序尝试连接未准备好的数据库时出现的重复连接失败,因为应用程序容器在数据库容器变为健康之前根本不会启动。
将一切联系起来
现在我们已经讨论了这些数据库最佳实践,是时候将它们与 Compose 文件结合起来,部署一个 WordPress 网站了。WordPress 需要一个 MySQL 数据库,因此在 Compose 文件中,我们部署了两个服务:wordpress01(WordPress 内容管理系统)和 wordpress01-db(MySQL 数据库)。

图 11.8 – 应用程序及其数据库的可视化拓扑
在 wordpress01 服务中,我们可以轻松地通过数据库服务的名称标签引用数据库主机——这一切都要归功于 Podman dns 插件所支持的出色名称解析功能。你还会看到,我们在 wordpress01-db 服务上使用了健康检查,确保在 mysqladmin 能从数据库服务获取响应之前,wordpress01-db 不会被标记为健康状态,同时 wordpress01 配置了 depends_on,这样它不会在 wordpress01-db 处于健康状态之前启动。由于这个示例旨在快速验证概念部署,我选择使用了一个命名卷而非绑定挂载来存储数据,但你也可以看到我们使用了绑定挂载来存储初始化脚本。最后,注意我们使用了一个专用的数据库容器(wordpress01-db),它与应用容器(wordpress01)互为补充。这个 WordPress 网站的 Compose 文件内容可能如下所示:

图 11.9 – WordPress 的 Compose 文件
请尝试自行部署这个设置。你可以使用 podman logs -f wordpress01 查看应用程序的日志,确保它在第一次尝试时成功连接到数据库。接下来,让我们使用 Docker Compose 创建并启动容器。你可以像我们之前在 Docker Compose 配方中描述的那样,通过进入存放 docker-compose.yml 文件的目录并运行以下命令来完成:
docker-compose up -d
Buildah 和 Skopeo – Podman 的得力伙伴
本章标题提到了 Podman 和它的朋友们。直到此时,你可能已经注意到我们并没有太多讨论 Podman 的朋友们。Podman 带来了几个伙伴,帮助你处理所有容器管理需求。这些 Podman 的伙伴分别是 Buildah 和 Skopeo。
Podman 主要专注于运行容器,而 Buildah 专注于构建容器,Skopeo 专注于处理镜像并将其传输到远程容器注册表或从远程注册表传输镜像。
准备工作
我们将需要以下内容:
-
Oracle Linux
-
Podman
-
Buildah
-
Skopeo
如何实现…
在本配方中,我们将探索 Buildah 和 Skopeo 的基本用法,展示这两款 Podman 的好伙伴如何提升你在处理容器时的体验和工作流。
使用 Buildah 构建容器镜像
虽然 Podman 可以用于基本的容器镜像构建,但 Buildah 是一款专注于构建符合 OCI 标准的镜像的工具。Buildah 不仅可以用来从 Containerfile 或 Dockerfile 构建镜像,还能非常简洁地修改现有的容器镜像。
首先,先了解一下如何使用 Buildah 从 Containerfile 构建镜像。使用 Podman 时,我们通过podman build -t <image_name>.命令来构建镜像。当我们调用 Podman 执行构建时,它实际上是使用 Buildah 的一部分功能来构建镜像。要直接使用 Buildah,我们只需使用稍微不同的命令。例如,假设我们有一个名为Containerfile的文件,其内容如下:
FROM oraclelinux:8
RUN dnf install -y rhn-setup yum-utils && dnf clean all
ENTRYPOINT ["/bin/bash"]
为了使用 Buildah 构建镜像,你需要输入buildah bud -t <image_name>。在这个示例中,我将镜像命名为ol-repo-sync。现在开始吧:
buildah bud -t ol-repo-sync .
在这种情况下,结果与使用 Podman 构建镜像是相同的。Buildah 真正的优势在于它能够对工作容器进行修改,并且还可以从工作容器创建新镜像。
为了简化本教程,我们将复制Containerfile中指定的内容,除了不直接使用Containerfile,而是通过 Buildah 按需进行操作。因此,我们将对一个现有的 Oracle Linux 8 镜像进行更改,并将其存储为一个新镜像。首先,我们将运行buildah from来加载一个工作容器到 Buildah:
buildah from oraclelinux:8
这将返回以下输出:
oraclelinux-working-container
这告诉我们新创建的工作容器的名称。现在我们已经有了一个准备好的 Buildah 容器,接下来让我们给它添加一些包。在这个示例中,我们将添加之前Containerfile中指定的相同包。请输入以下命令:
buildah run oraclelinux-working-container dnf -y install rhn-setup yum-utils
buildah run oraclelinux-working-container dnf clean all
你将看到 DNF 包管理器的工作过程,完成后,你将得到一个基于 Oracle Linux 的基础镜像,以及我们通过buildah的run命令安装的新软件包。
最后,我们需要定义该容器的entrypoint。我们可以通过使用buildah的config命令来实现:
buildah config --cmd '' oraclelinux-working-container
buildah config --entrypoint '["/bin/bash"]' oraclelinux-working-container
注意
在撰写本文时,Buildah 似乎存在一个 bug,会填充cmd值,除非我们显式地先给它一个空值。这可能导致生成镜像的行为异常。根据 Buildah 的文档,设置entrypoint而不为cmd定义值应该会清除cmd中已分配的任何值,但在我测试 Buildah 版本1.29.1时并非如此。为了解决这个问题,我发现最好在定义镜像的入口点之前,先显式地将cmd设置为空值。
为了从这个工作容器创建新镜像,我们需要做的就是运行buildah commit命令。在这个示例中,我们将镜像命名为ol-repo-sync-buildah,以便与之前提到的Containerfile构建的镜像进行比较:
buildah commit --rm oraclelinux-working-container ol-repo-sync-buildah
现在,我们已经使用 Buildah 创建了镜像,我们可以分别对ol-repo-sync和ol-repo-sync-buildah运行podman inspect,并看到这两个镜像几乎是一样的。还要注意两个镜像的大小。我们可以通过使用buildah的images命令来检查:
$ buildah images
输出将如下所示:

图 11.10 – Buildah 镜像列表示例
这一次,我们可以看到镜像大小稍微小了一些,因为我们利用了主机系统中的 DNF 包管理器,通过 buildah mount 命令将软件包安装到容器中。显然,大小的差异不大,但这开始显示出 Buildah 在容器管理中带来的好处。
正如你所看到的,Buildah 使我们能够对容器镜像进行精细化控制,它可以成为一个非常强大的助手,因为它允许我们从主机系统临时挂载文件和软件包到容器中,从而执行操作,而无需实际将这些文件和软件包安装到容器中。最终,你能够实现更精简的容器镜像。此外,Buildah 还提供了通过命令行脚本化构建容器镜像的能力。当与自动化和/或 CI/CD 流水线结合使用时,这非常强大。可能需要一些时间来掌握如何使用 Buildah 构建容器镜像,但如果你坚持下去,结果可能会很有价值。
使用 Skopeo 检查远程镜像
你还记得我们讨论过在检查镜像之前需要先拉取镜像吗?这一点在 创建实用容器 配方中有讲到。那么,如果我告诉你,我们可以利用 Skopeo 检查那些存在于远程仓库中的镜像,而不需要先将它们拉取到本地机器上呢?这正是我们在这里要做的事情。
在 创建实用容器 配方中,你被要求运行以下命令:
podman pull docker.io/pandoc/core
podman image inspect pandoc/core | podman run -i --rm stedolan/jq -r '.[].Config.Entrypoint[]'
这是因为如果你尝试在没有先将容器拉取到本地机器的情况下运行podman image inspect,你将看到以下错误:
错误:检查对象:pandoc/core: 镜像未知 Skopeo 允许我们直接处理存在于远程仓库中的容器镜像。为了说明这一点,让我们首先删除本地的 pandoc/core 容器镜像:
podman image rm pandoc/core
现在镜像已经从本地机器中删除,让我们使用 Skopeo 直接从其远程仓库检查该镜像:
skopeo inspect --config docker://docker.io/pandoc/core:latest | podman run -i --rm stedolan/jq -r '.config.Entrypoint[]'
很酷吧?我注意到 JSON 路径有一些小的变化,这影响了我如何构建 jq 命令来正确提取我想要的入口点,但总的来说,利用 Skopeo 检查远程镜像提供的信息与通过 Podman 首先拉取镜像后检查得到的信息相同。尤其是在处理较大的镜像和/或需要在自动化 CI/CD 流水线中检查镜像时,我确实看到了使用 Skopeo 的优势。
使用 Skopeo 处理远程镜像
Skopeo 还可以用于将容器镜像从一个远程容器仓库转移到另一个仓库,而无需先将其拉取/下载到本地。语法类似于标准的 Linux cp 命令。在 cp 中,我们使用 cp <source> <destination>,而在 Skopeo 中,我们使用 skopeo copy <source> <destination>。举个例子,如果我们想要将 pandoc/core 镜像从一个注册表复制到另一个注册表,只需运行以下命令:
skopeo copy docker://docker.io/pandoc/core:latest docker://example.com/pandoc/core:latest
同样,我们还可以通过使用 containers-storage 前缀将镜像转移到本地的 Podman 容器存储中,例如:
skopeo copy docker://docker.io/pandoc/core:latest containers-storage:pandoc/core:latest
此外,如果我们想指定其他位置,可以简单地使用 dir 前缀,后跟路径。但在这种情况下,请确保路径已经存在,并省略任何与 Linux 文件系统不兼容的字符,例如:
mkdir -p $(pwd)/pandoc/core
skopeo copy docker://docker.io/pandoc/core:latest dir:$(pwd)/pandoc/core
最后,Skopeo 还可以用于从远程仓库或本地容器存储中删除镜像。只需运行以下命令:
skopeo delete containers-storage:pandoc/core:latest
第十二章:探索 Ansible 的世界
在本章中,我们将通过几个食谱来扩展你对安装Oracle Linux 自动化管理器(OLAM)、管理其基础设施、创建剧本、最大化这些剧本的理解,并帮助你了解 OLAM 的功能。每个食谱都会让你看到自动化能实现的完整范围;从补丁管理到部署完全功能的混合云环境,OLAM 能改变你对计算的思维方式,打开你通向一个新世界的门,那里充满了“重复与清洗”的操作。以下是自动化可以简化的一个小子集的接触点。

图 12.1 – 自动化接触点
在本章中,以下食谱将涵盖 OLAM 平台的安装、配置和可用性:
-
安装 OLAM
-
从基础开始快速配置和管理 OLAM
-
OLAM 不是幻想足球,但它们都使用剧本
-
控制补丁混乱
-
超越自动化
-
设置后就忘记它
安装 OLAM
自从人类出现以来,我们作为一个物种,一直在努力让事情变得更简单、更快速、更高效。然而,我敢肯定我们大多数人都听过父母说过:“永远不要走捷径”,或者“我小时候得在雪地里单腿走路上学,还是上坡,两边都要走。”这些轶事从未改变;它们随着我们年纪的增长而演变,我们也试图将智慧传给下一代。好吧,如果我告诉你,你可以一举两得呢?自动化是计算机技术的进化,是可重复任务的自动化。当然,我们不能自动化所有事情,有些任务不值得去自动化,因为它们不是可重复的,或者某些因素变化到自动化会使得流程崩溃的程度。
自动化的字典定义是“应用技术、程序、机器人或流程以最小的人工输入实现预定的结果。” 注意流程——这是我们改变、执行或改变结果的过程。自动化就是这种过程的改变。我们可以自动化应用程序的安装,比如安装 Microsoft Office 或者杀毒软件;自计算机时代开始,我们就已经在自动化这些过程了。现在,我们将自动化带入了一个新的层级。例如,Red Hat 的自动化版本 Ansible Tower 就是如此。Ansible 和 OLAM 都是基于 AWX 构建的,AWX 是一个强大且现代化的 Web 用户界面和 API,能够让你轻松管理组织的 Ansible 剧本、库存、保险库和凭证。通过 AWX,你可以简化自动化流程,并简化基础设施管理任务,所有这些都能通过一个简单易用的界面进行操作。例如,假设某大学的计算机科学教授每周都需要准备实验室;这个实验室有 50 名学生,每个学生都需要一个独立的虚拟实验室来参与。教授肯定不想每周都坐在那里重建实验环境。通过 Ansible,一个剧本(不是足球战术书,而是一个大纲和功能需求)可以编写,用来执行一系列命令,自动化创建实验环境。通过创建这个剧本,工程师可以更改一些变量,调整虚拟机数量、内存、vCPU 或者其他资源或应用程序的使用。实际上,Ansible 和 Ansible 剧本极大地缩短了创建实验环境的过程,使其变得可重复,从而节省了教授每周重建的时间。
OLAM 是一款自动化套件,作为开源的 Linux 发行版(Oracle Linux)捆绑发布,基于 AWX 和 Ansible Tower。OLAM 是一个可配置的自动化平台,非常类似于 Ansible,具有创建、管理和更改剧本的能力。OLAM 安装时附带了一个 UI,如你将在后续食谱中看到的,还有一个 CLI。UI 和 CLI 都是完全功能的,并且具备 Ansible Tower 的所有细致功能,并且提供免费使用,配合高级支持订阅。OLAM 可以如以下图所示,用来创建剧本,自动化多个领域的流程,从本地虚拟化农场和 HCI 环境,到应用程序部署,再到多个云平台和混合云分发的应用。

图 12.2 – 自动化剧本层级
在本指南中,我们将安装 OLAM。与任何应用程序安装一样,我们需要准备一个基础环境来安装应用程序——当然,这里是 Oracle Linux 8。我们需要准备并配置该操作系统,虽然本书中的前一个指南已经详细介绍了这一部分内容,但我们不会在此重复。然而,建议您安装带 GUI 的操作系统。
准备中
我们将在 Oracle Cloud Infrastructure(OCI)中作为虚拟机安装 OLAM。请参考 第三章 和 第四章 了解如何浏览和配置 OCI 虚拟机。接下来,我们将简要介绍 VM 创建的步骤:
- 转到 OCI 实例,以为 OLAM 创建主机实例:

图 12.3 – 创建 VM 实例
- 您需要通过点击 创建实例 来创建一个实例:

图 12.4 – 实例创建
- 您可以为实例命名,并选择一个隔离的区域来托管 VM:

图 12.5 – 为实例命名
- 在命名 VM 后,您可以选择您希望托管 VM 的位置或 可用性域(AD)。我们使用的 AD 是 OCI 的默认 AD:

图 12.6 – 可用性域
- 我们为 VM 配置了 8 GB 的 RAM 和 2 个 vCPU,因此我们需要选择正确的主机配置。您可以按照以下屏幕截图编辑并更改形状:

图 12.7 – 镜像大小和形状
- 点击 更改形状 来编辑形状,并在 形状名称 下选择您的形状:

图 12.8 – VM 形状选择
- VM.Standard.E3.FLEX 形状允许您指定您的资源:

图 12.9 – VM 资源配置
- 我们将选择 8 GB 的 RAM(内存)和 2 个 vCPU。OLAM 的最低要求是 2 个 vCPU 和 4 GB 的 RAM:

图 12.10 – VM 资源选择
- 配置完 VM 资源后,您需要配置访问密钥(公钥):

图 12.11 – SSH 密钥选择
- 您可以创建、上传、粘贴密钥,或者选择不使用密钥。我们将通过选择密钥并复制粘贴密钥来进行粘贴:

图 12.12 – SSH 密钥粘贴
- 配置完密钥后,滚动到实例页面的底部,并点击 创建:

图 12.13 – VM 创建
-
创建实例后,您可以使用 SSH 以
opc用户和您的密钥访问 VM:% ssh -i sshkey_private_lab opc@193.122.148.147 The authenticity of host '193.122.148.147 (193.122.148.147)' can't be established. ED25519 key fingerprint is SHA256:nF+ilxdx0SpWZZxiFZOJFvektZc8YhBI76j1Qm64w3A. This key is not known by any other names Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '193.122.148.147' (ED25519) to the list of known hosts. Activate the web console with: systemctl enable --now cockpit.socket [opc@instance-20231213-2350 ~]$ -
添加 YUM 仓库非常简单,它使你能够在操作系统和内核级别更新、安装、卸载或修补某些方面,包括应用程序。如本章前面所提到的,你可以通过 DNF 将这些仓库添加到操作系统中,同时也可以在 GUI 界面中或安装后进行添加。无论哪种方式,你必须能够访问外部环境,这意味着我们需要能够连接到 Oracle 仓库或设置本地镜像。我们不会详细说明如何设置本地镜像,但我们会演示如何使用 DNF 添加这些仓库:
[opc@olam-test ~]$ sudo DNF -y install oraclelinux-release-el8 Ksplice for Oracle Linux 8 (x86_64) 39 MB/s | 3.2 MB 00:00 MySQL 8.0 for Oracle Linux 8 (x86_64) 38 MB/s | 3.0 MB 00:00 MySQL 8.0 Tools Community for Oracle Linux 8 (x86_64) 7.3 MB/s | 491 kB 00:00 MySQL 8.0 Connectors Community for Oracle Linux 8 (x86_64) 600 kB/s | 30 kB 00:00 Oracle Software for OCI users on Oracle Linux 8 (x86_64) 96 MB/s | 93 MB 00:00 Oracle Linux 8 BaseOS Latest (x86_64) 118 MB/s | 62 MB 00:00 Oracle Linux 8 Application Stream (x86_64) 114 MB/s | 48 MB 00:00 Oracle Linux 8 Addons (x86_64) 56 MB/s | 6.9 MB 00:00 Latest Unbreakable Enterprise Kernel Release 7 for Oracle Linux 8 (x86_64) 95 MB/s | 18 MB 00:00 Package oraclelinux-release-el8-1.0-32.el8.x86_64 is already installed. Dependencies resolved. Nothing to do. Complete!如前面的代码所示,我们正在添加多个仓库;其中大多数仓库是用于操作系统级别的补丁或安装 OLAM 所必需的。
-
所有前提条件中最重要的一点是应用程序能否看到外部环境;为了做到这一点,我们需要打开一个外部门户——换句话说,就是打开防火墙端口,如下所示:
[opc@olam-test ~]$ sudo firewall-cmd --add-port=27199/tcp --permanent success [opc@olam-test ~]$ sudo firewall-cmd --add-service=http --permanent success [opc@olam-test ~]$ sudo firewall-cmd --add-service=https --permanent success [opc@olam-test ~]$ sudo firewall-cmd --reload success [opc@olam-test ~]$ -
在打开这些端口后,我们需要启用我们刚刚使用 DNF 安装的仓库。这个步骤也可以在配置防火墙之前完成:
[opc@olam-test ~]$ sudo DNF config-manager --enable ol8_baseos_latest [opc@olam-test ~]$ -
启用该仓库后,我们需要安装并配置 OLAM 仓库,如下所示:
[opc@olam-test ~]$ sudo DNF install oraclelinux-automation-manager-release-el8 Oracle Linux 8 BaseOS Latest Oracle Linux 8 Application Stream Oracle Linux 8 Addons Truncated for size Complete! -
就像我们做的基础仓库一样,我们也需要启用 OLAM 仓库:
[opc@olam-test ~]$ sudo DNF config-manager --enable ol8_automation2 ol8_addons ol8_UEKR7 ol8_appstream -
启用更新的 OLAM 仓库后,我们需要禁用旧的仓库:
[opc@olam-test ~]$ sudo DNF config-manager --disable ol8_automation -
一旦完成这些,我们就完成了从应用程序角度来看安装 OLAM 的前提条件。然而,我们现在需要为 OLAM 准备数据库。为了做到这一点,我们需要安装并配置数据库模块。OLAM 使用 Postgres 数据库,它是基于 SQL 的。以下是安装该模块的命令:
[opc@olam-test ~]$ sudo DNF module reset postgresql Oracle Linux 8 BaseOS Latest (x86_64) 157 kB/s | 3.6 kB 00:00 Oracle Linux 8 Application Stream (x86_64) 233 kB/s | 3.9 kB 00:00 Oracle Linux 8 Addons (x86_64) 153 kB/s | 3.0 kB 00:00 Oracle Linux Automation Manager 2.0 based on the open source projects Ansib 3.1 MB/s | 644 kB 00:00 Latest Unbreakable Enterprise Kernel Release 7 for Oracle Linux 8 (x86_64) 147 kB/s | 3.0 kB 00:00 Dependencies resolved. Nothing to do. Complete! -
安装模块后,它需要启用:
[opc@olam-test ~]$ sudo DNF module enable postgresql:13 Last metadata expiration check: 0:00:54 ago on Tue 22 Aug 2023 07:12:29 PM GMT. Dependencies resolved. ============================================================================================================ Package Architecture Version Repository Size ============================================================================================================ Enabling module streams: postgresql 13 Transaction Summary ============================================================================================================ Is this ok [y/N]: y Complete! -
现在我们已经安装并启用了 Postgres 模块,接下来可以安装数据库:
[opc@olam-test ~]$ sudo DNF install postgresql-server Last metadata expiration check: 0:02:35 ago on Tue 22 Aug 2023 07:12:29 PM GMT. Dependencies resolved. ============================================================================================================ Package Arch Version Repository Size ============================================================================================================ Installing: postgresql-server x86_64 13.11-1.0.1.module+el8.8.0+21141+00b1aed9 ol8_appstream 5.6 M Installing dependencies: libpq x86_64 13.5-1.el8 ol8_appstream 198 k postgresql x86_64 13.11-1.0.1.module+el8.8.0+21141+00b1aed9 ol8_appstream 1.5 M Transaction Summary ============================================================================================================ Install 3 Packages The output has been truncated… Installed: libpq-13.5-1.el8.x86_64 postgresql-13.11-1.0.1.module+el8.8.0+21141+00b1aed9.x86_64 postgresql-server-13.11-1.0.1.module+el8.8.0+21141+00b1aed9.x86_64 Complete! -
下一步是初始化数据库。这一步为使用数据库做准备,并允许在已有数据时进行覆盖:
[opc@olam-test ~]$ sudo postgresql-setup --initdb * Initializing database in '/var/lib/pgsql/data' * Initialized, logs are in /var/lib/pgsql/initdb_postgresql.log -
在初始化之后,你需要更改密码模式以符合要求:
[opc@olam-test ~]$ sudo sed -i "s/#password_encryption.*/password_encryption = scram-sha-256/" /var/lib/pgsql/data/postgresql.conf -
现在,我们将启用数据库,如下所示:
[opc@olam-test ~]$ sudo systemctl enable --now postgresql Created symlink /etc/systemd/system/multi-user.target.wants/postgresql.service → /usr/lib/systemd/system/postgresql.service. -
启用数据库后,我们需要确保一切为 OLAM 安装做好准备,因此我们需要查看数据库的状态。以下是显示状态的命令:
[opc@olam-test ~]$ sudo systemctl status postgresql ● postgresql.service - PostgreSQL database server Loaded: loaded (/usr/lib/systemd/system/postgresql.service; enabled; vendor preset: disabled) Active: active (running) since Tue 2023-08-22 19:18:44 GMT; 23s ago Process: 46810 ExecStartPre=/usr/libexec/postgresql-check-db-dir postgresql (code=exited, status=0/SUCCES> Main PID: 46813 (postmaster) Tasks: 8 (limit: 22519) Memory: 16.9M CGroup: /system.slice/postgresql.service ├─46813 /usr/bin/postmaster -D /var/lib/pgsql/data ├─46814 postgres: logger ├─46816 postgres: checkpointer ├─46817 postgres: background writer ├─46818 postgres: walwriter ├─46819 postgres: autovacuum launcher ├─46820 postgres: stats collector └─46821 postgres: logical replication launcher Aug 22 19:18:44 olam-test systemd[1]: Starting PostgreSQL database server... Aug 22 19:18:44 olam-test postmaster[46813]: 2023-08-22 19:18:44.097 GMT [46813] LOG: redirecting log outp> Aug 22 19:18:44 olam-test postmaster[46813]: 2023-08-22 19:18:44.097 GMT [46813] HINT: Future log output w> active (running) tells you that the database is active and running, and you’re ready to start the installation of OLAM.
完成后,我们就准备进入重点内容——安装 OLAM。
如何操作…
完成前提条件后,我们可以继续进行安装。请记住,防火墙端口、安装 YUM 仓库和 Postgres 并启用它们是非常重要的。如果没有这些前提条件,你将无法继续,安装会失败:
-
安装 OLAM 的第一步是创建 AWX 用户。记住,AWX 是 OLAM 的基础,所以这一步非常重要:
[opc@olam-test ~]$ sudo su - postgres -c "createuser -S -P awx" Enter password for new role: welcome1 Enter it again: welcome1 -
现在,安装完数据库引擎后,我们将安装数据库,如下所示:
[opc@olam-test ~]$ sudo su - postgres -c "createdb -O awx awx" -
安装数据库后,我们需要编辑配置文件:
[root@olam-test ~]# vi /var/lib/pgsql/data/pg_hba.conf -
您还记得我们在定义密码变量时的步骤吗?在这里,我们在主机身份验证配置文件中标注了这些内容,在以下片段中突出显示。完成后,我们需要确保保存并退出配置:
# TYPE DATABASE USER ADDRESS METHOD # "local" is for Unix domain socket connections only local all all peer # IPv4 local connections: host all all 127.0.0.1/32 ident # IPv6 local connections: host all all ::1/128 ident # Allow replication connections from localhost, by a user with the # replication privilege. local replication all peer host replication all 127.0.0.1/32 ident host replication all ::1/128 ident 'OCI NAT Address':[root@olam-test ~]# vi /var/lib/pgsql/data/postgresql.conf
------------------------------------------------------------------------------
连接和身份验证
------------------------------------------------------------------------------
- 连接设置 -
listen_addresses = 'OCI NAT Address' – 在 ifconfig 中的 IP 地址
listen_addresses = 'localhost' # 监听的 IP 地址;
-
编辑完该文件后,请再次确保保存并退出配置。保存文件后,您需要重启 Postgres,确保所有更改已提交:
[root@olam-test ~]# systemctl restart postgresql -
在完成所有这些更改后,我总是喜欢更新所有的 YUM 仓库,并确保加载了所有的更新。为了做到这一点,我们需要更新系统。以下是用于更新仓库的 DNF 命令:
[root@olam-test ~]# DNF update -y Last metadata expiration check: 1:43:57 ago on Tue 22 Aug 2023 10:48:21 PM GMT. Dependencies resolved. ============================================================================================================================================ Package Architecture Version Repository Size ============================================================================================================================================ The output has been truncated for length. -
更新完所有 YUM 仓库后,快速查看一下前面的代码,并注意我们在前一节中添加并启用的所有仓库。您需要重启虚拟机,以确保所有更改已生效:
[root@olam-test ~]# reboot -
以下是安装 OLAM 的命令和输出:
[root@olam-test ~]# DNF -y install ol-automation-manager Last metadata expiration check: 1:52:46 ago on Tue 22 Aug 2023 10:48:21 PM GMT. Dependencies resolved. ============================================================================================================================================ Package Architecture Version Repository Size ============================================================================================================================================ Installing: ol-automation-manager x86_64 2.0.1-3.el8 ol8_automation2 41 M Installing dependencies: The output has been truncated for length [root@olam-test ~]# vi /etc/redis.conf -
现在,您需要退出 root 用户,这是非常重要的;您不能以 root 用户身份继续进行 AWX:
awx to continue the installation:[opc@olam-test ~]# su -l awx -s /bin/bash
-
由于 OLAM 运行在云原生环境中,我们使用 Podman 来协调调优和创建该架构。以下是使用 Podman 最新版本迁移并在虚拟机中创建该环境的命令:
[awx@olam-test ~]$ podman system migrate -
现在,我们将通过运行以下命令,从 Oracle Docker 注册表拉取 OLAM 的最新版本:
[awx@olam-test ~]$ podman pull container-registry.oracle.com/oracle_linux_automation_manager/olam-ee:latest Trying to pull container-registry.oracle.com/oracle_linux_automation_manager/olam-ee:latest... Getting image source signatures Copying blob 1ca7c848b9e5 done Copying blob a2cd216732a7 done Copying blob 13ec27f79a4b done Copying blob 0b5aff3da93f done Copying config b764e737f4 done Writing manifest to image destination Storing signatures -
现在,我们要将环境迁移到容器中:
[awx@olam-test ~]$ awx-manage migrate Operations to perform: Apply all migrations: auth, conf, contenttypes, main, oauth2_provider, sessions, sites, social_django, sso, taggit Running migrations: The output has been truncated for length. -
现在,我们要创建我们的用户:
[awx@olam-test ~]$ awx-manage createsuperuser --username admin --email bubba@nobody.com Password: Password (again) -
在创建好我们的环境和用户后,我们需要配置该环境。这将写入加密密钥,并注释位置、地址、主机名和其他标识符。然而,虚拟机特定的数据是必需的:
[awx@olam-test ~]$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/tower/tower.key -out /etc/tower/tower.crt Generating a RSA private key ....................................+++++ ...............................................................................+++++ writing new private key to '/etc/tower/tower.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:01 State or Province Name (full name) []:Florida Locality Name (eg, city) [Default City]:Miami Organization Name (eg, company) [Default Company Ltd]: Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname) []:olam-test awx user now and su to root:[awx@olam-test ~]$ exit
[awx@olam-test ~]$ sudo su - root
-
现在,我们要设置我们的 Web 服务器。这是通过一个典型的、广泛分发的预配置文件来完成的,如下所示:
cat << EOF | sudo tee /etc/nginx/nginx.conf > /dev/null > user nginx; > worker_processes auto; > error_log /var/log/nginx/error.log; > pid /run/nginx.pid; > > # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic. > include /usr/share/nginx/modules/*.conf; > > events { > worker_connections 1024; > } > > http { > log_format main '$remote_addr - $remote_user [$time_local] "$request" ' > '$status $body_bytes_sent "$http_referer" ' > '"$http_user_agent" "$http_x_forwarded_for"'; > > access_log /var/log/nginx/access.log main; > > sendfile on; > tcp_nopush on; > tcp_nodelay on; > keepalive_timeout 65; > types_hash_max_size 2048; > > include /etc/nginx/mime.types; > default_type application/octet-stream; > > # Load modular configuration files from the /etc/nginx/conf.d directory. > # See http://nginx.org/en/docs/ngx_core_module.html#include > # for more information. > include /etc/nginx/conf.d/*.conf; > } awx user:[root@olam-test ~]# sudo su -l awx -s /bin/bash
[awx@olam-test ~]$ awx-manage provision_instance --hostname=10.0.0.193 --node_type=hybrid
成功注册实例 10.0.0.193
(已更改:True)
-
我们将通过运行以下命令来注册默认环境:
[awx@olam-test ~]$ awx-manage register_default_execution_environments 'OLAM EE (latest)' Default Execution Environment registered. 'OLAM EE (latest)' Default Execution Environment updated. Control Plane Execution Environment registered. (changed: True) [awx@olam-test ~]$ awx-manage register_queue --queuename=controlplane --hostnames=10.0.0.193 Creating instance group controlplane Added instance 10.0.0.193 to controlplane (changed: True) controlplane user to root, if you’re not already root, again here:[root@olam-test ~]# vi /etc/receptor/receptor.conf
- node:
id: 10.0.0.44
-
log-level: debug
-
tcp-listener:
端口:27199
- work-signing:
privatekey: /etc/receptor/work_private_key.pem
tokenexpiration: 1m
- work-verification:
publickey: /etc/receptor/work_public_key.pem
- tcp-peer:
address: 100.100.253.53:27199
redial: true
- tls-server:
name: mutual-tls
cert: /etc/receptor/certs/awx.crt
key: /etc/receptor/certs/awx.key
requireclientcert: true
clientcas: /etc/receptor/certs/ca.crt
- control-service:
service: control
filename: /var/run/receptor/receptor.sock
- work-command:
worktype: local
command: /var/lib/ol-automation-manager/venv/awx/bin/ansible-runner
params: worker
allowruntimeparams: true
verifysignature: true
-
现在,我们将通过运行以下命令来启用 OLAM 服务;这将开始访问 OLAM 的过程:
[root@olam-test ~]# systemctl enable --now ol-automation-manager.service Created symlink /etc/systemd/system/multi-user.target.wants/ol-automation-manager.service → /usr/lib/systemd/system/ol-automation-manager.service. -
现在,我们希望通过运行以下命令来预加载我们的数据。一旦完成,我们就可以登录到 OLAM 实例,安装将会完成:
https://'public_IP'. You can find this in your OCI console, within your VM configuration. You will be asked to enter your password twice. Once this is done, your OLAM installation is complete and your console is configured.

图 12.14 – OLAM 密码创建
从基础开始快速配置和管理 OLAM
管理 OLAM 可以通过 UI 或 CLI 完成。在这里,我们将通过 UI 操作。可以这样理解——OLAM 是一个平台,你将在其上管理你的项目、库存、playbooks 和自动化,无论是通过 UI 还是 CLI。项目位于最顶层,层级结构从项目开始,向下延伸至 playbooks,最终触发自动化。无论使用 UI 还是 CLI,你都可以对你的关键环境进行精细控制。

图 12.15 – OLAM 层级结构
本指南将带你了解如何在 OLAM 环境中查看、理解和执行基本命令,创建项目,管理组以及添加到库存中。
准备就绪
如下图所示,并在之前的步骤中,你需要登录到你的 OLAM 环境:

图 12.16 – OLAM 首次登录
OLAM 层级结构中的第一个也是最高层级是项目。你必须创建一个项目,它将作为该层级中所有 playbooks 和自动化的宿主。你可以有多个项目,分配给不同的资产和库存。接下来让我们看看如何在以下步骤中完成这项操作:
- 要创建一个项目,你需要进入 资源 标签页并导航到 项目:

图 12.17 – OLAM 项目选项
- 一旦进入 项目,点击 添加。这将打开一个窗口,在这里你可以定义项目。

图 12.18 – 添加项目
- 一旦打开你的项目配置页面,你需要规划你的项目外观。在这个例子中,我们正在创建一个测试环境,并且已为实验室用途设置了两个独立的测试节点。默认设置用于 playbook 目录和项目路径。

图 12.19 – 项目变量
- 配置完项目后,你需要保存这些信息,这将带你进入一个显示已完全配置项目的屏幕。

图 12.20 – 项目配置页面
- 配置好项目后,你需要配置凭证,方式与项目类似,如下所示:

图 12.21 – 凭证选项
- 下一步是添加你
opc用户和机器的凭证数据。

图 12.22 – 凭证添加
- 你需要复制或创建一个密钥,用于访问机器。将其粘贴到SSH 私钥部分,并输入你的密钥名称和用户。

图 12.23 – 凭证变量和 SSH 私钥
- 保存凭证后,配置好的凭证将会显示,如下所示:

图 12.24 – 凭证配置页面
- 接下来,你需要添加一个库存。记住,已经创建了两个测试虚拟机,在这个示例中,它们将作为测试环境使用。选择库存,然后按照接下来的步骤在选择后定义库存。

图 12.25 – 库存选项
- 点击添加来创建并定义你的新库存:

图 12.26 – 添加库存
- 你将使用默认组织定义库存名称:

图 12.27 – 库存变量
- 配置好的测试库存如下所示:

图 12.28 – 库存配置页面
- 创建库存后,我们需要向其中添加主机。这将涉及添加可以进行自动化测试的机器。在菜单中选择主机,然后从列表中选择主机,如下所示:

图 12.29 – 主机选项
- 然后,你可以添加新的主机,如下所示:

图 12.30 – 添加主机
- 以下是创建新主机的配置页面;确保选择你刚创建的库存:

图 12.31 – 主机变量
- 确保保存你的配置。完成后,主机配置将会显示。

图 12.32 – 主机配置页面
- 你需要重复此操作,因为这里只有一台主机被创建;为了展示多样性,必须创建两台主机以模拟一个工作环境。

图 12.33 – 主机
OLAM 的设置和基本配置已经完成。在接下来的几项操作中,我们将回顾如何运行战术手册并进一步配置 OLAM。在下一个操作中,我们将通过对创建的两台测试服务器运行命令来测试最终配置。
如何执行……
- 在添加了这两台主机后,你可以对它们执行一组命令进行测试。要运行这些命令,你需要返回到主机并点击运行命令:

图 12.34 – 在主机上运行简单命令
- 你将选择要运行的模块,在这种情况下,
uptime是作为变量参数。这个命令在一个 shell 环境中运行,就像你在任何 Linux 环境中运行它一样。

图 12.35 – 命令变量
- 我们需要定义我们希望运行的环境,即OLAM EE(最新版本)。

图 12.36 – 执行环境
- 这些是我们之前在两个测试节点上使用的凭据:

图 12.37 – 凭据选择
- 以下是测试的输出;如你所见,
olam-target-1和olam-target-2的每个环境的正常运行时间都列出在内。

图 12.38 – 命令运行输出
OLAM 不是幻想足球,但它们都使用战术手册
我们大多数人都知道幻想足球,在其中我们跟随球队,选拔球员,并对赢家和输家进行下注。嗯,在这里我们并没有下注什么,除了我们的环境是否能够正常工作,但我们确实使用了一种叫做战术手册的东西。可以把战术手册看作是足球教练用来训练球队的工具;这是相同的概念。我们在预定义一个环境或事件,并且以编程的方式构建它,使其按照我们指定的方式行为,创建或更改我们所定义的环境,甚至回收资源(从已废弃的环境中回收 CPU、RAM 和磁盘空间)。无论我们在 OLAM 的约束下定义什么,我们都可以执行。
为了创建我们的战术手册,我们需要弄清楚谁、什么、哪里、何时,甚至可能是为什么:
-
Who – 我们针对哪些资源组?
-
What – 我们针对什么样的资源?是虚拟机?物理机?
-
Where – 这些资源位于哪里?是在 CSP、虚拟机农场,还是物理服务器上?
-
When – 我们何时执行这个环境?是基于事件的(例如,当日志填满
/tmp时我们清理磁盘空间)? -
为什么 – 为什么我们要针对这个环境?是数据库服务器磁盘空间满了,网页服务器过度利用,还是某个事件反复发生影响了系统?
一个剧本可以通过多种方式触发,在 AIOps 中,我们关注触发条件;这些可以是 SNMP Trap、基于代理的触发条件(例如前面提到的磁盘已满),或来自平台的定向事件。让我们回到其他四个变量——谁、什么、哪里和何时;谁是哪个环境,什么是使用了哪些机器,哪里是环境的地点,何时是这个剧本将运行的时间,是否会在特定时间触发或运行。这些都可以逐步定义。

图 12.39 – 剧本和它们的触发点
准备开始
准备构建你自己的剧本和/或使用现有剧本并不像看起来那么庞大。在这份指南中,我们将探讨如何将 Git 仓库添加到 OLAM 实例中。这么做有几个原因:
-
版本控制 – 管理你的代码,谁编辑了它,以及你当前的版本。记住,事物会发生变化,包括基础设施和操作系统版本。你需要追踪剧本中的变化,以便适应这些变化。
-
跟踪你的剧本 – 保存它们,协作,并共享。你可以共享你的模板并重新使用它们。记住,自动化如此有用的一个重要原因是它的重复性,限制了在重复步骤中对人工交互的需求。
-
Git 为你的模板提供了一个管道,并允许你轻松地将你编写的剧本添加到你编写并创建的模板中。
为了将 Git 仓库添加到 OLAM,你需要先创建它并将其添加到你的 OLAM 项目中:
- 首先,进入项目标签页,如图所示。

图 12.40 – 项目菜单
- 进入我们创建的测试项目,或创建一个新项目 – 在这个例子中,Oracle 已创建,因为我们将把 Oracle 示例剧本添加到 OLAM。

图 12.41 – 添加项目
- 输入项目的信息,包括你的 Git 数据:

图 12.42 – Oracle Git 仓库的项目配置和变量
- 然后,保存项目,这将带你进入项目的详情页面。

图 12.43 – Oracle Git 项目详情
如何操作…
一旦你添加了 Git 账户数据,以及 Oracle Ansible 示例剧本,你可以开始创建一个新模板,使用你的 Oracle Hello World 剧本:
- 你需要再次进入模板:

图 12.44 – 模板选项
- 点击添加以创建一个新模板。

图 12.45 – 添加作业模板
- 按照我们在之前配方中所做的那样,完成工作表并填写正确的变量。

图 12.46 – 作业模板变量
- 这次,我们将从我们选择的 Oracle 示例中选择一个 playbook。

图 12.47 – 选择 Oracle Git 示例 playbook
- 我们要选择 Oracle Hello World playbook:

图 12.48 – Hello World playbook
- 确保将特权提升访问权限分配给模板。

图 12.49 – 作业权限凭证
- 保存您的模板,这将带您到详细信息页面。

图 12.50 – 作业配置详情
- 你可以启动模板以查看结果。

图 12.51 – 作业启动
- 请记得,您的结果将显示在输出选项卡下。

图 12.52 – 作业输出和结果
控制补丁管理混乱
对许多人来说,打补丁是一个脏字,对一些人来说是安慰,对所有人来说都是必要的。关于什么时候打补丁、如何打补丁以及打什么补丁,确实存在理性的恐惧。这里也适用谁、什么、哪里、何时和如何这些词。这些担忧是合理的;我的意思是,谁愿意打补丁呢?它可能很混乱,而且费时。我们可能无法消除这些担忧,但我们可以缩短自动化所需的时间。这就是自动化有助于加快操作速度的一个方面,它减轻了必须为多个环境打补丁的挫败感。
一个常见的自动化问题是:“我们能做些什么来最小化工作量,哪些必须手动完成?”我们能够为任何事情创建 playbook 并自动化一切的想法显然是不现实的。首先,有些事情我们不希望自动化,这取决于你为谁工作,或者你所在组织的政策和标准操作程序(SOPs)对自动化的态度。我曾与一些防务承包商和机构合作,他们有多个委员会投票决定允许哪些自动化,他们对哪些可以批准,哪些不能批准非常严格。不过,总体来说,自动化在节省时间和精力方面是一个伟大的平衡器。
本配方将简要介绍补丁管理,并帮助你理解自动化如何超越传统,节省时间和精力,通过自动化可重复的步骤。
准备就绪
在我们启动任何 Playbook 之前,我们必须确保所有前提条件已经就绪,包括编写 Playbook 本身。在这种情况下,我们将编写一个基础 Playbook,在两台服务器上更新 YUM 仓库,并在更新完成后重启这些服务器。这可以扩展到多个操作系统、内核和/或应用程序修补——无限可能。
如何操作…
- 如前所述,我们需要先检查并为我们的补丁工作创建一个新的 Playbook。为了做到这一点,我们将导航到我们的模板(Playbook):

图 12.53 – 模板选项
- 如前所述,我们已经有了之前写的模板。但是,我们将点击添加来创建另一个模板。

图 12.54 – 添加模板
- 选择添加 作业模板。

图 12.55 – 添加作业模板
- 你需要遵循我们为最初创建的模板所使用的相同流程。然而,这一次,我们将选择一个不同的 Playbook:

图 12.56 – 添加作业变量
- 我们将命名为
Patching,并选择更新后的 YUM Playbook。

图 12.57 – Playbook 选择
- 如下图所示,模板已完全填充。

图 12.58 – 作业变量
- 确保给你的模板权限提升访问权限,即管理员访问权限。

图 12.59 – 权限提升
- 保存你的模板,这将带你进入模板的详细信息界面。

图 12.60 – 作业配置详情与启动
- 执行你的模板和 Playbook,通过点击启动。模板的输出将显示在输出标签下,展示任何错误、遗漏和/或成功。记得仔细查看输出,因为即使输出成功,也可能有错误和/或跳过/漏掉的步骤。

图 12.61 – 作业输出与结果
超越自动化的思考
在我们创建任何资源之前,我们需要有一个创建这些资源的地方。在本例中,我们使用 OCI 作为我们的孵化器,因此显然,我们需要将 OCI 添加到我们的 OLAM 实例中。为了做到这一点,我们需要创建凭据,以允许 OLAM 访问 OCI。这不仅仅局限于 OCI。OLAM 是你进入混合云解决方案的大门。你可以通过虚拟化平台和 HCI 解决方案,如 VxRail、VMware 和 OpenStack,部署本地解决方案。我们在本食谱中不会涉及混合云解决方案,尽管我们在之前的食谱中讨论过混合云,例如将虚拟机作为模板迁移到 OCI,或上传镜像以在 AWS 中创建 AMI 镜像。这些技术也可以用于混合云场景,处理和移动工作负载的进出到云服务提供商(CSPs)。正如你所看到的,可能性是存在的,而且是无尽的。
要深入了解IaC(基础设施即代码),我们需要查看作为服务的基础设施定义。退后一步,重新框定你对基础设施的思考方式,然后将其在脑海中重新构建为移动的数字、字段和景观。这就是 IaC;它是一个不断演变的景观,始终在不断变化其定义,以匹配最终状态。你玩过俄罗斯方块吗?IaC 看起来和感觉就像俄罗斯方块,不过在这种情况下,我们每次都赢;我们只是将各个部分拼接在一起,创建出一个符合我们需求的环境。我们可以使用许多不同的变量将日常任务转化为 IaC——例如,扩展计算、存储和/或网络。例如,假设我们有虚拟机 A,这是一个用于 Web 服务器的镜像。我们为一所小型大学部署了两个 Web 服务器。该大学在普通招生期间面临挑战,需要无缝扩展。我们可以使用自动扩展或工作负载扩展来实施新的 Web 服务器,补充大学的需求,直到需求过期。这些示例比本食谱中的示例更复杂,但在我们走在这条不断变化的 IT 景观高速公路上时,理解代码的价值是至关重要的。
准备工作
Ansible 为平台配置和管理计算实例提供了构建模块。在本食谱中,我们将以不同的方式来看待 Ansible,并学习如何使用它编写剧本来在 OCI 中实例化一个新的虚拟机。我们将学习剧本的基础知识,超越我们之前在几篇食谱中探索过的 Oracle 基本预定义内容,发现通过 Ansible 实现 IaC 的好处,并且我们还将学习如何为 Ansible 创建一个以剧本形式使用的基础。最后,你将学习如何创建剧本,并在 OCI 上配置和管理资源。
首先,我们需要配置我们的环境。这包括将我们的 OLAM 实例连接到 OCI。这将允许我们在 OCI 租户中执行我们的 playbook。
- 首先,我们需要进入凭据。

图 12.62 – 凭据选项
- 你需要为 OCI 添加一个凭据。

图 12.63 – 添加凭据
-
你需要从 OCI 租户中收集以下信息——用户Oracle Cloud Identifier(OCID)、指纹、租户 OCID 和区域。所有这些信息可以在用户 | 用户设置 | API 密钥下找到。
导航并登录到你的 OCI 控制台,进入用户(右侧的人物图标):

图 12.64 – 右侧的用户图标
然后,导航到用户设置:

图 12.65 – OCI 用户设置选项
所有数据都将在API 密钥下:

图 12.66 – OCI API 密钥菜单
- 确保选择查看配置 文件选项:

图 12.67 – 配置文件
- 你需要的 OCI 设置数据将在此配置文件中:

图 12.68 – 配置文件详情
- 输入所有收集到的信息。

图 12.69 – OCI 用户 OCID、指纹和租户 OCID 的凭据变量
- 别忘了剪切并粘贴用于访问 OCI 帐户的私钥。这是你在系统上用于登录 OCI 的密钥。

图 12.70 – OCI 私钥
- 保存凭据,这将把你带到详情页面,显示你刚刚配置的凭据摘要。

图 12.71 – OCI OLAM 凭据配置详情
如何操作…
-
检查 Ansible 核心的版本:
[opc@olam-target-1 ~]$ ansible --version ansible [core 2.14.2] config file = /etc/ansible/ansible.cfg configured module search path = ['/home/opc/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] ansible python module location = /usr/lib/python3.11/site-packages/ansible ansible collection location = /home/opc/.ansible/collections:/usr/share/ansible/collections executable location = /usr/bin/ansible python version = 3.11.2 (main, Jun 14 2023, 13:00:29) [GCC 8.5.0 20210514 (Red Hat 8.5.0-18.0.2)] (/usr/bin/python3.11) jinja version = 3.1.2 libyaml = True [opc@olam-target-1 ~]$ -
创建库存:
[opc@olam-target-1 ~]$ mkdir ~/ol-automation [opc@olam-target-1 ol-automation]$ vi inventory 130.61.100.96 ~ ~ ~ ~ -
查看并确认库存清单:
[opc@olam-target-1 ol-automation]$ ansible-inventory -i inventory --list { "_meta": { "hostvars": {} }, "all": { "children": [ "ungrouped" ] }, "ungrouped": { "hosts": [ "130.61.100.96" ] } } [opc@olam-target-1 ol-automation]$ -
向库存中添加一个组:
[opc@olam-target-1 ol-automation]$ vi inventory [preproduction] 130.61.100.96 ~ ~ ~ ~ -
再次运行库存清单,如下所示:
[opc@olam-target-1 ol-automation]$ ansible-inventory -i inventory --list { "_meta": { "hostvars": {} }, "all": { "children": [ "ungrouped", "preproduction" ] }, "preproduction": { "hosts": [ "130.61.100.96" ] } ping to verify your inventory:[opc@olam-target-1 ol-automation]$ ansible all -i inventory -m ping
olam-target-1 | 成功 => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
-
创建你的 playbook:
[opc@olam-target-1 ansible]$ sudo vi packt.yml --- - hosts: olam-target-2 tasks: - name: Print message debug: msg: Hello from Packt Oracle Linux 8 Cookbook ~ ~ ~ ~ -
运行你的 playbook:
[opc@olam-target-1 ansible]$ ansible-playbook -i inventory packt.yml PLAY [all] ********************************************************************* TASK [Gathering Facts] ********************************************************* [WARNING]: Platform linux on host olam-target-2 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change this. See https://docs.ansible.com/ansible/2.14.2/referen ce_appendices/interpreter_discovery.html for more information. ok: [olam-target-2] TASK [Print message] *********************************************************** ok: [olam-target-2] => { "msg": "Hello from Packt Oracle Linux 8 Cookbook" } PLAY RECAP ********************************************************************* olam-target-2: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
设置并忘记它
在 Ansible 剧本中,循环提供了灵活性和高效性,能够通过 OLAM 自动化 Oracle Linux 环境或任何 Linux 环境。用户可以在剧本中定义字典,并使用循环语句。字典就像书籍,其中包含所有基础设施或应用程序的列表,可以用来描述自动化中的变量。这使得每个循环项都能执行一组任务,减少了重复编写代码的需要,使剧本更加简洁和易于管理。
例如,如果你想在一组 Oracle Linux 服务器上安装多个软件包,而不使用循环,你需要为每个软件包和服务器写独立的任务。然而,通过在 OLAM 中使用 Ansible 的循环功能,你可以定义软件包列表和服务器列表,并在单个任务中对每个服务器安装软件包。
准备就绪
在前面的示例中,我们展示了 OLAM 具有额外的功能和能力,能够通过基于 Web 的 UI 或命令行增强自动化功能。用户可以细化并直观地定义和管理自动化工作流,简化创建和管理复杂自动化任务的过程。此外,这还提供了一个集中的平台来管理和监控 Ansible 剧本的执行。
在以下示例中,我们有两个示例服务器,分别是之前示例中的target-1和target-2服务器,我们需要更改这两个服务器上特定用户的权限。如果不使用循环,我们需要为每个服务器编写独立的任务,导致代码冗余。然而,通过利用循环,我们可以简化剧本并提高其效率。
在这个例子中,我们首先通过hosts指令定义剧本的名称和目标主机。我们还将become设置为true,表示剧本将以管理员权限运行:
```yaml
---
- name: 更改用户权限
hosts: server_group
become: true
vars:
target_users:
- user1
- user2
tasks:
- name: 更改用户权限
file:
path: /home/{{ item }}/documents
owner: {{ item }}
group: {{ item }}
mode: "0755"
with_items: "{{ target_users }}"
接下来,我们定义一个变量`target_users`,它包含了我们要更改权限的用户列表。在这个例子中,我们的目标用户是`user1`和`user2`。
`tasks`部分包含一个名为`更改用户权限`的任务。该任务使用`file`模块更改指定目录的所有权、组和模式。
`with_items`循环用于遍历`target_users`列表。每次循环会将`item`变量设置为当前列表中的用户。然后,这个变量会用于`file`模块的`path`、`owner`和`group`参数。
通过使用这个循环,剧本将为`target_users`列表中的每个用户执行任务,从而有效地更改用户和文件夹权限:
- name: 更改用户权限
hosts: all
tasks:
- name: 为用户更改权限
file:
路径:/path/to/directory
owner: "{{ item }}"
状态:目录
loop: "{{ users }}"
在上面的示例中,`file` 被用来将指定目录的所有权更改为 `users` 列表中的每个用户。`item` 变量表示循环中的当前用户。
通过遵循这些步骤,你可以在 OLAM 中编写并执行 Ansible 循环来更改不同服务器及其描述目录中的用户权限。这将使你能够自动化该过程,确保多个系统间权限的一致性,并且管理多个环境时,能够提高效率。
## 如何操作…
1. 你需要首先编写 playbook;为了简便起见,我使用了示例项目:
```
[opc@olam-test /]$ cd /var/lib/awx/
[opc@olam-test awx]$ ls
awxfifo projects rsyslog uwsgi.stats venv
[opc@olam-test awx]$ cd projects/
[opc@olam-test projects]$ cd demo_bundled/
[opc@olam-test demo_bundled]$ ls
httpd.yaml permissions.yaml yum_update.yaml
[opc@olam-test demo_bundled]$
[opc@olam-test demo_bundled]$ sudo vi change_permissions.yaml
---
- name: Change file permissions
hosts: olam-test-1, olam-test-2
become: true
tasks:
- name: Change permissions for /tmp/changedir
file:
path: /tmp/changedir
owner: root
group: root
mode: "0755"
```
[opc@olam-target-2 tmp]$ ls -ltr
总计 0
drwxr-xr-x. 2 root root 6 10 月 18 11:53 unified-monitoring-agent
drwxrwxr-x. 2 opc opc 6 10 月 26 15:27 changedir
name: 这是 playbook 的名称。
```
2. `hosts`: This specifies the target servers where the playbook will be executed. You can define the hosts directly in the playbook or use an inventory file.
3. `become: true`: This allows the playbook to run with elevated privileges, which might be required to change user permissions.
4. `tasks`: This section contains the list of tasks to be executed.
5. `name`: This is a description of the task.
6. `file`: This module is used to change the permissions of a directory.
7. `path`: This is the path to the directory where you want to change permissions.
8. `owner`: This parameter specifies the username that the ownership should be changed to. In this example, we used the `item` variable, which represents the current user in the loop.
9. `state`: `directory`: This ensures that the path is a directory.
10. OLAM will execute the playbook on the specified servers, changing the user permissions for the specified directory to users `user1` and `user2` in this example.
11. Make sure to replace `/path/to/directory` with the actual path of the directory you want to change permissions for, and update the list of users as per your requirements.
12. Ensure that you have proper SSH connectivity and the necessary privileges to change permissions on the target servers. The following code snippet is a simple, canned YAML file depicting file permissions:
```
```yaml
---
- name: Change file permissions
hosts: olam-test-1, olam-test-2
become: true
tasks:
- name: Change permissions for /tmp/changedir
file:
path: /tmp/changedir
owner: root
group: root
mode: "0755"
```
```
1. OLAM 将在指定的服务器上运行 playbook,将 `/tmp/changedir` 的权限更改为 `root:root`,并设置为 `0755` 权限模式。
1. 保存 playbook 文件。
1. 确保你能与目标服务器建立正确的 SSH 连接。
1. 打开 OLAM 基于 Web 的用户界面。
1. 在 OLAM 中创建一个新的 playbook,或打开一个已有的 playbook。
1. 将 `change_permissions.yaml` playbook 文件的内容复制到 OLAM 的 playbook 编辑器中。
1. 在 OLAM 中保存 playbook。
1. 通过从库存中选择目标服务器(`olam-test-1` 和 `olam-test-2`)或手动指定它们的 IP 地址来执行 playbook。
1. 点击 OLAM 中的 **Run** 按钮来执行 playbook。
1. OLAM 将在指定的服务器上运行 playbook,将 `/tmp/changedir` 的权限更改为 `root:root`,并设置为 `0755` 权限模式。
# 第十三章:一起走向云端
在虚拟化方面,我们已经走过了很长的路。从在数百个大学校园内将虚拟切片和条带(虚拟化的前身)DNA 测序仪分割到最先进的虚拟农场,能够托管数千个**虚拟机**(**VMs**)和数 PB 的存储,它们有一个共同点:复杂性。但这真的必须如此复杂吗?当我想到虚拟化时,我会想到四个资源:计算、内存、存储和网络。它们相互交织,共同构成了这个网络。没有计算或内存,你无法托管工作负载;没有存储,你无法托管或存储应用程序或工作负载组件;没有网络,你的工作负载无法流动。想象一下,你的车就是你的工作负载,高速公路是你的网络,乘客是你的计算和内存,行李厢就是存储。
在本章中,我们将演示如何在本地环境以及公共云中充分利用 Oracle Linux,诸如**Oracle Cloud Infrastructure**(**OCI**)或**Amazon Web Services**(**AWS**)。我们将演练在本地构建一个定制的 Oracle Linux 8.x 环境,并将其作为镜像迁移到 OCI,以及迁移到其他**云服务提供商**(**CSPs**),包括作为 AMI 的 AWS。*云原生*是一个热门词汇,也是一个颠覆性技术。*使用 Portainer 管理 Docker Desktop*的配方将演示如何创建一个 Portainer 环境,以管理围绕一个应用程序的容器生态系统。
本章将涵盖以下内容:
+ 云中的 Oracle Linux
+ 使用 Portainer 让 Docker Desktop 更易于管理
+ 使用 VirtualBox 将虚拟机迁移到 OCI
+ 对于其他人,我们将为 AWS 创建自定义镜像
# 技术要求
一般来说,在这种情况下,使用带**图形用户界面**(**GUI**)的操作系统会更为简便。也就是说,即使最初没有使用 GUI 来构建服务器,你仍然可以安装 GUI。以下是添加和配置 GUI 的详细步骤:
1. 安装 GUI 软件包:
```
$ (sudo if not root) dnf groupinstall "Server with GUI"
```
1. 设置 GUI 为默认目标:
```
$ (sudo if not root) systemctl set-default graphical.target
```
1. 设置 GUI 为默认启动源:
```
$ (sudo if not root) ln -sf /lib/systemd/system/runlevel5.target /etc/systemd/system/default.target
```
1. 重启服务器:
```
$ (sudo if not root) reboot (or shutdown –r now)
```
# 云中的 Oracle Linux
我们可以列出所有的 CSP 并详细分析它们的优缺点,但归根结底,每个 CSP 都有其主要竞争力。Oracle Linux 所做的是在此基础上进行扩展,使得产品更强大、更具多样性。就像任何其他(开源)Linux 发行版一样,Oracle Linux 是一个多功能且强大的操作系统。就 Oracle Linux 而言,操作系统的设计兼容 RHEL 的元素,不是为了与之竞争,而是为了添加功能,同时为用户提供超越 RHEL 的 Oracle 功能。
Oracle Linux 的灵活性,类似于 RHEL,使其不仅仅是一个操作系统。Oracle Linux 扩展了操作系统的功能,最大化了围绕虚拟化的 Linux 工具集,通过 **Oracle Linux 虚拟化管理器**(**OLVM**)进入虚拟机管理、跨平台的云功能,以及自动化等方面。Oracle 的目标是提供一个 RHEL 操作系统的功能,但又超越这一点,将操作系统与全球业务网络中的工具集连接,以推动业务成功。现在,经过前面的铺垫,才是 Oracle Linux 的真正力量与多功能性,其中一些内容在本章开头已提到。本部分讲述了哪些 CSP 与 Oracle Linux 最兼容;然而,了解操作系统的功能及其运作方式,对于理解哪些 CSP 与 Oracle Linux 更加兼容并最大化其能力是至关重要的。
Oracle 支持并推广适用于业务关键环境的开源技术。Oracle 是 Linux 基金会、Eclipse 基金会和 Java 社区流程的创始成员,并为开源项目做出了重大贡献。将 Oracle 软件与开源技术结合,能够提供高性能、可靠性和数据安全,同时降低计算成本。
下图提供了对比 Oracle Linux 的“免费”版本(唯一收费组件是支持)与 RHEL 加上扩展功能的成本效益分析,如前文所述。

图 13.1 – RHEL 与 Oracle Linux
和任何 Linux 发行版一样,每个 CSP(云服务提供商)都有自己的 Linux 平台版本。例如,AWS 有 **Amazon Linux 2**(**AL2**),Azure 提供与任何基于 RHEL 或 Ubuntu 的平台兼容的服务,而 Oracle 自然也有 Oracle Linux。Ubuntu 和 Oracle Linux、AL2 等之间有许多不同之处,但我们今天不讨论这些差异。归根结底,所有 CSP 都可以运行 Linux 发行版,但并非所有都针对 Oracle Linux 做了优化。使用 AWS 和 Azure 时,你可以选择购买 Oracle 的技术支持(**BYOS**,即购买自己的支持),支持内容包括访问补丁、升级和操作系统支持,或者在没有技术支持的情况下免费使用这些服务。使用 OCI Premier 服务时,支持是免费的。下图显示了主要的 CSP 及其对 Oracle Linux 的不同采用方式。

图 13.2 – 云选项
谁是最美的?我们来看看 AWS 提供了哪些 Linux 发行版。我们将简要介绍 AWS EC2 镜像构建器,以展示 Linux 在 AWS 及其他环境中的多功能性。稍后在本章中,这将用于 *使用 VirtualBox 将虚拟机导入 OCI* 这一部分。
## 准备就绪
首先,你需要有一个 AWS 账户,无论是个人账户还是通过你的组织,关键是你拥有正确的授权来访问账户并构建基础设施。在这种情况下,我选择了**Root 用户**,因为这是我的个人账户,并且我拥有这些权限。

图 13.3 – Root 登录
输入用户类型后,你需要提供密码并继续完成身份验证选项。我已启用**多重身份认证**(**MFA**),并强烈建议使用此方法来保护你的账户。如果启用了 MFA,接下来你将看到捕获验证码的步骤,如下图所示。注意,虽然还有其他双因素认证选项,但使用 Google Authenticator 是最佳实践。当然,也可以使用其他应用,如 Microsoft、RSA 等。

图 13.4 – MFA
完成登录和 MFA 部分后,你将进入 AWS 登陆页面。你需要进入 EC2,AWS 计算资源(CPU,RAM),以了解可用的 Linux 版本及其选择,超出标准 Linux 镜像(AMI)的默认选项。请注意,虽然某些版本未列出,但并不意味着不可用:你可以通过 Marketplace 或自定义镜像找到其他选项。

图 13.5 – 计算
一旦进入 AWS EC2 世界,最简单的方式是查看 **EC2 镜像构建器**。镜像构建器将复杂的镜像世界转化为更容易理解的概念,帮助你将技术需求转化为执行:

图 13.6 – 镜像构建器
进入 **镜像构建器** 后,你需要进入 **Amazon Marketplace** 下的 **镜像产品**。这是 AWS 提供的其他所有服务的入口,将直接带你进入镜像产品页面。

图 13.7 – 镜像产品
注意
选择 Oracle AMI 时需要小心。有些第三方会收取费用使用 AMI,但不会提供 Oracle 技术支持。它们中的一些可能会非常昂贵,每年花费数百美元。
如前所述,你不会在**AWS Marketplace**标签下找到官方的 Oracle Linux 镜像。请按照*如何操作...*部分中的说明,访问官方的 Oracle Linux 镜像。

图 13.8 – 在 Marketplace 中搜索 Oracle Linux
如果你像前面的截图那样在 AWS Marketplace 中搜索`oracle linux`,你将只看到其他组织构建并通过 AWS Marketplace 公开提供的 Oracle Linux 发行版。*这些不是官方的 Oracle Linux 镜像。* 本章稍后我们将介绍如何在 Oracle VirtualBox 中构建虚拟机,并通过 AWS 将该镜像转换为 AMI。
## 如何操作…
以下是找到 Oracle AMI 的步骤:
1. 在浏览器中打开[`console.aws.amazon.com/ec2/`](https://console.aws.amazon.com/ec2/)。

图 13.9 – 在镜像下拉菜单中查找 AMI
1. 在左侧导航面板中,选择**AMIs**,然后从弹出的窗口中选择**公共镜像**:

图 13.10 – 公共镜像
1. 使用 ID `131827586825`按所有者筛选。该 ID 与官方 Oracle 镜像相关,只会显示由 Oracle 创建的官方 Oracle Linux AMI:

图 13.11 – Oracle AMI
1. 选择你希望使用的官方 Oracle AMI。选择 AMI 后,直接启动该 AMI 以继续配置资源和操作系统:

图 13.12 – 实例启动
1. 启动后,这将引导你进入操作系统镜像和虚拟机构建页面(见下图)。在这里,你为虚拟机添加一个合适的名称,并选择虚拟机的操作系统和网络密钥对,如下所示的实例启动窗口所示。

图 13.13 – 实例配置
1. 一旦你从选定的 AMI 启动了新的虚拟机,你将看到启动状态:

图 13.14 – 启动状态
1. 一旦你的新 Oracle Linux 虚拟机创建完成,你可以在 OCI 的**计算** | **EC2** | **镜像**选项卡中查看该虚拟机。然后,点击实例 ID 并复制公共 IP 地址。

图 13.15 – 公共 IP
1. 打开 PuTTY 或终端,具体取决于你是使用 Windows 机器还是 Mac,然后使用 OPC 作为用户通过`ssh`连接到你的机器(这是默认的 Oracle 用户;这些术语是可以更改的,但这里我们不讨论)。第一次运行`ssh`命令时,将会永久添加密钥对到已知主机的身份验证列表中:
```
% ssh opc@18.116.203.168
The authenticity of host '18.116.203.168 (18.116.203.168)' can't be established.
ED25519 key fingerprint is SHA256:HS1eSJOOs3slMxDU41nYfDkxMQ7uocISC21lxLnQJTk.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '18.116.203.168' (ED25519) to the list of known hosts.
```
# 使用 Portainer 使 Docker Desktop 更易于管理
Portainer 是一个容器管理平台,如本章介绍中所提到的。Portainer 最初是作为 Docker 的用户界面设计的,但现在它也支持其他几个容器环境。Portainer 拥有超过 100 万用户,并在 GitHub 上有着显著的存在。Portainer 提供两个版本:免费且开源的 **Community Edition** (**CE**) 和收费的 **Enterprise Edition** (**EE**)。在本食谱中,我们将使用免费和开源版本。
如果你更喜欢通过图形界面(GUI)管理容器,Portainer 是一个极好的选择。尽管命令行界面(CLI)和 API 端点对于开发很有用,但 GUI 往往更适合用于管理生产应用。通过 Portainer,你可以轻松监控多个端点,并授予团队成员访问共享部署环境的权限。下图展示了 Portainer 如何与 Docker 的容器镜像对齐,以及 Portainer 如何简化镜像管理。Portainer 提供了一个 Docker CLI 上的用户界面,使得无论是普通用户还是资深工程师,都能更轻松地管理容器。

图 13.16 – Portainer 容器管理
Portainer 通常部署在自己的容器内。如果你使用的是 Docker,本指南将帮助你启动和运行 Portainer。然而,如果你更喜欢使用 Kubernetes,也可以使用官方的 Helm 图表直接运行 Portainer。以下是设置 Portainer 所需步骤的简要概述:
1. 安装 Docker。
1. 创建并配置 Portainer 的容器。
1. 打开必要的端口并相应地配置 OCI。
1. 登录 Portainer 界面并设置 UI。
以下部分将详细解释每个步骤。继续之前,请确保已经安装 Docker。如果你使用的是 Windows 或 Mac 计算机,可以下载并安装最新版本的 Docker Desktop 安装程序。Linux 用户可以试用 Docker Desktop for Linux 的测试版,或者使用以下说明安装 Docker Engine。对于本指南,我们将在 OCI 云中创建一个 Oracle Linux 虚拟机,并在该虚拟机上安装 Portainer,而不是在本地环境中安装。
## 准备工作
需要进行一些初步工作。如前所述,Docker 是一个容器管理环境。在本食谱中,Portainer 将位于 Docker 容器中,因此我们需要安装并配置 Docker。你将在本章稍后创建镜像时再次使用其中一些技能。实际上,我们在这里做的基础工作将帮助你贯穿整个章节,因为这些技能为管理 Oracle Linux 环境打下了基础,无论它们是在云中还是本地。

图 13.17 – Portainer 虚拟机创建
登录 Portainer 虚拟机所需的信息位于前面显示的镜像数据中。记住,就像前面在创建 OCI 虚拟机时提到的那样,需要创建并添加公钥。正如我们之前所看到的,这是你能够登录到这个环境的唯一方式。
如图所示,使用默认的 OPC 用户登录到虚拟机:
% ssh opc@132.226.58.24
Activate the web console with: systemctl enable --now cockpit.socket
Last login: Mon Aug 21 14:15:13 2023 from 107.200.172.229
[opc@portainer2 ~]$
登录后,你需要更新仓库。与本书中其他食谱类似,你需要超级用户权限。由于输出内容较长,更新的输出已被截断:
[opc@portainer2 ~]$ sudo su -
Last login: Mon Aug 21 15:28:41 GMT 2023 on pts/0
[root@portainer2 ~]# yum upgrade -y && yum update -y
Package Arch Version Repository Size
Upgrading:
cloud-init noarch 22.1-8.0.4.el8_8.1 ol8_appstream 1.1 M
iscsi-initiator-utils x86_64 6.2.1.4-8.git095f59c.0.1.el8_8 ol8_baseos_latest 382 k
iscsi-initiator-utils-iscsiuio x86_64 6.2.1.4-8.git095f59c.0.1.el8_8 ol8_baseos_latest 102 k
microcode_ctl x86_64 4:20230214-2.0.3.el8 ol8_baseos_latest 7.7 M
systemd x86_64 239-74.0.4.el8_8.3 ol8_baseos_latest 3.6 M
systemd-libs x86_64 239-74.0.4.el8_8.3 ol8_baseos_latest 1.1 M
systemd-pam x86_64 239-74.0.4.el8_8.3 ol8_baseos_latest 506 k
systemd-udev x86_64 239-74.0.4.el8_8.3 ol8_baseos_latest 1.6 M
更新仓库后,我们准备好开始安装 Docker 并开启我们的容器之旅。为了安装 Docker,我们需要安装 ZIP 工具以解压我们已下载的所需文件。为此,我们将使用 `dnf` 命令:
[root@portainer2 ~]# dnf install -y dnf-utils zip unzip
安装 ZIP 工具后,我们需要启用 Docker 仓库,以便下载 Docker。以下是启用仓库并将其添加到仓库列表的命令:
[root@portainer2 ~]# dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo
Adding repo from: https://download.docker.com/linux/centos/docker-ce.repo
注意
我们需要消除一个漏洞,该漏洞允许攻击者通过执行任何类型的容器中的 root 命令来覆盖主机的 `runc` 二进制文件。攻击者可以利用这个漏洞,通过使用攻击者控制的镜像启动新容器,或者如果他们之前拥有写入权限,还可以渗透到现有容器中:
**[root@portainer2 ~]# dnf remove -****y runc**
使用以下 `dnf` 命令安装 Docker。由于输出内容较长,已被截断:
[root@portainer2 ~]# dnf install -y docker-ce --nobest
Docker CE Stable – x86_64 1.3 MB/s | 49 kB 00:00
Dependencies resolved.
Package Arch Version Repository Size
Installing:
docker-ce x86_64 3:24.0.5-1.el8 docker-ce-stable 24 M
…
[Truncated due to length]
...
Complete!
一旦 Docker 安装完成,我们可以继续启用 Docker 服务并启动 Docker 引擎。为了启用 Docker 服务,我们需要使用 `systemctl`,如下所示:
[root@portainer2 ~]# systemctl enable docker.service
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service.
一旦服务启用,我们可以继续启动 Docker 服务/Docker 引擎。我们将再次使用 `systemctl` 调用 Docker 引擎启动:
[root@portainer2 ~]# systemctl start docker.service
启动服务后,我们需要检查服务的状态,以确保 Docker 已正确启动且服务正在运行且健康:
[root@portainer2 ~]# systemctl status docker.service
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since Mon 2023-08-21 15:50:49 GMT; 1min 19s ago
Docs: https://docs.docker.com
Main PID: 76180 (dockerd)
Tasks: 9
Memory: 28.2M
CGroup: /system.slice/docker.service
└─76180 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
Aug 21 15:50:48 portainer2 systemd[1]: Starting Docker Application Container Engine...
...
Truncated due to length lines 1-20/20 (END)
...
现在我们的 Docker 引擎已启动并运行,我们想查看正在运行的 Docker 版本,以及其健康状态和所有其他与 Docker 引擎相关的数据:
[root@portainer2 ~]# docker info
Client: Docker Engine - Community
Version: 24.0.5
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.11.2
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.20.2
Path: /usr/libexec/docker/cli-plugins/docker-compose
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 24.0.5
Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: true
Using metacopy: false
Native Overlay Diff: false
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: runc io.containerd.runc.v2
Default Runtime: runc
Init Binary: docker-init
containerd version: 8165feabfdfe38c65b599c4993d227328c231fca
runc version: v1.1.8-0-g82f18fe
init version: de40ad0
Security Options:
seccomp
Profile: builtin
Kernel Version: 5.15.0-103.114.4.el8uek.x86_64
Operating System: Oracle Linux Server 8.8
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 15.32GiB
Name: portainer2
ID: 597d584f-bf1c-4cda-aa22-8ca2c28f33c0
Docker Root Dir: /var/lib/docker
Debug Mode: false
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
由于 Portainer 需要更高版本的 Python 环境,我们需要确保安装了正确的版本。Python 是安装的前提条件。以下命令的输出由于内容较长,已被截断:
yum install -y libffi libffi-devel openssl-devel python3 python3-pip python3-devel
Last metadata expiration check: 0:13:58 ago on Mon 21 Aug 2023 03:43:32 PM GMT.
Package libffi-3.1-24.el8.x86_64 is already installed.
Package openssl-devel-1:1.1.1k-9.el8_7.x86_64 is already installed.
Package python36-3.6.8-38.module+el8.5.0+20329+5c5719bc.x86_64 is already installed.
Package python3-pip-9.0.3-22.el8.noarch is already installed.
Dependencies resolved.
Package Arch Version Repository Size
Installing:
Complete!
安装 Python 时,我们使用 PIP,这是 Python 的标准包管理器。PIP 允许你管理和安装所有非标准 Python 库中的包。安装 Python 是 Portainer 安装的基础要求。
你需要退出 root 用户来安装此版本的 Python:
[opc@portainer2 ~]$ pip install --upgrade --ignore-installed pip setuptools
Defaulting to user installation because normal site-packages is not writeable
Collecting pip
Downloading pip-21.3.1-py3-none-any.whl (1.7 MB)
|████████████████████████████████| 1.7 MB 38.3 MB/s
Collecting setuptools
Downloading setuptools-59.6.0-py3-none-any.whl (952 kB)
|████████████████████████████████| 952 kB 78.6 MB/s
Installing collected packages: setuptools, pip
Successfully installed pip-21.3.1 setuptools-59.6.0
你需要再次以 root 身份登录来安装和更新 yum 包。Yum 需要 root 权限来执行,所以你需要使用 `sudo` 或 `su` 切换到 root 用户。
更新 Python 安装后,我们需要安装并更新 Docker 和 Portainer 的 Python 库要求:
[opc@portainer2 ~]$ sudo su -
Last login: Mon Aug 21 15:33:33 GMT 2023 on pts/0
[root@portainer2 ~]# yum install -y libffi libffi-devel openssl-devel python3 python3-pip python3-devel
你需要退出 root 账户以安装`docker-compose`,并使用 Python pip 来执行。Python pip 是安装任何 Python 包的标准方法,是以安全方式安装这些包的首选方法:
[root@portainer2 ~]# exit
logout
[opc@portainer2 ~]$ pip3 install docker-compose
## 如何操作……
1. 现在我们准备开始安装和配置 Portainer 环境。我们首先需要为 Portainer 创建一个卷。我们通过告诉 Docker 创建该卷来完成此操作:
```
[opc@portainer2 ~]$ sudo docker volume create portainer_data
portainer_data
```
1. 创建卷后,我们安装 Portainer 容器并暴露 Portainer UI 将使用的端口,通过该端口我们将访问 UI:
```
[opc@portainer2 ~]$ sudo docker run -d -p 9000:9000 --name portainer --restart always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest
Unable to find image 'portainer/portainer-ce:latest' locally
latest: Pulling from portainer/portainer-ce
772227786281: Pull complete
96fd13befc87: Pull complete
5171176db7f2: Pull complete
a143fdc4fa02: Pull complete
b622730c7bdc: Pull complete
c1cad9f5200f: Pull complete
d8a77b01f2cb: Pull complete
0d4d8543f764: Pull complete
c6fd0bcf10c9: Pull complete
889200668c1c: Pull complete
4f4fb700ef54: Pull complete
Digest: sha256:94c3056dbe879f3a3df06b427713392a0962924914f5c2fc 557de3797f59f926
docker ps to ascertain which containers are running and their health, within Docker Engine.
```

图 13.18 – Docker 容器运行
1. 一旦 Portainer 安装完成,并且`docker ps`显示 Portainer 已经启动,我们需要确保 OCI 已配置为允许端口`9000`可见。为了暴露这个端口,我们需要告诉 OCI 我们正在使用的**虚拟云网络**(**VCN**),以允许该端口开放。

图 13.19 – 安全列表导航
当我们导航到相关的安全列表后,我们将创建一个如以下截图所示的规则。

图 13.20 – VCN 安全列表规则创建
一旦规则创建完成,我们可以看到端口已暴露在 OCI 之外。

图 13.21 – 安全列表规则
我们可以打开浏览器并访问 Portainer UI。为了访问该 UI,我们需要两个信息:虚拟机的公网 IP 和端口。以下截图显示了端口`9000`,IP 地址与我们使用`ssh`登录虚拟机时使用的 IP 相同。
你也可以在 OCI 控制台找到该 IP。通过**计算**菜单导航到你的虚拟机,然后进入**实例**,这将带你到 OCI 控制台菜单中所有已创建的虚拟机。然后,复制虚拟机的 IP 地址,如下图所示。

图 13.22 – 虚拟机的 IP
1. 获得地址后,打开浏览器并以`https://<IP>:9000`的形式输入该信息。在我们的例子中,这是`https://132.226.58.24:9000`。
注意:如果你遇到过时的页面,可能需要刷新 Portainer 环境,像下面这样:

图 13.23 – Portainer 登录页面
1. 为了刷新,你需要通过运行`docker`的`restart`命令来重启 Portainer 环境:
```
[opc@portainer2 ~]$ sudo docker restart portainer
portainer
```
1. 重启 Portainer 后,你可以返回浏览器并刷新页面。现在应该能够进入 Portainer 欢迎页面。

图 13.24 – Portainer 初始配置
1. Portainer 将要求你设置一个 12 位字母数字密码以保护环境安全。

图 13.25 – Portainer 密码创建
现在,你的工作 Portainer 环境正在 OCI 中的 VM 中的 Docker 容器内运行。
# 使用 VirtualBox 将 VM 跳板到 OCI
工作时间从早上 9 点到下午 5 点?
在许多这些步骤中的一个共同因素是将工作负载从一个环境移动到另一个环境。使用通用格式(例如**开放虚拟化格式**/**开放虚拟化设备**(**OVF**/**OVA**)),可以在不同的虚拟化主机环境之间完成不同类型的虚拟化(例如 VMware、KVM 和 Xen)。基本上,这将组件放入一个大多数虚拟化主机环境可以理解的中心化可理解格式中。图像可以在虚拟化格式之间进行传输和交换。在这种情况下,还需要一些拼图块,如网络、存储和连接的驱动器数量限制。
想象一个世界,在这个世界中,任何工作负载(无论是基于应用程序还是数据库的)都可以在整个项目生命周期中与你同在,并且可以在不同的虚拟化农场或云服务提供商之间转移。你可以在你的不同环境中携带这些创建的环境。
VirtualBox 作为主机存在于你的系统上,并被归类为“类型 2”虚拟化监视程序,允许你在主机环境上托管多个客户机。你的主机环境,VirtualBox,拥有大企业产品所期望的每个虚拟农场的方面,只是将其分解为更小、更简单的部分。计算和内存方面从主机环境(你的计算机)中划分出来。存储组件由你的本地硬盘部分或外部存储环境(如外部连接的 NVMe 驱动器)组成。最后,网络由桥接组件组成,这些虚拟网络位于你的物理接口之上。
虚拟机和操作系统,哪个先来?
每一次进化都从一个基础开始。在我们考虑将虚拟机从 VirtualBox 迁移到 OCI 之前,我们必须准备好这个虚拟机进行迁移。在 VirtualBox 的情况下,建立云环境(如 OCI)中可以迁移的虚拟机之前,只需要完成一些预先工作。我们将在这个步骤中详细介绍这些先决条件。以下图解释了配置、安装和迁移 VM 到云服务提供商的阶段。

图 13.26 – 虚拟机配置阶段
## 准备工作
准备操作系统与建房子前的基础设置没有什么不同。我发现最好在 VirtualBox 用户界面配置操作系统,然后在网络设置并建立通信后使用`ssh`,这意味着你可以连接到虚拟机。
在准备将 VM 镜像导入 OCI 作为镜像时,有五个阶段。如下所示:
1. **接口名称**:这涉及标准化,以确保接口名称被主机环境识别。这可以转化为主机系统如何实现网络连接。
1. **接口配置**:在这里,我们确认没有显示 MAC 地址,及其他预配置任务。重复的 MAC 地址会导致额外的复杂性,这使得它在配置中成为一个关键点。
1. **GRUB(2)配置**:这涉及准备内核。
1. **串口控制台配置**:这是导入和使用过程中最常见的错误之一。没有这个配置,OCI 环境将在导入时失败,或者虚拟机无法启动。
1. **重启操作系统**;即重新启动你的机器。
以下图示展示了操作系统从启动到重启的配置阶段:

图 13.27 – 操作系统配置阶段
注意更改后的接口名称:
[root@small-ol8 ~]# dmesg | grep -i eth
[ 4.702620] e1000 0000:00:03.0 eth0: (PCI:33MHz:32-bit) 08:00:27:8d:0f:64
[ 4.702628] e1000 0000:00:03.0 eth0: Intel(R) PRO/1000 Network Connection
[ 5.371103] e1000 0000:00:08.0 eth1: (PCI:33MHz:32-bit) 08:00:27:89:87:98
[ 5.371132] e1000 0000:00:08.0 eth1: Intel(R) PRO/1000 Network Connection
[ 5.373296] e1000 0000:00:08.0 enp0s8: renamed from eth1
[ 5.374971] e1000 0000:00:03.0 enp0s3: renamed from eth0
我们需要在内核上执行以下代码块中显示的更改,重命名接口以进行匹配。这将需要 GRUB(2),因为 GRUB 是内核和操作系统之间的中介。现在我们有了当前的接口名称,那么接下来怎么办呢?我们这里做的事情是将接口重命名为更合适的名称,如`net0`或`Eth0`。因此,我们需要移动(`mv`)或重命名接口文件名:
[root@small-ol8 network-scripts]# mv /etc/sysconfig/network-scripts/ifcfg-enp0s3 /etc/sysconfig/network-scripts/ifcfg-net0
[root@small-ol8 network-scripts]# mv /etc/sysconfig/network-scripts/ifcfg-enp0s8 /etc/sysconfig/network-scripts/ifcfg-net1
重命名接口后,我们需要在配置文件中更改相应的条目以匹配文件名。在以下代码中,我们重命名了`net0`的配置:
[root@small-ol8 network-scripts]# vi /etc/sysconfig/network-scripts/ifcfg-net0
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=dhcp
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=eui64
NAME=enp0s3
UUID=e9e58f08-3fcc-4a43-b605-797a6bc9998f
DEVICE=enp0s3
ONBOOT=yes
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=dhcp
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=eui64
NAME=net0
UUID=e9e58f08-3fcc-4a43-b605-797a6bc9998f
DEVICE=net0
ONBOOT=yes
我们在这里做的与之前相同,不过这次我们更改的是`net1`:
[root@small-ol8 network-scripts]# vi /etc/sysconfig/network-scripts/ifcfg-net1
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=dhcp
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=eui64
NAME=enp0s8
UUID=eb2e5ed7-ec13-4f76-a0bf-48e7bcf45e84
DEVICE=enp0s8
ONBOOT=yes
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=dhcp
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=eui64
NAME=net1
UUID=eb2e5ed7-ec13-4f76-a0bf-48e7bcf45e84
DEVICE=net1
ONBOOT=yes
在下面的代码块中,我们使用`ip a`来识别接口,并确保我们的更改已生效:
[root@small-ol8 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: net0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 08:00:27:8d:0f:64 brd ff:ff:ff:ff:ff:ff
inet 10.0.2.5/24 brd 10.0.2.255 scope global dynamic noprefixroute net0
valid_lft 459sec preferred_lft 459sec
inet6 fe80::a00:27ff:fe8d:f64/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: net1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 08:00:27:89:87:98 brd ff:ff:ff:ff:ff:ff
inet 192.168.56.5/24 brd 192.168.56.255 scope global dynamic noprefixroute net0
valid_lft 85059sec preferred_lft 85059sec
inet6 fe80::a00:27ff:fe89:8798/64 scope link noprefixroute
valid_lft forever preferred_lft forever
4: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
link/ether 52:54:00:9a🇩🇪c3 brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
valid_lft forever preferred_lft forever
[root@small-ol8 ~]#
GRUB 配置有什么作用?它改变了操作系统的启动方式和加载内核的方式。例如,我们来看看改变串口连接详情的作用。(我们有点跑题了;不过,了解 OCI 在最坏情况下的工作方式是很重要的。)假设你无法连接到你的服务器,网络中断了,但服务器却是绿色的并且在线。你可以使用串口连接作为后门。以下`console`编辑指示操作系统允许与虚拟机的带外连接:
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="\((sed 's, release .*\),,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
~
~
~
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="\((sed 's, release .*\),,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL="serial console"
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="console=tty1 console=ttyS0,115200"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
GRUB_SERIAL_COMMAND="serial --unit=0 –speed=115200"
~
~
~
以下命令重新加载 GRUB。由于我们不能直接编辑 GRUB,所以通过配置文件来编辑它,并使用此文件执行 GRUB 上的修改。这告诉操作系统我们已准备好重新加载并输入了新的数据:
[root@small-ol8 ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
由于我们编辑了 GRUB 并进行了其他一些操作系统更改,重新开始是个不错的选择:
[root@small-ol8 network-scripts]# reboot
完成这些配置更改可能会让人感到困惑。归根结底,我们是在缩小 OCI 创建的实例和我们在此食谱中配置的实例之间的差异。GRUB 更改是为了使环境准备好在 OCI 租户中运行。
你需要在主机机器上配置几个步骤,以便实现 VirtualBox 和 OCI 之间的连接。VirtualBox 与 OCI 之间的通信通过**应用程序编程接口**(**API**)实现。此连接需要创建公钥和私钥,并将公钥上传到 OCI。
VirtualBox 和 OCI 之间的身份验证过程包含多个步骤。以下是组件及其 OCID/输出,它们是与 OCI 连接所必需的。
+ OCI 账户:
+ 租户
+ 分区
+ VCN
+ 存储桶
+ API 密钥
+ VirtualBox —— 确保创建并保存所需的密钥,如下所示:
+ API 密钥
+ 主机操作系统(你的计算机)——确保创建并保存所需的密钥,如下所示:
+ API 密钥
私钥和公钥是从一个环境共享信息到另一个环境的关键信息。公钥可以共享,并用作加密方法来保护数据包。私钥保留在本地,不会被共享,仅由该用户使用,用于解密数据包。当公钥和私钥一起使用时,它们形成一个锁箱,在传输过程中保护数据包在两个系统之间流动的安全性。`openssl` 被用来生成公钥和私钥。

图 13.28 – OpenSSL 密钥创建
在创建上述密钥后,你需要更改权限,使得该密钥只能由你使用。我们将使用`chmod`来配置这些权限,允许该密钥由用户使用。

图 13.29 – OpenSSL 密钥权限
在创建私钥之后,我们需要创建公钥。这个公钥将上传到 OCI,以便 VirtualBox 和 OCI 进行通信。我们使用私钥来创建公钥,从而使两个环境能够互相通信。

图 13.30 – 公钥创建
下一步是从 OCI 云账户中收集必要的数据,以便输入到 VirtualBox 配置中。所输入的信息将帮助 VirtualBox 通过 OCI API 集成你的 OCI 租户和分区,通过你的 VCN。可以将其想象为在 VirtualBox 和 OCI 之间架设一条高速公路。公钥和私钥就像是这条公路的钥匙,允许数据包在高速公路上穿行。
## 如何操作……
以下步骤将介绍如何上传密钥并配置 VirtualBox 与 OCI 的通信:
1. 首先,就像任何其他云服务提供商(CSP)一样,我们需要登录到我们的账户。

图 13.31 – 登录到你的账户
现在我们就等着 OCI 登录我们了……

图 13.32 – 登录中
1. 登录到你的账户后,你就准备好登录到租户了。这是操作的起点,你将开始看到自己的努力得到回报。我们从识别租户开始,然后继续进行。

图 13.33 – 选择并登录以验证身份提供者
1. 一旦登录并进入租户,你需要的大部分数据将会出现在用户设置中,并且与公钥上传相关联。密钥本身会生成一个指纹,这个指纹是 OCI 与 VirtualBox 之间的通道。
你将在 OCI 门户的右侧看到你的用户图标。点击它将带你进入包含账户、租户和个人数据的区域。这里也是你配置密钥访问权限的地方。

图 13.34 – OCI 配置文件
展开该菜单后,你将看到**用户设置**。这是你访问 OCI 的所有用户设置的入口。

图 13.35 – 用户设置
1. **API 密钥**部分将允许你输入用于访问的密钥值。

图 13.36 – 管理员权限和 API 密钥
1. 在下面的截图中,你可以看到所有当前上传到 OCI 的密钥,显示的是你的特定用户。如果点击**添加 API 密钥**,将会弹出添加密钥的选项。

图 13.37 – API 密钥
1. 选择**选择公钥文件**,然后从本地环境中选择文件。记得我们在上一节中创建了一个公钥。我们将在这里选择那个公钥。

图 13.38 – 公钥
1. 一旦选择了密钥并将其上传到 OCI,你将在屏幕上看到该密钥。点击**添加**:

图 13.39 – 已提交的已添加密钥
1. 现在我们已经完成了密钥导入,我们来到了可以开始配置访问权限的阶段。在你正式添加密钥后,将会显示一个配置界面。这个配置文件就是你所需要的一切,除了一个我们稍后会讨论的**分区 OCID**,用于配置 VirtualBox/OCI 接口。

图 13.40 – 显示的配置
复制**配置文件预览**下的信息。你将需要这些信息来配置 VirtualBox 与 OCI 的通信。
1. 现在我们回到 VirtualBox。接近图钉图标的地方会有一个菜单栏。这个菜单是 VirtualBox 的核心,允许您更改从 vdisk(如以下截图所示)到网络配置,当然也包括与云相关的设置。展开 **Cloud** 菜单项以访问 OCI 设置:

图 13.41 – VirtualBox OCI 云配置设置
1. 选择此选项后,您需要输入一个名称。我将输入 `OCI`,因为我们正在使用 OCI。

图 13.42 – 配置名称
1. 现在,在 **Oracle Cloud Infrastructure** 下,您会看到您的新配置文件 **OCI**。您可以点击 **属性**,这将允许您配置该 OCI 配置文件。

图 13.43 – 名称已提交
1. 这时,打开另一个窗口中的 OCI 门户,或者将变量复制粘贴到记事本中会非常方便。您需要我们在几节前的 *图 13.40* 中讲解的所有信息。
1. 您需要复制的第一个 OCID 是 `user` 的:

图 13.44 – 用户 OCID
1. 将该 OCID 粘贴到 OCI 配置文件中的 **user** 属性中,如前面的截图所示,再粘贴到 VirtualBox 中。希望您现在能明白我们要做什么。

图 13.45 – 配置用户 OCID
1. 如之前所示,这次复制 `tenancy` 的 OCID 并返回到 VirtualBox。

图 13.46 – 租户 OCID
1. 再次,如之前所示,将租户 OCID 粘贴到 **tenancy** 字段中。

图 13.47 – 配置租户 OCID
1. 返回到您的记事本或 OCI 门户并复制 `region` 值,在本例中是 `us-asburn-1`,如下截图所示。记住,所有这些很快就会变得清晰。基本上,我们正在指示 VirtualBox 去哪里,如何到达那里,并使用哪些区域、租户、用户和密钥来进行访问。

图 13.48 – 区域
1. 如之前所示,将区域粘贴到正确的字段中。

图 13.49 – 配置区域
1. 接下来,您需要进入 OCI 控制台或记事本,并复制 `fingerprint` 值以输入到 VirtualBox 中。

图 13.50 – Fingerprint
1. 再次将该 fingerprint 值粘贴到相应字段中。

图 13.51 – 配置 fingerprint
1. 最后一个条目是你创建的私钥的位置。这个位置不在 OCI 中,而是在你本地系统中创建它的地方。记住,私钥是本地密钥,不应与他人共享。你需要记录该路径并返回 VirtualBox。

图 13.52 – API 密钥位置
1. 如前所示,将路径粘贴到相应的字段中。

图 13.53 – 配置密钥位置
1. 最后,你需要回到 OCI 门户并找到 **隔离区** 菜单。我发现简单搜索是定位此选项的最简便方法,但如果你想直接前往,可以在 **身份** 下找到它。

图 13.54 – 隔离区
1. 展开你想使用的隔离区并复制 OCID,将其输入到 VirtualBox OCI 配置中。

图 13.55 – 隔离区选择
1. 如前所示,将该 OCID 粘贴到相应字段中。

图 13.56 – 配置隔离区
1. 在输入所有数据后,你应该能看到 OCID 的区域、用户、租户、密钥文件位置、隔离区和指纹属性都已填充。

图 13.57 – 完成的配置
1. 一旦确认一切已完成,应用设置。你会看到新配置文件出现;我们将其命名为 **OCI**。

图 13.58 – VirtualBox OCI
1. 如果你展开该配置文件,你会看到租户现在是空的。如果你之前在该租户下部署了基础设施,你会看到那些资源显示在这里,前提是它们运行在与配置文件中输入的 OCID 相同的隔离区。

图 13.59 – 扩展的 OCI
现在你已经准备好开始移动我们在本节中创建的虚拟机:
1. 导出虚拟机到 OCI 的第一步,一旦配置好 VirtualBox OCI 配置文件,就是在 VirtualBox 主欢迎菜单中点击 **导出**。

图 13.60 – 导出
1. 接下来,你需要选择要导出到 OCI 的虚拟机,如下截图所示——在此例中,虚拟机名称为 **small-ol8.8**。这将根据你为虚拟机命名的不同而有所变化。

图 13.61 – 镜像选择
1. 选择虚拟机后,你必须配置导出虚拟机的格式。我们将扩展 `.ova` 文件扩展名。

图 13.62 – 镜像格式配置
1. 如前所示,选择**Oracle Cloud Infrastructure**作为格式,选择**OCI**作为 VirtualBox 配置文件,正如下面截图中的红色高亮所示。

图 13.63 – 配置文件
1. 你需要确保所有变量都是正确的,如以下截图所示,并确认你有一个可用的存储桶:

图 13.64 – 镜像输出
1. 你需要展开`VM.Optimized.Flex`,它不会被 OCI 识别。我在以下图中识别了一个可用且轻量的形状,它是可用的。请按照以下图片选择形状:

图 13.65 – 形状选择
1. 如前所示,展开此部分将为你提供多个形状选择。需要注意的是,形状是预设的大小,反映了一个固定数量的资源。在这种情况下,我们选择**VM.Standard.E2.1**:

图 13.66 – 镜像形状
注意
`VM.Optimized3.Flex` 不是一个被认可的形状,无法导入。你可以在虚拟机部署后随时更改形状。
1. 一旦选择了合适的形状,完成配置导出,然后点击**完成**以执行迁移到 OCI。

图 13.67 – 镜像形状提交
1. 确保你的镜像形状已经识别并且选择了正确的形状:

图 13.68 – 镜像写入
1. 一旦导出完成,你将看到你的虚拟机在 OCI 中运行,并且你可以登录到你的门户,看到该虚拟机在你的 OCI 租户中运行。

图 13.69 – 镜像运行
如前面的截图所示,镜像现在作为虚拟机在 OCI 中运行。
# 对于其他人来说,让我们为 AWS 创建自定义镜像
看起来非常简单:构建镜像,导出镜像,然后导入镜像(洗净,冲洗,再重复)。这个概念并不比这更复杂。然而,还是有一些步骤需要走,而且其中有些步骤是有陷阱的。
你首先需要完成设置和配置 AWS CLI 的步骤。类似于 OCI CLI,AWS 的 CLI 是一个直接通过命令行执行 AWS API 的工具。安装并配置 CLI 后,我们将通过设置 S3 存储桶、配置存储桶以及更改访问权限以允许上传的步骤。下图展示了本教程中各个阶段及其触点。AWS CLI 是在分阶段和执行过程中与图形用户界面共同使用的核心工具。AWS 中的存储由访问控制和身份验证管理,这使得我们能够创建、存储和操作存储的对象和存储桶。

图 13.70 – AWS CLI 存储连接
## 准备就绪
在开始使用 CLI 之前,我们必须下载并安装必要的包。对于本教程,我使用的是 Mac。你可以轻松地访问 AWS 并下载适用于 Windows 或 Linux 的 CLI。不管怎样,一旦 CLI 安装完成,命令的使用没有区别,唯一不同的是位置和一些操作系统特定的更改,这些更改仅适用于 Windows:
root# curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
下载完包后,你需要安装 CLI。执行安装包时,如下所示:
root# installer -pkg ./AWSCLIV2.pkg -target /
在这种情况下,我们将 Python 版本升级到与 AWS CLI 所要求的版本匹配。你可以通过在终端中运行`which`命令来检查 AWS CLI 的安装位置,再使用`--version`命令查看 AWS CLI 和 Python 的版本:
root# which aws
/usr/local/bin/aws
root# aws --version
aws-cli/2.7.28 Python/3.9.11 Darwin/21.6.0 exe/x86_64
安装好 AWS CLI 之后,我们将继续配置 Oracle Linux 操作系统。接下来,我们会用我们的 AWS 账户信息和数据中心位置来配置 AWS CLI:

图 13.71 – 创建一个新的虚拟机
你需要像前面章节那样填写所有字段。确保通过引用你创建的磁盘(`/Users/USER/Desktop/<NAME>`)来命名你的虚拟机。这样可以帮助你稍后保持文件的整洁。你可以随时返回 VirtualBox 中的虚拟机并找到关联的介质,但现在命名磁盘会更容易。

图 13.72 – ISO 选择
如果你记得,在前一部分中,我们已分配了 CPU 和内存。就像在其他任何构建环境中一样,我们需要指定、安装和配置资源。无论它们是虚拟的还是物理的,我们都在安装资源。在这种情况下,我们为这台虚拟机配置了 4 GB 的 RAM 和两个 vCPU。记住,vCPU 相当于一个处理器线程。所以,这里我们安装了两个 vCPU,相当于一个物理核心(两个线程(vCPU)=一个处理器核心)。

图 13.73 – 资源
配置完 CPU 和内存资源后,我们准备选择要附加到虚拟机的介质(磁盘)。在这种情况下,我们不会选择默认的创建磁盘选项,而是使用现有的磁盘。记得,我们已经创建了自己的`.vmdk`格式磁盘文件,所以在这里选择使用现有的虚拟硬盘文件。

图 13.74 – 创建或使用现有磁盘的选项
记得选择与你的虚拟机名称匹配的驱动器(假设你之前已经创建了),或者创建一个新的驱动器。注意,`.vmdk`扩展名必须再次使用,才能被识别。

图 13.75 – 磁盘选择
和之前的步骤一样,我们在 **摘要** 屏幕上确认我们的选择,并通过选择 **完成** 执行配置。我们不会深入讲解构建过程,因为我们有其他教程可以引导你配置操作系统。

图 13.76 – 配置总结
一旦我们构建了 Linux 操作系统,就可以通过配置我们的 AWS 环境来执行操作,包括设置 CLI 上传并在创建后执行我们的 AMI(亚马逊机器镜像),从 OVA 文件导入。记住,在前面的步骤中,我们在 VirtualBox 中构建了一个虚拟机,并从该 OVA 镜像创建了一个 OCI。我们在这里也会做同样的事情,从 VirtualBox 导出并导入到 AWS。这里的区别在于,我们没有一个复杂的 VirtualBox 环境可供操作。我们将使用 AWS CLI 将该 OVA 镜像导入到我们的 S3 环境中。然而,如前所述,为了做到这一点,我们需要配置连接并确保其到位。我们将一步步展示如何在 AWS 上进行这些设置,并迁移 VirtualBox 到 AWS,看看这个过程需要哪些步骤。
在导出 OVA 文件时,你需要开始准备 AWS CLI 配置。
## 如何操作…
你可以通过两种方式上传导出的 OVA,一种是通过命令行,另一种是通过 S3 控制台。无论哪种方式,实际上都是将文件上传到 AWS S3,方式并不重要。
通过 S3 控制台上传是一个相当简单的过程:
1. 登录到你的 AWS 控制台,如下所示:

图 13.77 – 以 root 用户登录
1. 登录后,导航到 S3。

图 13.78 – AWS 菜单
如果 S3 不在你最近访问的列表中,可以在搜索栏中导航到 `S3`。

图 13.79 – S3 存储
1. 导航到 S3 后,你需要为上传的 OVA 创建一个存储桶。存储桶本质上是对象存储,是存储图片等内容的理想位置。

图 13.80 – S3 存储桶
1. 选择 **创建存储桶** 后,你需要为存储桶命名并配置其他方面的内容。

图 13.81 – 存储桶名称和区域
1. 命名后,根据 AWS 文档选择存储桶应创建的区域。记得在与你操作的区域相同的区域创建存储桶,并且在这个练习中使用该区域。在这个例子中,我们将在美国东部 2 - 俄亥俄地区部署。
1. 我们在这里不会启用任何 ACLs。

图 13.82 – ACLs
1. 如前所述,关于 AWS 访问控制,我们将取消勾选 **阻止所有公共访问**,并允许直接公共(即外部)访问 S3 存储桶。
注意
这通常不是最佳实践,我们这样做只是为了测试目的。

图 13.83 – 公共访问
1. 我们将保持禁用版本管理(默认设置),如以下截图所示,因为这是一个一次性桶,不会永久保留。当您在多个版本的项目生命周期中工作时,您可能会启用版本管理,例如图像的多个版本。

图 13.84 – 版本管理
1. 由于我们保持操作的基础性,我们不会关联任何标签。

图 13.85 – 标签
1. 我们将使用标准的服务器端加密,使用 S3 托管的密钥。

图 13.86 – 加密
1. 同样忽略高级选项,直接创建桶。

图 13.87 – 桶显示
1. 转到新创建的`vb-aws-us-east-2`桶,点击**上传**。

图 13.88 – 对象上传
1. 点击**添加文件**。这将允许您从本地文件系统中选择正确的 OVA 文件上传到桶中。

图 13.89 – 添加文件
1. 我们将选择在本教程开始时创建的 OVA。

图 13.90 – 文件选择
1. 一旦您添加了文件,进行上传。

图 13.91 – 文件目标
1. 状态栏将显示进度,**摘要**部分将显示 S3 中的目标位置,如下图所示。

图 13.92 – 上传
注意
如果您离开此状态页面,您将无法返回,所以请停留在页面上,直到上传完成。
1. 上传完成后——或者,如果您喜欢多任务处理,可以在此期间打开另一个 AWS 控制台会话——您需要为刚创建的桶设置角色和访问权限。转到**身份与访问管理**(**IAM**)以访问角色数据。
1. 在**角色**下,您可以创建自定义角色以用于访问、认证或其他与 IAM 相关的标准。

图 13.93 – AWS 角色
我们将通过命令行配置角色和权限。我们必须创建一个 IAM 用户和密钥,因为没有访问权限或认证,CLI 将无法操作。然后,我们可以配置 CLI 与我们的账户连接。
要配置并将用户与该访问密钥关联,您需要返回到 IAM,接下来的步骤将引导您完成。

图 13.94 – 安全、身份与合规菜单
1. 一旦你在搜索栏中展开了`IAM`,为了帮助你熟悉控制台,我们将详细说明获取此选项的具体步骤。

图 13.95 – IAM
1. 为了访问和创建密钥,我们必须了解密钥的用途以及它如何与用户相关联。所以,让我们导航到**用户**。我们将按以下步骤创建密钥。

图 13.96 – 用户
1. 你需要按照以下截图所示创建用户,你可以通过进入`user-admin`来做到这一点:

图 13.97 – 用户名
1. 现在我们已经命名了用户,就像任何其他系统一样,我们需要定义用户,将他们加入一个组,并分配权限。

图 13.98 – 用户定义
1. 我们将把此用户分配到管理员组,然后点击**下一步**继续。你可以通过创建一个与您的政策或组织政策更为贴切的组来定义权限。创建用户后,我们可以在此生成一个密钥,正如以下截图所示,附带密钥。以下步骤将演示如何操作。

图 13.99 – 凭证
1. **安全凭证**选项卡是创建访问密钥的地方。

图 13.100 – CLI 访问控制和凭证创建
这个访问密钥是专门为 CLI 创建的,因此我们需要选择这个选项,如前面的截图所示,然后点击**下一步**。我们在这个步骤中不会创建任何标签,所以可以跳过这一步,直接创建访问密钥。
注意
下载`.csv`文件(凭证文档),或通过点击密钥旁边的两个方框来显示并复制密钥。这是唯一可以复制这些密钥的地方,无论是写下来还是粘贴到记事本中。**一旦你关闭此页面,将无法恢复这些信息。** 你可以重新创建并重新配置 CLI 而不丢失数据,但这会是很多不必要的工作,所以请确保写下密钥。

图 13.101 – 密钥
确保复制密钥,如下所示——你将看到不同的密钥:`eZ5mZxzGhEYM0AfyBznLDqIT6TMsUz//AO2DMQst`。
1. 一旦你创建了密钥并记录下了秘密访问密钥,访问密钥将变为有效。

图 13.102 – 访问密钥
1. 在添加了访问密钥后,你将能够在 CLI 中运行`aws configure`:
```
root# aws configure
AWS Access Key ID [****************AZHA]: AKIA3HX45UYOK7HIAZHA
AWS Secret Access Key [****************MQst]:
Default region name [us-east-2]: us-east-2
Default output format [json]: json
```
注意
如果你将`JSON`写成全大写字母,这将导致失败。它不会报告失败,但当你运行命令时,会在 API 中失败。
1. 配置 CLI 后,你可以执行以下命令将你的镜像从 OVA 转换为 AMI:
```
root# aws ec2 import-image --description "VM Image" --disk-containers Format=ova,UserBucket="{S3Bucket=vb-aws-us-east-2,S3Key=vb-aws.ova}"
{
"Description": "VM Image",
"ImportTaskId": "import-ami-0908bf8d72b678cdf",
"Progress": "1",
"SnapshotDetails": [
{
"DiskImageSize": 0.0,
"Format": "OVA",
"UserBucket": {
"S3Bucket": "vb-aws-us-east-2",
"S3Key": "vb-aws.ova"
}
}
],
"Status": "active",
"StatusMessage": "pending"
}
```
1. 以下命令将确认转换状态:
注意
`import-ami-xxxxxxxx` 每次执行转换时都会变化。
aws ec2 describe-import-image-tasks --import-task-ids import-ami-
我已经执行了这个命令并多次运行,以展示每个过程步骤。完成以下步骤后,你将能够在你的 AWS 租户中使用新创建的 AMI。在执行导入任务时,我刷新了页面以展示所有版本的更新。
1. 运行以下命令查看导入状态:
```
root# aws ec2 describe-import-image-tasks --import-task-ids import-ami-0908bf8d72b678cdf
{
"ImportImageTasks": [
{
"Description": "VM Image",
"ImportTaskId": "import-ami-0908bf8d72b678cdf",
"Progress": "19",
"SnapshotDetails": [
{
"DiskImageSize": 8211946496.0,
"Format": "VMDK",
"Status": "active",
"UserBucket": {
"S3Bucket": "vb-aws-us-east-2",
"S3Key": "vb-aws.ova"
}
}
],
"Status": "active",
"StatusMessage": "converting",
"Tags": []
}
]
active: The import task has started
```
1. `converting`: 镜像正在转换为 AMI
1. `updating`: 正在更新 AMI 导入
1. `validating`: 正在验证导入
1. `validated`: 验证已完成
1. `completed`: AMI 准备好使用
1. `deleted`: 导入任务已取消
当 AMI 完成时,以下将是最终状态:
{
"ImportImageTasks": [
{
"Architecture": "x86_64",
"Description": "VM Image",
"ImageId": "ami-055ce6a1f65862de6",
"ImportTaskId": "import-ami-0908bf8d72b678cdf",
"LicenseType": "BYOL",
"Platform": "Linux",
"SnapshotDetails": [
{
"DeviceName": "/dev/sda1",
"DiskImageSize": 8211946496.0,
"Format": "VMDK",
"SnapshotId": "snap-08a2c2a985caf8a6c",
"Status": "completed",
"UserBucket": {
"S3Bucket": "vb-aws-us-east-2",
"S3Key": "vb-aws.ova"
}
}
],
"Status": "completed",
"Tags": [],
"BootMode": "legacy_bios"
}
]
}
1. 处理完成后,你将能够重新登录 AWS 控制台并导航到你的 EC2 环境。为了启动一个新的虚拟机并选择你的 AMI 作为模板,请点击**启动实例**。

图 13.103 – 启动实例
1. 一旦进入启动菜单,你可以深入浏览其他可用的 AMI。

图 13.104 – 浏览 AMI
1. 这将带你进入自定义的 AMI(如前所示在*图 13.7,镜像产品*中),以及市场。市场是你可以与社区分享自己创建的 AMI,或者使用他人上传的 AMI 的地方。

图 13.105 – 创建的 AMI
1. 如前所示,你将看到在本指南中创建的可用 AMI。同时,顺便提一下,除了市场中提供的 AMI,你还可以找到许多操作系统,包括 Oracle Linux。
1. 如果你导航到新创建的 AMI,你会看到你可以选择该镜像作为 AMI 来执行并创建虚拟机。

图 13.106 – 选择 AMI
通过选择 AMI,你将该 AMI 附加为镜像,并执行从所选镜像(AMI)创建虚拟机的操作。

图 13.107 – 实例启动配置
1. 在选择 AMI 并执行启动后,你将进入标准的 AWS 虚拟机创建流程,包括创建密钥对、命名密钥对并下载密钥。你也可以事先创建这些密钥。

图 13.108 – 密钥对
1. 一旦创建了密钥对,私钥将下载到你的本地机器上,你可以继续启动虚拟机。

图 13.109 – 成功状态
1. 你可以通过点击实例 ID 来导航到你的虚拟机。进入实例后,你将能够捕获 IP 并登录到你的新虚拟机。

图 13.110 – 公共 IP
1. 要登录到机器,你可以使用在创建机器时生成的密钥对或密码;两者都可以使用:
```
root# ssh oracle@3.135.211.36
oracle@3.135.211.36's password:
Activate the web console with: systemctl enable --now cockpit.socket
Last login: Sat Aug 12 01:45:46 2023 from 107.200.172.229
```


浙公网安备 33010602011771号