MS-DOS was structured the same as CP/M: there was a small-ish machine dependent part you ported (called an 'OEM Adaption Kit' at one time), and a hardware independent kernel. At least through 3.0 and probably later, it did not require a PC clone. It ran on all sorts of non-PC 8088/8086 machines. Ever run MS-DOS on an 80186 with 8" floppies? I have. Now, your apps might not run because of machine level assumptions (video, usually), but MS-DOS did.
But the real problem with almost-clones was (as you said) that in practice applications more often than not bypassed the "ABI" and went directly to the hardware, and admittedly that's not MS-DOS fault per se. The result was anyway that lots of software wouldn't run on almost-clones, especially if they moved around too many of the assumed interrupts (e.g. 80186-based PCs - they had some of the peripherals of the 8088/8086 integrated, just not exactly in an IBM PC layout). One system I ran across was an "enhanced" PC-like semi-clone, probably using an 8086 or something better - the local health services had just started a huge campaign where they tried to get everyone to volunteer for a health checkup, and they were followed up with a new one some years later, and on and on (it still goes on, to this day). Anyway, for that early start, they used this MS-DOS computer to collect and print information. But the printer didn't work - the PC was nonstandard. I went to the hospital and figured out why, and patched things and got it working (I don't recall anything today about what or how or even why I could).
CP/M applications though - they didn't, for the most part, bypass anything - maybe that's because people writing the software knew that the hardware could vary wildly. Screen-oriented apps like WordStar usually needed a machine-specific patch for that, but otherwise CP/M software was way more portable than MS-DOS software. PC software though - vendors just thought "IBM PC hardware" and that was it, for the most part.
There were many MSDOS but not 100% IBM PC compatible machines made that got hit in the market because of this, such as the Zenith Z-100/Z-120 , TI PC, etc. If the memory map and everything else didn't exactly match the IBM BIOS setup the application would fail.