OK, there are a couple of problems here:
1) You read all the rows, and only use the last value returned (because the loop throws away all the other values) - but you don't specify an order, so SQL can happily return the rows
in any order it sees fit. They will not necessarily be returned in the order they were entered.
In addition, it is a bad idea to return data you don't need - it can slow things down considerably, and waste a lot of memory / SQL server time / bandwidth. Use SELECT only with the data you actually want.
Consider returning only the row you are interested in:
SELECT MAX(ReservationID) FROM Reservation
Will return only the current highest number, which is what I suspect you are interested in.
2) When you convert a string to an integer, you don't "lose" zeros - but the normal method to convert an integer back to a string does not insert leading zeros - so that is the effect you get. To an integer, 00000001 is the same as 1 because leading zeros are completely irrelevant.
Try using ToString with a format to specify the leading zeros instead, or String.Format:
string sub1 = s.Substring(0,1);
int reserveNp = Convert.ToInt32(s.Substring(1)) + 1;
lblReservationID.Text = string.Format("{0}{1:00000}", sub1, reserveNo);
3) There is another problem though: Since you are using SQL there is a good chance that this will be used in a multi user environment, where the idea you are using here will not work: if two users go for a reservation number at the same time, there is a very, very good chance that they will both get the same value.
Where are you creating this reservation ID, and why aren't you keeping the value from there?