Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add ability to set DockerClusterSpec load balancer #4951

Merged
merged 1 commit into from
Jul 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions test/infrastructure/docker/api/v1alpha3/conversion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
Copyright 2021 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha3

import (
apiconversion "k8s.io/apimachinery/pkg/conversion"
"sigs.k8s.io/cluster-api/test/infrastructure/docker/api/v1alpha4"
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
"sigs.k8s.io/controller-runtime/pkg/conversion"
)

func (src *DockerCluster) ConvertTo(dstRaw conversion.Hub) error {
dst := dstRaw.(*v1alpha4.DockerCluster)

if err := Convert_v1alpha3_DockerCluster_To_v1alpha4_DockerCluster(src, dst, nil); err != nil {
return err
}

// Manually restore data.
restored := &v1alpha4.DockerCluster{}
if ok, err := utilconversion.UnmarshalData(src, restored); err != nil || !ok {
return err
}

if restored.Spec.LoadBalancer.ImageRepository != "" {
dst.Spec.LoadBalancer.ImageRepository = restored.Spec.LoadBalancer.ImageRepository
}

if restored.Spec.LoadBalancer.ImageTag != "" {
dst.Spec.LoadBalancer.ImageTag = restored.Spec.LoadBalancer.ImageTag
}

return nil
}

func (dst *DockerCluster) ConvertFrom(srcRaw conversion.Hub) error {
src := srcRaw.(*v1alpha4.DockerCluster)

if err := Convert_v1alpha4_DockerCluster_To_v1alpha3_DockerCluster(src, dst, nil); err != nil {
return err
}

// Preserve Hub data on down-conversion except for metadata
if err := utilconversion.MarshalData(src, dst); err != nil {
return err
}

return nil
}

// Convert_v1alpha4_DockerClusterSpec_To_v1alpha3_DockerClusterSpec is an autogenerated conversion function.
func Convert_v1alpha4_DockerClusterSpec_To_v1alpha3_DockerClusterSpec(in *v1alpha4.DockerClusterSpec, out *DockerClusterSpec, s apiconversion.Scope) error {
// DockerClusterSpec.LoadBalancer was added in v1alpha4, so automatic conversion is not possible
return autoConvert_v1alpha4_DockerClusterSpec_To_v1alpha3_DockerClusterSpec(in, out, s)
}
16 changes: 6 additions & 10 deletions test/infrastructure/docker/api/v1alpha3/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions test/infrastructure/docker/api/v1alpha4/conversion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
Copyright 2021 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha4

func (*DockerCluster) Hub() {}
func (*DockerClusterList) Hub() {}
24 changes: 24 additions & 0 deletions test/infrastructure/docker/api/v1alpha4/dockercluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,30 @@ type DockerClusterSpec struct {
// controllers to do what they will with the defined failure domains.
// +optional
FailureDomains clusterv1.FailureDomains `json:"failureDomains,omitempty"`

// LoadBalancer allows defining configurations for the cluster load balancer.
// +optional
LoadBalancer DockerLoadBalancer `json:"loadBalancer,omitempty"`
}

// DockerLoadBalancer allows defining configurations for the cluster load balancer.
type DockerLoadBalancer struct {
// ImageMeta allows customizing the image used for the cluster load balancer.
ImageMeta `json:",inline"`
}

// ImageMeta allows customizing the image used for components that are not
// originated from the Kubernetes/Kubernetes release process.
stmcginnis marked this conversation as resolved.
Show resolved Hide resolved
type ImageMeta struct {
// ImageRepository sets the container registry to pull the haproxy image from.
// if not set, "kindest" will be used instead.
// +optional
ImageRepository string `json:"imageRepository,omitempty"`

// ImageTag allows to specify a tag for the haproxy image.
// if not set, "v20210715-a6da3463" will be used instead.
// +optional
ImageTag string `json:"imageTag,omitempty"`
}

