Spain strengthened their position at the top of Nations League Group A4 with a 1-0 win over Switzerland in Madrid.
Spain went close again with a header by Manchester City's Ferran Torres, which was palmed away by the Swiss keeper.
Wolves forward Adama Traore was sent on to make his competitive debut as the hour mark approached, but Spain could not conjure a second goal.
Borussia Monchengladbach defender Matthias Ginter put Germany in front in the 20th minute when he stabbed in a low cross from Antonio Rudiger on the right.
Ukraine goalkeeper Georgiy Bushchan had produced some fine reaction stops, but his handling error saw Germany move 2-0 ahead early in the second half.
Lukas Klostermann floated a deep cross in from the right, which Bushchan spilled onto Leon Goretzka's head and the ball dropped back into the net.
As the hour passed, Dynamo Kyiv winger Viktor Tsygankov shot straight at Germany goalkeeper Manuel Neuer.
With 15 minutes left, Ukraine were awarded a penalty when Roman Yaremchuk was tripped by Niklas Sule, and Ruslan Malinovskyi converted to set up a tense finale.
Germany, though, saw out the closing stages to collect all three points, which moves them two behind Spain in second place.
Elsewhere on Saturday, in Group C1 Montenegro beat Azerbaijan 2-0 to maintain a 100 per cent record from three games.
Luxembourg beat Cyprus 2-0 with a first-half brace from Norwich midfielder Danel Sinani, who is on loan at Belgian club Waasland-Beveren.