Christofer Hoff, the director of cloud and virtualization solutions for Cisco's Security Technology Business Unit, said it best in a 2009 personal blog entry: "Incomplete Thought: Virtual Machines Are the Problem, Not the Solution": "VMs have allowed us to take the first steps toward defining, compartmentalizing, and isolating some pretty nasty problems anchored on the sins of our fathers, but they don't do a damned thing to fix them. VMs have certainly allowed us to (literally) 'think outside the box' about how we characterize 'workloads' and have enabled us to begin talking about how we make them somewhat mobile, portable ... There's a bloated, parasitic resource-gobbling cancer inside every VM. For the most part, it's the real reason we even have mass market virtualization today."
If you move a VM to a cloud service, all the problems and limitations move with it. You can only scale vertically before you reach the performance limits by adding more CPU, RAM or IO. Microsoft Exchange 2003 and earlier is a good example where you can add users only for so long before you need to add another server. Breaking up big applications into smaller tiers that can be augmented by adding more of some resource at each tier is one way to increase performance. Exchange 2007 started to break that monolithic model, and certainly Exchange 2010 goes much further. Microsoft's migration from Exchange 2003 to Exchange 2010 (not including the ForeFront Security features) meant a re-architecting of the entire application.
Architecting applications for the cloud is not a matter of just moving process to separate physical boxes or virtual boxes; the inter-process communication needs to be figured out. For example, the underlying network assumptions have to be addressed. Will all the services be on the same network? Will they communicate using unicast, broadcast or multicast? Are the services named in a way that doesn't rely on fixed addresses--i.e., using DNS or something similar? Can the services act independently of each other? Is there a way to notify other relying services, in tiers above and below, that a new instance is available? Is there a way to bleed off connections so that you can gracefully remove the service without cutting off users? I am just beginning to scratch the surface, I haven't touched on storage or discussed making the service available to stakeholders, but you can see why moving a VM to a cloud service is not a hybrid cloud service. There are many, many moving parts that need to be addressed.
Building applications in tiers is not new. N-tier Web applications that have a front end to connect to users, an application tier to perform application processing and a database tier for data storage and retrieval have been built for years, but adding tiers doesn't magically make scaling problems go away, because each tier can be monolithic and inflexible. The move to Web services and the service-oriented architecture (SOA) that was all the rage a few years back was probably the first big step in breaking the tiers into atomic units that could scale horizontally by adding more services into a tier. Each part of a SOA application was responsible for a specific process, much like functions and objects in modern programming languages are responsible for specific processing needs. RESTful services are one way to pull off inter-process communication.