Skip to content

Commit

Permalink
AKO won't be installed in IPv6 single-stack and IPv6 Primary dual-sta…
Browse files Browse the repository at this point in the history
…ck cluster (#176)
  • Loading branch information
chenlin07 authored Nov 28, 2023
1 parent 8f0289d commit ce32f01
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 37 deletions.
24 changes: 12 additions & 12 deletions api/v1alpha1/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,18 @@ const (
AkoPackageInstallName = "load-balancer-and-ingress-service"
AkoPreferredIPAnnotation = "ako.vmware.com/load-balancer-ip"

AviClusterLabel = "networking.tkg.tanzu.vmware.com/avi"
AviClusterDeleteConfigLabel = "networking.tkg.tanzu.vmware.com/avi-config-delete"
AviClusterSecretType = "avi.cluster.x-k8s.io/secret"
AviNamespace = "avi-system"
AviCredentialName = "avi-controller-credentials"
AviCAName = "avi-controller-ca"
AviCertificateKey = "certificateAuthorityData"
AviResourceCleanupReason = "AviResourceCleanup"
AviResourceCleanupSucceededCondition clusterv1.ConditionType = "AviResourceCleanupSucceeded"
AviUserCleanupSucceededCondition clusterv1.ConditionType = "AviUserCleanupSucceeded"
AKOIpFamilyValidationSucceededCondition clusterv1.ConditionType = "AKOIpFamilyValidationSucceeded"
PreTerminateAnnotation = clusterv1.PreTerminateDeleteHookAnnotationPrefix + "/avi-cleanup"
AviClusterLabel = "networking.tkg.tanzu.vmware.com/avi"
AviClusterDeleteConfigLabel = "networking.tkg.tanzu.vmware.com/avi-config-delete"
AviClusterSecretType = "avi.cluster.x-k8s.io/secret"
AviNamespace = "avi-system"
AviCredentialName = "avi-controller-credentials"
AviCAName = "avi-controller-ca"
AviCertificateKey = "certificateAuthorityData"
AviResourceCleanupReason = "AviResourceCleanup"
AviResourceCleanupSucceededCondition clusterv1.ConditionType = "AviResourceCleanupSucceeded"
AviUserCleanupSucceededCondition clusterv1.ConditionType = "AviUserCleanupSucceeded"
ClusterIpFamilyValidationSucceededCondition clusterv1.ConditionType = "ClusterIpFamilyValidationSucceeded"
PreTerminateAnnotation = clusterv1.PreTerminateDeleteHookAnnotationPrefix + "/avi-cleanup"

HAServiceName = "control-plane"
HAServiceBootstrapClusterFinalizer = "ako-operator.networking.tkg.tanzu.vmware.com/ha"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ import (
runv1alpha3 "github.com/vmware-tanzu/tanzu-framework/apis/run/v1alpha3"
)

const (
IPv4IpFamily = "V4"
IPv6IpFamily = "V6"
DualStackIPv6Primary = "V6,V4"
DualStackIPv4Primary = "V4,V6"
)

func (r *ClusterReconciler) ReconcileAddonSecret(
ctx context.Context,
log logr.Logger,
Expand Down Expand Up @@ -59,13 +66,13 @@ func (r *ClusterReconciler) ReconcileAddonSecret(
}
}

//Stop reconciling if AKO ip family doesn't match cluster ip family
if err = ValidateADCAndClusterIpFamily(cluster, obj, isVIPProvider, log); err != nil {
errInfo := "Selected AKODeploymentConfig " + obj.Name + "'s IP family doesn't match cluster " + cluster.Namespace +
"-" + cluster.Name + "'s ip family, stop deploying AKO into cluster " + cluster.Namespace + "-" + cluster.Name
//Stop reconciling if cluster ip family doesn't satisfy the condition
if err = ValidateClusterIpFamily(cluster, obj, isVIPProvider, log); err != nil {
errInfo := "cluster " + cluster.Namespace +
"-" + cluster.Name + "'s ip family is not allowed, stop deploying AKO into cluster " + cluster.Namespace + "-" + cluster.Name
log.Error(err, errInfo)
clusterCondition := &clusterv1.Condition{
Type: akoov1alpha1.AKOIpFamilyValidationSucceededCondition,
Type: akoov1alpha1.ClusterIpFamilyValidationSucceededCondition,
Status: corev1.ConditionFalse,
Message: errInfo,
}
Expand Down Expand Up @@ -358,30 +365,32 @@ func getAKOPackageRefFromClusterBootstrap(log logr.Logger, cb *runv1alpha3.Clust
return -1, nil
}

func ValidateADCAndClusterIpFamily(cluster *clusterv1.Cluster, adc *akoov1alpha1.AKODeploymentConfig, isVIPProvider bool, log logr.Logger) error {
adcIpFamily := "V4"
if adc.Spec.ExtraConfigs.IpFamily != "" {
adcIpFamily = adc.Spec.ExtraConfigs.IpFamily
}
func ValidateClusterIpFamily(cluster *clusterv1.Cluster, adc *akoov1alpha1.AKODeploymentConfig, isVIPProvider bool, log logr.Logger) error {
clusterIpFamily, err := utils.GetClusterIPFamily(cluster)
if err != nil {
log.Error(err, "can't get cluster ip family")
return err
}
// AKO limitations: AKO doesn't work in IPv6 single-stack and IPv6 Primary dual-stack cluster
if clusterIpFamily == IPv6IpFamily || clusterIpFamily == DualStackIPv6Primary {
return errors.New("AKO doesn't work in IPv6 single-stack and IPv6 Primary dual-stack cluster")
}

adcIpFamily := IPv4IpFamily
if adc.Spec.ExtraConfigs.IpFamily != "" {
adcIpFamily = adc.Spec.ExtraConfigs.IpFamily
}

// AKO limitations: AKO can't configure backend pool ip family
// TODO:(chenlin) Remove validation after AKO supports configurable ip pool
if (adcIpFamily == "V4" && clusterIpFamily == "V6") || (adcIpFamily == "V6" && clusterIpFamily == "V4") {
if adcIpFamily == IPv6IpFamily && clusterIpFamily == IPv4IpFamily {
errInfo := "AKO with IP family " + adcIpFamily + " can not work together with cluster with IP family " + clusterIpFamily
return errors.New(errInfo)
}
// When enable avi as control plane ha, backend server shouldn't use secondary ip type
// TODO:(chenlin) Remove validation after AKO supports configurable ip pool
if isVIPProvider {
if adcIpFamily == "V4" && clusterIpFamily == "V6,V4" {
return errors.New("When enabling avi as control plane HA, AKO with IP family V4 can not work together with ipv6 primary dual-stack cluster")
} else if adcIpFamily == "V6" && clusterIpFamily == "V4,V6" {
return errors.New("When enabling avi as control plane HA, AKO with IP family V6 can not work together with ipv4 primary dual-stack cluster")
}
if isVIPProvider && adcIpFamily == IPv6IpFamily && clusterIpFamily == DualStackIPv4Primary {
return errors.New("When enabling avi as control plane HA, AKO with IP family V6 can not work together with ipv4 primary dual-stack cluster")
}
return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,123 @@ func unitTestAKODeploymentYaml() {
})
}

func unitTestValidateADCAndClusterIpFamily() {
func unitTestValidateClusterIpFamily() {
Context("Validate ipv6 cluster ip family", func() {
var (
akoDeploymentConfig *akoov1alpha1.AKODeploymentConfig
capiCluster *clusterv1.Cluster
logger logr.Logger
isVIPProvider bool
)

BeforeEach(func() {
log.SetLogger(zap.New())
logger = log.Log
})

When("cluster is valid", func() {
BeforeEach(func() {
akoDeploymentConfig = &akoov1alpha1.AKODeploymentConfig{
Spec: akoov1alpha1.AKODeploymentConfigSpec{
ExtraConfigs: akoov1alpha1.ExtraConfigs{
IpFamily: "V4",
},
},
}

capiCluster = &clusterv1.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: "test-cluster",
Namespace: "default",
},
Spec: clusterv1.ClusterSpec{
ClusterNetwork: &clusterv1.ClusterNetwork{
Pods: &clusterv1.NetworkRanges{
CIDRBlocks: []string{"192.168.0.0/16"},
},
Services: &clusterv1.NetworkRanges{
CIDRBlocks: []string{"192.168.0.0/16"},
},
},
},
}
})

It("should return no error", func() {
err := cluster.ValidateClusterIpFamily(capiCluster, akoDeploymentConfig, isVIPProvider, logger)
Expect(err).ShouldNot(HaveOccurred())
})
})

When("cluster is invalid single-stack IPv6", func() {
BeforeEach(func() {
akoDeploymentConfig = &akoov1alpha1.AKODeploymentConfig{
Spec: akoov1alpha1.AKODeploymentConfigSpec{
ExtraConfigs: akoov1alpha1.ExtraConfigs{
IpFamily: "V4",
},
},
}

capiCluster = &clusterv1.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: "test-cluster",
Namespace: "default",
},
Spec: clusterv1.ClusterSpec{
ClusterNetwork: &clusterv1.ClusterNetwork{
Pods: &clusterv1.NetworkRanges{
CIDRBlocks: []string{"2002::1234:abcd:ffff:c0a8:101/64"},
},
Services: &clusterv1.NetworkRanges{
CIDRBlocks: []string{"2002::1234:abcd:ffff:c0a8:101/64"},
},
},
},
}
})

It("should return no error", func() {
err := cluster.ValidateClusterIpFamily(capiCluster, akoDeploymentConfig, isVIPProvider, logger)
Expect(err).Should(HaveOccurred())
})
})

When("cluster is invalid dual-stack IPv6 Primary", func() {
BeforeEach(func() {
akoDeploymentConfig = &akoov1alpha1.AKODeploymentConfig{
Spec: akoov1alpha1.AKODeploymentConfigSpec{
ExtraConfigs: akoov1alpha1.ExtraConfigs{
IpFamily: "V4",
},
},
}

capiCluster = &clusterv1.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: "test-cluster",
Namespace: "default",
},
Spec: clusterv1.ClusterSpec{
ClusterNetwork: &clusterv1.ClusterNetwork{
Pods: &clusterv1.NetworkRanges{
CIDRBlocks: []string{"2002::1234:abcd:ffff:c0a8:101/64, 192.168.0.0/16"},
},
Services: &clusterv1.NetworkRanges{
CIDRBlocks: []string{"2002::1234:abcd:ffff:c0a8:101/64, 192.168.0.0/16"},
},
},
},
}
})

It("should return no error", func() {
err := cluster.ValidateClusterIpFamily(capiCluster, akoDeploymentConfig, isVIPProvider, logger)
Expect(err).Should(HaveOccurred())
})
})
})

Context("Validate AKODeploymentConfig ip family and cluster ip family", func() {
var (
akoDeploymentConfig *akoov1alpha1.AKODeploymentConfig
Expand Down Expand Up @@ -335,7 +451,7 @@ func unitTestValidateADCAndClusterIpFamily() {
})

It("should return no error", func() {
err := cluster.ValidateADCAndClusterIpFamily(capiCluster, akoDeploymentConfig, isVIPProvider, logger)
err := cluster.ValidateClusterIpFamily(capiCluster, akoDeploymentConfig, isVIPProvider, logger)
Expect(err).ShouldNot(HaveOccurred())
})
})
Expand Down Expand Up @@ -383,7 +499,7 @@ func unitTestValidateADCAndClusterIpFamily() {
})

It("should return error since cluster ip family is invalid", func() {
err := cluster.ValidateADCAndClusterIpFamily(capiCluster, akoDeploymentConfig, isVIPProvider, logger)
err := cluster.ValidateClusterIpFamily(capiCluster, akoDeploymentConfig, isVIPProvider, logger)
Expect(err).Should(HaveOccurred())
})
})
Expand Down Expand Up @@ -428,7 +544,7 @@ func unitTestValidateADCAndClusterIpFamily() {
})

