Instead of endpoints being a flat list, it is now a list of "subsets"
where each is a struct of {Addresses, Ports}. To generate the list of
endpoints you need to take union of the Cartesian products of the
subsets. This is compact in the vast majority of cases, yet still
represents named ports and corner cases (e.g. each pod has a different
port number).
This also stores subsets in a deterministic order (sorted by hash) to
avoid spurious updates and comparison problems.
This is a fully compatible change - old objects and clients will
keepworking as long as they don't need the new functionality.
This is the prep for multi-port Services, which will add API to produce
endpoints in this new structure.
Prior to attempting to create new ones, cleanup from previous runs.
Timeouts, 500s, etc. are possible here, and if they happen, you don't
want to die forever.
Along the way: Remove the timeout, it was clearly copied from the
previous function and is actually an anti-pattern that needs to be
fixed after discovering it doesn't play well with defers.
Fixes#5722