Every container is given the mesh's names
Internal names are written to the machine's hosts file, which serves the machine and not what the machine runs: a container gets its own hosts file holding only its own hostname. So every name the mesh wrote was invisible to the majority of things that need one — and on the machine it always worked, which is exactly what made it easy to miss. It was hit for real in the lab, and worked around by resolving the address on the machine and passing it in. That workaround is now removed, and its absence is the assertion. A file rather than a resolver, which is the decision the mesh already made about names and this extends rather than overturns: it works on every runtime, needs no package and has no failure mode of its own. The stated trigger for a resolver — names that are not one-per-node, service names, wildcards — is still not met. Given by the mesh, not chosen by a module: a module that listed the machines would go stale the day one joins, and one that did not would be a module whose containers cannot reach anything by name. A container that named its own keeps them and gets the mesh's beside them. Only containers, and not the ones on the machine's own network: a runtime refuses to write a hosts file for those, and a file or a service given the field is a declaration the host refuses outright — so getting it wrong breaks the whole machine for something that was never about names.
This commit is contained in:
@@ -1353,9 +1353,17 @@ func declarationWith(ctx context.Context, inv *inventory.Inventory, node string,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// And every machine's name, so a container can reach one. The same set that writes the
|
||||
// machine's own hosts file — one reading, so a container and its machine cannot disagree
|
||||
// about where another machine is.
|
||||
names, err := namesInTheMesh(ctx, inv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return plan.Declaration(catalogue.Rendering{
|
||||
Settings: settings, Generators: gens, Grants: grants, Needed: needed,
|
||||
Certificate: certificate, Authority: authority, Mesh: private})
|
||||
Certificate: certificate, Authority: authority, Mesh: private, Names: names})
|
||||
}
|
||||
|
||||
// onThePrivateNetwork is every node's address on the overlay, sorted.
|
||||
@@ -2736,3 +2744,24 @@ func wouldSend(ctx context.Context, inv *inventory.Inventory,
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// namesInTheMesh is every machine's internal name and the address behind it.
|
||||
//
|
||||
// A machine with no address has no name: writing one that resolves to nothing is worse than not
|
||||
// writing it, because a connection to an address that does not answer hangs where a name that
|
||||
// does not resolve fails at once and says so. That is the rule the hosts file already follows,
|
||||
// and this is the same set read the same way.
|
||||
func namesInTheMesh(ctx context.Context, inv *inventory.Inventory) (map[string]string, error) {
|
||||
places, err := inv.Overlays(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := map[string]string{}
|
||||
for _, p := range places {
|
||||
if strings.TrimSpace(p.Address) == "" {
|
||||
continue
|
||||
}
|
||||
out[overlay.InternalName(p.Name)] = p.Address
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user