@@ -46,12 +46,12 @@ import (
46
46
// reconcileDockerContainers manages the Docker containers for a MachinePool such that it
47
47
// - Ensures the number of up-to-date Docker containers is equal to the MachinePool's desired replica count.
48
48
// - Does not delete any containers as that must be triggered in reconcileDockerMachines to ensure node cordon/drain.
49
+ // - Create the DockerMachine CR after creating the container.
49
50
//
50
51
// Providers should similarly create their infrastructure instances and reconcile any additional logic.
51
52
func (r * DockerMachinePoolReconciler ) reconcileDockerContainers (ctx context.Context , cluster * clusterv1.Cluster , machinePool * expv1.MachinePool , dockerMachinePool * infraexpv1.DockerMachinePool ) error {
52
53
log := ctrl .LoggerFrom (ctx )
53
-
54
- log .V (2 ).Info ("Reconciling Docker containers" , "DockerMachinePool" , klog .KObj (dockerMachinePool ))
54
+ log .Info ("Reconciling Docker containers" , "DockerMachinePool" , klog .KObj (dockerMachinePool ))
55
55
56
56
labelFilters := map [string ]string {dockerMachinePoolLabel : dockerMachinePool .Name }
57
57
@@ -63,8 +63,15 @@ func (r *DockerMachinePoolReconciler) reconcileDockerContainers(ctx context.Cont
63
63
matchingMachineCount := len (machinesMatchingInfrastructureSpec (ctx , machines , machinePool , dockerMachinePool ))
64
64
numToCreate := int (* machinePool .Spec .Replicas ) - matchingMachineCount
65
65
for range numToCreate {
66
- log .V (2 ).Info ("Creating a new Docker container for machinePool" , "MachinePool" , klog .KObj (machinePool ))
67
66
name := fmt .Sprintf ("worker-%s" , util .RandomString (6 ))
67
+
68
+ log .Info ("Creating a new DockerMachine for dockerMachinePool" , "DockerMachinePool" , klog .KObj (dockerMachinePool ))
69
+ dockerMachine := computeDesiredDockerMachine (name , cluster , machinePool , dockerMachinePool , nil )
70
+ if err := ssa .Patch (ctx , r .Client , dockerMachinePoolControllerName , dockerMachine ); err != nil {
71
+ return errors .Wrap (err , "failed to create a new docker machine" )
72
+ }
73
+
74
+ log .Info ("Creating a new Docker container for machinePool" , "MachinePool" , klog .KObj (machinePool ))
68
75
if err := createDockerContainer (ctx , name , cluster , machinePool , dockerMachinePool ); err != nil {
69
76
return errors .Wrap (err , "failed to create a new docker machine" )
70
77
}
@@ -107,15 +114,15 @@ func createDockerContainer(ctx context.Context, name string, cluster *clusterv1.
107
114
108
115
// reconcileDockerMachines creates and deletes DockerMachines to match the MachinePool's desired number of replicas and infrastructure spec.
109
116
// It is responsible for
110
- // - Ensuring each Docker container has an associated DockerMachine by creating one if it doesn't already exist.
111
- // - Ensuring that deletion for Docker container happens by calling delete on the associated Machine so that the node is cordoned/drained and the infrastructure is cleaned up .
117
+ // - Update DockerMachine owner references
118
+ // - Create Docker containers for its corresponding DockerMachine if not exist .
112
119
// - Deleting DockerMachines referencing a container whose Kubernetes version or custom image no longer matches the spec.
113
120
// - Deleting DockerMachines that correspond to a deleted/non-existent Docker container.
114
121
// - Deleting DockerMachines when scaling down such that DockerMachines whose owner Machine has the clusterv1.DeleteMachineAnnotation is given priority.
115
122
func (r * DockerMachinePoolReconciler ) reconcileDockerMachines (ctx context.Context , cluster * clusterv1.Cluster , machinePool * expv1.MachinePool , dockerMachinePool * infraexpv1.DockerMachinePool ) error {
116
123
log := ctrl .LoggerFrom (ctx )
117
124
118
- log .V ( 2 ). Info ("Reconciling DockerMachines" , "DockerMachinePool" , klog .KObj (dockerMachinePool ))
125
+ log .Info ("Reconciling DockerMachines" , "DockerMachinePool" , klog .KObj (dockerMachinePool ))
119
126
120
127
dockerMachineList , err := getDockerMachines (ctx , r .Client , * cluster , * machinePool , * dockerMachinePool )
121
128
if err != nil {
@@ -127,58 +134,37 @@ func (r *DockerMachinePoolReconciler) reconcileDockerMachines(ctx context.Contex
127
134
dockerMachineMap [dockerMachine .Name ] = dockerMachine
128
135
}
129
136
130
- // List the Docker containers. This corresponds to a InfraMachinePool instance for providers.
137
+ // Get the Docker containers. This corresponds to a InfraMachinePool instance for providers.
131
138
labelFilters := map [string ]string {dockerMachinePoolLabel : dockerMachinePool .Name }
132
- externalMachines , err := docker . ListMachinesByCluster (ctx , cluster , labelFilters )
139
+ externalMachineMap , err := getExternalMachinesMap (ctx , cluster , labelFilters )
133
140
if err != nil {
134
141
return errors .Wrapf (err , "failed to list all machines in the cluster" )
135
142
}
136
143
137
- externalMachineMap := make (map [string ]* docker.Machine )
138
- for _ , externalMachine := range externalMachines {
139
- externalMachineMap [externalMachine .Name ()] = externalMachine
140
- }
141
-
142
144
// Step 1:
143
- // Create a DockerMachine for each Docker container so we surface the information to the user. Use the same name as the Docker container for the Docker Machine for ease of lookup.
144
- // Providers should iterate through their infrastructure instances and ensure that each instance has a corresponding InfraMachine .
145
- for _ , machine := range externalMachines {
146
- if existingMachine , ok := dockerMachineMap [ machine .Name () ]; ok {
147
- log .V ( 2 ). Info ("Patching existing DockerMachine" , "DockerMachine" , klog .KObj (& existingMachine ))
145
+ // Update the DockerMachine to set its owner reference
146
+ // Create Dockercontainer for DockerMachine if not exist .
147
+ for _ , existingMachine := range dockerMachineMap {
148
+ if machine , ok := externalMachineMap [ existingMachine .Name ]; ok {
149
+ log .Info ("Patching existing DockerMachine" , "DockerMachine" , klog .KObj (& existingMachine ))
148
150
desiredMachine := computeDesiredDockerMachine (machine .Name (), cluster , machinePool , dockerMachinePool , & existingMachine )
149
151
if err := ssa .Patch (ctx , r .Client , dockerMachinePoolControllerName , desiredMachine , ssa.WithCachingProxy {Cache : r .ssaCache , Original : & existingMachine }); err != nil {
150
152
return errors .Wrapf (err , "failed to update DockerMachine %q" , klog .KObj (desiredMachine ))
151
153
}
152
-
153
- dockerMachineMap [desiredMachine .Name ] = * desiredMachine
154
154
} else {
155
- log .V (2 ).Info ("Creating a new DockerMachine for Docker container" , "container" , machine .Name ())
156
- desiredMachine := computeDesiredDockerMachine (machine .Name (), cluster , machinePool , dockerMachinePool , nil )
157
- if err := ssa .Patch (ctx , r .Client , dockerMachinePoolControllerName , desiredMachine ); err != nil {
158
- return errors .Wrap (err , "failed to create a new docker machine" )
155
+ log .Info ("Creating a new Docker container for DockerMachine" , "DockerMachine" , klog .KObj (& existingMachine ))
156
+ if err := createDockerContainer (ctx , existingMachine .Name , cluster , machinePool , dockerMachinePool ); err != nil {
157
+ return errors .Wrap (err , "failed to create a new docker container" )
159
158
}
160
-
161
- dockerMachineMap [desiredMachine .Name ] = * desiredMachine
162
159
}
163
160
}
164
-
165
- // Step 2:
166
- // Delete any DockerMachines that correspond to a deleted Docker container.
167
- // Providers should iterate through the InfraMachines to ensure each one still corresponds to an existing infrastructure instance.
168
- // This allows the InfraMachine (and owner Machine) to be deleted and avoid hanging resources when a user deletes an instance out-of-band.
169
- for _ , dockerMachine := range dockerMachineMap {
170
- if _ , ok := externalMachineMap [dockerMachine .Name ]; ! ok {
171
- dockerMachine := dockerMachine
172
- log .V (2 ).Info ("Deleting DockerMachine with no underlying infrastructure" , "DockerMachine" , klog .KObj (& dockerMachine ))
173
- if err := r .deleteMachinePoolMachine (ctx , dockerMachine ); err != nil {
174
- return err
175
- }
176
-
177
- delete (dockerMachineMap , dockerMachine .Name )
178
- }
161
+ // Get the Docker containers after creating missing containers.
162
+ externalMachineMap , err = getExternalMachinesMap (ctx , cluster , labelFilters )
163
+ if err != nil {
164
+ return errors .Wrapf (err , "failed to list all machines in the cluster" )
179
165
}
180
166
181
- // Step 3 :
167
+ // Step 2 :
182
168
// This handles the scale down/excess replicas case and the case where a rolling upgrade is needed.
183
169
// If there are more ready DockerMachines than desired replicas, start to delete the excess DockerMachines such that
184
170
// - DockerMachines with an outdated Kubernetes version or custom image are deleted first (i.e. the rolling upgrade).
@@ -218,7 +204,7 @@ func (r *DockerMachinePoolReconciler) reconcileDockerMachines(ctx context.Contex
218
204
for _ , dockerMachine := range outdatedMachines {
219
205
if overProvisionCount > 0 {
220
206
dockerMachine := dockerMachine
221
- log .V ( 2 ). Info ("Deleting DockerMachine because it is outdated" , "DockerMachine" , klog .KObj (& dockerMachine ))
207
+ log .Info ("Deleting DockerMachine because it is outdated" , "DockerMachine" , klog .KObj (& dockerMachine ))
222
208
if err := r .deleteMachinePoolMachine (ctx , dockerMachine ); err != nil {
223
209
return err
224
210
}
@@ -231,7 +217,7 @@ func (r *DockerMachinePoolReconciler) reconcileDockerMachines(ctx context.Contex
231
217
for _ , dockerMachine := range readyMachines {
232
218
if overProvisionCount > 0 {
233
219
dockerMachine := dockerMachine
234
- log .V ( 2 ). Info ("Deleting DockerMachine because it is an excess replica" , "DockerMachine" , klog .KObj (& dockerMachine ))
220
+ log .Info ("Deleting DockerMachine because it is an excess replica" , "DockerMachine" , klog .KObj (& dockerMachine ))
235
221
if err := r .deleteMachinePoolMachine (ctx , dockerMachine ); err != nil {
236
222
return err
237
223
}
@@ -243,6 +229,21 @@ func (r *DockerMachinePoolReconciler) reconcileDockerMachines(ctx context.Contex
243
229
return nil
244
230
}
245
231
232
+ // getExternalMachinesMap will return a map of docker.Machines (containers) that belong to the give cluster and filter. Docker machine name as key and docker.Machine as value.
233
+ func getExternalMachinesMap (ctx context.Context , cluster * clusterv1.Cluster , labels map [string ]string ) (map [string ]* docker.Machine , error ) {
234
+ externalMachines , err := docker .ListMachinesByCluster (ctx , cluster , labels )
235
+ if err != nil {
236
+ return nil , errors .Wrapf (err , "failed to list all machines in the cluster" )
237
+ }
238
+
239
+ externalMachineMap := make (map [string ]* docker.Machine )
240
+ for _ , externalMachine := range externalMachines {
241
+ externalMachineMap [externalMachine .Name ()] = externalMachine
242
+ }
243
+
244
+ return externalMachineMap , nil
245
+ }
246
+
246
247
// computeDesiredDockerMachine creates a DockerMachine to represent a Docker container in a DockerMachinePool.
247
248
// These DockerMachines have the clusterv1.ClusterNameLabel and clusterv1.MachinePoolNameLabel to support MachinePool Machines.
248
249
func computeDesiredDockerMachine (name string , cluster * clusterv1.Cluster , machinePool * expv1.MachinePool , dockerMachinePool * infraexpv1.DockerMachinePool , existingDockerMachine * infrav1.DockerMachine ) * infrav1.DockerMachine {
@@ -272,6 +273,7 @@ func computeDesiredDockerMachine(name string, cluster *clusterv1.Cluster, machin
272
273
Name : dockerMachinePool .Name ,
273
274
UID : dockerMachinePool .UID ,
274
275
}))
276
+
275
277
dockerMachine .Labels [clusterv1 .ClusterNameLabel ] = cluster .Name
276
278
dockerMachine .Labels [clusterv1 .MachinePoolNameLabel ] = format .MustFormatValue (machinePool .Name )
277
279
@@ -288,7 +290,7 @@ func (r *DockerMachinePoolReconciler) deleteMachinePoolMachine(ctx context.Conte
288
290
}
289
291
// util.GetOwnerMachine() returns a nil Machine without error if there is no Machine kind in the ownerRefs, so we must verify that machine is not nil.
290
292
if machine == nil {
291
- log .V ( 2 ). Info ("No owner Machine exists for DockerMachine" , "dockerMachine" , klog .KObj (& dockerMachine ))
293
+ log .Info ("No owner Machine exists for DockerMachine" , "dockerMachine" , klog .KObj (& dockerMachine ))
292
294
293
295
// If the DockerMachine does not have an owner Machine, do not attempt to delete the DockerMachine as the MachinePool controller will create the
294
296
// Machine and we want to let it catch up. If we are too hasty to delete, that introduces a race condition where the DockerMachine could be deleted
@@ -297,7 +299,8 @@ func (r *DockerMachinePoolReconciler) deleteMachinePoolMachine(ctx context.Conte
297
299
// In the case where the MachinePool is being deleted and the Machine will never come online, the DockerMachine will be deleted via its ownerRef to the
298
300
// DockerMachinePool, so that is covered as well.
299
301
300
- return nil
302
+ // Returning error as we need the dockerMachine not to proceed.
303
+ return errors .New ("No owner Machine exists for DockerMachine" )
301
304
}
302
305
303
306
log .Info ("Deleting Machine for DockerMachine" , "Machine" , klog .KObj (machine ), "DockerMachine" , klog .KObj (& dockerMachine ))
0 commit comments