Merge pull request #80003 from wongma7/cloudprovider-authoritative-hostname

Fix cloud reported hostname being overridden if nodeIP set
This commit is contained in:
Kubernetes Prow Robot 2019-08-21 20:50:32 -07:00 committed by GitHub
commit ebf15029da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 14 deletions

View File

@ -90,40 +90,52 @@ func NodeAddress(nodeIP net.IP, // typically Kubelet.nodeIP
} }
} }
if cloud != nil { if cloud != nil {
nodeAddresses, err := nodeAddressesFunc() cloudNodeAddresses, err := nodeAddressesFunc()
if err != nil { if err != nil {
return err return err
} }
var nodeAddresses []v1.NodeAddress
// For every address supplied by the cloud provider that matches nodeIP, nodeIP is the enforced node address for
// that address Type (like InternalIP and ExternalIP), meaning other addresses of the same Type are discarded.
// See #61921 for more information: some cloud providers may supply secondary IPs, so nodeIP serves as a way to
// ensure that the correct IPs show up on a Node object.
if nodeIP != nil { if nodeIP != nil {
enforcedNodeAddresses := []v1.NodeAddress{} enforcedNodeAddresses := []v1.NodeAddress{}
nodeIPTypes := make(map[v1.NodeAddressType]bool) nodeIPTypes := make(map[v1.NodeAddressType]bool)
for _, nodeAddress := range nodeAddresses { for _, nodeAddress := range cloudNodeAddresses {
if nodeAddress.Address == nodeIP.String() { if nodeAddress.Address == nodeIP.String() {
enforcedNodeAddresses = append(enforcedNodeAddresses, v1.NodeAddress{Type: nodeAddress.Type, Address: nodeAddress.Address}) enforcedNodeAddresses = append(enforcedNodeAddresses, v1.NodeAddress{Type: nodeAddress.Type, Address: nodeAddress.Address})
nodeIPTypes[nodeAddress.Type] = true nodeIPTypes[nodeAddress.Type] = true
} }
} }
if len(enforcedNodeAddresses) > 0 {
for _, nodeAddress := range nodeAddresses {
if !nodeIPTypes[nodeAddress.Type] && nodeAddress.Type != v1.NodeHostName {
enforcedNodeAddresses = append(enforcedNodeAddresses, v1.NodeAddress{Type: nodeAddress.Type, Address: nodeAddress.Address})
}
}
enforcedNodeAddresses = append(enforcedNodeAddresses, v1.NodeAddress{Type: v1.NodeHostName, Address: hostname}) // nodeIP must be among the addresses supplied by the cloud provider
node.Status.Addresses = enforcedNodeAddresses if len(enforcedNodeAddresses) == 0 {
return nil return fmt.Errorf("failed to get node address from cloud provider that matches ip: %v", nodeIP)
} }
return fmt.Errorf("failed to get node address from cloud provider that matches ip: %v", nodeIP)
// nodeIP was found, now use all other addresses supplied by the cloud provider NOT of the same Type as nodeIP.
for _, nodeAddress := range cloudNodeAddresses {
if !nodeIPTypes[nodeAddress.Type] {
enforcedNodeAddresses = append(enforcedNodeAddresses, v1.NodeAddress{Type: nodeAddress.Type, Address: nodeAddress.Address})
}
}
nodeAddresses = enforcedNodeAddresses
} else {
// If nodeIP is unset, just use the addresses provided by the cloud provider as-is
nodeAddresses = cloudNodeAddresses
} }
switch { switch {
case len(nodeAddresses) == 0: case len(cloudNodeAddresses) == 0:
// the cloud provider didn't specify any addresses // the cloud provider didn't specify any addresses
nodeAddresses = append(nodeAddresses, v1.NodeAddress{Type: v1.NodeHostName, Address: hostname}) nodeAddresses = append(nodeAddresses, v1.NodeAddress{Type: v1.NodeHostName, Address: hostname})
case !hasAddressType(nodeAddresses, v1.NodeHostName) && hasAddressValue(nodeAddresses, hostname): case !hasAddressType(cloudNodeAddresses, v1.NodeHostName) && hasAddressValue(cloudNodeAddresses, hostname):
// the cloud provider didn't specify an address of type Hostname, // the cloud provider didn't specify an address of type Hostname,
// but the auto-detected hostname matched an address reported by the cloud provider, // but the auto-detected hostname matched an address reported by the cloud provider,
// so we can add it and count on the value being verifiable via cloud provider metadata // so we can add it and count on the value being verifiable via cloud provider metadata

View File

@ -179,6 +179,21 @@ func TestNodeAddress(t *testing.T) {
}, },
shouldError: false, shouldError: false,
}, },
{
name: "cloud reports hostname, nodeIP is set, no override",
nodeIP: net.ParseIP("10.1.1.1"),
nodeAddresses: []v1.NodeAddress{
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
{Type: v1.NodeExternalIP, Address: "55.55.55.55"},
{Type: v1.NodeHostName, Address: "cloud-host"},
},
expectedAddresses: []v1.NodeAddress{
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
{Type: v1.NodeExternalIP, Address: "55.55.55.55"},
{Type: v1.NodeHostName, Address: "cloud-host"}, // cloud-reported hostname wins over detected hostname
},
shouldError: false,
},
{ {
name: "cloud reports hostname, overridden", name: "cloud reports hostname, overridden",
nodeAddresses: []v1.NodeAddress{ nodeAddresses: []v1.NodeAddress{
@ -233,6 +248,37 @@ func TestNodeAddress(t *testing.T) {
}, },
shouldError: false, shouldError: false,
}, },
{
name: "cloud doesn't report hostname, nodeIP is set, no override, detected hostname match",
nodeIP: net.ParseIP("10.1.1.1"),
nodeAddresses: []v1.NodeAddress{
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
{Type: v1.NodeExternalIP, Address: "55.55.55.55"},
{Type: v1.NodeExternalDNS, Address: testKubeletHostname}, // cloud-reported address value matches detected hostname
},
expectedAddresses: []v1.NodeAddress{
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
{Type: v1.NodeExternalIP, Address: "55.55.55.55"},
{Type: v1.NodeExternalDNS, Address: testKubeletHostname},
{Type: v1.NodeHostName, Address: testKubeletHostname}, // detected hostname gets auto-added
},
shouldError: false,
},
{
name: "cloud doesn't report hostname, nodeIP is set, no override, detected hostname match with same type as nodeIP",
nodeIP: net.ParseIP("10.1.1.1"),
nodeAddresses: []v1.NodeAddress{
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
{Type: v1.NodeInternalIP, Address: testKubeletHostname}, // cloud-reported address value matches detected hostname
{Type: v1.NodeExternalIP, Address: "55.55.55.55"},
},
expectedAddresses: []v1.NodeAddress{
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
{Type: v1.NodeExternalIP, Address: "55.55.55.55"},
{Type: v1.NodeHostName, Address: testKubeletHostname}, // detected hostname gets auto-added
},
shouldError: false,
},
{ {
name: "cloud doesn't report hostname, hostname override, hostname mismatch", name: "cloud doesn't report hostname, hostname override, hostname mismatch",
nodeAddresses: []v1.NodeAddress{ nodeAddresses: []v1.NodeAddress{