openSUSE MicroOS | (基于Cockpit)虚拟化安装指南
1. First | 序
本篇简单记录 openSUSE MicroOS 安装记录
openSUSE MicroOS 是一款专门针对容器化工作负载打造的超可靠、轻量级的操作系统
是不可变的 Real-Time OS
1.1. openSUSE MicroOS Features | 特征
- 只读根文件系统,防止对操作系统的意外修改
- Transactional Updates 技术利用 Btrfs 快照在不干扰正在运行的系统的情况下应用软件包更新
- health-checker 在更新后验证操作系统是否正常运行,若出现问题会自动回滚
- cloud-init 用于云环境首次启动时的系统初始配置(包括 OpenStack)
- Combustion 和 Ignition 用于其他所有镜像在首次启动时的系统初始配置
- 设计与现有的 openSUSE 或 SUSE Linux Enterprise 环境无缝衔接
- 提供 Podman 容器运行时
- 滚动发行版:每个新的 openSUSE Tumbleweed 快照都会自动生成一个新的 openSUSE MicroOS 版本;基于 Leap 的版本则会在 Leap 发布维护更新时自动更新
1.2. Installation environment | 安装环境
Virtualized installation
-
Host 宿主机

-
cockpit

1.3. Requirements | 要求
| 项目 | 要求说明 |
|---|---|
| BIOS | 仅支持设置为 UEFI 的主机,不支持传统 BIOS。 |
| CPU 架构 | 支持 AMD64/Intel 64 v2、AArch64、IBM Z。 |
| 最大 CPU 数量 | 支持最多 8192 个 CPU。 |
| 内存 | 最少需要 1 GB RAM(实际需求取决于工作负载)。 |
| 硬盘空间 | 最少 12 GB,推荐 20 GB;如使用 qcow2 映像,至少需要 32 GB。 |
| 容器存储需求 | 需额外规划用于容器工作负载的空间。 |
2. Procedure | 步骤
- 获取 MicroOS 镜像
- Cockpit 设置虚拟机配置参数
- Cockpit 安装过程
2.1. 获取 MicroOS 镜像
根据自身架构登录以下网站获取 MicroOS 镜像

2.2. Cockpit 设置虚拟配置参数
2.2.1. screen | 截图


