金鱼哥RHCA回忆录:CL210执行镜像操作--比较镜像格式+构建定制镜像
🎹 个人简介:大家好,我是 金鱼哥,CSDN运维领域新星创作者,华为云·云享专家,阿里云社区·专家博主
📚个人资质:CCNA、HCNP、CSNA(网络分析师),软考初级、中级网络工程师、RHCSA、RHCE、RHCA、RHCI、ITIL😜
💬格言:努力不一定成功,但要想成功就必须努力🔥🎈支持我:可点赞👍、可收藏⭐️、可留言📝
📚比较镜像格式
📜常见的镜像格式
构建自定义镜像是在整个组织中对软件配置和特性进行标准化的一种方法。镜像定制可能包括软件包、安全强化、第三方监控或备份代理,以及使用SSH密钥的操作人员或自动化帐户
Red Hat OpenStack平台使用Linux KVM管理程序和QEMU仿真器技术,支持许多虚拟磁盘镜像格式,直接或通过QEMU转换。Red Hat OpenStack平台主要使用RAW和QCOW2格式,这部分将对此进行解释。
📑镜像格式概述
RAW格式是一个可引导的、未压缩的虚拟磁盘镜像。对以RAW格式存储的磁盘镜像不应用格式化。对RAW磁盘镜像的数据操作不需要额外的格式处理。写入磁盘位置偏移量的数据被写入卷上的备份文件中的相同偏移量。这是提高RAW镜像性能的基础。
QCOW2格式是一个空间优化的文件,可以最小化网络带宽和卷操作大小。尽管QCOW2的使用需要实时处理,但该格式支持流行的特性,如快照、即写即拷和加密,这些特性也是动态的。
📑比较RAW和QCOW2镜像格式
属性 | RAW | QCOW2 |
---|---|---|
镜像大小 | RAW镜像是源磁盘的对等位副本,包括空白空间。在支持稀疏存储的文件系统或后端,RAW镜像通常使用的实际空间比它们报告的要少。 | QCOW2是虚拟磁盘镜像的空间优化表示。不要与压缩或稀疏存储混淆,这种优化是在文件结构内部进行的。通常,QCOW2文件比来自相同来源的RAW镜像要小。QCOW2还支持zlib压缩。QCOW2文件已经经过优化,因此可能不会使用稀疏文件系统或存储特性。 |
性能 | RAW格式的性能要高于QCOW2性能,这是因为在实例部署时预先分配了磁盘空间,避免了随需应变的空间分配相关的延迟。RAW镜像在使用期间不需要额外的处理。 | QCOW2格式的性能低于RAW格式,因为镜像特性需要动态处理。当请求的空间超过当前优化的分配,就会在空间扩展时产生延迟。 |
加密 | 不适用。 | 可选的。使用256位AES (CRC)密码或LUKS加密。 |
快照 | 不适用。 | QCOW2支持多个快照,每个快照都是某个时间点上的镜像的只读记录。QCOW2快照存储在内部。 |
copy-on-write(写时拷贝技术) | 不适用。 | QCOW2文件更改被写入一个单独的覆盖文件中,保留原始镜像文件,复制修改前要更改的块到覆盖。几个覆盖文件可以共享相同的基础镜像。使用多个文件允许从同一基本镜像运行多个实例。 |
您的应用程序用例决定了RAW或QCOW2镜像的选择。当从同一基本镜像创建大量实例时,QCOW2 的copy-on-write特性可以节省大量空间。随着每个计算主机上每个映像部署的实例数量的增加,这种优势也会相应增加。虽然RAW镜像是预先分配的,不能由多个实例共享,但由于缺乏额外的镜像处理,CPU处理显著减少,并且当QCOW2需要超过当前分配的空间时,不会中断添加空间的工作。需要最高可用性能的遗留服务器配置和应用程序很可能使用RAW格式。
📜镜像大小的考虑
在OpenStack中创建镜像时,应该设置最小磁盘(GB)和最小RAM (MB)屏幕字段。或具有足够大小值的–min-disk和–min-ram命令行选项。RAM值应该反映被启动实例的运行时内存需求。磁盘值必须至少是镜像的虚拟大小,即源磁盘的原始大小。在决定设置什么值时,请记住镜像的实际大小、物理大小和虚拟大小之间的差异。这些值会受到镜像类型和稀疏文件存储支持的影响。
当文件部分为空时,稀疏文件尝试更有效地使用文件系统空间。支持它的文件系统将向磁盘写入表示空块的元数据,而不是在文件中写入空空间。只有在支持文件系统或存储服务中存储文件时,文件才能是稀疏的。ext2、ext3、ext4、XFS、最近的NTFS和APFS文件系统都支持稀疏文件,而不是fat 32或HFS+。Ceph RBD还支持稀疏文件存储。
通常,QCOW2文件被认为是稀疏的,因为它们使用了类似的空间优化方法。与使用稀疏元数据文件系统或存储服务方法不同,QCOW2文件在其自身的文件结构中进行了内部优化。QCOW2格式的文件延迟存储分配直到需要的时候,它们的文件系统大小只表示当前分配的非空数据块。QcOW2文件的物理和逻辑大小相同,而虚拟大小更大,表示重新创建原始源文件系统所需的空间。ls -s命令的物理(分配的)大小包括没有包含在qemu-img命令的匹配磁盘大小字段中的文件系统指针块。
相反,RAW镜像是原始源文件的对等位副本。RAW镜像文件清单显示为完整大小,但由文件系统或存储后端驱动程序以稀疏的形式有效地存储。对于RAW文件,逻辑大小与虚拟大小匹配,但物理(分配的)大小更小。
建议的做法是 --min-disk和 --min-ram选项不应留空。如果没有这个要求,计算服务仍然会尝试启动实例,即使样式可能太小。当生成的卷对于镜像的虚拟大小来说太小时,它最终会失败。当选项具有有效的设置时,启动一个样式太小的实例会正确地显示错误消息而不进行尝试。
镜像格式也影响带宽效率。尽管大多数存储都能正确地处理稀疏文件,但典型的API调用和网络文件传输却不能。RAW文件以全尺寸处理或转换,包括空块,这与块(非共享)实时迁移和首次镜像使用相关,但具有可导出到其他仿真器的优点。QCOW2格式更适合文件传输情况,因为即使在使用非稀疏文件系统时,QCOW2文件也是空间优化的,并且在API调用和网络传输上占用更少的带宽。QCOW2格式还支持额外的zlib压缩,以更高的CPU利用率换取更小的传输规模。
📜OPENSTACK服务中的镜像
计算服务在Red Hat OpenStack平台中运行和管理实例。所需的镜像格式取决于可靠的后端存储系统。在默认的基于文件的后端中,QCOW2是首选,因为libvirt不支持RAW镜像快照。当使用Ceph时,镜像可以转换为RAW格式,以使用Ceph集群的快照功能。
运行以下命令将QCOW2镜像文件转换为RAW镜像文件。
在本地存储配置中部署实例时,镜像作为基本镜像缓存在计算节点上,然后展开以匹配风格指定的大小。调整大小的镜像用于为实例创建虚拟磁盘。计算服务的默认配置将非RAW镜像转换为RAW格式。如果存在缓慢的I/O或磁盘空间限制,则可以禁用此功能,但用于镜像处理的CPU使用将增加。
📚构建定制镜像
📜构建自定义镜像
构建自定义镜像的好处包括:确保存在监控代理,与组织的安全策略保持一致,并提供一组常见的故障排除工具。可以使用三种方法中的任何一种来生成定制镜像:使用diskimage-builder构建镜像,使用guestfish或virt-customize定制现有镜像。或者使用cloud-init在实例部署后执行定制。部署后定制使用配置管理系统,如红帽可自动化是本课程的范围。本节讨论磁盘镜像构建器;下面讨论另外两种方法。
diskimage-builder是一个用于构建和定制云镜像的工具。它可以输出各种格式的虚拟磁盘镜像,比如QCOW2和RAW。diskimage-builder在构建过程中应用元素来定制镜像。元素是在chroot环境中运行的代码集,它改变镜像的构建方式。例如,docker元素从命名容器中导出tar文件,允许其他元素在该文件上构建。或者元素引导加载程序,它在系统的引导分区上安装grub2。
📜DISKIMAGE-BUILDER架构
diskimage-builder绑定在chroot环境中挂载/proc、/sys和/dev。镜像构建过程生成最小的系统,这些系统拥有使用OpenStack实现其目的所需的所有组件。镜像可以像文件系统镜像那样简单,也可以定制为提供整个磁盘镜像。在完成文件系统树之后,将构建一个带文件系统(或分区表和文件系统)的环回设备,并将文件系统树复制到其中。
📑Diskimage-builder元素
元素用于指定进入镜像的内容,所需镜像的任何修改都需要使用至少一个基础。分布元素,对于一个给定的分布有多个元素。例如,分布元素可以是rhel7,然后使用其他元素修改rhel7基本镜像。脚本将根据多个元素调用并应用于镜像。
📑Diskimage-builder元素的依赖关系
每个元素都可以使用element-deps和element-provides来定义或影响依赖项。element-deps是一个纯文本文件,包含一个元素列表,这些元素在创建镜像时被添加到镜像内建的元素列表中。element -provides是一个纯文本文件,其中包含此元素提供的元素列表。在创建时,这些特定的元素没有包含在镜像内建的元素中。
diskimage-builder包 包括许多元素:
[root@director ~]# ls /usr/share/diskimage-builder/elements/
apt-conf devuser install-static rhel7
apt-preferences dhcp-all-interfaces install-types rhel-common
apt-sources dib-init-system ironic-agent rpm-distro
baremetal dib-python iso runtime-ssh-host-keys
base dib-run-parts local-config select-boot-kernel-initrd
block-device-efi disable-selinux manifests selinux-permissive
block-device-gpt dkms mellanox simple-init
block-device-mbr docker modprobe-blacklist source-repositories
bootloader dpkg no-final-image stable-interface-names
cache-url dracut-network oat-client svc-map
centos7 dracut-ramdisk openssh-server sysctl
centos-minimal dracut-regenerate openstack-ci-mirrors sysprep
cleanup-kernel-initrd dynamic-login opensuse uboot
cloud-init element-manifest opensuse-minimal ubuntu
cloud-init-datasources enable-serial-console package-installs ubuntu-common
cloud-init-disable-resizefs epel pip-and-virtualenv ubuntu-core
cloud-init-nocloud fedora pip-cache ubuntu-minimal
debian fedora-minimal pkg-map ubuntu-signed
debian-minimal gentoo posix vm
debian-systemd growroot proliant-tools yum
debian-upstart grub2 pypi yum-minimal
debootstrap hpdsa python-brickclient zipl
deploy-baremetal hwburnin ramdisk zypper
deploy-kexec hwdiscovery ramdisk-base zypper-minimal
deploy-targetcli ilo rax-nova-agent
deploy-tgtadm install-bin redhat-common
每个元素都有在构建镜像时应用到镜像的脚本。下面的示例显示了基本元素的脚本。
[root@director ~]# tree /usr/share/diskimage-builder/elements/base/
/usr/share/diskimage-builder/elements/base/
├── element-deps
├── install.d
│ ├── 00-baseline-environment
│ ├── 00-up-to-date
│ └── 10-cloud-init
├── pkg-map
├── pre-install.d
│ └── 03-baseline-tools
└── README.rst
2 directories, 7 files
📑Diskimage-builder阶段子目录
阶段子目录应该位于元素目录下;默认情况下,它们可能存在,也可能不存在,因此根据需要创建它们。它们包含具有两位数数字前缀的可执行脚本,并按数字顺序执行。约定是将数据文件存储在元素目录中,但是只将可执行脚本存储在阶段子目录中。如果一个脚本是不可执行的,它将不会运行。阶段子目录的处理顺序如下表所示:
📑阶段的子目录
阶段的子目录 | 描述 |
---|---|
root.d | 构建或修改初始根文件系统内容。这是添加定制的地方,比如在现有镜像上构建。只有一个元素一次可以使用它,除非特别注意不要覆盖它,而是调整由其他元素提取的上下文。应该调整前面元素提取的上下文,注意不要覆盖它。 |
extra-data.d | 包括来自主机环境的额外数据,hooks在构建镜像时可能需要这些数据。这会复制$TMP_HOOKS_PATH下的任何数据,比如SSH密钥或HTTP代理设置。 |
pre-install.d | 在进行任何定制或包安装之前,此代码在chroot环境中运行。 |
install.d | 在这个阶段安装操作系统和包。这段代码在chroot环境中运行。 |
post-install.d | 建议在此阶段执行必须在操作系统和应用程序安装之后、镜像第一次引导之前处理的任务。例如,运行systemctl enable来启用所需的服务。 |
block-device.d | 自定义块设备,例如,使分区在cleanup.d阶段之前运行,但在目标树被完全填充之后。 |
finalize.d | 在根文件系统内容复制到挂载的文件系统后,在chroot环境中运行。根文件系统在此阶段进行了调优,因此将操作限制为只影响文件系统元数据和镜像本身所必需的操作,这一点很重要。post-install.d是大多数的首选操作。 |
cleanup.d | 根文件系统内容将清除临时文件。 |
📑Diskimage-builder环境变量
许多环境变量都必须导出,这具体取决于所需的镜像定制。通常,至少导出以下变量:
变量 | 描述 |
---|---|
DIB_LOCAL_IMAGE | 要构建的基础镜像。 |
DIB_YUM_REPO_CONF | 在构建镜像期间,要将客户机Yum存储库配置文件复制到chroot环境中。 |
ELEMENTS_PATH | 元素工作副本的路径。 |
重要:在镜像构建期间将DIB_YUM_REPO_CONF指定的Yum存储库配置文件复制到/etc/yum.repos.d,并在构建完成时删除。这样做的目的是只在构建期间提供指定的Yum存储库访问,而不是在最终的镜像中保留对Yum存储库的访问。然而,这种删除行为可能会导致意想不到的结果;在DIB_YUM_REPO_CONF中指定的Yum存储库配置文件与起始镜像中已经存在的配置文件相匹配,将导致在构建结束时从最终镜像中删除该配置文件。如果需要保留在最终构建的镜像中,则需确保检查现有的存储库配置,并将其排除在DIB_YUM_REPO_CONF之外。
📑Diskimage-builder选项
本节将在以下示例的上下文中讨论一些可用的选项:
vm分配定义了要使用的元素。vm元素为虚拟机磁盘镜像提供了健全的缺省值。rhel7选项指定镜像为Red Hat Enterprise Linux 7。-n选项跳过了默认包含的基本元素,如果您不希望安装cloud-init和包更新,这可能是可取的。-p选项指定要安装哪些包;在本例中,安装了python-dian-compressor package。选项-a指定镜像的体系结构。-o选项指定输出镜像名称。
📑Diskimage-builder的执行
每个元素都包含一组要执行的脚本。在以下摘自diskimage-build.log的日志文件。您可以看到作为根阶段的一部分执行的脚本。
每个脚本的运行时间显示在右侧。驻留在extra-data.d脚本。然后执行阶段子目录:
从这些示例中,您可以确认各个阶段的执行顺序以及每个阶段的脚本执行顺序。
📜课本练习
-
使用diskimage-builder构建和定制镜像。
-
将镜像上传到OpenStack镜像服务中。
-
使用自定义镜像启动实例。
[student@workstation ~]$ lab customization-img-building setup
📑1. 在工作站上,检索http://materials.example.com/osp-small.qcow2磁盘镜像并将其保存在/home/student/下。
[student@workstation ~]$ wget http://materials.example.com/osp-small.qcow2
📑2. 在/home/student/下创建要使用的/usr/share/diskimage-builder/elements目录的副本。
[student@workstation ~]$ cp -a /usr/share/diskimage-builder/elements /home/student/
[student@workstation ~]$ ll
total 1593940
-rw-rw-r--. 1 student student 799 Oct 23 2018 admin-rc
-rw-r--r--. 1 student student 343 Oct 20 12:21 architect1-finance-rc
-rw-r--r--. 1 student student 343 Oct 20 12:22 developer1-finance-rc
drwxr-xr-x. 104 student student 4096 Oct 20 12:21 elements
-rw-r--r--. 1 student student 347 Oct 17 21:57 operator1-production-rc
-rw-rw-r--. 1 student student 1632174080 Oct 11 22:45 osp-small.qcow2
📑3.创建post-install.d目录下的rhe17元素。
[student@workstation ~]$ mkdir -p /home/student/elements/rhel7/post-install.d
📑4.在rhel7元素下post-install.d添加两个脚本,目录中启用命名服务,并将forwards选项添加到/etc/ named.conf。
[student@workstation post-install.d]$ cat 01-enable-services
#!/bin/bash
systemctl enable named
[student@workstation post-install.d]$ cat 02-configure-named
#!/bin/bash
# add forwarders
sed -i 's|\(.*\)\(recursion yes;\)|\1\2\n\1forwarders {172.25.250.254;};|' /etc/named.conf
# allow queries from the local subnet
sed -i 's|\(.*allow-query\).*|\1 { localhost; 192.168.1.0/24; };|' /etc/named.conf
# disable dnssec validation
sed -i 's|\(.*dnssec-validation\).*|\1 no;|' /etc/named.conf
📑5. 更改到/home/student目录并设置脚本的可执行权限。
[student@workstation post-install.d]$ pwd
/home/student/elements/rhel7/post-install.d
[student@workstation post-install.d]$ ll
total 8
-rw-rw-r--. 1 student student 35 Oct 20 14:22 01-enable-services
-rw-rw-r--. 1 student student 333 Oct 20 14:27 02-configure-named
[student@workstation post-install.d]$ chmod +x *
[student@workstation post-install.d]$ ll
total 8
-rwxrwxr-x. 1 student student 35 Oct 20 14:22 01-enable-services
-rwxrwxr-x. 1 student student 333 Oct 20 14:27 02-configure-named
📑6. 导出diskimage-builder需要的以下环境变量。DIB_NO_TMPFS变量是必需的,因为workstation有一个小的硬盘,在大多数情况下不需要它。
[student@workstation ~]$ export DIB_LOCAL_IMAGE=/home/student/osp-small.qcow2
[student@workstation ~]$ export DIB_YUM_REPO_CONF=/etc/yum.repos.d/openstack.repo
[student@workstation ~]$ export ELEMENTS_PATH=/home/student/elements
[student@workstation ~]$ export DIB_NO_TMPFS=1
📑7.构建finance-rhel-dns.qcow2磁盘镜像,包括bind和bind-utils包。前面创建的脚本会自动集成。当提示时输入student的密码。
[student@workstation ~]$ disk-image-create vm rhel7 -t qcow2 -p bind,bind-utils -o finance-rhel-dns.qcow2
📑8. 作为OpenStack的用户developer1,上传finance-rhel-dns.qcow2磁盘镜像到OpenStack镜像服务为finance-rhel-dns,最低磁盘需求为10 GiB,最低RAM需求为2 GiB。
[student@workstation ~(developer1-finance)]$ openstack image create --disk-format qcow2 --min-disk 10 --min-ram 2048 --file finance-rhel-dns.qcow2 finance-rhel-dns
+------------------+----------------------------------------------------------------+
| Field | Value |
+------------------+----------------------------------------------------------------+
| checksum | ba8a1e5d12fe3762753fcab2437f2ba2
| container_format | bare
| created_at | 2020-10-20T07:07:16Z
| disk_format | qcow2
| file | /v2/images/31b174fa-e045-4013-98bd-35e5b796c33a/file
| id | 31b174fa-e045-4013-98bd-35e5b796c33a
| min_disk | 10
| min_ram | 2048
| name | finance-rhel-dns
| owner | 3c003f65d8d64914a053f178fbbf953c
| properties | direct_url='rbd://fe8e3db0-d6c3-11e8-a76d-52540001fac8/images/31b174fa-e045-4013-98bd-35e5b796c33a/snap', locations='[{u'url': u'rbd://fe8e3db0-d6c3-11e8-a76d-52540001fac8/images/31b174fa-e045-4013-98bd-35e5b796c33a/snap', u'metadata': {}}]' |
| protected | False
| schema | /v2/schemas/image
| size | 687603712
| status | active
| tags |
| updated_at | 2020-10-20T07:07:52Z
| virtual_size | None
| visibility | shared
+------------------+----------------------------------------------------------------+
📑9. 使用以下属性在环境中启动实例。
[student@workstation ~(developer1-finance)]$ openstack server create --flavor default --key-name example-keypair --nic net-id=finance-network1 --image finance-rhel-dns --security-group finance-dns --wait finance-dns1
+-----------------------------+-----------------------------------------------------+
| Field | Value
+-----------------------------+-----------------------------------------------------+
| OS-DCF:diskConfig | MANUAL
| OS-EXT-AZ:availability_zone | nova
| OS-EXT-STS:power_state | Running
| OS-EXT-STS:task_state | None
| OS-EXT-STS:vm_state | active
| OS-SRV-USG:launched_at | 2020-10-20T07:22:28.000000
| OS-SRV-USG:terminated_at | None
| accessIPv4 |
| accessIPv6 |
| addresses | finance-network1=192.168.1.4
| adminPass | YeAFGoGd5y3x
| config_drive |
| created | 2020-10-20T07:18:54Z
| flavor | default (e04380ed-b027-4a72-a697-4307bc014b6c)
| hostId | c439f7c83de10e6a305fc9bc9caefdef52c9f503e4aa5733eae8573c |
| id | 837d9b4f-f035-4624-9fa6-b3e92355fc8d
| image | finance-rhel-dns (31b174fa-e045-4013-98bd-35e5b796c33a)
| key_name | example-keypair
| name | finance-dns1
| progress | 0
| project_id | 3c003f65d8d64914a053f178fbbf953c
| properties |
| security_groups | name='finance-dns'
| status | ACTIVE
| updated | 2020-10-20T07:22:29Z
| user_id | e4035d555f6b88cf42ca4cacb9fa9999dca9787392222d2eb0875e4e34e6d76f |
| volumes_attached | |
+-----------------------------+-----------------------------------------------------+
📑10. 列出可用的浮动IP地址,并分配一个给finance-dns1。
[student@workstation ~(developer1-finance)]$ openstack floating ip list -c "Floating IP Address" -c Port
+---------------------+------+
| Floating IP Address | Port |
+---------------------+------+
| 172.25.250.101 | None |
+---------------------+------+
[student@workstation ~(developer1-finance)]$ openstack floating ip list
+--------------------------------------+---------------------+------------------+------+--------------------------------------+----------------------------------+
| ID | Floating IP Address | Fixed IP Address | Port | Floating Network | Project |
+--------------------------------------+---------------------+------------------+------+--------------------------------------+----------------------------------+
| 20e6fda9-9284-4f6a-891e-0d8889c27098 | 172.25.250.101 | None | None | fc5472ee-98d9-4f6b-9bc9-544ca18aefb3 | 3c003f65d8d64914a053f178fbbf953c |
+--------------------------------------+---------------------+------------------+------+--------------------------------------+----------------------------------+
[student@workstation ~(developer1-finance)]$ openstack server add floating ip finance-dns1 172.25.250.101
📑11. 如果镜像构建成功,生成的DNS服务器应该接受查询,并将它们转发到运行在工作站上的域名服务。
[student@workstation ~(developer1-finance)]$ ssh cloud-user@172.25.250.101
[cloud-user@finance-dns1 ~]$
[cloud-user@finance-dns1 ~]$ sudo ss -4lntup | grep named
udp UNCONN 0 0 127.0.0.1:53 *:* users:(("named",pid=884,fd=513),("named",pid=884,fd=512))
tcp LISTEN 0 10 127.0.0.1:53 *:* users:(("named",pid=884,fd=21))
tcp LISTEN 0 128 127.0.0.1:953 *:* users:(("named",pid=884,fd=23))
[cloud-user@finance-dns1 ~]$ dig @localhost example.com NS
; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> @localhost example.com NS
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37700
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;example.com. IN NS
;; ANSWER SECTION:
example.com. 86400 IN NS classroom.example.com.
;; ADDITIONAL SECTION:
classroom.example.com. 86400 IN A 172.25.254.254
;; Query time: 275 msec
;; SERVER: ::1#53(::1)
;; WHEN: Tue Oct 20 03:51:13 EDT 2020
;; MSG SIZE rcvd: 80
注意:输出的flags部分中没有aa标志,这意味着我们查询的服务器不是该example.com域的权威服务器。因此,查询由上游名称服务器回答,finance-dns1必须按照设计工作。
📑清除实验
[student@workstation ~]$ lab customization-img-building cleanup
💡总结
RHCA认证需要经历5门的学习与考试,还是需要花不少时间去学习与备考的,好好加油,可以噶🤪。
以上就是【金鱼哥】对 第四章 执行镜像操作–比较镜像格式+构建定制镜像 的简述和讲解。希望能对看到此文章的小伙伴有所帮助。
💾红帽认证专栏系列:
RHCSA专栏:戏说 RHCSA 认证
RHCE专栏:戏说 RHCE 认证
此文章收录在RHCA专栏:RHCA 回忆录
如果这篇【文章】有帮助到你,希望可以给【金鱼哥】点个赞👍,创作不易,相比官方的陈述,我更喜欢用【通俗易懂】的文笔去讲解每一个知识点。
如果有对【运维技术】感兴趣,也欢迎关注❤️❤️❤️ 【金鱼哥】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💕💕!
- 点赞
- 收藏
- 关注作者
评论(0)