Bernardo beat Thibaut Courtois at his near post to put City ahead after Erling Haaland had already forced two saves from the Madrid goalkeeper.
Toni Kroos then hit the bar for the visitors, but Bernardo struck again when heading in a rebound after Ilkay Gundogan’s effort was blocked.
Madrid have been the comeback kings over the past two season — including in last year’s semifinal against City when going through 6-5 after extra time.
There was to be no repeat on this occasion, however, as Militao headed into his own net in the second half to end Madrid’s hopes, before Alvarez’ late strike.
Guardiola twice won the Champions League when coach of Barcelona, but has failed to add to that total at former club Bayern Munich or City.
His ongoing struggles with City have been difficult to explain.
While the quality of his team has rarely been in question over his seven years in charge, its temperament on Europe’s biggest stage has been.
On too many occasions it has fallen short when the pressure was on — losing to underdogs such as Monaco, Lyon and Tottenham.
It was in command for almost the entirety of the two-legged semifinal against Madrid last year, but still managed to lose after blowing a two-goal lead in the last few minutes at the Bernabeu.
That never looked likely on this occasion, however, as City provided further evidence that it is finally ready to lift the Champions League trophy.
Having been dominated for long periods by Madrid in the first leg, City took control from the start in front of their own fans.
Haaland had two clear chances to score before Bernardo’s opening goal.
He rose to meet Jack Grealish’s scooped cross in the 13th, but could only head straight at Courtois, who blocked the effort on the line.
Haaland forced the keeper into a save at full stretch shortly after with another header that was tipped away.
With the crowd roaring on every challenge, it felt like a matter of time before City would find a breakthrough — and it came in the 23rd.
After denying Haaland twice, Courtois could not keep out Bernardo, who raced onto Kevin de Bruyne’s pass before firing in at the near post.
The sense of relief was unmistakable — from Guardiola as much as anyone else in the stadium as he turned to the crowd, double fist-pumped and blew kisses toward the supporters.
City knows better than anyone how dangerous Madrid can be when the odds are against it.
Having been passive for the opening 30 minutes, the visitors sprung into life.
Vinicius Jr. almost broke clear of Kyle Walker in the box and Karim Benzema nearly seized on another chance.
Madrid was finding their feet and was fractions away from evening the score when Kroos hit the bar from around 25 metres.
It was a warning to City and moments later the home team was celebrating a second goal, with Bernardo the scorer again.
Gundogan burst into the box and when his shot was blocked, Bernardo was the quickest to react, heading the rebound beyond Militao on the line.
Haaland could have killed the game when he came one-on-one with Courtois in the 73rd, but saw his shot diverted onto the bar.
City did not have to wait long for a third, with Militao diverting De Bruyne’s free kick into his own net.
The crowd was already in celebratory mood and was given another goal to cheer when Alvarez burst through and slid a shot past Courtois in injury time.