mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-14 13:45:06 +00:00
Merge pull request #125237 from aojea/ipmode_integration
improve loadbalancer IPMode testing
This commit is contained in:
@@ -84,6 +84,7 @@ type Cloud struct {
|
|||||||
ClusterList []string
|
ClusterList []string
|
||||||
MasterName string
|
MasterName string
|
||||||
ExternalIP net.IP
|
ExternalIP net.IP
|
||||||
|
BalancerIPMode *v1.LoadBalancerIPMode
|
||||||
Balancers map[string]Balancer
|
Balancers map[string]Balancer
|
||||||
updateCallLock sync.Mutex
|
updateCallLock sync.Mutex
|
||||||
UpdateCalls []UpdateBalancerCall
|
UpdateCalls []UpdateBalancerCall
|
||||||
@@ -224,7 +225,15 @@ func (f *Cloud) EnsureLoadBalancer(ctx context.Context, clusterName string, serv
|
|||||||
f.Balancers[name] = Balancer{name, region, spec.LoadBalancerIP, spec.Ports, nodes}
|
f.Balancers[name] = Balancer{name, region, spec.LoadBalancerIP, spec.Ports, nodes}
|
||||||
|
|
||||||
status := &v1.LoadBalancerStatus{}
|
status := &v1.LoadBalancerStatus{}
|
||||||
status.Ingress = []v1.LoadBalancerIngress{{IP: f.ExternalIP.String()}}
|
// process Ports
|
||||||
|
portStatus := []v1.PortStatus{}
|
||||||
|
for _, port := range spec.Ports {
|
||||||
|
portStatus = append(portStatus, v1.PortStatus{
|
||||||
|
Port: port.Port,
|
||||||
|
Protocol: port.Protocol,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
status.Ingress = []v1.LoadBalancerIngress{{IP: f.ExternalIP.String(), IPMode: f.BalancerIPMode, Ports: portStatus}}
|
||||||
|
|
||||||
return status, f.Err
|
return status, f.Err
|
||||||
}
|
}
|
||||||
|
@@ -19,14 +19,15 @@ package service
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"reflect"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
||||||
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
@@ -39,6 +40,7 @@ import (
|
|||||||
"k8s.io/kubernetes/test/integration/framework"
|
"k8s.io/kubernetes/test/integration/framework"
|
||||||
"k8s.io/utils/net"
|
"k8s.io/utils/net"
|
||||||
utilpointer "k8s.io/utils/pointer"
|
utilpointer "k8s.io/utils/pointer"
|
||||||
|
"k8s.io/utils/ptr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Test_ServiceLoadBalancerAllocateNodePorts tests that a Service with spec.allocateLoadBalancerNodePorts=false
|
// Test_ServiceLoadBalancerAllocateNodePorts tests that a Service with spec.allocateLoadBalancerNodePorts=false
|
||||||
@@ -644,21 +646,62 @@ func newServiceController(t *testing.T, client *clientset.Clientset) (*serviceco
|
|||||||
|
|
||||||
// Test_ServiceLoadBalancerIPMode tests whether the cloud provider has correctly updated the ipMode field.
|
// Test_ServiceLoadBalancerIPMode tests whether the cloud provider has correctly updated the ipMode field.
|
||||||
func Test_ServiceLoadBalancerIPMode(t *testing.T) {
|
func Test_ServiceLoadBalancerIPMode(t *testing.T) {
|
||||||
ipModeVIP := corev1.LoadBalancerIPModeVIP
|
baseService := &corev1.Service{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test-update-load-balancer-ip-mode",
|
||||||
|
},
|
||||||
|
Spec: corev1.ServiceSpec{
|
||||||
|
Type: corev1.ServiceTypeLoadBalancer,
|
||||||
|
Ports: []corev1.ServicePort{{
|
||||||
|
Port: int32(80),
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
ipModeEnabled bool
|
ipModeEnabled bool
|
||||||
externalIP string
|
setIPMode *corev1.LoadBalancerIPMode
|
||||||
expectedIPMode *corev1.LoadBalancerIPMode
|
externalIP string
|
||||||
|
expectedIngress corev1.LoadBalancerIngress
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
ipModeEnabled: false,
|
ipModeEnabled: false,
|
||||||
externalIP: "1.2.3.4",
|
externalIP: "1.2.3.4",
|
||||||
expectedIPMode: nil,
|
expectedIngress: corev1.LoadBalancerIngress{
|
||||||
|
IP: "1.2.3.4",
|
||||||
|
IPMode: nil,
|
||||||
|
Ports: []corev1.PortStatus{{Port: 80, Protocol: corev1.ProtocolTCP}},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ipModeEnabled: true,
|
ipModeEnabled: true,
|
||||||
externalIP: "1.2.3.5",
|
setIPMode: nil,
|
||||||
expectedIPMode: &ipModeVIP,
|
externalIP: "1.2.3.4",
|
||||||
|
expectedIngress: corev1.LoadBalancerIngress{
|
||||||
|
IP: "1.2.3.4",
|
||||||
|
IPMode: ptr.To(corev1.LoadBalancerIPModeVIP),
|
||||||
|
Ports: []corev1.PortStatus{{Port: 80, Protocol: corev1.ProtocolTCP}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ipModeEnabled: true,
|
||||||
|
setIPMode: ptr.To(corev1.LoadBalancerIPModeVIP),
|
||||||
|
externalIP: "1.2.3.4",
|
||||||
|
expectedIngress: corev1.LoadBalancerIngress{
|
||||||
|
IP: "1.2.3.4",
|
||||||
|
IPMode: ptr.To(corev1.LoadBalancerIPModeVIP),
|
||||||
|
Ports: []corev1.PortStatus{{Port: 80, Protocol: corev1.ProtocolTCP}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ipModeEnabled: true,
|
||||||
|
setIPMode: ptr.To(corev1.LoadBalancerIPModeProxy),
|
||||||
|
externalIP: "1.2.3.4",
|
||||||
|
expectedIngress: corev1.LoadBalancerIngress{
|
||||||
|
IP: "1.2.3.4",
|
||||||
|
IPMode: ptr.To(corev1.LoadBalancerIPModeProxy),
|
||||||
|
Ports: []corev1.PortStatus{{Port: 80, Protocol: corev1.ProtocolTCP}},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -678,43 +721,68 @@ func Test_ServiceLoadBalancerIPMode(t *testing.T) {
|
|||||||
|
|
||||||
controller, cloud, informer := newServiceController(t, client)
|
controller, cloud, informer := newServiceController(t, client)
|
||||||
cloud.ExternalIP = net.ParseIPSloppy(tc.externalIP)
|
cloud.ExternalIP = net.ParseIPSloppy(tc.externalIP)
|
||||||
|
cloud.BalancerIPMode = tc.expectedIngress.IPMode
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
informer.Start(ctx.Done())
|
informer.Start(ctx.Done())
|
||||||
go controller.Run(ctx, 1, controllersmetrics.NewControllerManagerMetrics("loadbalancer-test"))
|
go controller.Run(ctx, 1, controllersmetrics.NewControllerManagerMetrics("loadbalancer-test"))
|
||||||
|
|
||||||
service := &corev1.Service{
|
service, err := client.CoreV1().Services(ns.Name).Create(ctx, baseService, metav1.CreateOptions{})
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "test-update-load-balancer-ip-mode",
|
|
||||||
},
|
|
||||||
Spec: corev1.ServiceSpec{
|
|
||||||
Type: corev1.ServiceTypeLoadBalancer,
|
|
||||||
Ports: []corev1.ServicePort{{
|
|
||||||
Port: int32(80),
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
service, err = client.CoreV1().Services(ns.Name).Create(ctx, service, metav1.CreateOptions{})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error creating test service: %v", err)
|
t.Fatalf("Error creating test service: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(5 * time.Second) // sleep 5 second to wait for the service controller reconcile
|
err = wait.PollUntilContextTimeout(ctx, 500*time.Millisecond, 10*time.Second, true, func(_ context.Context) (done bool, err error) {
|
||||||
service, err = client.CoreV1().Services(ns.Name).Get(ctx, service.Name, metav1.GetOptions{})
|
service, err = client.CoreV1().Services(ns.Name).Get(ctx, service.Name, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error getting test service: %v", err)
|
||||||
|
}
|
||||||
|
if len(service.Status.LoadBalancer.Ingress) != 1 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error getting test service: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(service.Status.LoadBalancer.Ingress) == 0 {
|
|
||||||
t.Fatalf("unexpected load balancer status")
|
t.Fatalf("unexpected load balancer status")
|
||||||
}
|
}
|
||||||
|
|
||||||
gotIngress := service.Status.LoadBalancer.Ingress[0]
|
ingress := service.Status.LoadBalancer.Ingress[0]
|
||||||
if gotIngress.IP != tc.externalIP || !reflect.DeepEqual(gotIngress.IPMode, tc.expectedIPMode) {
|
if !apiequality.Semantic.DeepEqual(&ingress, &tc.expectedIngress) {
|
||||||
t.Errorf("unexpected load balancer ingress, got ingress %v, expected IP %v, expected ipMode %v",
|
t.Errorf("expected Ingress %v, got IP %v",
|
||||||
gotIngress, tc.externalIP, tc.expectedIPMode)
|
ingress, tc.expectedIngress)
|
||||||
|
if ingress.IPMode != nil && tc.expectedIngress.IPMode != nil {
|
||||||
|
t.Logf("IPMode %v expected %v", *ingress.IPMode, *tc.expectedIngress.IPMode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mutate the service and check the status is preserved
|
||||||
|
newService := service.DeepCopy()
|
||||||
|
newService.Spec.Ports[0].Port = 443
|
||||||
|
service, err = client.CoreV1().Services(ns.Name).Update(ctx, newService, metav1.UpdateOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error updating test service: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedIngress := tc.expectedIngress
|
||||||
|
expectedIngress.Ports[0].Port = 443
|
||||||
|
err = wait.PollUntilContextTimeout(ctx, 500*time.Millisecond, 10*time.Second, true, func(_ context.Context) (done bool, err error) {
|
||||||
|
service, err = client.CoreV1().Services(ns.Name).Get(ctx, service.Name, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error getting test service: %v", err)
|
||||||
|
}
|
||||||
|
if len(service.Status.LoadBalancer.Ingress) != 1 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
ingress = service.Status.LoadBalancer.Ingress[0]
|
||||||
|
if !apiequality.Semantic.DeepEqual(&ingress, &expectedIngress) {
|
||||||
|
t.Logf("Ingress %v Expected %v", ingress, expectedIngress)
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected load balancer status")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user