mirror of https://github.com/k3s-io/k3s
Merge pull request #67739 from liggitt/hostname-override
Automatic merge from submit-queue (batch tested with PRs 67739, 65222). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.
Honor --hostname-override, report compatible hostname addresses with cloud provider
xref #67714
7828e5d
made cloud providers authoritative for the addresses reported on Node objects, so that the addresses used by the node (and requested as SANs in serving certs) could be verified via cloud provider metadata.
This had the effect of no longer reporting addresses of type Hostname for Node objects for some cloud providers. Cloud providers that have the instance hostname available in metadata should add a `type: Hostname` address to node status. This is being tracked in #67714
This PR does a couple other things to ease the transition to authoritative cloud providers:
* if `--hostname-override` is set on the kubelet, make the kubelet report that `Hostname` address. if it can't be verified via cloud-provider metadata (for cert approval, etc), the kubelet deployer is responsible for fixing the situation by adjusting the kubelet configuration (as they were in 1.11 and previously)
* if `--hostname-override` is not set, *and* the cloud provider didn't report a Hostname address, *and* the auto-detected hostname matches one of the addresses the cloud provider *did* report, make the kubelet report that as a Hostname address. That lets the addresses remain verifiable via cloud provider metadata, while still including a `Hostname` address whenever possible.
/sig node
/sig cloud-provider
/cc @mikedanese
fyi @hh
```release-note
NONE
```
pull/8/head
commit
a26e1ddacc
|
@ -481,6 +481,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
|
|||
|
||||
klet := &Kubelet{
|
||||
hostname: hostname,
|
||||
hostnameOverridden: len(hostnameOverride) > 0,
|
||||
nodeName: nodeName,
|
||||
kubeClient: kubeDeps.KubeClient,
|
||||
heartbeatClient: kubeDeps.HeartbeatClient,
|
||||
|
@ -867,7 +868,11 @@ type serviceLister interface {
|
|||
type Kubelet struct {
|
||||
kubeletConfiguration kubeletconfiginternal.KubeletConfiguration
|
||||
|
||||
hostname string
|
||||
// hostname is the hostname the kubelet detected or was given via flag/config
|
||||
hostname string
|
||||
// hostnameOverridden indicates the hostname was overridden via flag/config
|
||||
hostnameOverridden bool
|
||||
|
||||
nodeName types.NodeName
|
||||
runtimeCache kubecontainer.RuntimeCache
|
||||
kubeClient clientset.Interface
|
||||
|
|
|
@ -490,7 +490,7 @@ func (kl *Kubelet) defaultNodeStatusFuncs() []func(*v1.Node) error {
|
|||
}
|
||||
var setters []func(n *v1.Node) error
|
||||
setters = append(setters,
|
||||
nodestatus.NodeAddress(kl.nodeIP, kl.nodeIPValidator, kl.hostname, kl.externalCloudProvider, kl.cloud, nodeAddressesFunc),
|
||||
nodestatus.NodeAddress(kl.nodeIP, kl.nodeIPValidator, kl.hostname, kl.hostnameOverridden, kl.externalCloudProvider, kl.cloud, nodeAddressesFunc),
|
||||
nodestatus.MachineInfo(string(kl.nodeName), kl.maxPods, kl.podsPerCore, kl.GetCachedMachineInfo, kl.containerManager.GetCapacity,
|
||||
kl.containerManager.GetDevicePluginResourceCapacity, kl.containerManager.GetNodeAllocatableReservation, kl.recordEvent),
|
||||
nodestatus.VersionInfo(kl.cadvisor.VersionInfo, kl.containerRuntime.Type, kl.containerRuntime.Version),
|
||||
|
|
|
@ -59,6 +59,7 @@ type Setter func(node *v1.Node) error
|
|||
func NodeAddress(nodeIP net.IP, // typically Kubelet.nodeIP
|
||||
validateNodeIPFunc func(net.IP) error, // typically Kubelet.nodeIPValidator
|
||||
hostname string, // typically Kubelet.hostname
|
||||
hostnameOverridden bool, // was the hostname force set?
|
||||
externalCloudProvider bool, // typically Kubelet.externalCloudProvider
|
||||
cloud cloudprovider.Interface, // typically Kubelet.cloud
|
||||
nodeAddressesFunc func() ([]v1.NodeAddress, error), // typically Kubelet.cloudResourceSyncManager.NodeAddresses
|
||||
|
@ -111,10 +112,38 @@ func NodeAddress(nodeIP net.IP, // typically Kubelet.nodeIP
|
|||
return fmt.Errorf("failed to get node address from cloud provider that matches ip: %v", nodeIP)
|
||||
}
|
||||
|
||||
// Only add a NodeHostName address if the cloudprovider did not specify any addresses.
|
||||
// (we assume the cloudprovider is authoritative if it specifies any addresses)
|
||||
if len(nodeAddresses) == 0 {
|
||||
nodeAddresses = []v1.NodeAddress{{Type: v1.NodeHostName, Address: hostname}}
|
||||
switch {
|
||||
case len(nodeAddresses) == 0:
|
||||
// the cloud provider didn't specify any addresses
|
||||
nodeAddresses = append(nodeAddresses, v1.NodeAddress{Type: v1.NodeHostName, Address: hostname})
|
||||
|
||||
case !hasAddressType(nodeAddresses, v1.NodeHostName) && hasAddressValue(nodeAddresses, 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,
|
||||
// so we can add it and count on the value being verifiable via cloud provider metadata
|
||||
nodeAddresses = append(nodeAddresses, v1.NodeAddress{Type: v1.NodeHostName, Address: hostname})
|
||||
|
||||
case hostnameOverridden:
|
||||
// the hostname was force-set via flag/config.
|
||||
// this means the hostname might not be able to be validated via cloud provider metadata,
|
||||
// but was a choice by the kubelet deployer we should honor
|
||||
var existingHostnameAddress *v1.NodeAddress
|
||||
for i := range nodeAddresses {
|
||||
if nodeAddresses[i].Type == v1.NodeHostName {
|
||||
existingHostnameAddress = &nodeAddresses[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if existingHostnameAddress == nil {
|
||||
// no existing Hostname address found, add it
|
||||
glog.Warningf("adding overridden hostname of %v to cloudprovider-reported addresses", hostname)
|
||||
nodeAddresses = append(nodeAddresses, v1.NodeAddress{Type: v1.NodeHostName, Address: hostname})
|
||||
} else {
|
||||
// override the Hostname address reported by the cloud provider
|
||||
glog.Warningf("replacing cloudprovider-reported hostname of %v with overridden hostname of %v", existingHostnameAddress.Address, hostname)
|
||||
existingHostnameAddress.Address = hostname
|
||||
}
|
||||
}
|
||||
node.Status.Addresses = nodeAddresses
|
||||
} else {
|
||||
|
@ -163,6 +192,23 @@ func NodeAddress(nodeIP net.IP, // typically Kubelet.nodeIP
|
|||
}
|
||||
}
|
||||
|
||||
func hasAddressType(addresses []v1.NodeAddress, addressType v1.NodeAddressType) bool {
|
||||
for _, address := range addresses {
|
||||
if address.Type == addressType {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
func hasAddressValue(addresses []v1.NodeAddress, addressValue string) bool {
|
||||
for _, address := range addresses {
|
||||
if address.Address == addressValue {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// MachineInfo returns a Setter that updates machine-related information on the node.
|
||||
func MachineInfo(nodeName string,
|
||||
maxPods int,
|
||||
|
|
|
@ -55,6 +55,7 @@ const (
|
|||
func TestNodeAddress(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
hostnameOverride bool
|
||||
nodeIP net.IP
|
||||
nodeAddresses []v1.NodeAddress
|
||||
expectedAddresses []v1.NodeAddress
|
||||
|
@ -151,6 +152,85 @@ func TestNodeAddress(t *testing.T) {
|
|||
expectedAddresses: nil,
|
||||
shouldError: true,
|
||||
},
|
||||
{
|
||||
name: "no cloud reported hostnames",
|
||||
nodeAddresses: []v1.NodeAddress{},
|
||||
expectedAddresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeHostName, Address: testKubeletHostname}, // detected hostname is auto-added in the absence of cloud-reported hostnames
|
||||
},
|
||||
shouldError: false,
|
||||
},
|
||||
{
|
||||
name: "cloud reports hostname, no override",
|
||||
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",
|
||||
nodeAddresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
|
||||
{Type: v1.NodeHostName, Address: "cloud-host"},
|
||||
{Type: v1.NodeExternalIP, Address: "55.55.55.55"},
|
||||
},
|
||||
expectedAddresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
|
||||
{Type: v1.NodeHostName, Address: testKubeletHostname}, // hostname-override wins over cloud-reported hostname
|
||||
{Type: v1.NodeExternalIP, Address: "55.55.55.55"},
|
||||
},
|
||||
hostnameOverride: true,
|
||||
shouldError: false,
|
||||
},
|
||||
{
|
||||
name: "cloud doesn't report hostname, no override, detected hostname mismatch",
|
||||
nodeAddresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
|
||||
{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"},
|
||||
// detected hostname is not auto-added if it doesn't match any cloud-reported addresses
|
||||
},
|
||||
shouldError: false,
|
||||
},
|
||||
{
|
||||
name: "cloud doesn't report hostname, no override, detected hostname match",
|
||||
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, hostname override, hostname mismatch",
|
||||
nodeAddresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
|
||||
{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}, // overridden hostname gets auto-added
|
||||
},
|
||||
hostnameOverride: true,
|
||||
shouldError: false,
|
||||
},
|
||||
}
|
||||
for _, testCase := range cases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
|
@ -178,6 +258,7 @@ func TestNodeAddress(t *testing.T) {
|
|||
setter := NodeAddress(nodeIP,
|
||||
nodeIPValidator,
|
||||
hostname,
|
||||
testCase.hostnameOverride,
|
||||
externalCloudProvider,
|
||||
cloud,
|
||||
nodeAddressesFunc)
|
||||
|
|
Loading…
Reference in New Issue