It loads the segment descriptor caches (inside the CPU) from the new GDT which the lgdt told the CPU about.
The segment descriptions inside the CPU don't update automatically when you change table entries, or change where the table points.
You can even switch back to real mode with DS base=0 limit=4GiB (and same for ES and SS), and use 32-bit addresses in real mode until the next mov ds, r16 or pop ds instruction overwrites the cached segment description. (This is called big / huge unreal mode, huge if you do it for CS as well, but that's less convenient because interrupts in real mode only save IP, not EIP.)
ljmp is a far jmp, which sets CS (in this case to use a different descriptor than the data descriptors). x86 doesn't allow mov or pop to set CS, only far jump. Presumably the CPU isn't changing modes with this jump, otherwise the asm source would need to use a .code32 or .code16 directive.
The target is the 1: label, in the forward direction. So the mov to %esp is decoded/run with whatever code-segment settings were in GDT index 1. (The low 3 bits of segment selectors are permission bits, so $8 is GDT index 1, and $0x10 is GDT index 2.)
It's a bit weird to separate the mov to %ss from the instruction that sets %esp, because x86 automatically defers interrupts until the instruction after a mov to SS. This lets you atomically set SS:SP without using cli/sti, but probably this code runs with interrupts disabled already. This code probably only runs once during bootup, so it makes sense to just disable interrupts for as long as necessary to set up a new GDT and IDT.
movinstruction. The1fis the address of the label:. So the JMP effectively jumps to the next instruction but sets CS at the same time. - Michael Petch