Skip to content

Commit

Permalink
Configure IPFamily in control plane HA service (#170)
Browse files Browse the repository at this point in the history
 Configure IPFamily in control plane HA service
  • Loading branch information
chenlin07 authored Oct 17, 2023
1 parent 31b319e commit b6cd7e6
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 2 deletions.
20 changes: 20 additions & 0 deletions pkg/haprovider/haprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package haprovider

import (
"context"
"github.com/vmware-tanzu/load-balancer-operator-for-kubernetes/pkg/utils"
"net"
"sync"

Expand All @@ -25,6 +26,12 @@ import (
akov1alpha1 "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/pkg/apis/ako/v1alpha1"
)

const (
IPv4IpFamily = "IPv4"
IPv6IpFamily = "IPv6"
IPv6IpType = "V6"
)

type HAProvider struct {
client.Client
log logr.Logger
Expand Down Expand Up @@ -96,6 +103,17 @@ func (r *HAProvider) createService(
return nil, err
}

// Get cluster primary ip family, which is used for HA service
primaryIPFamily, err := utils.GetPrimaryIPFamily(cluster)
if err != nil {
return nil, err
}
if primaryIPFamily == IPv6IpType {
primaryIPFamily = IPv6IpFamily
} else {
primaryIPFamily = IPv4IpFamily
}

service := &corev1.Service{
TypeMeta: metav1.TypeMeta{
Kind: "Service",
Expand All @@ -108,6 +126,8 @@ func (r *HAProvider) createService(
},
Spec: corev1.ServiceSpec{
Type: corev1.ServiceTypeLoadBalancer,
//TODO:(chenlin) Add two ip families after AKO fully supports dual-stack load balancer type of service
IPFamilies: []corev1.IPFamily{corev1.IPFamily(primaryIPFamily)},
Ports: []corev1.ServicePort{{
Protocol: "TCP",
Port: port,
Expand Down
80 changes: 80 additions & 0 deletions pkg/haprovider/haprovider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,86 @@ var _ = Describe("Control Plane HA provider", func() {
})
})

When("cluster is dual-stack IPv4 Primary", func() {
BeforeEach(func() {
cluster = &clusterv1.Cluster{
ObjectMeta: v1.ObjectMeta{
Name: "test-cluster",
Namespace: "default",
Annotations: map[string]string{"tkg.tanzu.vmware.com/cluster-controlplane-endpoint": "2.2.2.2"},
},
Spec: clusterv1.ClusterSpec{
ClusterNetwork: &clusterv1.ClusterNetwork{
Pods: &clusterv1.NetworkRanges{
CIDRBlocks: []string{"10.0.0.0/24", "2002::1234:abcd:ffff:c0a8:101/64"},
},
},
},
}
})
It("should create service successfully", func() {
svc, err = haProvider.createService(ctx, cluster)
Expect(err).ShouldNot(HaveOccurred())
Expect(svc.Spec.LoadBalancerIP).Should(Equal("2.2.2.2"))
Expect(svc.Spec.IPFamilies[0]).Should(Equal(corev1.IPFamily("IPv4")))
Expect(svc.Annotations[akoov1alpha1.AkoPreferredIPAnnotation]).Should(Equal("2.2.2.2"))
Expect(haProvider.Client.Delete(ctx, svc)).ShouldNot(HaveOccurred())
})
})

When("cluster is dual-stack IPv6 Primary", func() {
BeforeEach(func() {
cluster = &clusterv1.Cluster{
ObjectMeta: v1.ObjectMeta{
Name: "test-cluster",
Namespace: "default",
Annotations: map[string]string{"tkg.tanzu.vmware.com/cluster-controlplane-endpoint": "2.2.2.2"},
},
Spec: clusterv1.ClusterSpec{
ClusterNetwork: &clusterv1.ClusterNetwork{
Pods: &clusterv1.NetworkRanges{
CIDRBlocks: []string{"2002::1234:abcd:ffff:c0a8:101/64", "10.0.0.0/24"},
},
},
},
}
})
It("should create service successfully", func() {
svc, err = haProvider.createService(ctx, cluster)
Expect(err).ShouldNot(HaveOccurred())
Expect(svc.Spec.LoadBalancerIP).Should(Equal("2.2.2.2"))
Expect(svc.Spec.IPFamilies[0]).Should(Equal(corev1.IPFamily("IPv6")))
Expect(svc.Annotations[akoov1alpha1.AkoPreferredIPAnnotation]).Should(Equal("2.2.2.2"))
Expect(haProvider.Client.Delete(ctx, svc)).ShouldNot(HaveOccurred())
})
})

When("cluster is single-stack IPv4", func() {
BeforeEach(func() {
cluster = &clusterv1.Cluster{
ObjectMeta: v1.ObjectMeta{
Name: "test-cluster",
Namespace: "default",
Annotations: map[string]string{"tkg.tanzu.vmware.com/cluster-controlplane-endpoint": "2.2.2.2"},
},
Spec: clusterv1.ClusterSpec{
ClusterNetwork: &clusterv1.ClusterNetwork{
Pods: &clusterv1.NetworkRanges{
CIDRBlocks: []string{"10.0.0.0/24"},
},
},
},
}
})
It("should create service successfully", func() {
svc, err = haProvider.createService(ctx, cluster)
Expect(err).ShouldNot(HaveOccurred())
Expect(svc.Spec.LoadBalancerIP).Should(Equal("2.2.2.2"))
Expect(svc.Spec.IPFamilies[0]).Should(Equal(corev1.IPFamily("IPv4")))
Expect(svc.Annotations[akoov1alpha1.AkoPreferredIPAnnotation]).Should(Equal("2.2.2.2"))
Expect(haProvider.Client.Delete(ctx, svc)).ShouldNot(HaveOccurred())
})
})
})

Context("Test_CreateOrUpdateHAEndpoints", func() {
Expand Down
2 changes: 1 addition & 1 deletion pkg/utils/get_ipfamily.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ func GetPrimaryIPFamily(c *capi.Cluster) (string, error) {
if err != nil {
return InvalidIPFamily, fmt.Errorf("Invalid IP Family: %s", err)
}
if ipFamily == IPv4IpFamily || ipFamily == DualStackIPv4Primary{
if ipFamily == IPv4IpFamily || ipFamily == DualStackIPv4Primary {
return IPv4IpFamily, nil
}
return IPv6IpFamily, nil
Expand Down
2 changes: 1 addition & 1 deletion pkg/utils/get_ipfamily_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ var _ = ginkgo.Describe("Test get primary ipFamily", func() {
Spec: capi.ClusterSpec{
ClusterNetwork: &capi.ClusterNetwork{
Pods: &capi.NetworkRanges{
CIDRBlocks: []string{"192.168.0.0/16","2002::1234:abcd:ffff:c0a8:101/64","10.10.0.0/16"},
CIDRBlocks: []string{"192.168.0.0/16", "2002::1234:abcd:ffff:c0a8:101/64", "10.10.0.0/16"},
},
Services: &capi.NetworkRanges{
CIDRBlocks: []string{"192.168.0.0/16"},
Expand Down

0 comments on commit b6cd7e6

Please sign in to comment.