Skip to content

Commit e29bc2e

Browse files
committed
test: Add E2E test for zone-redundant load balancers
Add dedicated end-to-end test to verify zone-redundant load balancer functionality in real Azure environments. The test: - Creates a cluster with zone-redundant load balancers configured - Uses the apiserver-ilb flavor with zones set to 1,2,3 - Verifies zones are correctly set in AzureCluster spec - Validates Azure resources have zones on frontend IP configurations - Tests all three load balancer types: - API Server Load Balancer (internal) - Node Outbound Load Balancer - Control Plane Outbound Load Balancer This is an optional test that validates the complete feature works end-to-end by creating actual Azure infrastructure and verifying the zone configuration.
1 parent c7aec86 commit e29bc2e

File tree

1 file changed

+153
-0
lines changed

1 file changed

+153
-0
lines changed

test/e2e/azure_test.go

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import (
2727
"strings"
2828
"time"
2929

30+
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
31+
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4"
3032
"github.com/Azure/azure-service-operator/v2/pkg/common/config"
3133
. "github.com/onsi/ginkgo/v2"
3234
. "github.com/onsi/gomega"
@@ -37,6 +39,8 @@ import (
3739
"sigs.k8s.io/cluster-api/test/framework/clusterctl"
3840
"sigs.k8s.io/cluster-api/util"
3941
"sigs.k8s.io/controller-runtime/pkg/client"
42+
43+
infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
4044
)
4145

4246
var _ = Describe("Workload cluster creation", func() {
@@ -1427,5 +1431,154 @@ var _ = Describe("Workload cluster creation", func() {
14271431
})
14281432
})
14291433

1434+
Context("Creating a cluster with zone-redundant load balancers [OPTIONAL]", func() {
1435+
It("with zone-redundant API server, node outbound, and control plane outbound load balancers", func() {
1436+
clusterName = getClusterName(clusterNamePrefix, "lb-zones")
1437+
1438+
// Set up zone-redundant load balancer configuration
1439+
Expect(os.Setenv("EXP_APISERVER_ILB", "true")).To(Succeed())
1440+
Expect(os.Setenv("AZURE_INTERNAL_LB_PRIVATE_IP", "40.0.0.100")).To(Succeed())
1441+
Expect(os.Setenv("AZURE_VNET_CIDR", "40.0.0.0/8")).To(Succeed())
1442+
Expect(os.Setenv("AZURE_CP_SUBNET_CIDR", "40.0.0.0/16")).To(Succeed())
1443+
Expect(os.Setenv("AZURE_NODE_SUBNET_CIDR", "40.1.0.0/16")).To(Succeed())
1444+
Expect(os.Setenv("AZURE_LB_ZONES", "1,2,3")).To(Succeed())
1445+
1446+
clusterctl.ApplyClusterTemplateAndWait(ctx, createApplyClusterTemplateInput(
1447+
specName,
1448+
withFlavor("apiserver-ilb"),
1449+
withNamespace(namespace.Name),
1450+
withClusterName(clusterName),
1451+
withControlPlaneMachineCount(3),
1452+
withWorkerMachineCount(2),
1453+
withControlPlaneInterval(specName, "wait-control-plane-ha"),
1454+
withControlPlaneWaiters(clusterctl.ControlPlaneWaiters{
1455+
WaitForControlPlaneInitialized: EnsureControlPlaneInitialized,
1456+
}),
1457+
withPostMachinesProvisioned(func() {
1458+
EnsureDaemonsets(ctx, func() DaemonsetsSpecInput {
1459+
return DaemonsetsSpecInput{
1460+
BootstrapClusterProxy: bootstrapClusterProxy,
1461+
Namespace: namespace,
1462+
ClusterName: clusterName,
1463+
}
1464+
})
1465+
}),
1466+
), result)
1467+
1468+
By("Verifying load balancer zones are configured correctly in Azure", func() {
1469+
expectedZones := []string{"1", "2", "3"}
1470+
1471+
subscriptionID := getSubscriptionID(Default)
1472+
cred, err := azidentity.NewDefaultAzureCredential(nil)
1473+
Expect(err).NotTo(HaveOccurred())
1474+
1475+
mgmtClient := bootstrapClusterProxy.GetClient()
1476+
Expect(mgmtClient).NotTo(BeNil())
1477+
1478+
azureCluster := &infrav1.AzureCluster{}
1479+
err = mgmtClient.Get(ctx, client.ObjectKey{
1480+
Namespace: namespace.Name,
1481+
Name: clusterName,
1482+
}, azureCluster)
1483+
Expect(err).NotTo(HaveOccurred())
1484+
1485+
resourceGroupName := azureCluster.Spec.ResourceGroup
1486+
Expect(resourceGroupName).NotTo(BeEmpty())
1487+
1488+
lbClient, err := armnetwork.NewLoadBalancersClient(subscriptionID, cred, nil)
1489+
Expect(err).NotTo(HaveOccurred())
1490+
1491+
// Verify API Server Load Balancer zones
1492+
if azureCluster.Spec.NetworkSpec.APIServerLB != nil {
1493+
Expect(azureCluster.Spec.NetworkSpec.APIServerLB.AvailabilityZones).To(Equal(expectedZones),
1494+
"APIServerLB should have zones configured in AzureCluster spec")
1495+
1496+
lbName := azureCluster.Spec.NetworkSpec.APIServerLB.Name
1497+
Eventually(func(g Gomega) {
1498+
lb, err := lbClient.Get(ctx, resourceGroupName, lbName, nil)
1499+
g.Expect(err).NotTo(HaveOccurred())
1500+
g.Expect(lb.Properties).NotTo(BeNil())
1501+
g.Expect(lb.Properties.FrontendIPConfigurations).NotTo(BeEmpty())
1502+
1503+
for _, frontendIP := range lb.Properties.FrontendIPConfigurations {
1504+
g.Expect(frontendIP.Zones).NotTo(BeNil(), "Frontend IP should have zones configured")
1505+
g.Expect(frontendIP.Zones).To(HaveLen(3), "Frontend IP should have 3 zones")
1506+
1507+
zonesMap := make(map[string]bool)
1508+
for _, zone := range frontendIP.Zones {
1509+
if zone != nil {
1510+
zonesMap[*zone] = true
1511+
}
1512+
}
1513+
for _, expectedZone := range expectedZones {
1514+
g.Expect(zonesMap[expectedZone]).To(BeTrue(), "Zone %s should be configured", expectedZone)
1515+
}
1516+
}
1517+
}, retryableOperationTimeout, retryableOperationSleepBetweenRetries).Should(Succeed())
1518+
}
1519+
1520+
// Verify Node Outbound Load Balancer zones
1521+
if azureCluster.Spec.NetworkSpec.NodeOutboundLB != nil {
1522+
Expect(azureCluster.Spec.NetworkSpec.NodeOutboundLB.AvailabilityZones).To(Equal(expectedZones),
1523+
"NodeOutboundLB should have zones configured in AzureCluster spec")
1524+
1525+
lbName := azureCluster.Spec.NetworkSpec.NodeOutboundLB.Name
1526+
Eventually(func(g Gomega) {
1527+
lb, err := lbClient.Get(ctx, resourceGroupName, lbName, nil)
1528+
g.Expect(err).NotTo(HaveOccurred())
1529+
g.Expect(lb.Properties).NotTo(BeNil())
1530+
g.Expect(lb.Properties.FrontendIPConfigurations).NotTo(BeEmpty())
1531+
1532+
for _, frontendIP := range lb.Properties.FrontendIPConfigurations {
1533+
g.Expect(frontendIP.Zones).NotTo(BeNil(), "Frontend IP should have zones configured")
1534+
g.Expect(frontendIP.Zones).To(HaveLen(3), "Frontend IP should have 3 zones")
1535+
1536+
zonesMap := make(map[string]bool)
1537+
for _, zone := range frontendIP.Zones {
1538+
if zone != nil {
1539+
zonesMap[*zone] = true
1540+
}
1541+
}
1542+
for _, expectedZone := range expectedZones {
1543+
g.Expect(zonesMap[expectedZone]).To(BeTrue(), "Zone %s should be configured", expectedZone)
1544+
}
1545+
}
1546+
}, retryableOperationTimeout, retryableOperationSleepBetweenRetries).Should(Succeed())
1547+
}
1548+
1549+
// Verify Control Plane Outbound Load Balancer zones
1550+
if azureCluster.Spec.NetworkSpec.ControlPlaneOutboundLB != nil {
1551+
Expect(azureCluster.Spec.NetworkSpec.ControlPlaneOutboundLB.AvailabilityZones).To(Equal(expectedZones),
1552+
"ControlPlaneOutboundLB should have zones configured in AzureCluster spec")
1553+
1554+
lbName := azureCluster.Spec.NetworkSpec.ControlPlaneOutboundLB.Name
1555+
Eventually(func(g Gomega) {
1556+
lb, err := lbClient.Get(ctx, resourceGroupName, lbName, nil)
1557+
g.Expect(err).NotTo(HaveOccurred())
1558+
g.Expect(lb.Properties).NotTo(BeNil())
1559+
g.Expect(lb.Properties.FrontendIPConfigurations).NotTo(BeEmpty())
1560+
1561+
for _, frontendIP := range lb.Properties.FrontendIPConfigurations {
1562+
g.Expect(frontendIP.Zones).NotTo(BeNil(), "Frontend IP should have zones configured")
1563+
g.Expect(frontendIP.Zones).To(HaveLen(3), "Frontend IP should have 3 zones")
1564+
1565+
zonesMap := make(map[string]bool)
1566+
for _, zone := range frontendIP.Zones {
1567+
if zone != nil {
1568+
zonesMap[*zone] = true
1569+
}
1570+
}
1571+
for _, expectedZone := range expectedZones {
1572+
g.Expect(zonesMap[expectedZone]).To(BeTrue(), "Zone %s should be configured", expectedZone)
1573+
}
1574+
}
1575+
}, retryableOperationTimeout, retryableOperationSleepBetweenRetries).Should(Succeed())
1576+
}
1577+
})
1578+
1579+
By("PASSED!")
1580+
})
1581+
})
1582+
14301583
// TODO: add a same test as above for a windows cluster
14311584
})

0 commit comments

Comments
 (0)