Real, eyeing a third straight title, needed a 44th-minute equaliser by Marcelo against the run of play to cancel out Joshua Kimmich's opener after Bayern, chasing three trophies this season, had missed a hatful of chances.
A perfect break allowed Real substitute Marco Asensio to beat Sven Ulreich with a fine effort and grab the winner in the 57th minute.
The result was identical to last year's quarter-final first leg between the teams before Real won the return game as well on the way to the first successful Champions League title defence.
Liverpool crushed AS Roma 5-2 in the other semi-final first leg on Tuesday.
They almost scored after 25 seconds when Real defender Dani Carvajal failed to clear properly in a furious and physical start to the match.
The hosts' game plan seemed to go out the window after eight minutes with speedy winger Arjen Robben was forced off with an ankle injury.
The Bavarians should have scored again even after another setback when Jerome Boateng went off with a thigh muscle injury, with chances falling to Franck Ribery, Mats Hummels and Thomas Mueller.
But it was Real who struck against the run of play with a low drive from Marcelo a minute before the break as the Brazilian full back added to his goals against Paris St Germain and Juventus in previous rounds.
Bayern struggled to recover from the blow and despite having nearly 60 percent of possession they could not find an equaliser.
The defeat snapped Bayern coach Jupp Heynckes's 12-game winning streak in the competition stretching back to 2013.