1
1
package node
2
2
3
3
import (
4
+ "bytes"
4
5
"context"
6
+ "net"
7
+ "sort"
5
8
"strings"
6
9
10
+ "github.com/xiaods/k8e/pkg/nodepassword"
7
11
"github.com/pkg/errors"
8
- coreclient "github.com/rancher/wrangler/pkg/generated/controllers/core/v1"
12
+ coreclient "github.com/rancher/wrangler/v3/ pkg/generated/controllers/core/v1"
9
13
"github.com/sirupsen/logrus"
10
- "github.com/xiaods/k8e/pkg/nodepassword"
11
14
core "k8s.io/api/core/v1"
15
+ v1 "k8s.io/api/core/v1"
16
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12
17
)
13
18
14
19
func Register (ctx context.Context ,
@@ -47,14 +52,22 @@ func (h *handler) onRemove(key string, node *core.Node) (*core.Node, error) {
47
52
48
53
func (h * handler ) updateHosts (node * core.Node , removed bool ) (* core.Node , error ) {
49
54
var (
50
- nodeName string
51
- nodeAddress string
55
+ nodeName string
56
+ hostName string
57
+ nodeIPv4 string
58
+ nodeIPv6 string
52
59
)
53
60
nodeName = node .Name
54
61
for _ , address := range node .Status .Addresses {
55
- if address .Type == "InternalIP" {
56
- nodeAddress = address .Address
57
- break
62
+ switch address .Type {
63
+ case v1 .NodeInternalIP :
64
+ if strings .Contains (address .Address , ":" ) {
65
+ nodeIPv6 = address .Address
66
+ } else {
67
+ nodeIPv4 = address .Address
68
+ }
69
+ case v1 .NodeHostName :
70
+ hostName = address .Address
58
71
}
59
72
}
60
73
if removed {
@@ -63,58 +76,101 @@ func (h *handler) updateHosts(node *core.Node, removed bool) (*core.Node, error)
63
76
}
64
77
}
65
78
if h .modCoreDNS {
66
- if err := h .updateCoreDNSConfigMap (nodeName , nodeAddress , removed ); err != nil {
79
+ if err := h .updateCoreDNSConfigMap (nodeName , hostName , nodeIPv4 , nodeIPv6 , removed ); err != nil {
67
80
return nil , err
68
81
}
69
82
}
70
83
return nil , nil
71
84
}
72
85
73
- func (h * handler ) updateCoreDNSConfigMap (nodeName , nodeAddress string , removed bool ) error {
74
- if nodeAddress == "" && ! removed {
75
- logrus .Errorf ("No InternalIP found for node " + nodeName )
86
+ func (h * handler ) updateCoreDNSConfigMap (nodeName , hostName , nodeIPv4 , nodeIPv6 string , removed bool ) error {
87
+ if removed {
88
+ nodeIPv4 = ""
89
+ nodeIPv6 = ""
90
+ } else if nodeIPv4 == "" && nodeIPv6 == "" {
91
+ logrus .Errorf ("No InternalIP addresses found for node " + nodeName )
76
92
return nil
77
93
}
78
94
79
- configMapCache , err := h .configMaps .Cache ().Get ("kube-system" , "coredns" )
80
- if err != nil || configMapCache == nil {
95
+ nodeNames := nodeName
96
+ if hostName != nodeName {
97
+ nodeNames += " " + hostName
98
+ }
99
+
100
+ configMap , err := h .configMaps .Get ("kube-system" , "coredns" , metav1.GetOptions {})
101
+ if err != nil || configMap == nil {
81
102
logrus .Warn (errors .Wrap (err , "Unable to fetch coredns config map" ))
82
103
return nil
83
104
}
84
105
85
- configMap := configMapCache .DeepCopy ()
86
- hosts := configMap .Data ["NodeHosts" ]
87
- hostsMap := map [string ]string {}
106
+ addressMap := map [string ]string {}
88
107
89
- for _ , line := range strings .Split (hosts , "\n " ) {
108
+ // extract current entries from hosts file, skipping any entries that are
109
+ // empty, unparsable, or hold an incorrect address for the current node.
110
+ for _ , line := range strings .Split (configMap .Data ["NodeHosts" ], "\n " ) {
111
+ line , _ , _ = strings .Cut (line , "#" )
90
112
if line == "" {
91
113
continue
92
114
}
93
115
fields := strings .Fields (line )
94
- if len (fields ) != 2 {
116
+ if len (fields ) < 2 {
95
117
logrus .Warnf ("Unknown format for hosts line [%s]" , line )
96
118
continue
97
119
}
98
120
ip := fields [0 ]
99
- host := fields [1 ]
100
- if host == nodeName {
101
- if removed {
102
- continue
103
- }
104
- if ip == nodeAddress {
105
- return nil
121
+ if fields [1 ] == nodeName {
122
+ if strings .Contains (ip , ":" ) {
123
+ if ip != nodeIPv6 {
124
+ continue
125
+ }
126
+ } else {
127
+ if ip != nodeIPv4 {
128
+ continue
129
+ }
106
130
}
107
131
}
108
- hostsMap [host ] = ip
132
+ names := strings .Join (fields [1 :], " " )
133
+ addressMap [ip ] = names
109
134
}
110
135
111
- if ! removed {
112
- hostsMap [nodeName ] = nodeAddress
136
+ // determine what names we should have for each address family
137
+ var namesv6 , namesv4 string
138
+ if nodeIPv4 != "" {
139
+ namesv4 = nodeNames
140
+ }
141
+ if nodeIPv6 != "" {
142
+ namesv6 = nodeNames
113
143
}
114
144
145
+ // don't need to do anything if the addresses are in sync
146
+ if ! removed && addressMap [nodeIPv4 ] == namesv4 && addressMap [nodeIPv6 ] == namesv6 {
147
+ return nil
148
+ }
149
+
150
+ // Something's out of sync, set the desired entries
151
+ if nodeIPv4 != "" {
152
+ addressMap [nodeIPv4 ] = namesv4
153
+ }
154
+ if nodeIPv6 != "" {
155
+ addressMap [nodeIPv6 ] = namesv6
156
+ }
157
+
158
+ // sort addresses by IP
159
+ addresses := make ([]string , 0 , len (addressMap ))
160
+ for ip := range addressMap {
161
+ addresses = append (addresses , ip )
162
+ }
163
+ sort .Slice (addresses , func (i , j int ) bool {
164
+ return bytes .Compare (net .ParseIP (addresses [i ]), net .ParseIP (addresses [j ])) < 0
165
+ })
166
+
115
167
var newHosts string
116
- for host , ip := range hostsMap {
117
- newHosts += ip + " " + host + "\n "
168
+ for _ , ip := range addresses {
169
+ newHosts += ip + " " + addressMap [ip ] + "\n "
170
+ }
171
+
172
+ if configMap .Data == nil {
173
+ configMap .Data = map [string ]string {}
118
174
}
119
175
configMap .Data ["NodeHosts" ] = newHosts
120
176
@@ -128,10 +184,10 @@ func (h *handler) updateCoreDNSConfigMap(nodeName, nodeAddress string, removed b
128
184
} else {
129
185
actionType = "Updated"
130
186
}
131
- logrus .Infof ("%s coredns node hosts entry [%s] " , actionType , nodeAddress + " " + nodeName )
187
+ logrus .Infof ("%s coredns NodeHosts entry for %s " , actionType , nodeName )
132
188
return nil
133
189
}
134
190
135
191
func (h * handler ) removeNodePassword (nodeName string ) error {
136
192
return nodepassword .Delete (h .secrets , nodeName )
137
- }
193
+ }
0 commit comments