mirror of https://github.com/k3s-io/k3s
Report node DNS info with --node-ip
```release-note Report node DNS info with --node-ip flag ```pull/8/head
parent
029c1d8b23
commit
1a218aaee2
|
@ -191,7 +191,6 @@ func (cnc *CloudNodeController) updateNodeAddress(node *v1.Node, instances cloud
|
||||||
glog.Errorf("Specified Node IP not found in cloudprovider")
|
glog.Errorf("Specified Node IP not found in cloudprovider")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nodeAddresses = []v1.NodeAddress{*nodeIP}
|
|
||||||
}
|
}
|
||||||
newNode := node.DeepCopy()
|
newNode := node.DeepCopy()
|
||||||
newNode.Status.Addresses = nodeAddresses
|
newNode.Status.Addresses = nodeAddresses
|
||||||
|
|
|
@ -854,7 +854,7 @@ func TestNodeProvidedIPAddresses(t *testing.T) {
|
||||||
|
|
||||||
assert.Equal(t, 1, len(fnh.UpdatedNodes), "Node was not updated")
|
assert.Equal(t, 1, len(fnh.UpdatedNodes), "Node was not updated")
|
||||||
assert.Equal(t, "node0", fnh.UpdatedNodes[0].Name, "Node was not updated")
|
assert.Equal(t, "node0", fnh.UpdatedNodes[0].Name, "Node was not updated")
|
||||||
assert.Equal(t, 1, len(fnh.UpdatedNodes[0].Status.Addresses), "Node status unexpectedly updated")
|
assert.Equal(t, 3, len(fnh.UpdatedNodes[0].Status.Addresses), "Node status unexpectedly updated")
|
||||||
|
|
||||||
cloudNodeController.Run()
|
cloudNodeController.Run()
|
||||||
|
|
||||||
|
@ -862,7 +862,7 @@ func TestNodeProvidedIPAddresses(t *testing.T) {
|
||||||
|
|
||||||
updatedNodes := fnh.GetUpdatedNodesCopy()
|
updatedNodes := fnh.GetUpdatedNodesCopy()
|
||||||
|
|
||||||
assert.Equal(t, 1, len(updatedNodes[0].Status.Addresses), 1, "Node Addresses not correctly updated")
|
assert.Equal(t, 3, len(updatedNodes[0].Status.Addresses), "Node Addresses not correctly updated")
|
||||||
assert.Equal(t, "10.0.0.1", updatedNodes[0].Status.Addresses[0].Address, "Node Addresses not correctly updated")
|
assert.Equal(t, "10.0.0.1", updatedNodes[0].Status.Addresses[0].Address, "Node Addresses not correctly updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ package apis
|
||||||
const (
|
const (
|
||||||
// When kubelet is started with the "external" cloud provider, then
|
// When kubelet is started with the "external" cloud provider, then
|
||||||
// it sets this annotation on the node to denote an ip address set from the
|
// it sets this annotation on the node to denote an ip address set from the
|
||||||
// cmd line flag. This ip is verified with the cloudprovider as valid by
|
// cmd line flag (--node-ip). This ip is verified with the cloudprovider as valid by
|
||||||
// the cloud-controller-manager
|
// the cloud-controller-manager
|
||||||
AnnotationProvidedIPAddr = "alpha.kubernetes.io/provided-node-ip"
|
AnnotationProvidedIPAddr = "alpha.kubernetes.io/provided-node-ip"
|
||||||
)
|
)
|
||||||
|
|
|
@ -521,6 +521,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
|
||||||
containerManager: kubeDeps.ContainerManager,
|
containerManager: kubeDeps.ContainerManager,
|
||||||
containerRuntimeName: containerRuntime,
|
containerRuntimeName: containerRuntime,
|
||||||
nodeIP: parsedNodeIP,
|
nodeIP: parsedNodeIP,
|
||||||
|
nodeIPValidator: validateNodeIP,
|
||||||
clock: clock.RealClock{},
|
clock: clock.RealClock{},
|
||||||
enableControllerAttachDetach: kubeCfg.EnableControllerAttachDetach,
|
enableControllerAttachDetach: kubeCfg.EnableControllerAttachDetach,
|
||||||
iptClient: utilipt.New(utilexec.New(), utildbus.New(), utilipt.ProtocolIpv4),
|
iptClient: utilipt.New(utilexec.New(), utildbus.New(), utilipt.ProtocolIpv4),
|
||||||
|
@ -1070,6 +1071,9 @@ type Kubelet struct {
|
||||||
// If non-nil, use this IP address for the node
|
// If non-nil, use this IP address for the node
|
||||||
nodeIP net.IP
|
nodeIP net.IP
|
||||||
|
|
||||||
|
// use this function to validate the kubelet nodeIP
|
||||||
|
nodeIPValidator func(net.IP) error
|
||||||
|
|
||||||
// If non-nil, this is a unique identifier for the node in an external database, eg. cloudprovider
|
// If non-nil, this is a unique identifier for the node in an external database, eg. cloudprovider
|
||||||
providerID string
|
providerID string
|
||||||
|
|
||||||
|
|
|
@ -407,7 +407,7 @@ func (kl *Kubelet) recordNodeStatusEvent(eventType, event string) {
|
||||||
// Set IP and hostname addresses for the node.
|
// Set IP and hostname addresses for the node.
|
||||||
func (kl *Kubelet) setNodeAddress(node *v1.Node) error {
|
func (kl *Kubelet) setNodeAddress(node *v1.Node) error {
|
||||||
if kl.nodeIP != nil {
|
if kl.nodeIP != nil {
|
||||||
if err := validateNodeIP(kl.nodeIP); err != nil {
|
if err := kl.nodeIPValidator(kl.nodeIP); err != nil {
|
||||||
return fmt.Errorf("failed to validate nodeIP: %v", err)
|
return fmt.Errorf("failed to validate nodeIP: %v", err)
|
||||||
}
|
}
|
||||||
glog.V(2).Infof("Using node IP: %q", kl.nodeIP.String())
|
glog.V(2).Infof("Using node IP: %q", kl.nodeIP.String())
|
||||||
|
@ -467,12 +467,22 @@ func (kl *Kubelet) setNodeAddress(node *v1.Node) error {
|
||||||
}
|
}
|
||||||
if kl.nodeIP != nil {
|
if kl.nodeIP != nil {
|
||||||
enforcedNodeAddresses := []v1.NodeAddress{}
|
enforcedNodeAddresses := []v1.NodeAddress{}
|
||||||
|
|
||||||
|
var nodeIPType v1.NodeAddressType
|
||||||
for _, nodeAddress := range nodeAddresses {
|
for _, nodeAddress := range nodeAddresses {
|
||||||
if nodeAddress.Address == kl.nodeIP.String() {
|
if nodeAddress.Address == kl.nodeIP.String() {
|
||||||
enforcedNodeAddresses = append(enforcedNodeAddresses, v1.NodeAddress{Type: nodeAddress.Type, Address: nodeAddress.Address})
|
enforcedNodeAddresses = append(enforcedNodeAddresses, v1.NodeAddress{Type: nodeAddress.Type, Address: nodeAddress.Address})
|
||||||
|
nodeIPType = nodeAddress.Type
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(enforcedNodeAddresses) > 0 {
|
if len(enforcedNodeAddresses) > 0 {
|
||||||
|
for _, nodeAddress := range nodeAddresses {
|
||||||
|
if nodeAddress.Type != nodeIPType && nodeAddress.Type != v1.NodeHostName {
|
||||||
|
enforcedNodeAddresses = append(enforcedNodeAddresses, v1.NodeAddress{Type: nodeAddress.Type, Address: nodeAddress.Address})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enforcedNodeAddresses = append(enforcedNodeAddresses, v1.NodeAddress{Type: v1.NodeHostName, Address: kl.GetHostname()})
|
enforcedNodeAddresses = append(enforcedNodeAddresses, v1.NodeAddress{Type: v1.NodeHostName, Address: kl.GetHostname()})
|
||||||
node.Status.Addresses = enforcedNodeAddresses
|
node.Status.Addresses = enforcedNodeAddresses
|
||||||
return nil
|
return nil
|
||||||
|
@ -513,7 +523,7 @@ func (kl *Kubelet) setNodeAddress(node *v1.Node) error {
|
||||||
var addrs []net.IP
|
var addrs []net.IP
|
||||||
addrs, _ = net.LookupIP(node.Name)
|
addrs, _ = net.LookupIP(node.Name)
|
||||||
for _, addr := range addrs {
|
for _, addr := range addrs {
|
||||||
if err = validateNodeIP(addr); err == nil {
|
if err = kl.nodeIPValidator(addr); err == nil {
|
||||||
if addr.To4() != nil {
|
if addr.To4() != nil {
|
||||||
ipAddr = addr
|
ipAddr = addr
|
||||||
break
|
break
|
||||||
|
|
|
@ -139,80 +139,163 @@ func TestNodeStatusWithCloudProviderNodeIP(t *testing.T) {
|
||||||
kubelet.kubeClient = nil // ensure only the heartbeat client is used
|
kubelet.kubeClient = nil // ensure only the heartbeat client is used
|
||||||
kubelet.hostname = testKubeletHostname
|
kubelet.hostname = testKubeletHostname
|
||||||
|
|
||||||
existingNode := v1.Node{
|
cases := []struct {
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname, Annotations: make(map[string]string)},
|
name string
|
||||||
Spec: v1.NodeSpec{},
|
nodeIP net.IP
|
||||||
|
nodeAddresses []v1.NodeAddress
|
||||||
|
expectedAddresses []v1.NodeAddress
|
||||||
|
shouldError bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "A single InternalIP",
|
||||||
|
nodeIP: net.ParseIP("10.1.1.1"),
|
||||||
|
nodeAddresses: []v1.NodeAddress{
|
||||||
|
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
|
||||||
|
{Type: v1.NodeHostName, Address: testKubeletHostname},
|
||||||
|
},
|
||||||
|
expectedAddresses: []v1.NodeAddress{
|
||||||
|
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
|
||||||
|
{Type: v1.NodeHostName, Address: testKubeletHostname},
|
||||||
|
},
|
||||||
|
shouldError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "NodeIP is external",
|
||||||
|
nodeIP: net.ParseIP("55.55.55.55"),
|
||||||
|
nodeAddresses: []v1.NodeAddress{
|
||||||
|
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
|
||||||
|
{Type: v1.NodeExternalIP, Address: "55.55.55.55"},
|
||||||
|
{Type: v1.NodeHostName, Address: testKubeletHostname},
|
||||||
|
},
|
||||||
|
expectedAddresses: []v1.NodeAddress{
|
||||||
|
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
|
||||||
|
{Type: v1.NodeExternalIP, Address: "55.55.55.55"},
|
||||||
|
{Type: v1.NodeHostName, Address: testKubeletHostname},
|
||||||
|
},
|
||||||
|
shouldError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Accommodating #45201 and #49202
|
||||||
|
name: "InternalIP and ExternalIP are the same",
|
||||||
|
nodeIP: net.ParseIP("55.55.55.55"),
|
||||||
|
nodeAddresses: []v1.NodeAddress{
|
||||||
|
{Type: v1.NodeInternalIP, Address: "55.55.55.55"},
|
||||||
|
{Type: v1.NodeExternalIP, Address: "55.55.55.55"},
|
||||||
|
{Type: v1.NodeHostName, Address: testKubeletHostname},
|
||||||
|
},
|
||||||
|
expectedAddresses: []v1.NodeAddress{
|
||||||
|
{Type: v1.NodeInternalIP, Address: "55.55.55.55"},
|
||||||
|
{Type: v1.NodeExternalIP, Address: "55.55.55.55"},
|
||||||
|
{Type: v1.NodeHostName, Address: testKubeletHostname},
|
||||||
|
},
|
||||||
|
shouldError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "An Internal/ExternalIP, an Internal/ExternalDNS",
|
||||||
|
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.NodeInternalDNS, Address: "ip-10-1-1-1.us-west-2.compute.internal"},
|
||||||
|
{Type: v1.NodeExternalDNS, Address: "ec2-55-55-55-55.us-west-2.compute.amazonaws.com"},
|
||||||
|
{Type: v1.NodeHostName, Address: testKubeletHostname},
|
||||||
|
},
|
||||||
|
expectedAddresses: []v1.NodeAddress{
|
||||||
|
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
|
||||||
|
{Type: v1.NodeExternalIP, Address: "55.55.55.55"},
|
||||||
|
{Type: v1.NodeInternalDNS, Address: "ip-10-1-1-1.us-west-2.compute.internal"},
|
||||||
|
{Type: v1.NodeExternalDNS, Address: "ec2-55-55-55-55.us-west-2.compute.amazonaws.com"},
|
||||||
|
{Type: v1.NodeHostName, Address: testKubeletHostname},
|
||||||
|
},
|
||||||
|
shouldError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "An Internal with multiple internal IPs",
|
||||||
|
nodeIP: net.ParseIP("10.1.1.1"),
|
||||||
|
nodeAddresses: []v1.NodeAddress{
|
||||||
|
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "10.2.2.2"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "10.3.3.3"},
|
||||||
|
{Type: v1.NodeExternalIP, Address: "55.55.55.55"},
|
||||||
|
{Type: v1.NodeHostName, Address: testKubeletHostname},
|
||||||
|
},
|
||||||
|
expectedAddresses: []v1.NodeAddress{
|
||||||
|
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
|
||||||
|
{Type: v1.NodeExternalIP, Address: "55.55.55.55"},
|
||||||
|
{Type: v1.NodeHostName, Address: testKubeletHostname},
|
||||||
|
},
|
||||||
|
shouldError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "An InternalIP that isn't valid: should error",
|
||||||
|
nodeIP: net.ParseIP("10.2.2.2"),
|
||||||
|
nodeAddresses: []v1.NodeAddress{
|
||||||
|
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
|
||||||
|
{Type: v1.NodeExternalIP, Address: "55.55.55.55"},
|
||||||
|
{Type: v1.NodeHostName, Address: testKubeletHostname},
|
||||||
|
},
|
||||||
|
expectedAddresses: nil,
|
||||||
|
shouldError: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
for _, testCase := range cases {
|
||||||
// TODO : is it possible to mock validateNodeIP() to avoid relying on the host interface addresses ?
|
// testCase setup
|
||||||
addrs, err := net.InterfaceAddrs()
|
existingNode := v1.Node{
|
||||||
assert.NoError(t, err)
|
ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname, Annotations: make(map[string]string)},
|
||||||
for _, addr := range addrs {
|
Spec: v1.NodeSpec{},
|
||||||
var ip net.IP
|
|
||||||
switch v := addr.(type) {
|
|
||||||
case *net.IPNet:
|
|
||||||
ip = v.IP
|
|
||||||
case *net.IPAddr:
|
|
||||||
ip = v.IP
|
|
||||||
}
|
}
|
||||||
if ip != nil && !ip.IsLoopback() && ip.To4() != nil {
|
|
||||||
kubelet.nodeIP = ip
|
kubelet.nodeIP = testCase.nodeIP
|
||||||
break
|
|
||||||
|
fakeCloud := &fakecloud.FakeCloud{
|
||||||
|
Addresses: testCase.nodeAddresses,
|
||||||
|
Err: nil,
|
||||||
|
}
|
||||||
|
kubelet.cloud = fakeCloud
|
||||||
|
kubelet.cloudproviderRequestParallelism = make(chan int, 1)
|
||||||
|
kubelet.cloudproviderRequestSync = make(chan int)
|
||||||
|
kubelet.cloudproviderRequestTimeout = 10 * time.Second
|
||||||
|
kubelet.nodeIPValidator = func(nodeIP net.IP) error {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
assert.NotNil(t, kubelet.nodeIP)
|
|
||||||
|
|
||||||
fakeCloud := &fakecloud.FakeCloud{
|
// execute method
|
||||||
Addresses: []v1.NodeAddress{
|
err := kubelet.setNodeAddress(&existingNode)
|
||||||
{
|
if err != nil && !testCase.shouldError {
|
||||||
Type: v1.NodeExternalIP,
|
t.Errorf("Unexpected error for test %s: %q", testCase.name, err)
|
||||||
Address: "132.143.154.163",
|
continue
|
||||||
},
|
} else if err != nil && testCase.shouldError {
|
||||||
{
|
// expected an error
|
||||||
Type: v1.NodeExternalIP,
|
continue
|
||||||
Address: kubelet.nodeIP.String(),
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
Type: v1.NodeInternalIP,
|
|
||||||
Address: "132.143.154.164",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Type: v1.NodeInternalIP,
|
|
||||||
Address: kubelet.nodeIP.String(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Type: v1.NodeInternalIP,
|
|
||||||
Address: "132.143.154.165",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Type: v1.NodeHostName,
|
|
||||||
Address: testKubeletHostname,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Err: nil,
|
|
||||||
}
|
|
||||||
kubelet.cloud = fakeCloud
|
|
||||||
kubelet.cloudproviderRequestParallelism = make(chan int, 1)
|
|
||||||
kubelet.cloudproviderRequestSync = make(chan int)
|
|
||||||
kubelet.cloudproviderRequestTimeout = 10 * time.Second
|
|
||||||
|
|
||||||
kubelet.setNodeAddress(&existingNode)
|
// Sort both sets for consistent equality
|
||||||
|
sortNodeAddresses(testCase.expectedAddresses)
|
||||||
|
sortNodeAddresses(existingNode.Status.Addresses)
|
||||||
|
|
||||||
expectedAddresses := []v1.NodeAddress{
|
assert.True(
|
||||||
{
|
t,
|
||||||
Type: v1.NodeExternalIP,
|
apiequality.Semantic.DeepEqual(
|
||||||
Address: kubelet.nodeIP.String(),
|
testCase.expectedAddresses,
|
||||||
},
|
existingNode.Status.Addresses,
|
||||||
{
|
),
|
||||||
Type: v1.NodeInternalIP,
|
fmt.Sprintf("Test %s failed %%s", testCase.name),
|
||||||
Address: kubelet.nodeIP.String(),
|
diff.ObjectDiff(testCase.expectedAddresses, existingNode.Status.Addresses),
|
||||||
},
|
)
|
||||||
{
|
|
||||||
Type: v1.NodeHostName,
|
|
||||||
Address: testKubeletHostname,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
assert.True(t, apiequality.Semantic.DeepEqual(expectedAddresses, existingNode.Status.Addresses), "%s", diff.ObjectDiff(expectedAddresses, existingNode.Status.Addresses))
|
}
|
||||||
|
|
||||||
|
// sortableNodeAddress is a type for sorting []v1.NodeAddress
|
||||||
|
type sortableNodeAddress []v1.NodeAddress
|
||||||
|
|
||||||
|
func (s sortableNodeAddress) Len() int { return len(s) }
|
||||||
|
func (s sortableNodeAddress) Less(i, j int) bool {
|
||||||
|
return (string(s[i].Type) + s[i].Address) < (string(s[j].Type) + s[j].Address)
|
||||||
|
}
|
||||||
|
func (s sortableNodeAddress) Swap(i, j int) { s[j], s[i] = s[i], s[j] }
|
||||||
|
|
||||||
|
func sortNodeAddresses(addrs sortableNodeAddress) {
|
||||||
|
sort.Sort(addrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateNewNodeStatus(t *testing.T) {
|
func TestUpdateNewNodeStatus(t *testing.T) {
|
||||||
|
|
Loading…
Reference in New Issue