dual stack services (#91824)
* api: structure change * api: defaulting, conversion, and validation * [FIX] validation: auto remove second ip/family when service changes to SingleStack * [FIX] api: defaulting, conversion, and validation * api-server: clusterIPs alloc, printers, storage and strategy * [FIX] clusterIPs default on read * alloc: auto remove second ip/family when service changes to SingleStack * api-server: repair loop handling for clusterIPs * api-server: force kubernetes default service into single stack * api-server: tie dualstack feature flag with endpoint feature flag * controller-manager: feature flag, endpoint, and endpointSlice controllers handling multi family service * [FIX] controller-manager: feature flag, endpoint, and endpointSlicecontrollers handling multi family service * kube-proxy: feature-flag, utils, proxier, and meta proxier * [FIX] kubeproxy: call both proxier at the same time * kubenet: remove forced pod IP sorting * kubectl: modify describe to include ClusterIPs, IPFamilies, and IPFamilyPolicy * e2e: fix tests that depends on IPFamily field AND add dual stack tests * e2e: fix expected error message for ClusterIP immutability * add integration tests for dualstack the third phase of dual stack is a very complex change in the API, basically it introduces Dual Stack services. Main changes are: - It pluralizes the Service IPFamily field to IPFamilies, and removes the singular field. - It introduces a new field IPFamilyPolicyType that can take 3 values to express the "dual-stack(mad)ness" of the cluster: SingleStack, PreferDualStack and RequireDualStack - It pluralizes ClusterIP to ClusterIPs. The goal is to add coverage to the services API operations, taking into account the 6 different modes a cluster can have: - single stack: IP4 or IPv6 (as of today) - dual stack: IPv4 only, IPv6 only, IPv4 - IPv6, IPv6 - IPv4 * [FIX] add integration tests for dualstack * generated data * generated files Co-authored-by: Antonio Ojea <aojea@redhat.com> Kubernetes-commit: 6675eba3eff1c8e565c4060a9c1396f75da7cc3e
This commit is contained in:
parent
f28a68d5aa
commit
2bf7244939
|
@ -764,11 +764,11 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api",
|
||||
"Rev": "ccbd11b5dd0a"
|
||||
"Rev": "0415de894212"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery",
|
||||
"Rev": "554eef9dbf66"
|
||||
"Rev": "ab98f4dc11fb"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/cli-runtime",
|
||||
|
|
8
go.mod
8
go.mod
|
@ -34,8 +34,8 @@ require (
|
|||
github.com/stretchr/testify v1.4.0
|
||||
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4
|
||||
gopkg.in/yaml.v2 v2.2.8
|
||||
k8s.io/api v0.0.0-20201023125151-ccbd11b5dd0a
|
||||
k8s.io/apimachinery v0.0.0-20201020200440-554eef9dbf66
|
||||
k8s.io/api v0.0.0-20201026202134-0415de894212
|
||||
k8s.io/apimachinery v0.0.0-20201026201559-ab98f4dc11fb
|
||||
k8s.io/cli-runtime v0.0.0-20201023084906-87ad57c444cb
|
||||
k8s.io/client-go v0.0.0-20201020200834-d1a4fe5f2d96
|
||||
k8s.io/component-base v0.0.0-20201020201314-b8c7ac1518d8
|
||||
|
@ -48,8 +48,8 @@ require (
|
|||
)
|
||||
|
||||
replace (
|
||||
k8s.io/api => k8s.io/api v0.0.0-20201023125151-ccbd11b5dd0a
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20201020200440-554eef9dbf66
|
||||
k8s.io/api => k8s.io/api v0.0.0-20201026202134-0415de894212
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20201026201559-ab98f4dc11fb
|
||||
k8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20201023084906-87ad57c444cb
|
||||
k8s.io/client-go => k8s.io/client-go v0.0.0-20201020200834-d1a4fe5f2d96
|
||||
k8s.io/code-generator => k8s.io/code-generator v0.0.0-20201020200306-60862b8acf58
|
||||
|
|
4
go.sum
4
go.sum
|
@ -508,8 +508,8 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh
|
|||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
k8s.io/api v0.0.0-20201023125151-ccbd11b5dd0a/go.mod h1:ZstqwXfkQ55HZmXltK0DHYZaNJbMq4U/mnlyigw1pH0=
|
||||
k8s.io/apimachinery v0.0.0-20201020200440-554eef9dbf66/go.mod h1:6s3VNb000AUbBIxR7q3WHlbBwfpEGqIJsCG5gIX+0LI=
|
||||
k8s.io/api v0.0.0-20201026202134-0415de894212/go.mod h1:ZHfIarpAhcOE82iD+VeQxQXxatIY63UubJAgxUq67ig=
|
||||
k8s.io/apimachinery v0.0.0-20201026201559-ab98f4dc11fb/go.mod h1:6s3VNb000AUbBIxR7q3WHlbBwfpEGqIJsCG5gIX+0LI=
|
||||
k8s.io/cli-runtime v0.0.0-20201023084906-87ad57c444cb/go.mod h1:8J/p/CEj2WGIZobSh/Oe9kVIVndBvFpmRutcbtZVJ1U=
|
||||
k8s.io/client-go v0.0.0-20201020200834-d1a4fe5f2d96/go.mod h1:MEvNyY+iZEFaAPeMVco7LyFmysN3O9jX9QSKcacQ0O8=
|
||||
k8s.io/code-generator v0.0.0-20201020200306-60862b8acf58/go.mod h1:oioc17TXBB973K4R+ytm5k9jY1BktboxJc7qu3i29V0=
|
||||
|
|
|
@ -2721,10 +2721,27 @@ func describeService(service *corev1.Service, endpoints *corev1.Endpoints, event
|
|||
printAnnotationsMultiline(w, "Annotations", service.Annotations)
|
||||
w.Write(LEVEL_0, "Selector:\t%s\n", labels.FormatLabels(service.Spec.Selector))
|
||||
w.Write(LEVEL_0, "Type:\t%s\n", service.Spec.Type)
|
||||
w.Write(LEVEL_0, "IP:\t%s\n", service.Spec.ClusterIP)
|
||||
|
||||
if service.Spec.IPFamily != nil {
|
||||
w.Write(LEVEL_0, "IPFamily:\t%s\n", *(service.Spec.IPFamily))
|
||||
if service.Spec.IPFamilyPolicy != nil {
|
||||
w.Write(LEVEL_0, "IP Family Policy:\t%s\n", *(service.Spec.IPFamilyPolicy))
|
||||
}
|
||||
|
||||
if len(service.Spec.IPFamilies) > 0 {
|
||||
ipfamiliesStrings := make([]string, 0, len(service.Spec.IPFamilies))
|
||||
for _, family := range service.Spec.IPFamilies {
|
||||
ipfamiliesStrings = append(ipfamiliesStrings, string(family))
|
||||
}
|
||||
|
||||
w.Write(LEVEL_0, "IP Families:\t%s\n", strings.Join(ipfamiliesStrings, ","))
|
||||
} else {
|
||||
w.Write(LEVEL_0, "IP Families:\t%s\n", "<none>")
|
||||
}
|
||||
|
||||
w.Write(LEVEL_0, "IP:\t%s\n", service.Spec.ClusterIP)
|
||||
if len(service.Spec.ClusterIPs) > 0 {
|
||||
w.Write(LEVEL_0, "IPs:\t%s\n", strings.Join(service.Spec.ClusterIPs, ","))
|
||||
} else {
|
||||
w.Write(LEVEL_0, "IPs:\t%s\n", "<none>")
|
||||
}
|
||||
|
||||
if len(service.Spec.ExternalIPs) > 0 {
|
||||
|
|
|
@ -358,8 +358,7 @@ func getResourceList(cpu, memory string) corev1.ResourceList {
|
|||
}
|
||||
|
||||
func TestDescribeService(t *testing.T) {
|
||||
defaultServiceIPFamily := corev1.IPv4Protocol
|
||||
|
||||
singleStack := corev1.IPFamilyPolicySingleStack
|
||||
testCases := []struct {
|
||||
name string
|
||||
service *corev1.Service
|
||||
|
@ -373,8 +372,7 @@ func TestDescribeService(t *testing.T) {
|
|||
Namespace: "foo",
|
||||
},
|
||||
Spec: corev1.ServiceSpec{
|
||||
Type: corev1.ServiceTypeLoadBalancer,
|
||||
IPFamily: &defaultServiceIPFamily,
|
||||
Type: corev1.ServiceTypeLoadBalancer,
|
||||
Ports: []corev1.ServicePort{{
|
||||
Name: "port-tcp",
|
||||
Port: 8080,
|
||||
|
@ -384,6 +382,7 @@ func TestDescribeService(t *testing.T) {
|
|||
}},
|
||||
Selector: map[string]string{"blah": "heh"},
|
||||
ClusterIP: "1.2.3.4",
|
||||
IPFamilies: []corev1.IPFamily{corev1.IPv4Protocol},
|
||||
LoadBalancerIP: "5.6.7.8",
|
||||
SessionAffinity: "None",
|
||||
ExternalTrafficPolicy: "Local",
|
||||
|
@ -412,8 +411,7 @@ func TestDescribeService(t *testing.T) {
|
|||
Namespace: "foo",
|
||||
},
|
||||
Spec: corev1.ServiceSpec{
|
||||
Type: corev1.ServiceTypeLoadBalancer,
|
||||
IPFamily: &defaultServiceIPFamily,
|
||||
Type: corev1.ServiceTypeLoadBalancer,
|
||||
Ports: []corev1.ServicePort{{
|
||||
Name: "port-tcp",
|
||||
Port: 8080,
|
||||
|
@ -423,6 +421,7 @@ func TestDescribeService(t *testing.T) {
|
|||
}},
|
||||
Selector: map[string]string{"blah": "heh"},
|
||||
ClusterIP: "1.2.3.4",
|
||||
IPFamilies: []corev1.IPFamily{corev1.IPv4Protocol},
|
||||
LoadBalancerIP: "5.6.7.8",
|
||||
SessionAffinity: "None",
|
||||
ExternalTrafficPolicy: "Local",
|
||||
|
@ -451,8 +450,7 @@ func TestDescribeService(t *testing.T) {
|
|||
Namespace: "foo",
|
||||
},
|
||||
Spec: corev1.ServiceSpec{
|
||||
Type: corev1.ServiceTypeLoadBalancer,
|
||||
IPFamily: &defaultServiceIPFamily,
|
||||
Type: corev1.ServiceTypeLoadBalancer,
|
||||
Ports: []corev1.ServicePort{{
|
||||
Name: "port-tcp",
|
||||
Port: 8080,
|
||||
|
@ -462,6 +460,7 @@ func TestDescribeService(t *testing.T) {
|
|||
}},
|
||||
Selector: map[string]string{"blah": "heh"},
|
||||
ClusterIP: "1.2.3.4",
|
||||
IPFamilies: []corev1.IPFamily{corev1.IPv4Protocol},
|
||||
LoadBalancerIP: "5.6.7.8",
|
||||
SessionAffinity: "None",
|
||||
ExternalTrafficPolicy: "Local",
|
||||
|
@ -474,7 +473,51 @@ func TestDescribeService(t *testing.T) {
|
|||
"Selector", "blah=heh",
|
||||
"Type", "LoadBalancer",
|
||||
"IP", "1.2.3.4",
|
||||
"IPFamily", "IPv4",
|
||||
"IP Families", "IPv4",
|
||||
"Port", "port-tcp", "8080/TCP",
|
||||
"TargetPort", "targetPort/TCP",
|
||||
"NodePort", "port-tcp", "31111/TCP",
|
||||
"Session Affinity", "None",
|
||||
"External Traffic Policy", "Local",
|
||||
"HealthCheck NodePort", "32222",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test-ServiceIPFamilyPolicy+ClusterIPs",
|
||||
service: &corev1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "bar",
|
||||
Namespace: "foo",
|
||||
},
|
||||
Spec: corev1.ServiceSpec{
|
||||
Type: corev1.ServiceTypeLoadBalancer,
|
||||
Ports: []corev1.ServicePort{{
|
||||
Name: "port-tcp",
|
||||
Port: 8080,
|
||||
Protocol: corev1.ProtocolTCP,
|
||||
TargetPort: intstr.FromString("targetPort"),
|
||||
NodePort: 31111,
|
||||
}},
|
||||
Selector: map[string]string{"blah": "heh"},
|
||||
ClusterIP: "1.2.3.4",
|
||||
IPFamilies: []corev1.IPFamily{corev1.IPv4Protocol},
|
||||
IPFamilyPolicy: &singleStack,
|
||||
ClusterIPs: []string{"1.2.3.4"},
|
||||
LoadBalancerIP: "5.6.7.8",
|
||||
SessionAffinity: "None",
|
||||
ExternalTrafficPolicy: "Local",
|
||||
HealthCheckNodePort: 32222,
|
||||
},
|
||||
},
|
||||
expect: []string{
|
||||
"Name", "bar",
|
||||
"Namespace", "foo",
|
||||
"Selector", "blah=heh",
|
||||
"Type", "LoadBalancer",
|
||||
"IP", "1.2.3.4",
|
||||
"IP Families", "IPv4",
|
||||
"IP Family Policy", "SingleStack",
|
||||
"IPs", "1.2.3.4",
|
||||
"Port", "port-tcp", "8080/TCP",
|
||||
"TargetPort", "targetPort/TCP",
|
||||
"NodePort", "port-tcp", "31111/TCP",
|
||||
|
|
Loading…
Reference in New Issue