mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 11:21:47 +00:00
Merge pull request #96296 from aojea/extip
kube-proxy treat ExternalIPs as ClusterIPs
This commit is contained in:
commit
9d81c4ebfa
@ -1128,24 +1128,22 @@ func (proxier *Proxier) syncProxyRules() {
|
||||
)
|
||||
|
||||
destChain := svcXlbChain
|
||||
// We have to SNAT packets to external IPs if externalTrafficPolicy is cluster.
|
||||
// We have to SNAT packets to external IPs if externalTrafficPolicy is cluster
|
||||
// and the traffic is NOT Local. Local traffic coming from Pods and Nodes will
|
||||
// be always forwarded to the corresponding Service, so no need to SNAT
|
||||
// If we can't differentiate the local traffic we always SNAT.
|
||||
if !svcInfo.OnlyNodeLocalEndpoints() {
|
||||
destChain = svcChain
|
||||
writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...)
|
||||
// This masquerades off-cluster traffic to a External IP.
|
||||
if proxier.localDetector.IsImplemented() {
|
||||
writeLine(proxier.natRules, proxier.localDetector.JumpIfNotLocal(args, string(KubeMarkMasqChain))...)
|
||||
} else {
|
||||
writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...)
|
||||
}
|
||||
}
|
||||
// Sent traffic bound for external IPs to the service chain.
|
||||
writeLine(proxier.natRules, append(args, "-j", string(destChain))...)
|
||||
|
||||
// Allow traffic for external IPs that does not come from a bridge (i.e. not from a container)
|
||||
// nor from a local process to be forwarded to the service.
|
||||
// This rule roughly translates to "all traffic from off-machine".
|
||||
// This is imperfect in the face of network plugins that might not use a bridge, but we can revisit that later.
|
||||
externalTrafficOnlyArgs := append(args,
|
||||
"-m", "physdev", "!", "--physdev-is-in",
|
||||
"-m", "addrtype", "!", "--src-type", "LOCAL")
|
||||
writeLine(proxier.natRules, append(externalTrafficOnlyArgs, "-j", string(destChain))...)
|
||||
dstLocalOnlyArgs := append(args, "-m", "addrtype", "--dst-type", "LOCAL")
|
||||
// Allow traffic bound for external IPs that happen to be recognized as local IPs to stay local.
|
||||
// This covers cases like GCE load-balancers which get added to the local routing table.
|
||||
writeLine(proxier.natRules, append(dstLocalOnlyArgs, "-j", string(destChain))...)
|
||||
} else {
|
||||
// No endpoints.
|
||||
writeLine(proxier.filterRules,
|
||||
|
@ -829,6 +829,10 @@ func testReachabilityOverClusterIP(clusterIP string, sp v1.ServicePort, execPod
|
||||
return nil
|
||||
}
|
||||
|
||||
func testReachabilityOverExternalIP(externalIP string, sp v1.ServicePort, execPod *v1.Pod) error {
|
||||
return testEndpointReachability(externalIP, sp.Port, sp.Protocol, execPod)
|
||||
}
|
||||
|
||||
func testReachabilityOverNodePorts(nodes *v1.NodeList, sp v1.ServicePort, pod *v1.Pod, clusterIP string) error {
|
||||
internalAddrs := e2enode.CollectAddresses(nodes, v1.NodeInternalIP)
|
||||
externalAddrs := e2enode.CollectAddresses(nodes, v1.NodeExternalIP)
|
||||
@ -911,6 +915,7 @@ func testEndpointReachability(endpoint string, port int32, protocol v1.Protocol,
|
||||
func (j *TestJig) checkClusterIPServiceReachability(svc *v1.Service, pod *v1.Pod) error {
|
||||
clusterIP := svc.Spec.ClusterIP
|
||||
servicePorts := svc.Spec.Ports
|
||||
externalIPs := svc.Spec.ExternalIPs
|
||||
|
||||
err := j.waitForAvailableEndpoint(ServiceEndpointsTimeout)
|
||||
if err != nil {
|
||||
@ -926,6 +931,14 @@ func (j *TestJig) checkClusterIPServiceReachability(svc *v1.Service, pod *v1.Pod
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(externalIPs) > 0 {
|
||||
for _, externalIP := range externalIPs {
|
||||
err = testReachabilityOverExternalIP(externalIP, servicePort, pod)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -1179,6 +1179,37 @@ var _ = SIGDescribe("Services", func() {
|
||||
framework.ExpectNoError(err)
|
||||
})
|
||||
|
||||
/*
|
||||
Create a ClusterIP service with an External IP that is not assigned to an interface.
|
||||
The IP ranges here are reserved for documentation according to
|
||||
[RFC 5737](https://tools.ietf.org/html/rfc5737) Section 3 and should not be used by any host.
|
||||
*/
|
||||
ginkgo.It("should be possible to connect to a service via ExternalIP when the external IP is not assigned to a node", func() {
|
||||
serviceName := "externalip-test"
|
||||
ns := f.Namespace.Name
|
||||
externalIP := "203.0.113.250"
|
||||
if framework.TestContext.ClusterIsIPv6() {
|
||||
externalIP = "2001:DB8::cb00:71fa"
|
||||
}
|
||||
|
||||
jig := e2eservice.NewTestJig(cs, ns, serviceName)
|
||||
|
||||
ginkgo.By("creating service " + serviceName + " with type=clusterIP in namespace " + ns)
|
||||
clusterIPService, err := jig.CreateTCPService(func(svc *v1.Service) {
|
||||
svc.Spec.Type = v1.ServiceTypeClusterIP
|
||||
svc.Spec.ExternalIPs = []string{externalIP}
|
||||
svc.Spec.Ports = []v1.ServicePort{
|
||||
{Port: 80, Name: "http", Protocol: v1.ProtocolTCP, TargetPort: intstr.FromInt(9376)},
|
||||
}
|
||||
})
|
||||
framework.ExpectNoError(err)
|
||||
err = jig.CreateServicePods(2)
|
||||
framework.ExpectNoError(err)
|
||||
execPod := e2epod.CreateExecPodOrFail(cs, ns, "execpod", nil)
|
||||
err = jig.CheckServiceReachability(clusterIPService, execPod)
|
||||
framework.ExpectNoError(err)
|
||||
})
|
||||
|
||||
// TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed.
|
||||
ginkgo.It("should be able to change the type and ports of a service [Slow] [DisabledForLargeClusters]", func() {
|
||||
// requires cloud load-balancer support
|
||||
|
Loading…
Reference in New Issue
Block a user