TechSomething

Proxmox cluster with dishomogeneous cpu types

TL;DR: #

NO:
for live migration within a proxmox cluster build it with same cpus

Preface: #

I have a proxmox cluster built with what I find lying around or is cheap enough to be justifiable,
so I have different cpu types in the cluster nodes: Amd Ryzen (node1) and Intel i5 (node2).

Using the default cpu type, that has a limited set of instructions, everything work as intended, particularly live migration between the hosts.

Tests: #

I've then tried to edit the custom cpu types (/etc/pve/virtual-guest/cpu-models.conf) adding a custom one that has more cpu instructions thatn the base kvm64 cpu.

But I did not find a reliable way to tell which flags were compatible with the underlying host.

I know that the best scenario is to run a cluster with homogeneous hardware, but I also know that this is what I have available :D

So, my aim is to create a custom cpu profile that contains the flags that are common to both the nodes cpus, so I can have better performance thank the standard kvm64.

So I wrote myself a script to try to match the flags that are common to both the nodes:

#clean the working file:
echo "" > result.txt

cat host1.txt | tr " " "\n" > host1_list.txt
cat host2.txt | tr " " "\n" > host2_list.txt

#loop the list of flags from node 2 against list of flags of node1 and display only the commone ones:
while read p; do
grep -E "(^| )$p( |$)" host1_list.txt >> result.txt
done < host2_list.txt

#format the flags to be used in a proxmox custom cpus file, see: https://pve.proxmox.com/pve-docs/cpu-models.conf.5.html
# sed ':a;N;$!ba;s/\n/;+/g' : substitutes the carriage returns with ;+
# sed 's/;//' : removes the first occurrence of ; from the line
flags=$(cat result.txt | sed ':a;N;$!ba;s/\n/;+/g' | sed 's/;//')

#echo the configurations to write to: /etc/pve/virtual-guest/cpu-models.conf
echo "##############################################"
echo "cpu-model: test"
echo " flags $flags"
echo " phys-bits host"
echo " hidden 0"
echo " hv-vendor-id proxmox"
echo " reported-model kvm64"
echo "##############################################"

#remove workfiles not needed anymore:
rm host1_list.txt host2_list.txt result.txt

Usage: #

# Proxmox_Cpu_Flags
trying to find minimum cpu flags common to 2 nodes in a cluster

## Usage:
execute lscpu on your proxmox nodes, and take the output of the line "Flags:", for example:

```
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand lahf_lm abm cpuid_fault epb invpcid_single pti tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt dtherm ida arat pln pts
```

and save the content without the "Flags:" part in the files:
* host1.txt
* host2.txt

I've used host2.txt with the older cpu but it should be the same

Then execute compare.sh, you should have an output similar to:
```
##############################################
cpu-model: test
flags +fpu;+vme;+de;+pse;+tsc;+msr;+pae;+mce;+cx8;+apic;+sep;+mtrr;+pge;+mca;+cmov;+pat;+pse36;+clflush;+mmx;+fxsr;+sse;+sse2;+ht;+syscall;+nx;+pdpe1gb;+rdtscp;+lm;+constant_tsc;+rep_good;+nopl;+nonstop_tsc;+cpuid;+aperfmperf;+pni;+pclmulqdq;+monitor;+ssse3;+fma;+cx16;+sse4_1;+sse4_2;+movbe;+popcnt;+aes;+xsave;+avx;+f16c;+rdrand;+lahf_lm;+abm;+3dnowprefetch;+ssbd;+ibpb;+fsgsbase;+bmi1;+avx2;+smep;+bmi2;+rdseed;+adx;+smap;+clflushopt;+xsaveopt;+xsavec;+xgetbv1;+xsaves;+arat
phys-bits host
hidden 0
hv-vendor-id proxmox
reported-model kvm64
##############################################

```


this should be inserted on your proxmox node (one is enough) in the file: /etc/pve/virtual-guest/cpu-models.conf

