I think I can now narrow the problem down considerably. When I run the image manually as
/usr/libexec/qemu-kvm -name test -enable-kvm -cpu host -m 4G -nographic -hda /home/kcli/images/podvm.qcow2 -device virtio-net,netdev=netdev0,id=net0 -netdev tap,br=virbr0,helper=/usr/libexec/qemu-bridge-helper,id=netdev0
it will correctly acquire an IP address via virbr0's DHCP, in other words it will do what I expect it to do. I guess this means there's nothing wrong about the image and its DHCP setup.
For comparison, when launched from peer pods the command line is
/usr/libexec/qemu-kvm -name guest=podvm-podsandbox-totok-8f10756a,debug-threads=on -S -object {"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain-23-podvm-podsandbox-tot/master-key.aes"} -machine pc-i440fx-rhel10.0.0,usb=off,vmport=off,dump-guest-core=on,memory-backend=pc.ram,acpi=on -accel kvm -cpu Cascadelake-Server,vmx=on,pdcm=on,hypervisor=on,ss=on,tsc-adjust=on,fdp-excptn-only=on,zero-fcs-fds=on,mpx=on,umip=on,pku=on,md-clear=on,stibp=on,flush-l1d=on,arch-capabilities=on,xsaves=on,ibpb=on,ibrs=on,amd-stibp=on,amd-ssbd=on,rdctl-no=on,ibrs-all=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on,tsx-ctrl=on,sbdr-ssdp-no=on,psdp-no=on,fb-clear=on,gds-no=on,rfds-no=on,vmx-ins-outs=on,vmx-true-ctls=on,vmx-store-lma=on,vmx-activity-hlt=on,vmx-activity-wait-sipi=on,vmx-vmwrite-vmexit-fields=on,vmx-apicv-xapic=on,vmx-ept=on,vmx-desc-exit=on,vmx-rdtscp-exit=on,vmx-apicv-x2apic=on,vmx-vpid=on,vmx-wbinvd-exit=on,vmx-unrestricted-guest=on,vmx-apicv-register=on,vmx-apicv-vid=on,vmx-rdrand-exit=on,vmx-invpcid-exit=on,vmx-vmfunc=on,vmx-shadow-vmcs=on,vmx-rdseed-exit=on,vmx-pml=on,vmx-xsaves=on,vmx-tsc-scaling=on,vmx-ept-execonly=on,vmx-page-walk-4=on,vmx-ept-2mb=on,vmx-ept-1gb=on,vmx-invept=on,vmx-eptad=on,vmx-invept-single-context=on,vmx-invept-all-context=on,vmx-invvpid=on,vmx-invvpid-single-addr=on,vmx-invvpid-all-context=on,vmx-invept-single-context-noglobals=on,vmx-intr-exit=on,vmx-nmi-exit=on,vmx-vnmi=on,vmx-preemption-timer=on,vmx-posted-intr=on,vmx-vintr-pending=on,vmx-tsc-offset=on,vmx-hlt-exit=on,vmx-invlpg-exit=on,vmx-mwait-exit=on,vmx-rdpmc-exit=on,vmx-rdtsc-exit=on,vmx-cr3-load-noexit=on,vmx-cr3-store-noexit=on,vmx-cr8-load-exit=on,vmx-cr8-store-exit=on,vmx-flexpriority=on,vmx-vnmi-pending=on,vmx-movdr-exit=on,vmx-io-exit=on,vmx-io-bitmap=on,vmx-mtf=on,vmx-msr-bitmap=on,vmx-monitor-exit=on,vmx-pause-exit=on,vmx-secondary-ctls=on,vmx-exit-nosave-debugctl=on,vmx-exit-load-perf-global-ctrl=on,vmx-exit-ack-intr=on,vmx-exit-save-pat=on,vmx-exit-load-pat=on,vmx-exit-save-efer=on,vmx-exit-load-efer=on,vmx-exit-save-preemption-timer=on,vmx-exit-clear-bndcfgs=on,vmx-entry-noload-debugctl=on,vmx-entry-ia32e-mode=on,vmx-entry-load-perf-global-ctrl=on,vmx-entry-load-pat=on,vmx-entry-load-efer=on,vmx-entry-load-bndcfgs=on,vmx-eptp-switching=on,hle=off,rtm=off -m size=65536k -object {"qom-type":"memory-backend-ram","id":"pc.ram","size":67108864} -overcommit mem-lock=off -smp 1,sockets=1,cores=1,threads=1 -uuid d71c1e97-5764-4ae4-a1bc-6470523f459c -display none -no-user-config -nodefaults -chardev socket,id=charmonitor,fd=61,server=on,wait=off -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no-shutdown -boot strict=on -device {"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"} -device {"driver":"ahci","id":"sata0","bus":"pci.0","addr":"0x3"} -blockdev {"driver":"file","filename":"/root/kcli/images/podvm.qcow2","node-name":"libvirt-3-storage","auto-read-only":true,"discard":"unmap"} -blockdev {"node-name":"libvirt-3-format","read-only":true,"driver":"qcow2","file":"libvirt-3-storage","backing":null} -blockdev {"driver":"file","filename":"/root/kcli/images/podvm-podsandbox-totok-8f10756a-root.qcow2","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"} -blockdev {"node-name":"libvirt-2-format","read-only":false,"driver":"qcow2","file":"libvirt-2-storage","backing":"libvirt-3-format"} -device {"driver":"ide-hd","bus":"sata0.0","drive":"libvirt-2-format","id":"sata0-0-0","bootindex":1} -blockdev {"driver":"file","filename":"/root/kcli/images/podvm-podsandbox-totok-8f10756a-cloudinit.iso","node-name":"libvirt-1-storage","read-only":true} -device {"driver":"ide-cd","bus":"ide.0","unit":0,"drive":"libvirt-1-storage","id":"ide0-0-0"} -netdev {"type":"tap","fd":"62","vhost":true,"vhostfd":"65","id":"hostnet0"} -device {"driver":"virtio-net-pci","netdev":"hostnet0","id":"net0","mac":"52:54:00:ed:06:2e","bus":"pci.0","addr":"0x2"} -chardev pty,id=charserial0 -device {"driver":"isa-serial","chardev":"charserial0","id":"serial0","index":0} -audiodev {"id":"audio1","driver":"none"} -device {"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x4"} -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny -msg timestamp=on
and the machine doesn't get its IP address.
Where's the important difference? I include the whole domain xml(*) for completeness.
pvl
(*) # virsh dumpxml podvm-podsandbox-totok-8f10756a
<domain type='kvm' id='23'>
<name>podvm-podsandbox-totok-8f10756a</name>
<uuid>d71c1e97-5764-4ae4-a1bc-6470523f459c</uuid>
<description>This Virtual Machine is the peer-pod VM</description>
<memory dumpCore='on' unit='KiB'>65536</memory>
<currentMemory unit='KiB'>65536</currentMemory>
<vcpu placement='static'>1</vcpu>
<resource>
<partition>/machine</partition>
</resource>
<os>
<type arch='x86_64' machine='pc-i440fx-rhel10.0.0'>hvm</type>
</os>
<features>
<acpi/>
<apic/>
<vmport state='off'/>
</features>
<cpu mode='custom' match='exact' check='full'>
<model fallback='forbid'>Cascadelake-Server</model>
<vendor>Intel</vendor>
<feature policy='require' name='vmx'/>
<feature policy='require' name='pdcm'/>
<feature policy='require' name='hypervisor'/>
<feature policy='require' name='ss'/>
<feature policy='require' name='tsc_adjust'/>
<feature policy='require' name='fdp-excptn-only'/>
<feature policy='require' name='zero-fcs-fds'/>
<feature policy='require' name='mpx'/>
<feature policy='require' name='umip'/>
<feature policy='require' name='pku'/>
<feature policy='require' name='md-clear'/>
<feature policy='require' name='stibp'/>
<feature policy='require' name='flush-l1d'/>
<feature policy='require' name='arch-capabilities'/>
<feature policy='require' name='xsaves'/>
<feature policy='require' name='ibpb'/>
<feature policy='require' name='ibrs'/>
<feature policy='require' name='amd-stibp'/>
<feature policy='require' name='amd-ssbd'/>
<feature policy='require' name='rdctl-no'/>
<feature policy='require' name='ibrs-all'/>
<feature policy='require' name='skip-l1dfl-vmentry'/>
<feature policy='require' name='mds-no'/>
<feature policy='require' name='pschange-mc-no'/>
<feature policy='require' name='tsx-ctrl'/>
<feature policy='require' name='sbdr-ssdp-no'/>
<feature policy='require' name='psdp-no'/>
<feature policy='require' name='fb-clear'/>
<feature policy='require' name='gds-no'/>
<feature policy='require' name='rfds-no'/>
<feature policy='require' name='vmx-ins-outs'/>
<feature policy='require' name='vmx-true-ctls'/>
<feature policy='require' name='vmx-store-lma'/>
<feature policy='require' name='vmx-activity-hlt'/>
<feature policy='require' name='vmx-activity-wait-sipi'/>
<feature policy='require' name='vmx-vmwrite-vmexit-fields'/>
<feature policy='require' name='vmx-apicv-xapic'/>
<feature policy='require' name='vmx-ept'/>
<feature policy='require' name='vmx-desc-exit'/>
<feature policy='require' name='vmx-rdtscp-exit'/>
<feature policy='require' name='vmx-apicv-x2apic'/>
<feature policy='require' name='vmx-vpid'/>
<feature policy='require' name='vmx-wbinvd-exit'/>
<feature policy='require' name='vmx-unrestricted-guest'/>
<feature policy='require' name='vmx-apicv-register'/>
<feature policy='require' name='vmx-apicv-vid'/>
<feature policy='require' name='vmx-rdrand-exit'/>
<feature policy='require' name='vmx-invpcid-exit'/>
<feature policy='require' name='vmx-vmfunc'/>
<feature policy='require' name='vmx-shadow-vmcs'/>
<feature policy='require' name='vmx-rdseed-exit'/>
<feature policy='require' name='vmx-pml'/>
<feature policy='require' name='vmx-xsaves'/>
<feature policy='require' name='vmx-tsc-scaling'/>
<feature policy='require' name='vmx-ept-execonly'/>
<feature policy='require' name='vmx-page-walk-4'/>
<feature policy='require' name='vmx-ept-2mb'/>
<feature policy='require' name='vmx-ept-1gb'/>
<feature policy='require' name='vmx-invept'/>
<feature policy='require' name='vmx-eptad'/>
<feature policy='require' name='vmx-invept-single-context'/>
<feature policy='require' name='vmx-invept-all-context'/>
<feature policy='require' name='vmx-invvpid'/>
<feature policy='require' name='vmx-invvpid-single-addr'/>
<feature policy='require' name='vmx-invvpid-all-context'/>
<feature policy='require' name='vmx-invvpid-single-context-noglobals'/>
<feature policy='require' name='vmx-intr-exit'/>
<feature policy='require' name='vmx-nmi-exit'/>
<feature policy='require' name='vmx-vnmi'/>
<feature policy='require' name='vmx-preemption-timer'/>
<feature policy='require' name='vmx-posted-intr'/>
<feature policy='require' name='vmx-vintr-pending'/>
<feature policy='require' name='vmx-tsc-offset'/>
<feature policy='require' name='vmx-hlt-exit'/>
<feature policy='require' name='vmx-invlpg-exit'/>
<feature policy='require' name='vmx-mwait-exit'/>
<feature policy='require' name='vmx-rdpmc-exit'/>
<feature policy='require' name='vmx-rdtsc-exit'/>
<feature policy='require' name='vmx-cr3-load-noexit'/>
<feature policy='require' name='vmx-cr3-store-noexit'/>
<feature policy='require' name='vmx-cr8-load-exit'/>
<feature policy='require' name='vmx-cr8-store-exit'/>
<feature policy='require' name='vmx-flexpriority'/>
<feature policy='require' name='vmx-vnmi-pending'/>
<feature policy='require' name='vmx-movdr-exit'/>
<feature policy='require' name='vmx-io-exit'/>
<feature policy='require' name='vmx-io-bitmap'/>
<feature policy='require' name='vmx-mtf'/>
<feature policy='require' name='vmx-msr-bitmap'/>
<feature policy='require' name='vmx-monitor-exit'/>
<feature policy='require' name='vmx-pause-exit'/>
<feature policy='require' name='vmx-secondary-ctls'/>
<feature policy='require' name='vmx-exit-nosave-debugctl'/>
<feature policy='require' name='vmx-exit-load-perf-global-ctrl'/>
<feature policy='require' name='vmx-exit-ack-intr'/>
<feature policy='require' name='vmx-exit-save-pat'/>
<feature policy='require' name='vmx-exit-load-pat'/>
<feature policy='require' name='vmx-exit-save-efer'/>
<feature policy='require' name='vmx-exit-load-efer'/>
<feature policy='require' name='vmx-exit-save-preemption-timer'/>
<feature policy='require' name='vmx-exit-clear-bndcfgs'/>
<feature policy='require' name='vmx-entry-noload-debugctl'/>
<feature policy='require' name='vmx-entry-ia32e-mode'/>
<feature policy='require' name='vmx-entry-load-perf-global-ctrl'/>
<feature policy='require' name='vmx-entry-load-pat'/>
<feature policy='require' name='vmx-entry-load-efer'/>
<feature policy='require' name='vmx-entry-load-bndcfgs'/>
<feature policy='require' name='vmx-eptp-switching'/>
<feature policy='disable' name='hle'/>
<feature policy='disable' name='rtm'/>
</cpu>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/libexec/qemu-kvm</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/root/kcli/images/podvm-podsandbox-totok-8f10756a-root.qcow2' index='2'/>
<backingStore type='file' index='3'>
<format type='qcow2'/>
<source file='/root/kcli/images/podvm.qcow2'/>
<backingStore/>
</backingStore>
<target dev='sda' bus='sata'/>
<boot order='1'/>
<alias name='sata0-0-0'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/root/kcli/images/podvm-podsandbox-totok-8f10756a-cloudinit.iso' index='1'/>
<backingStore/>
<target dev='hda' bus='ide'/>
<readonly/>
<alias name='ide0-0-0'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
<controller type='usb' index='0' model='piix3-uhci'>
<alias name='usb'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='pci' index='0' model='pci-root'>
<alias name='pci.0'/>
</controller>
<controller type='ide' index='0'>
<alias name='ide'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<controller type='sata' index='0'>
<alias name='sata0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</controller>
<interface type='network'>
<mac address='52:54:00:ed:06:2e'/>
<source network='default' portid='315baa97-2c37-46ad-a0ff-8be16fffb275' bridge='virbr0'/>
<target dev='vnet21'/>
<model type='virtio'/>
<alias name='net0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</interface>
<serial type='pty'>
<source path='/dev/pts/0'/>
<target type='isa-serial' port='0'>
<model name='isa-serial'/>
</target>
<alias name='serial0'/>
</serial>
<console type='pty' tty='/dev/pts/0'>
<source path='/dev/pts/0'/>
<target type='serial' port='0'/>
<alias name='serial0'/>
</console>
<input type='mouse' bus='ps2'>
<alias name='input0'/>
</input>
<input type='keyboard' bus='ps2'>
<alias name='input1'/>
</input>
<audio id='1' type='none'/>
<memballoon model='virtio'>
<alias name='balloon0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</memballoon>
</devices>
<seclabel type='dynamic' model='selinux' relabel='yes'>
<label>system_u:system_r:svirt_t:s0:c62,c325</label>
<imagelabel>system_u:object_r:svirt_image_t:s0:c62,c325</imagelabel>
</seclabel>
<seclabel type='dynamic' model='dac' relabel='yes'>
<label>+107:+107</label>
<imagelabel>+107:+107</imagelabel>
</seclabel>
</domain>