@@ -25,142 +25,147 @@ import (
25
25
"github.com/submariner-io/admiral/pkg/federate"
26
26
"github.com/submariner-io/admiral/pkg/syncer"
27
27
admUtil "github.com/submariner-io/admiral/pkg/util"
28
- "github.com/submariner-io/submariner/pkg/cni "
28
+ submarinerv1 "github.com/submariner-io/submariner/pkg/apis/submariner.io/v1 "
29
29
"github.com/submariner-io/submariner/pkg/globalnet/constants"
30
- packetfilter "github.com/submariner-io/submariner/pkg/globalnet/controllers/packetfilter"
30
+ "github.com/submariner-io/submariner/pkg/globalnet/controllers/packetfilter"
31
31
"github.com/submariner-io/submariner/pkg/ipam"
32
- corev1 "k8s.io/api/core/v1"
33
32
"k8s.io/apimachinery/pkg/api/meta"
34
33
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
35
34
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
36
35
"k8s.io/apimachinery/pkg/runtime"
36
+ "k8s.io/client-go/tools/cache"
37
37
)
38
38
39
- func NewNodeController (config * syncer.ResourceSyncerConfig , pool * ipam.IPPool , nodeName string , clusterCIDRs []string ) (Interface , error ) {
39
+ func NewGatewayController (config * syncer.ResourceSyncerConfig , informer cache.SharedInformer , pool * ipam.IPPool , hostName ,
40
+ namespace , cniIP string ,
41
+ ) (Interface , error ) {
40
42
// We'll panic if config is nil, this is intentional
41
43
var err error
42
44
43
- logger .Info ("Creating Node controller" )
45
+ logger .Info ("Creating Gateway controller" )
44
46
45
47
pfIface , err := packetfilter .New ()
46
48
if err != nil {
47
49
return nil , errors .Wrap (err , "error creating the PacketFilter Interface handler" )
48
50
}
49
51
50
- controller := & nodeController {
52
+ controller := & gatewayController {
51
53
baseIPAllocationController : newBaseIPAllocationController (pool , pfIface ),
52
- nodeName : nodeName ,
54
+ hostName : hostName ,
55
+ cniIP : cniIP ,
53
56
}
54
57
55
- cniIface , err := cni .Discover (clusterCIDRs )
56
- if err == nil {
57
- controller .cniIP = cniIface .IPAddress
58
+ config = NewGatewayResourceSyncerConfig (config , namespace )
58
59
59
- logger .Infof ("Discovered CNI interface IP %q" , controller .cniIP )
60
- } else {
61
- logger .Errorf (err , "Error obtaining CNI IP address - health check functionality will not work" )
62
- }
63
-
64
- federator := federate .NewUpdateFederator (config .SourceClient , config .RestMapper , corev1 .NamespaceAll ,
60
+ config .Federator = federate .NewUpdateFederator (config .SourceClient , config .RestMapper , namespace ,
65
61
func (oldObj * unstructured.Unstructured , newObj * unstructured.Unstructured ) * unstructured.Unstructured {
66
- return updateNodeAnnotation (oldObj , newObj .GetAnnotations ()[constants .SmGlobalIP ]).(* unstructured.Unstructured )
62
+ return updateGlobalIPAnnotation (oldObj , newObj .GetAnnotations ()[constants .SmGlobalIP ]).(* unstructured.Unstructured )
67
63
})
68
64
69
- controller .resourceSyncer , err = syncer .NewResourceSyncer (& syncer.ResourceSyncerConfig {
70
- Name : "Node syncer" ,
71
- ResourceType : & corev1.Node {},
72
- SourceClient : config .SourceClient ,
73
- SourceNamespace : corev1 .NamespaceAll ,
74
- RestMapper : config .RestMapper ,
75
- Federator : federator ,
76
- Scheme : config .Scheme ,
77
- Transform : controller .process ,
78
- })
65
+ config .Transform = controller .process
66
+ config .Name = "Gateway syncer"
67
+
68
+ controller .resourceSyncer , err = syncer .NewResourceSyncerWithSharedInformer (config , informer )
79
69
if err != nil {
80
- return nil , errors .Wrap (err , "error creating the federator " )
70
+ return nil , errors .Wrap (err , "error creating the resource syncer " )
81
71
}
82
72
83
- _ , gvr , err := admUtil .ToUnstructuredResource (& corev1. Node {}, config .RestMapper )
73
+ _ , gvr , err := admUtil .ToUnstructuredResource (& submarinerv1. Gateway {}, config .RestMapper )
84
74
if err != nil {
85
75
return nil , errors .Wrap (err , "error converting resource" )
86
76
}
87
77
88
- controller .nodes = config .SourceClient .Resource (* gvr )
78
+ gatewayClient := config .SourceClient .Resource (* gvr ).Namespace (namespace )
79
+
80
+ // Gateways retain their allocated global IPs regardless of their HA status (active or passive) so reserve the global IPs
81
+ // for all the Gateways.
89
82
90
- localNodeInfo , err := controller . nodes . Get (context .TODO (), controller . nodeName , metav1.GetOptions {})
83
+ gateways , err := gatewayClient . List (context .TODO (), metav1.ListOptions {})
91
84
if err != nil {
92
- return nil , errors .Wrapf (err , "error retrieving local Node %q" , controller . nodeName )
85
+ return nil , errors .Wrap (err , "error listing Gateways" )
93
86
}
94
87
95
- if err := controller .reserveAllocatedIP (federator , localNodeInfo ); err != nil {
96
- return nil , err
88
+ for i := range gateways .Items {
89
+ if err := controller .reserveAllocatedIP (config .Federator , & gateways .Items [i ]); err != nil {
90
+ return nil , err
91
+ }
97
92
}
98
93
99
94
return controller , nil
100
95
}
101
96
102
- func (n * nodeController ) process (from runtime.Object , _ int , op syncer.Operation ) (runtime.Object , bool ) {
103
- node := from .(* corev1.Node )
104
-
105
- // If the event corresponds to a different node which has globalIP annotation, release the globalIP back to Pool.
106
- if node .Name != n .nodeName {
107
- if existingGlobalIP := node .GetAnnotations ()[constants .SmGlobalIP ]; existingGlobalIP != "" {
108
- logger .Infof ("Processing %sd non-gateway node %q - releasing GlobalIP %q" , op , node .Name , existingGlobalIP )
97
+ func NewGatewayResourceSyncerConfig (base * syncer.ResourceSyncerConfig , namespace string ) * syncer.ResourceSyncerConfig {
98
+ return & syncer.ResourceSyncerConfig {
99
+ ResourceType : & submarinerv1.Gateway {},
100
+ SourceClient : base .SourceClient ,
101
+ SourceNamespace : namespace ,
102
+ RestMapper : base .RestMapper ,
103
+ Scheme : base .Scheme ,
104
+ ResourcesEquivalent : func (_ , _ * unstructured.Unstructured ) bool {
105
+ return true // we don't need to handle updates
106
+ },
107
+ }
108
+ }
109
109
110
- if op == syncer .Delete {
111
- _ = n . pool . Release ( existingGlobalIP )
110
+ func ( n * gatewayController ) process ( from runtime. Object , _ int , op syncer.Operation ) (runtime. Object , bool ) {
111
+ gateway := from .( * submarinerv1. Gateway )
112
112
113
- return nil , false
114
- }
113
+ if op == syncer .Delete {
114
+ // Gateway deleted - here we just release its global IP, if any. If it's the local Gateway then the other Gateway controller
115
+ // started by the gatewayMonitor will remove the ingress rules in parallel.
116
+ if existingGlobalIP := gateway .GetAnnotations ()[constants .SmGlobalIP ]; existingGlobalIP != "" {
117
+ logger .Infof (" Gateway %q deleted - releasing its global IP %q" , gateway .Name , existingGlobalIP )
115
118
116
119
_ = n .pool .Release (existingGlobalIP )
117
-
118
- return updateNodeAnnotation (node , "" ), false
119
120
}
120
121
121
122
return nil , false
122
123
}
123
124
124
- logger .Infof ("Processing %sd Node %q" , op , node .Name )
125
+ if gateway .Name != n .hostName {
126
+ return nil , false
127
+ }
128
+
129
+ logger .Infof ("Processing %sd local Gateway %q" , op , gateway .Name )
125
130
126
- return n .allocateIP (node )
131
+ return n .allocateIP (gateway )
127
132
}
128
133
129
- func (n * nodeController ) allocateIP (node * corev1. Node ) (runtime.Object , bool ) {
134
+ func (n * gatewayController ) allocateIP (gateway * submarinerv1. Gateway ) (runtime.Object , bool ) {
130
135
if n .cniIP == "" {
131
136
// To support connectivity from HostNetwork to remote clusters, globalnet requires the CNI IP of the local node.
132
137
return nil , false
133
138
}
134
139
135
- globalIP := node .GetAnnotations ()[constants .SmGlobalIP ]
140
+ globalIP := gateway .GetAnnotations ()[constants .SmGlobalIP ]
136
141
if globalIP != "" {
137
142
return nil , false
138
143
}
139
144
140
145
ips , err := n .pool .Allocate (1 )
141
146
if err != nil {
142
- logger .Errorf (err , "Error allocating IPs for node %q" , node .Name )
147
+ logger .Errorf (err , "Error allocating IPs for Gateway %q" , gateway .Name )
143
148
return nil , true
144
149
}
145
150
146
151
globalIP = ips [0 ]
147
152
148
- logger .Infof ("Allocated global IP %s for node %q" , globalIP , node .Name )
153
+ logger .Infof ("Allocated global IP %s for Gateway %q" , globalIP , gateway .Name )
149
154
150
- logger .Infof ("Adding ingress rules for node %q with global IP %s, CNI IP %s" , node .Name , globalIP , n .cniIP )
155
+ logger .Infof ("Adding ingress rules for Gateway %q with global IP %s, CNI IP %s" , gateway .Name , globalIP , n .cniIP )
151
156
152
157
if err := n .pfIface .AddIngressRulesForHealthCheck (n .cniIP , globalIP ); err != nil {
153
- logger .Errorf (err , "Error programming rules for Gateway healthcheck on node %q" , node .Name )
158
+ logger .Errorf (err , "Error programming ingress rules for Gateway %q" , gateway .Name )
154
159
155
160
_ = n .pool .Release (globalIP )
156
161
157
162
return nil , true
158
163
}
159
164
160
- return updateNodeAnnotation ( node , globalIP ), false
165
+ return updateGlobalIPAnnotation ( gateway , globalIP ), false
161
166
}
162
167
163
- func (n * nodeController ) reserveAllocatedIP (federator federate.Federator , obj * unstructured.Unstructured ) error {
168
+ func (n * gatewayController ) reserveAllocatedIP (federator federate.Federator , obj * unstructured.Unstructured ) error {
164
169
existingGlobalIP := obj .GetAnnotations ()[constants .SmGlobalIP ]
165
170
if existingGlobalIP == "" {
166
171
return nil
@@ -170,32 +175,41 @@ func (n *nodeController) reserveAllocatedIP(federator federate.Federator, obj *u
170
175
return nil
171
176
}
172
177
178
+ // If this is not the Gateway on the local host then just reserve its global IP.
179
+
173
180
err := n .pool .Reserve (existingGlobalIP )
174
- if err == nil {
181
+ if err == nil && obj . GetName () == n . hostName {
175
182
err = n .pfIface .AddIngressRulesForHealthCheck (n .cniIP , existingGlobalIP )
176
183
if err != nil {
177
184
_ = n .pool .Release (existingGlobalIP )
178
185
}
179
186
}
180
187
181
188
if err != nil {
182
- logger .Warningf ("Could not reserve allocated GlobalIP for Node %q: %v" , obj .GetName (), err )
189
+ logger .Warningf ("Could not reserve allocated GlobalIP for Gateway %q: %v" , obj .GetName (), err )
190
+
191
+ // If this is not the Gateway on the local host/node then leave the annotation as is since we're not able to remove the
192
+ // ingress rules from another node. We'll let the globalnet process running on that host take care of it.
193
+
194
+ if obj .GetName () != n .hostName {
195
+ return nil
196
+ }
183
197
184
198
if err := n .pfIface .RemoveIngressRulesForHealthCheck (n .cniIP , existingGlobalIP ); err != nil {
185
- logger .Errorf (err , "Error deleting rules for Gateway healthcheck on node %q" , n .nodeName )
199
+ logger .Errorf (err , "Error deleting rules for Gateway %q" , n .hostName )
186
200
}
187
201
188
- return errors .Wrap (federator .Distribute (context .TODO (), updateNodeAnnotation (obj , "" )),
189
- "error updating the Node global IP annotation" )
202
+ return errors .Wrap (federator .Distribute (context .TODO (), updateGlobalIPAnnotation (obj , "" )),
203
+ "error updating the Gateway global IP annotation" )
190
204
}
191
205
192
- logger .Infof ("Successfully reserved allocated GlobalIP %q for node %q" , existingGlobalIP , obj .GetName ())
206
+ logger .Infof ("Successfully reserved allocated GlobalIP %q for Gateway %q" , existingGlobalIP , obj .GetName ())
193
207
194
208
return nil
195
209
}
196
210
197
- func updateNodeAnnotation ( node runtime.Object , globalIP string ) runtime.Object {
198
- objMeta , _ := meta .Accessor (node )
211
+ func updateGlobalIPAnnotation ( obj runtime.Object , globalIP string ) runtime.Object {
212
+ objMeta , _ := meta .Accessor (obj )
199
213
200
214
annotations := objMeta .GetAnnotations ()
201
215
if annotations == nil {
@@ -210,5 +224,5 @@ func updateNodeAnnotation(node runtime.Object, globalIP string) runtime.Object {
210
224
211
225
objMeta .SetAnnotations (annotations )
212
226
213
- return node
227
+ return obj
214
228
}
0 commit comments