Skip to content

Commit 6ac336a

Browse files
Replace HA proxy config with custom one if specified
1 parent dd5d210 commit 6ac336a

File tree

7 files changed

+316
-78
lines changed

7 files changed

+316
-78
lines changed

test/infrastructure/docker/api/v1beta1/dockercluster_types.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ type DockerLoadBalancer struct {
5555
// ImageMeta allows customizing the image used for the cluster load balancer.
5656
ImageMeta `json:",inline"`
5757

58-
// UnsafeHAProxyConfigTemplateRef allows you to replace the HAProxy config file.
58+
// CustomHAProxyConfigTemplateRef allows you to replace the default HAProxy config file.
5959
// This field is a reference to a config map that contains the configuration template. The key of the config map should be equal to 'value'.
6060
// The content of the config map will be processed and will replace the default HAProxy config file. Please use it with caution, as there are
6161
// no checks to ensure the validity of the configuration. This template will support the following variables that will be passed by the controller:
@@ -64,7 +64,7 @@ type DockerLoadBalancer struct {
6464
// where the key is the server name and the value is the address. This map is dynamic and is updated every time a new control plane
6565
// node is added or removed. The template will also support the JoinHostPort function to join the host and port of the backend server.
6666
// +optional
67-
CustomHAProxyConfigTemplateRef *corev1.LocalObjectReference `json:"unsafeHAProxyConfigTemplateRef,omitempty"`
67+
CustomHAProxyConfigTemplateRef *corev1.LocalObjectReference `json:"customHAProxyConfigTemplateRef,omitempty"`
6868
}
6969

7070
// ImageMeta allows customizing the image used for components that are not

test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockerclusters.yaml

Lines changed: 21 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockerclustertemplates.yaml

Lines changed: 23 additions & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/infrastructure/docker/internal/controllers/dockermachine_controller.go

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/pkg/errors"
2626
corev1 "k8s.io/api/core/v1"
2727
apierrors "k8s.io/apimachinery/pkg/api/errors"
28+
"k8s.io/apimachinery/pkg/types"
2829
"k8s.io/klog/v2"
2930
ctrl "sigs.k8s.io/controller-runtime"
3031
"sigs.k8s.io/controller-runtime/pkg/builder"
@@ -167,11 +168,11 @@ func (r *DockerMachineReconciler) Reconcile(ctx context.Context, req ctrl.Reques
167168

168169
// Handle deleted machines
169170
if !dockerMachine.ObjectMeta.DeletionTimestamp.IsZero() {
170-
return ctrl.Result{}, r.reconcileDelete(ctx, machine, dockerMachine, externalMachine, externalLoadBalancer)
171+
return ctrl.Result{}, r.reconcileDelete(ctx, dockerCluster, machine, dockerMachine, externalMachine, externalLoadBalancer)
171172
}
172173

173174
// Handle non-deleted machines
174-
res, err := r.reconcileNormal(ctx, cluster, machine, dockerMachine, externalMachine, externalLoadBalancer)
175+
res, err := r.reconcileNormal(ctx, cluster, dockerCluster, machine, dockerMachine, externalMachine, externalLoadBalancer)
175176
// Requeue if the reconcile failed because the ClusterCacheTracker was locked for
176177
// the current cluster because of concurrent access.
177178
if errors.Is(err, remote.ErrClusterLocked) {
@@ -204,7 +205,7 @@ func patchDockerMachine(ctx context.Context, patchHelper *patch.Helper, dockerMa
204205
)
205206
}
206207

207-
func (r *DockerMachineReconciler) reconcileNormal(ctx context.Context, cluster *clusterv1.Cluster, machine *clusterv1.Machine, dockerMachine *infrav1.DockerMachine, externalMachine *docker.Machine, externalLoadBalancer *docker.LoadBalancer) (res ctrl.Result, retErr error) {
208+
func (r *DockerMachineReconciler) reconcileNormal(ctx context.Context, cluster *clusterv1.Cluster, dockerCluster *infrav1.DockerCluster, machine *clusterv1.Machine, dockerMachine *infrav1.DockerMachine, externalMachine *docker.Machine, externalLoadBalancer *docker.LoadBalancer) (res ctrl.Result, retErr error) {
208209
log := ctrl.LoggerFrom(ctx)
209210

210211
// Check if the infrastructure is ready, otherwise return and wait for the cluster object to be updated
@@ -271,7 +272,11 @@ func (r *DockerMachineReconciler) reconcileNormal(ctx context.Context, cluster *
271272
// we should only do this once, as reconfiguration more or less ensures
272273
// node ref setting fails
273274
if util.IsControlPlaneMachine(machine) && !dockerMachine.Status.LoadBalancerConfigured {
274-
if err := externalLoadBalancer.UpdateConfiguration(ctx); err != nil {
275+
unsafeLoadBalancerConfigTemplate, err := r.getUnsafeLoadBalancerConfigTemplate(ctx, dockerCluster)
276+
if err != nil {
277+
return ctrl.Result{}, errors.Wrap(err, "failed to retrieve HAProxy configuration from CustomHAProxyConfigTemplateRef")
278+
}
279+
if err := externalLoadBalancer.UpdateConfiguration(ctx, unsafeLoadBalancerConfigTemplate); err != nil {
275280
return ctrl.Result{}, errors.Wrap(err, "failed to update DockerCluster.loadbalancer configuration")
276281
}
277282
dockerMachine.Status.LoadBalancerConfigured = true
@@ -390,7 +395,7 @@ func (r *DockerMachineReconciler) reconcileNormal(ctx context.Context, cluster *
390395
return ctrl.Result{}, nil
391396
}
392397

393-
func (r *DockerMachineReconciler) reconcileDelete(ctx context.Context, machine *clusterv1.Machine, dockerMachine *infrav1.DockerMachine, externalMachine *docker.Machine, externalLoadBalancer *docker.LoadBalancer) error {
398+
func (r *DockerMachineReconciler) reconcileDelete(ctx context.Context, dockerCluster *infrav1.DockerCluster, machine *clusterv1.Machine, dockerMachine *infrav1.DockerMachine, externalMachine *docker.Machine, externalLoadBalancer *docker.LoadBalancer) error {
394399
// Set the ContainerProvisionedCondition reporting delete is started, and issue a patch in order to make
395400
// this visible to the users.
396401
// NB. The operation in docker is fast, so there is the chance the user will not notice the status change;
@@ -411,7 +416,11 @@ func (r *DockerMachineReconciler) reconcileDelete(ctx context.Context, machine *
411416

412417
// if the deleted machine is a control-plane node, remove it from the load balancer configuration;
413418
if util.IsControlPlaneMachine(machine) {
414-
if err := externalLoadBalancer.UpdateConfiguration(ctx); err != nil {
419+
unsafeLoadBalancerConfigTemplate, err := r.getUnsafeLoadBalancerConfigTemplate(ctx, dockerCluster)
420+
if err != nil {
421+
return errors.Wrap(err, "failed to retrieve HAProxy configuration from CustomHAProxyConfigTemplateRef")
422+
}
423+
if err := externalLoadBalancer.UpdateConfiguration(ctx, unsafeLoadBalancerConfigTemplate); err != nil {
415424
return errors.Wrap(err, "failed to update DockerCluster.loadbalancer configuration")
416425
}
417426
}
@@ -510,6 +519,25 @@ func (r *DockerMachineReconciler) getBootstrapData(ctx context.Context, machine
510519
return base64.StdEncoding.EncodeToString(value), bootstrapv1.Format(format), nil
511520
}
512521

522+
func (r *DockerMachineReconciler) getUnsafeLoadBalancerConfigTemplate(ctx context.Context, dockerCluster *infrav1.DockerCluster) (string, error) {
523+
if dockerCluster.Spec.LoadBalancer.CustomHAProxyConfigTemplateRef == nil {
524+
return "", nil
525+
}
526+
var cm *corev1.ConfigMap
527+
key := types.NamespacedName{
528+
Name: dockerCluster.Spec.LoadBalancer.CustomHAProxyConfigTemplateRef.Name,
529+
Namespace: dockerCluster.Namespace,
530+
}
531+
if err := r.Get(ctx, key, cm); err != nil {
532+
return "", errors.Wrapf(err, "failed to retrieve custom HAProxy configuration ConfigMap %s", key)
533+
}
534+
template, ok := cm.Data["value"]
535+
if !ok {
536+
return "", fmt.Errorf("expected key \"value\" to exist in ConfigMap %s", key)
537+
}
538+
return template, nil
539+
}
540+
513541
// setMachineAddress gets the address from the container corresponding to a docker node and sets it on the Machine object.
514542
func setMachineAddress(ctx context.Context, dockerMachine *infrav1.DockerMachine, externalMachine *docker.Machine) error {
515543
machineAddresses, err := externalMachine.Address(ctx)

test/infrastructure/docker/internal/docker/loadbalancer.go

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ package docker
1919
import (
2020
"context"
2121
"fmt"
22-
"net"
22+
"strconv"
2323

2424
"github.com/pkg/errors"
2525
ctrl "sigs.k8s.io/controller-runtime"
@@ -38,12 +38,13 @@ type lbCreator interface {
3838

3939
// LoadBalancer manages the load balancer for a specific docker cluster.
4040
type LoadBalancer struct {
41-
name string
42-
image string
43-
container *types.Node
44-
ipFamily clusterv1.ClusterIPFamily
45-
lbCreator lbCreator
46-
controlPlanePort int
41+
name string
42+
image string
43+
container *types.Node
44+
ipFamily clusterv1.ClusterIPFamily
45+
lbCreator lbCreator
46+
backendControlPlanePort string
47+
frontendControlPlanePort string
4748
}
4849

4950
// NewLoadBalancer returns a new helper for managing a docker loadbalancer with a given name.
@@ -72,12 +73,13 @@ func NewLoadBalancer(ctx context.Context, cluster *clusterv1.Cluster, dockerClus
7273
image := getLoadBalancerImage(dockerCluster)
7374

7475
return &LoadBalancer{
75-
name: cluster.Name,
76-
image: image,
77-
container: container,
78-
ipFamily: ipFamily,
79-
lbCreator: &Manager{},
80-
controlPlanePort: dockerCluster.Spec.ControlPlaneEndpoint.Port,
76+
name: cluster.Name,
77+
image: image,
78+
container: container,
79+
ipFamily: ipFamily,
80+
lbCreator: &Manager{},
81+
frontendControlPlanePort: strconv.Itoa(dockerCluster.Spec.ControlPlaneEndpoint.Port),
82+
backendControlPlanePort: "6443",
8183
}, nil
8284
}
8385

@@ -137,7 +139,7 @@ func (s *LoadBalancer) Create(ctx context.Context) error {
137139
}
138140

139141
// UpdateConfiguration updates the external load balancer configuration with new control plane nodes.
140-
func (s *LoadBalancer) UpdateConfiguration(ctx context.Context) error {
142+
func (s *LoadBalancer) UpdateConfiguration(ctx context.Context, unsafeLoadBalancerConfig string) error {
141143
log := ctrl.LoggerFrom(ctx)
142144

143145
if s.container == nil {
@@ -161,17 +163,25 @@ func (s *LoadBalancer) UpdateConfiguration(ctx context.Context) error {
161163
return errors.Wrapf(err, "failed to get IP for container %s", n.String())
162164
}
163165
if s.ipFamily == clusterv1.IPv6IPFamily {
164-
backendServers[n.String()] = net.JoinHostPort(controlPlaneIPv6, "6443")
166+
backendServers[n.String()] = controlPlaneIPv6
165167
} else {
166-
backendServers[n.String()] = net.JoinHostPort(controlPlaneIPv4, "6443")
168+
backendServers[n.String()] = controlPlaneIPv4
167169
}
168170
}
169171

172+
loadBalancerConfigTemplate := loadbalancer.DefaultTemplate
173+
if unsafeLoadBalancerConfig != "" {
174+
loadBalancerConfigTemplate = unsafeLoadBalancerConfig
175+
}
176+
170177
loadBalancerConfig, err := loadbalancer.Config(&loadbalancer.ConfigData{
171-
ControlPlanePort: s.controlPlanePort,
172-
BackendServers: backendServers,
173-
IPv6: s.ipFamily == clusterv1.IPv6IPFamily,
174-
})
178+
FrontendControlPlanePort: s.frontendControlPlanePort,
179+
BackendControlPlanePort: s.backendControlPlanePort,
180+
BackendServers: backendServers,
181+
IPv6: s.ipFamily == clusterv1.IPv6IPFamily,
182+
},
183+
loadBalancerConfigTemplate,
184+
)
175185
if err != nil {
176186
return errors.WithStack(err)
177187
}

0 commit comments

Comments
 (0)