2.2.2. virsh dumpxml 输出
<domain type='kvm' id='5'>
<name>openSUSE_MicroOS</name>
<uuid>aea1e1ff-e52d-4b7e-9dee-bf2b465cfa5d</uuid>
<metadata xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0" xmlns:cockpit_machines="https://github.com/cockpit-project/cockpit-machines">
<libosinfo:libosinfo>
<libosinfo:os id="http://opensuse.org/opensuse/16.0"/>
</libosinfo:libosinfo>
<cockpit_machines:data>
<cockpit_machines:has_install_phase>false</cockpit_machines:has_install_phase>
<cockpit_machines:install_source_type>file</cockpit_machines:install_source_type>
<cockpit_machines:install_source>/home/data/vmiso/openSUSE-MicroOS-DVD-x86_64-Snapshot20250806-Media.iso</cockpit_machines:install_source>
<cockpit_machines:os_variant>opensuse16.0</cockpit_machines:os_variant>
</cockpit_machines:data>
</metadata>
<memory unit='KiB'>4194304</memory>
<currentMemory unit='KiB'>4194304</currentMemory>
<vcpu placement='static'>4</vcpu>
<resource>
<partition>/machine</partition>
</resource>
<os firmware='efi'>
<type arch='x86_64' machine='pc-q35-10.0'>hvm</type>
<firmware>
<feature enabled='yes' name='enrolled-keys'/>
<feature enabled='yes' name='secure-boot'/>
</firmware>
<loader readonly='yes' secure='yes' type='pflash' format='raw'>/usr/share/qemu/ovmf-x86_64-smm-ms-code.bin</loader>
<nvram template='/usr/share/qemu/ovmf-x86_64-smm-ms-vars.bin' templateFormat='raw' format='raw'>/var/lib/libvirt/qemu/nvram/openSUSE_MicroOS_VARS.fd</nvram>
</os>
<features>
<acpi/>
<apic/>
<vmport state='off'/>
<smm state='on'/>
</features>
<cpu mode='host-passthrough' check='none' migratable='on'/>
<clock offset='utc'>
<timer name='rtc' tickpolicy='catchup'/>
<timer name='pit' tickpolicy='delay'/>
<timer name='hpet' present='no'/>
</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<pm>
<suspend-to-mem enabled='no'/>
<suspend-to-disk enabled='no'/>
</pm>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2' discard='unmap'/>
<source file='/var/lib/libvirt/images/openSUSE_MicroOS.qcow2' index='1'/>
<backingStore/>
<target dev='vda' bus='virtio'/>
<boot order='2'/>
<alias name='virtio-disk0'/>
<address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
</disk>
<controller type='usb' index='0' model='qemu-xhci' ports='15'>
<alias name='usb'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x00' function='0x0'/>
</controller>
<controller type='pci' index='0' model='pcie-root'>
<alias name='pcie.0'/>
</controller>
<controller type='pci' index='1' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='1' port='0x10'/>
<alias name='pci.1'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0' multifunction='on'/>
</controller>
<controller type='pci' index='2' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='2' port='0x11'/>
<alias name='pci.2'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x1'/>
</controller>
<controller type='pci' index='3' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='3' port='0x12'/>
<alias name='pci.3'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x2'/>
</controller>
<controller type='pci' index='4' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='4' port='0x13'/>
<alias name='pci.4'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x3'/>
</controller>
<controller type='pci' index='5' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='5' port='0x14'/>
<alias name='pci.5'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x4'/>
</controller>
<controller type='pci' index='6' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='6' port='0x15'/>
<alias name='pci.6'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x5'/>
</controller>
<controller type='pci' index='7' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='7' port='0x16'/>
<alias name='pci.7'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x6'/>
</controller>
<controller type='pci' index='8' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='8' port='0x17'/>
<alias name='pci.8'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x7'/>
</controller>
<controller type='pci' index='9' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='9' port='0x18'/>
<alias name='pci.9'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0' multifunction='on'/>
</controller>
<controller type='pci' index='10' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='10' port='0x19'/>
<alias name='pci.10'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x1'/>
</controller>
<controller type='pci' index='11' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='11' port='0x1a'/>
<alias name='pci.11'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x2'/>
</controller>
<controller type='pci' index='12' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='12' port='0x1b'/>
<alias name='pci.12'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x3'/>
</controller>
<controller type='pci' index='13' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='13' port='0x1c'/>
<alias name='pci.13'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x4'/>
</controller>
<controller type='pci' index='14' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='14' port='0x1d'/>
<alias name='pci.14'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x5'/>
</controller>
<controller type='pci' index='15' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='15' port='0x1e'/>
<alias name='pci.15'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x6'/>
</controller>
<controller type='pci' index='16' model='pcie-to-pci-bridge'>
<model name='pcie-pci-bridge'/>
<alias name='pci.16'/>
<address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/>
</controller>
<controller type='sata' index='0'>
<alias name='ide'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/>
</controller>
<controller type='virtio-serial' index='0'>
<alias name='virtio-serial0'/>
<address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
</controller>
<controller type='scsi' index='0' model='lsilogic'>
<alias name='scsi0'/>
<address type='pci' domain='0x0000' bus='0x10' slot='0x01' function='0x0'/>
</controller>
<interface type='bridge'>
<mac address='52:54:00:22:72:e3'/>
<source bridge='vmbr0'/>
<target dev='vnet4'/>
<model type='virtio'/>
<alias name='net0'/>
<address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
</interface>
<serial type='pty'>
<source path='/dev/pts/1'/>
<target type='isa-serial' port='0'>
<model name='isa-serial'/>
</target>
<alias name='serial0'/>
</serial>
<console type='pty' tty='/dev/pts/1'>
<source path='/dev/pts/1'/>
<target type='serial' port='0'/>
<alias name='serial0'/>
</console>
<channel type='unix'>
<source mode='bind' path='/run/libvirt/qemu/channel/5-openSUSE_MicroOS/org.qemu.guest_agent.0'/>
<target type='virtio' name='org.qemu.guest_agent.0' state='connected'/>
<alias name='channel0'/>
<address type='virtio-serial' controller='0' bus='0' port='1'/>
</channel>
<channel type='spicevmc'>
<target type='virtio' name='com.redhat.spice.0' state='disconnected'/>
<alias name='channel1'/>
<address type='virtio-serial' controller='0' bus='0' port='2'/>
</channel>
<input type='tablet' bus='usb'>
<alias name='input0'/>
<address type='usb' bus='0' port='1'/>
</input>
<input type='mouse' bus='ps2'>
<alias name='input1'/>
</input>
<input type='keyboard' bus='ps2'>
<alias name='input2'/>
</input>
<tpm model='tpm-crb'>
<backend type='emulator' version='2.0'/>
<alias name='tpm0'/>
</tpm>
<graphics type='vnc' port='5900' autoport='yes' listen='127.0.0.1'>
<listen type='address' address='127.0.0.1'/>
</graphics>
<graphics type='spice' port='5901' autoport='yes' listen='::1'>
<listen type='address' address='::1'/>
<image compression='off'/>
</graphics>
<sound model='ich9'>
<alias name='sound0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x1b' function='0x0'/>
</sound>
<audio id='1' type='spice'/>
<video>
<model type='virtio' heads='1' primary='yes'/>
<alias name='video0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
</video>
<redirdev bus='usb' type='spicevmc'>
<alias name='redir0'/>
<address type='usb' bus='0' port='2'/>
</redirdev>
<redirdev bus='usb' type='spicevmc'>
<alias name='redir1'/>
<address type='usb' bus='0' port='3'/>
</redirdev>
<watchdog model='itco' action='reset'>
<alias name='watchdog0'/>
</watchdog>
<memballoon model='virtio'>
<alias name='balloon0'/>
<address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/>
</memballoon>
<rng model='virtio'>
<backend model='random'>/dev/urandom</backend>
<alias name='rng0'/>
<address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x0'/>
</rng>
</devices>
</domain>
- cdrom 的总线类型需要设置为 sata 而非 scsi , scsi 会出现无法启动的情况

