Change:
<!-- Please use this template while reporting a bug and provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner. Thanks! If the matter is security related, please disclose it privately via --What happened: Refer , health probes are not associated for UDP services on Azure, hence source IPs are not preserved for UDP services on Azure. What you expected to happen: When is set to for UDP services, source IPs should be preserved and the health probe should be associated with UDP load balancer rule. Per the , the health probe only supports TCP, HTTP and HTTPS. UDP is not supported as the probing protocol, hence we can’t enable the health probes for UDP services. However, when the externalTrafficPolicy is Local, Kubernetes would open an HTTP endpoint for UDP services, hence it’s actually supported on Azure. So, should associate the probes on externalTrafficPolicy=Local cases. How to reproduce it (as minimally and precisely as possible): Create a UDP service with : Then check the source IPs. Anything else we need to know?: Environment: Kubernetes version (use ): Cloud provider or hardware configuration: OS (e.g: ): Kernel (e.g. ): Install tools: Network plugin and version (if this is a network-related bug): Others: /kind bug /sig cloud-provider /area provider/azure

Discussion:
expectedRule.LoadBalancingRulePropertiesFormat.IdleTimeoutInMinutes = lbIdleTimeout } <del> // we didn't construct the probe objects for UDP or SCTP because they're not used/needed/allowed if protocol != v1.ProtocolUDP && protocol != v1.ProtocolSCTP { </del> <ins> // we didn't construct the probe objects for UDP or SCTP because they're not allowed on Azure. // However, when externalTrafficPolicy is Local, Kubernetes HTTP health check would be used for probing. if servicehelpers.NeedsHealthCheck(service) || (protocol != v1.ProtocolUDP && protocol != v1.ProtocolSCTP) { </ins> expectedRule.Probe = &network.SubResource{ ID: to.StringPtr(az.getLoadBalancerProbeID(lbName, lbRuleName)), }

}, } <ins> service6 := getTestService("test1", v1.ProtocolUDP, nil, 80) lb6 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("testCluster"), to.StringPtr("atest1"), service6, "basic") lb6.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{} lb6.Probes = &[]network.Probe{} expectedLB6 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("testCluster"), to.StringPtr("atest1"), service6, "basic") expectedLB6.Probes = &[]network.Probe{} (*expectedLB6.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].Probe = nil (*expectedLB6.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].EnableTCPReset = nil (*expectedLB6.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].DisableOutboundSnat = to.BoolPtr(false) expectedLB6.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{ { Name: to.StringPtr("atest1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("/subscriptions/subscription/" + "resourceGroups/rg/providers/Microsoft.Network/publicIPAddresses/pipName")}, }, }, } service7 := getTestService("test1", v1.ProtocolUDP, nil, 80) service7.Spec.HealthCheckNodePort = 10081 service7.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal lb7 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("testCluster"), to.StringPtr("atest1"), service7, "basic") lb7.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{} lb7.Probes = &[]network.Probe{} expectedLB7 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("testCluster"), to.StringPtr("atest1"), service7, "basic") (*expectedLB7.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].Probe = &network.SubResource{ ID: to.StringPtr("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Network/loadBalancers/testCluster/probes/atest1-UDP-80"), } (*expectedLB7.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].EnableTCPReset = nil (*expectedLB7.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].DisableOutboundSnat = to.BoolPtr(false) expectedLB7.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{ { Name: to.StringPtr("atest1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("/subscriptions/subscription/" + "resourceGroups/rg/providers/Microsoft.Network/publicIPAddresses/pipName")}, }, }, } expectedLB7.Probes = &[]network.Probe{ { Name: to.StringPtr("atest1-" + string(service7.Spec.Ports[0].Protocol) + "-" + strconv.Itoa(int(service7.Spec.Ports[0].Port))), ProbePropertiesFormat: &network.ProbePropertiesFormat{ Port:              to.Int32Ptr(10081), RequestPath:       to.StringPtr("/healthz"), Protocol:          network.ProbeProtocolHTTP, IntervalInSeconds: to.Int32Ptr(5), NumberOfProbes:    to.Int32Ptr(2), }, }, } </ins> testCases := []struct { desc                string service             v1.Service

expectedLB:          expectedSLb5, expectedError:       nil, }, <ins> { desc:            "reconcileLoadBalancer shall reconcile UDP services", loadBalancerSku: "basic", service:         service6, existingLB:      lb6, wantLb:          true, expectedLB:      expectedLB6, expectedError:   nil, }, { desc:            "reconcileLoadBalancer shall reconcile probes for local traffic policy UDP services", loadBalancerSku: "basic", service:         service7, existingLB:      lb7, wantLb:          true, expectedLB:      expectedLB7, expectedError:   nil, }, </ins> } for i, test := range testCases {