AppArmor is a pretty excellent framework. It clearly works according to its design. There are only two major problems, one of which is: apps can't give out useful error messages when an AppArmor check fails.
Since LSMs insert themselves inside the kernel, the only thing they can really do if an access check fails is force the system call to return EPERM, "permission denied." An app can't actually tell whether it has been denied access because of filesystem permissions, LSM interference, or the phase of the moon, because the return code can't carry any metadata like that. Besides which, it's considered bad practice to give an attacker detail about a failing security check, thus the ubiquitous and uninformative "We emailed you a password reset link if you gave us a valid email" message in password reset flows.
Thus, the hapless administrator does something perfectly reasonable, AppArmor denies it, and it becomes an adventure to find the real error message. AppArmor tends to hide its messages away in a special log file, so that the normal channels and the app's log (if different) only show a useless EPERM message for a file that the app would seem to have access to upon inspection of the filesystem.
Adding more trickiness, AppArmor itself doesn't always apply to an application, so testing a command from a root shell will generally work without issue. Those root shells are typically "unconfined" and don't apply the profiles to commands run from them.
The other main problem is that it requires profile developers to be near-omniscient. It's nice that tcpdump has a generic mechanism to run a command on log rotation, but the default AppArmor profile only sets up access for gzip or bzip2... and even then, if it's a *.pcap file outside of $HOME, it can't be compressed because the AppArmor profile doesn't support creating a file with the compressed extension. (That can be fixed.)
It's nice that charon (part of strongswan) has a mechanism to include /etc/ipsec.*.secrets so that I could store everyone's password in /etc/ipsec.$USER.secrets ... but the profile doesn't let charon list what those files are even though it grants access to the files in question. So using the include command straight out of the example/documentation will, by default, allow the strongswan service to start... but it won't be able to handle any connections.
I had SELinux issues in the past (which share all the drawbacks of AppArmor since it's just another LSM) when I put an Apache DocumentRoot outside of /var/www. In that case, though, I disabled SELinux entirely instead of trying to learn about it.
tl;dr: it's pretty much a recipe for Guide Dang It.