2.3. Cockpit 安装过程
-
启动此虚拟机选择 installation

-
选择安装语言和键盘类型

-
选择系统角色
这里我保持默认

-
NTP 配置
保持默认即可

-
配置 Root 密码

-
安装设置
此界面可以点击具体标题针对不同的项目进行自定义

-
确认安装
若并无自定义的项目则点击右下角进行安装即可

3. Ex | 拓展
当然可以针对安装过程进行适当自定义
这里我自定义如下内容
- Full Disk Encryption (FDE) 全盘加密
- Time Zone 时区
3.1. Full Disk Encryption (FDE) 全盘加密
以下演示 Full Disk Encryption (FDE) 基于 systemd 配合 TPM2 来实现 LUKS2 加密卷的自动解锁

-
点击 分区(Partitioning) 选项进入分区步骤

-
点击 专家分区(Start with Current Proposal) 从当前分区开始

忽略警告

-
选中需要加密的磁盘分区并点击下方的 Edit 编辑此分区

-
勾选 Encrypt Device 加密磁盘选项

-
依次选择以下加密选项即可
-
Encryption method
- Systemd-Based Full Disk Encryption
-
Encryption Password
- 解密密码(自定义即可)
-
PBKDF
- Argon2id
-
Authentication
- TPM2
-
-
忽略关于 LUKS2 and GRUB2 的警告
请忽略此警告
系统会自动将 Boot Loader Type 修改为 Systemd Boot

-
确认操作
确认操作无误后点击右下角 Accept 应用即可

-
验证
VM 安装完成后进入系统查看输入以下命令查看分区是否被加密并且TPM2是否被使用

bootctl 输出如下
👇
System: Firmware: UEFI 2.70 (EDK II 1.00) Firmware Arch: x64 Secure Boot: enabled (user) TPM2 Support: yes Measured UKI: no Boot into FW: supported Current Boot Loader: Product: systemd-boot 257.7+suse.22.g835af70f4e Features: + Boot counting + Menu timeout control + One-shot menu timeout control + Default entry control + One-shot entry control + Support for XBOOTLDR partition + Support for passing random seed to OS + Load drop-in drivers + Support Type #1 sort-key field + Support @saved pseudo-entry + Support Type #1 devicetree field + Enroll SecureBoot keys + Retain SHIM protocols + Menu can be disabled + Multi-Profile UKIs are supported + Boot loader set partition information Partition: /dev/disk/by-partuuid/ddb78fb2-02a9-40c8-9123-7a9a09eb28f9 Loader: `-/EFI/systemd/grub.efi Current Entry: opensuse-microos-6.15.8-1-default-3.conf Default Entry: opensuse-microos-6.15.8-1-default-3.conf

About argon2id
FDE 选项中的 argon2id 算法需要内存大于 4096 MB
请确保内存充足
否则你将会收到以下报错
Command failed (signaled): "/sbin/cryptsetup --batch-mode luksFormat '/dev/sda2' --type luks2 --tries 1 --pbkdf argon2id --key-file -"
sdbootutil-update-predictions.service
在 MicroOS 中 sdbootutil-update-predictions.service 负责预测下一次启动时 PCR 会是什么值,并把这个预测值告诉 TPM
如果 sdbootutil-update-predictions.service 因为种种原因失败
我们需要完全重新注册TPM2时请完成以下操作
-
un-enroll 旧的 TPM2
sudo sdbootutil unenroll --method=tpm2 -
重新注册
sudo sdbootutil --ask-pin enroll --method=tpm2
3.2. Time Zone 时区配置
-
点击 Time Zone 进入时区配置

-
选择所在时区
我这里选择中国台湾省
无误后单击 Accept 应用即可

Thanks & Copy
Full Disk Encryption (FDE)
SUSE Linux Micro 6.1 Documentation
Real-Time OS: The Total Guide to Why and How to Use a Real-Time Operating System
AeonDesktop Project wiki Advanced-Encryption