## Nota bene:
right now it's not working as intended (I'm posting on r/proxmox to ask for help)

But it's not working as hoped:

so I tried again to start the vm on Node1 and migrate to Node2, this time I got a nice kernel panic, which is the same output I get when I just start the vm on Node2 without the migration.

image of kernel panic:

description

So there's obviously something wrong in my process, but I am not understanding what, maybe the compatibility is not supported among different cpu types or I am starting from some very wrong assumptions.

I've found another thread where OP selected Ivy-Bridge or Sandy-Bridge to enhance compatibility for migration between the hosts he/she had (Amd and Intel),my question is:is there a reliable way to determine the highest cpu flags/cpu profile supported by both machines?(other than trial and error selecting the various cpu types and trying a live migration)

Reddit post and suggestions: #

I've posted a questione on r/proxmox: post
and u/elettronik gave me some insights I flew over.

Live migration for me is not essential, since most of the projects I host are not that sensitive to a soft and controlled shutdown and re-power on, so it definitely could be a way.

After another bit of fiddling and trying I've managed to fix what I think are the address size in the config file, setting it to the lowest value:

cpu-model: test3
flags +fpu;+de;+pse;+tsc;+msr;+pae;+mce;+cx8;+apic;+sep;+mtrr;+pge;+mca;+cmov;+pat;+pse36;+clflush;+mmx;+fxsr;+sse;+sse2;+syscall;+nx;+pdpe1gb;+rdtscp;+lm;+pni;+pclmulqdq;+ssse3;+cx16;+sse4_1;+sse4_2;+movbe;+popcnt;+aes;+xsave;+rdrand;+lahf_lm;+abm;+fsgsbase;+bmi1;+smep;+bmi2;+adx;+smap;+clflushopt;+xsaveopt;+xgetbv1;+arat;+hypervisor
phys-bits 39
hidden 0
hv-vendor-id proxmox
reported-model kvm64

The flags are tested with:

qemu-system-x86_64 -cpu qemu64,check,+fpu,+de,+pse,+tsc,+msr,+pae,+mce,+cx8,+apic,+sep,+mtrr,+pge,+mca,+cmov,+pat,+pse36,+clflush,+mmx,+fxsr,+sse,+sse2,+syscall,+nx,+pdpe1gb,+rdtscp,+lm,+pni,+pclmulqdq,+ssse3,+cx16,+sse4_1,+sse4_2,+movbe,+popcnt,+aes,+xsave,+rdrand,+lahf_lm,+abm,+fsgsbase,+bmi1,+smep,+bmi2,+adx,+smap,+clflushopt,+xsaveopt,+xgetbv1,+arat,+hypervisor

which with the flag "check" outputs errors in case the flags are not supported on the host, so this seems a reliable way to determine which flags are supported and which not.

So:
dual cpu works ok also on Ryzen, live migration is ok to Intel but the other way around the kernel panics.

Conclusions: #

Right now I've decided to stick with the default kvm64 for all the vms until I'll need some more performance or on the specific vms that will benefit from a broader set of cpu instructions, in the near future I will evaluate the possibility to apply a broader set of instructions but losing live migrations.

So, for reliable production hardware stick with Proxmox's manual and create cluster with same cpu types on the hosts,
otherwise you know what your problems might be.

Bonus: #

benchmark of different cpu flags:

128/256 F = with AES flag
128/256 N = without AWS flag

128 F 256 F 128 N 256 N 128 FvsN 256 FvsN
16B 662910 609306 154295 116026 4.2x 5.2x
64B 1414566 1040415 173676 127442 8x 6x
256B 1460026 1069234 187151 131995 7.8x 8x
1KB 1476740 1075118 375774 272275 4x 4x
8KB 1475370 1073244 383018 278899 3.8x 3.8x
16KB 1478732 1073479 383800 280018 3.8x 3.8x

test run as

openssl speed -evp aes-128-cbc
openssl speed -evp aes-256-cbc

obviously it's a single test but one can see the improvement.