It("should return error since the ipfamily combination is not supported", func() {
err := cluster.ValidateADCAndClusterIpFamily(capiCluster, akoDeploymentConfig, isVIPProvider, logger)
err := cluster.ValidateClusterIpFamily(capiCluster, akoDeploymentConfig, isVIPProvider, logger)
Expect(err).Should(HaveOccurred())
})
})
Expand Down Expand Up @@ -472,7 +588,7 @@ func unitTestValidateADCAndClusterIpFamily() {
})

It("should return error since the ipfamily combination is not supported", func() {
err := cluster.ValidateADCAndClusterIpFamily(capiCluster, akoDeploymentConfig, isVIPProvider, logger)
err := cluster.ValidateClusterIpFamily(capiCluster, akoDeploymentConfig, isVIPProvider, logger)
Expect(err).Should(HaveOccurred())
})
})
Expand Down Expand Up @@ -519,7 +635,7 @@ func unitTestValidateADCAndClusterIpFamily() {
})

It("should return error since the ipfamily combination is not supported", func() {
err := cluster.ValidateADCAndClusterIpFamily(capiCluster, akoDeploymentConfig, isVIPProvider, logger)
err := cluster.ValidateClusterIpFamily(capiCluster, akoDeploymentConfig, isVIPProvider, logger)
Expect(err).Should(HaveOccurred())
})
})
Expand Down Expand Up @@ -563,7 +679,7 @@ func unitTestValidateADCAndClusterIpFamily() {
})

It("should return error since the ipfamily combination is not supported", func() {
err := cluster.ValidateADCAndClusterIpFamily(capiCluster, akoDeploymentConfig, isVIPProvider, logger)
err := cluster.ValidateClusterIpFamily(capiCluster, akoDeploymentConfig, isVIPProvider, logger)
Expect(err).Should(HaveOccurred())
})
})
Expand Down
2 changes: 1 addition & 1 deletion controllers/akodeploymentconfig/cluster/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,5 @@ func intgTests() {

func unitTests() {
Describe("AKO Deployment Spec generation", unitTestAKODeploymentYaml)
Describe("AKODeploymentConfig and cluster ip family Validation", unitTestValidateADCAndClusterIpFamily)
Describe("Cluster ip family Validation", unitTestValidateClusterIpFamily)
}

0 comments on commit ce32f01

Please sign in to comment.