By xzllll

openSUSE MicroOS | (基于Cockpit)虚拟化安装指南

指南 | Guides 2025年8月9日

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

  1. Host 宿主机

  2. 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 | 步骤

  1. 获取 MicroOS 镜像
  2. Cockpit 设置虚拟机配置参数
  3. Cockpit 安装过程

2.1. 获取 MicroOS 镜像

根据自身架构登录以下网站获取 MicroOS 镜像

Portal:MicroOS/Downloads - openSUSE Wiki

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>

⚠️
注意
  1. cdrom 的总线类型需要设置为 sata 而非 scsi , scsi 会出现无法启动的情况

2.3. Cockpit 安装过程

  1. 启动此虚拟机选择 installation

  2. 选择安装语言和键盘类型

  3. 选择系统角色

    这里我保持默认

  4. NTP 配置

    保持默认即可

  5. 配置 Root 密码

  6. 安装设置

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

  7. 确认安装

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

3. Ex | 拓展

当然可以针对安装过程进行适当自定义

这里我自定义如下内容

  1. Full Disk Encryption (FDE) 全盘加密
  2. Time Zone 时区

3.1. Full Disk Encryption (FDE) 全盘加密

以下演示 Full Disk Encryption (FDE) 基于 systemd 配合 TPM2 来实现 LUKS2 加密卷的自动解锁

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

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

    忽略警告

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

  4. 勾选 Encrypt Device 加密磁盘选项

  5. 依次选择以下加密选项即可

    • Encryption method

      • Systemd-Based Full Disk Encryption
    • Encryption Password

      • 解密密码(自定义即可)
    • PBKDF

      • Argon2id
    • Authentication

      • TPM2
  6. 忽略关于 LUKS2 and GRUB2 的警告

    请忽略此警告

    系统会自动将 Boot Loader Type 修改为 Systemd Boot

  7. 确认操作

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

  8. 验证

    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时请完成以下操作

  1. un-enroll 旧的 TPM2

    sudo sdbootutil unenroll --method=tpm2
    
  2. 重新注册

    sudo sdbootutil --ask-pin enroll --method=tpm2
    

3.2. Time Zone 时区配置

  1. 点击 Time Zone 进入时区配置

  2. 选择所在时区

    我这里选择中国台湾省

    无误后单击 Accept 应用即可

Thanks & Copy

en.opensuse.org

Full Disk Encryption (FDE)

Documentation

documentation.suse.com

SUSE Linux Micro 6.1 Documentation

Documentation

suse.com

Real-Time OS: The Total Guide to Why and How to Use a Real-Time Operating System

Documentation

github.com

AeonDesktop Project wiki Advanced-Encryption

Learn more

标签

xzllll

三分钟热度三分钟收获