The Portuguese Movistar rider launched an attack with 2km to go on the slopes up to Verbier after a 218.3km ride from Verbania, successfully catching the RadioShack-Nissan rider to win by four seconds.
Luxembourg's Schleck had himself attacked with 6km remaining, but he had gone too early, unable to generate enough power for the final 200m sprint.
Euskaltel’s Mikel Nieve Ituralde was third, 12 seconds off Costa’s winning time of six hours, 21 minutes and 13 seconds.
Costa is eight seconds ahead of Schleck in the general classification, with Roman Kreuziger of Astana 15 seconds back in third.
Peter Sagan, who won the opening stage to take an early lead, dropped out of the running after struggling with a climb with 12km remaining.
The Slovakian Liquigas rider finished 129th on the day, almost 13 minutes off the pace.