The Premier League leaders raced into a 2-0 lead in a pulsating first-leg encounter with goals from the irrepressible Kevin De Bruyne and Gabriel Jesus in the first 11 minutes.
Real responded through the prolific Karim Benzema before Phil Foden and Vinicius Junior traded goals early in the second half.
Bernardo Silva gave City a two-goal advantage but Benzema scored a cheeky penalty – his 41st goal of the season in as many appearances – to cut the deficit once again.
Both sides spurned numerous other chances in a compelling and breathless clash that set the stage for a fascinating second leg next week.
City may regret not making the most of a number of early opportunities as they stormed out of the blocks. They could almost have put the tie out of sight in the opening half-hour but Real, after fine comebacks against Paris St Germain and Chelsea in the previous two rounds, fought back again.
Real were sluggish and sloppy and continually left spaces for the hosts to exploit. Some of Foden’s touches were exquisite and De Bruyne’s throughballs were a constant danger.
But despite City always having the edge, Foden knows there is still a long way to go.
He admitted it was always going to be a tough ask to hold onto an advantage against a team of Madrid’s European pedigree.
“We were up against a team which has won the Champions League many times and knew that if we gave the ball away in dangerous areas, they were going to punish us,” Foden told BT Sport.
City boss Pep Guardiola added: “It was a fantastic game for both sides.
“We did many good things, unfortunately we conceded goals and could not score more.
“It was a good game and we have another one in a week. We will go to Madrid and try to win the game.”