Los Blancos rebounded from a Joshua Kimmich strike in the 28th minute with goals from Marcelo in the 44th minute and substitute Marco Asensio in the 57th to give the reigning champions a commanding lead in the two-legged series.
It was a classic away performance in Europe from Real. While their opponents may have had the better run of play during the 90 minutes, Real’s sterling continental pedigree rose to the surface, as they took full advantage of the chances presented to them and scored with two ruthless finishes.
Manager Zinedine Zidane surprised a few by leaving out striker Karim Benzema from his starting XI. In place of the Frenchman was Lucas Vazquez, while Isco was favoured over Gareth Bale. Otherwise, it was an expected line-up for Los Blancos.
It was an inauspicious start for Bayern boss Jupp Heynckes, who was forced to make a very early change when Arjen Robben sank to the turf with an injury, with former Barcelona man Thiago replacing the Dutchman.
The first 25 minutes were cagey, with neither team getting any clean looks at goal. However, the Germans are capable of striking at any moment and Real got a good taste of that as Kimmich fired in a bullet to hand Bayern a 1-0 advantage.
It started with a brilliant ball from James, who found the charging Kimmich down the right; the right-back left Marcelo in his dust and once Real goalkeeper Keylor Navas leaned to his right in expectation of a cross, Kimmich went near post for the goal.
The injury bug would strike Bayern again, as Jerome Boateng limped off and was replaced by Niklas Sule, but Bayern would press on and Franck Ribery should have made it two but was let down by a heavy touch right in front of Navas. That was followed minutes later by a chance for Mats Hummels off a corner kick and then a Thomas Muller shot that was deflected to safety.
Real were struggling but there was a lifeline to come just before half-time, as Bayern dealt poorly with a ball played in deep and Marcelo made up for his defensive gaffe on the Kimmich goal by rocketing in a left-footer that pulled Los Blancos level 1-1.
The Marcelo goal made it a full-fledge heavyweight bout and back came Bayern fiercely in the closing seconds of the first-half with a pair of efforts that just narrowly missed finding the net.
Just like in the second leg versus Juventus in the previous round, Zidane made a switch at half-time, hauling off Isco and bringing on Asensio. It was a change that would pay handsomely early in the second stanza with Asensio scoring to give Real a 2-1 lead. A poor pass across from Rafinha was pounced on by Asensio, who played to Lucas Vazquez and then received the ball back before curling in a shot past Bayern stopper Ulreich.
Desperate to get back on level terms, Bayern threw everything at Navas and the Costa Rican had to be alert to twice deny Ribery. An injury to Dani Carvajal midway through the half then forced Zidane into his second change, with Benzema coming on to replace the right-back.
There was no let-up from the hosts and if Muller and Robert Lewandowski hadn’t run into each other right in front of goal, there surely would have been an equaliser. Bayern were leaving spaces open in the back though and Benzema was almost able to take advantage but saw his effort saved by Ulreich.
There was one more scare for Real to absorb, as a surgical ball from Tolisso found the streaking Lewandowski, but incredibly the Poland international missed wide, capping a frustrating day for the hosts and sealing another big-time European scalp for Real in 2018.
1.- Bayern Munich: Ulreich; Kimmich, Hummels, Boateng (Sule, min. 34), Rafinha; Javi Martinez (Tolisso, min. 75), Muller, James; Robben (Thiago, min. 8), Ribery, Lewandowski.
2.- Real Madrid: Keylor; Carvajal (Benzema, min. 67), Varane, Ramos, Marcelo; Casemiro (Kovacic, min. 83), Modric, Kroos; Lucas, Isco (Asensio, min. 46), Cristiano Ronaldo.
Goals: 1-0, min. 28: Kimmich; 1-1, min. 44: Marcelo; 1-2, min. 57: Asensio.
Referee: Bjorn Kuipers (Netherlands).
Yellow cards: Ribery (Min. 52) for Bayern Munich, Casemiro (Min. 77) for Real Madrid, Thiago (Min. 89) for Bayern Munich.
Red cards: None.