// DockerClusterStatus defines the observed state of DockerCluster.
Expand Down
32 changes: 32 additions & 0 deletions test/infrastructure/docker/api/v1alpha4/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,19 @@ spec:
will simply copy these into the Status and allow the Cluster API
controllers to do what they will with the defined failure domains.
type: object
loadBalancer:
description: LoadBalancer allows defining configurations for the cluster
load balancer.
properties:
imageRepository:
description: ImageRepository sets the container registry to pull
the haproxy image from. if not set, "kindest" will be used instead.
type: string
imageTag:
description: ImageTag allows to specify a tag for the haproxy
image. if not set, "v20210715-a6da3463" will be used instead.
type: string
type: object
type: object
status:
description: DockerClusterStatus defines the observed state of DockerCluster.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func (r *DockerClusterReconciler) Reconcile(ctx context.Context, req ctrl.Reques
log = log.WithValues("cluster", cluster.Name)

// Create a helper for managing a docker container hosting the loadbalancer.
externalLoadBalancer, err := docker.NewLoadBalancer(cluster)
externalLoadBalancer, err := docker.NewLoadBalancer(cluster, dockerCluster)
if err != nil {
return ctrl.Result{}, errors.Wrapf(err, "failed to create helper for managing the externalLoadBalancer")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func (r *DockerMachineReconciler) Reconcile(ctx context.Context, req ctrl.Reques
// NB. the machine controller has to manage the cluster load balancer because the current implementation of the
// docker load balancer does not support auto-discovery of control plane nodes, so CAPD should take care of
// updating the cluster load balancer configuration when control plane machines are added/removed
externalLoadBalancer, err := docker.NewLoadBalancer(cluster)
externalLoadBalancer, err := docker.NewLoadBalancer(cluster, dockerCluster)
if err != nil {
return ctrl.Result{}, errors.Wrapf(err, "failed to create helper for managing the externalLoadBalancer")
}
Expand Down
29 changes: 27 additions & 2 deletions test/infrastructure/docker/docker/loadbalancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/pkg/errors"
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha4"
"sigs.k8s.io/cluster-api/test/infrastructure/container"
"sigs.k8s.io/cluster-api/test/infrastructure/docker/api/v1alpha4"
"sigs.k8s.io/cluster-api/test/infrastructure/docker/docker/types"
"sigs.k8s.io/cluster-api/test/infrastructure/docker/third_party/forked/loadbalancer"
ctrl "sigs.k8s.io/controller-runtime"
Expand All @@ -37,13 +38,14 @@ type lbCreator interface {
// LoadBalancer manages the load balancer for a specific docker cluster.
type LoadBalancer struct {
name string
image string
container *types.Node
ipFamily clusterv1.ClusterIPFamily
lbCreator lbCreator
}

// NewLoadBalancer returns a new helper for managing a docker loadbalancer with a given name.
func NewLoadBalancer(cluster *clusterv1.Cluster) (*LoadBalancer, error) {
func NewLoadBalancer(cluster *clusterv1.Cluster, dockerCluster *v1alpha4.DockerCluster) (*LoadBalancer, error) {
if cluster.Name == "" {
return nil, errors.New("create load balancer: cluster name is empty")
}
Expand All @@ -65,14 +67,37 @@ func NewLoadBalancer(cluster *clusterv1.Cluster) (*LoadBalancer, error) {
return nil, fmt.Errorf("create load balancer: %s", err)
}

image := getLoadBalancerImage(dockerCluster)

return &LoadBalancer{
name: cluster.Name,
image: image,
container: container,
ipFamily: ipFamily,
lbCreator: &Manager{},
}, nil
}

// getLoadBalancerImage will return the image (e.g. "kindest/haproxy:2.1.1-alpine") to use for
// the load balancer.
func getLoadBalancerImage(dockerCluster *v1alpha4.DockerCluster) string {
// Check if a non-default image was provided
image := loadbalancer.Image
imageRepo := loadbalancer.DefaultImageRepository
imageTag := loadbalancer.DefaultImageTag

if dockerCluster != nil {
if dockerCluster.Spec.LoadBalancer.ImageRepository != "" {
imageRepo = dockerCluster.Spec.LoadBalancer.ImageRepository
}
if dockerCluster.Spec.LoadBalancer.ImageTag != "" {
imageTag = dockerCluster.Spec.LoadBalancer.ImageTag
}
}

return fmt.Sprintf("%s/%s:%s", imageRepo, image, imageTag)
}

// ContainerName is the name of the docker container with the load balancer.
func (s *LoadBalancer) containerName() string {
return fmt.Sprintf("%s-lb", s.name)
Expand All @@ -94,7 +119,7 @@ func (s *LoadBalancer) Create(ctx context.Context) error {
s.container, err = s.lbCreator.CreateExternalLoadBalancerNode(
ctx,
s.containerName(),
loadbalancer.Image,
s.image,
s.name,
listenAddr,
0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,14 @@ limitations under the License.

package loadbalancer

// Image defines the loadbalancer image:tag
const Image = "kindest/haproxy:v20210715-a6da3463"
stmcginnis marked this conversation as resolved.
Show resolved Hide resolved
// Image defines the loadbalancer image name
const Image = "haproxy"

// DefaultImageRepository defines the loadbalancer image repository
const DefaultImageRepository = "kindest"

// DefaultImageTag defines the loadbalancer image tag
const DefaultImageTag = "v20210715-a6da3463"

// ConfigPath defines the path to the config file in the image
const ConfigPath = "/usr/local/etc/haproxy/haproxy.cfg"