Skip to content

Commit c1d2ac4

Browse files
authored
Merge pull request kubernetes#80259 from Nordix/kubeadm-e2e-networking-config
Kubeadm Networking Configuration E2E Tests
2 parents 2ca023f + ca3bdfd commit c1d2ac4

File tree

2 files changed

+140
-0
lines changed

2 files changed

+140
-0
lines changed

test/e2e_kubeadm/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ go_test(
1717
"kubeadm_certs_test.go",
1818
"kubeadm_config_test.go",
1919
"kubelet_config_test.go",
20+
"networking_test.go",
2021
"nodes_test.go",
2122
"proxy_addon_test.go",
2223
],
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package e2e_kubeadm
18+
19+
import (
20+
"net"
21+
"strings"
22+
23+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24+
"k8s.io/kubernetes/test/e2e/framework"
25+
e2elog "k8s.io/kubernetes/test/e2e/framework/log"
26+
27+
"github.com/onsi/ginkgo"
28+
)
29+
30+
var (
31+
dualStack bool
32+
podSubnetInKubeadmConfig bool
33+
serviceSubnetInKubeadmConfig bool
34+
)
35+
36+
// Define container for all the test specification aimed at verifying
37+
// that kubeadm configures the networking as expected.
38+
// in case you want to skip this test use SKIP=setup-networking
39+
var _ = KubeadmDescribe("networking [setup-networking]", func() {
40+
41+
// Get an instance of the k8s test framework
42+
f := framework.NewDefaultFramework("networking")
43+
44+
// Tests in this container are not expected to create new objects in the cluster
45+
// so we are disabling the creation of a namespace in order to get a faster execution
46+
f.SkipNamespaceCreation = true
47+
48+
// Tests are either single-stack (either IPv4 or IPv6 address) or dual-stack
49+
// We can determine this from the kubeadm config by looking at the number of
50+
// IPs specified in networking.podSubnet
51+
ginkgo.BeforeEach(func() {
52+
53+
// gets the ClusterConfiguration from the kubeadm kubeadm-config ConfigMap as a untyped map
54+
cc := getClusterConfiguration(f.ClientSet)
55+
// Extract the networking.podSubnet
56+
// Please note that this test assumes that the user does not alter network configs
57+
// using the extraArgs option.
58+
if _, ok := cc["networking"]; ok {
59+
netCC := cc["networking"].(map[interface{}]interface{})
60+
if ps, ok := netCC["podSubnet"]; ok {
61+
// If podSubnet is not specified, podSubnet cases will be skipped.
62+
// Note that kubeadm does not currently apply defaults for PodSubnet, so we skip.
63+
podSubnetInKubeadmConfig = true
64+
cidrs := strings.Split(ps.(string), ",")
65+
if len(cidrs) > 1 {
66+
dualStack = true
67+
}
68+
}
69+
if _, ok := netCC["serviceSubnet"]; ok {
70+
// If serviceSubnet is not specified, serviceSubnet cases will be skipped.
71+
serviceSubnetInKubeadmConfig = true
72+
}
73+
}
74+
})
75+
76+
ginkgo.Context("single-stack", func() {
77+
ginkgo.Context("podSubnet", func() {
78+
ginkgo.It("should be properly configured if specified in kubeadm-config", func() {
79+
if dualStack {
80+
framework.Skipf("Skipping because cluster is dual-stack")
81+
}
82+
if !podSubnetInKubeadmConfig {
83+
framework.Skipf("Skipping because podSubnet was not specified in kubeadm-config")
84+
}
85+
cc := getClusterConfiguration(f.ClientSet)
86+
if _, ok := cc["networking"]; ok {
87+
netCC := cc["networking"].(map[interface{}]interface{})
88+
if ps, ok := netCC["podSubnet"]; ok {
89+
// Check that the pod CIDR allocated to the node(s) is within the kubeadm-config podCIDR.
90+
nodes, err := f.ClientSet.CoreV1().Nodes().List(metav1.ListOptions{})
91+
framework.ExpectNoError(err)
92+
for _, node := range nodes.Items {
93+
if !subnetWithinSubnet(ps.(string), node.Spec.PodCIDR) {
94+
e2elog.Failf("failed due to node(%v) IP %v not inside configured pod subnet: %s", node.Name, node.Spec.PodCIDR, ps)
95+
}
96+
}
97+
}
98+
}
99+
})
100+
})
101+
ginkgo.Context("serviceSubnet", func() {
102+
ginkgo.It("should be properly configured if specified in kubeadm-config", func() {
103+
if dualStack {
104+
framework.Skipf("Skipping because cluster is dual-stack")
105+
}
106+
if !serviceSubnetInKubeadmConfig {
107+
framework.Skipf("Skipping because serviceSubnet was not specified in kubeadm-config")
108+
}
109+
cc := getClusterConfiguration(f.ClientSet)
110+
if _, ok := cc["networking"]; ok {
111+
netCC := cc["networking"].(map[interface{}]interface{})
112+
if ss, ok := netCC["serviceSubnet"]; ok {
113+
// Get the kubernetes service in the default namespace.
114+
// Check that service CIDR allocated is within the serviceSubnet range.
115+
svc, err := f.ClientSet.CoreV1().Services("default").Get("kubernetes", metav1.GetOptions{})
116+
framework.ExpectNoError(err)
117+
if !ipWithinSubnet(ss.(string), svc.Spec.ClusterIP) {
118+
e2elog.Failf("failed due to service(%v) cluster-IP %v not inside configured service subnet: %s", svc.Name, svc.Spec.ClusterIP, ss)
119+
}
120+
}
121+
}
122+
})
123+
})
124+
})
125+
})
126+
127+
// ipWithinSubnet returns true if an IP (targetIP) falls within the reference subnet (refIPNet)
128+
func ipWithinSubnet(refIPNet, targetIP string) bool {
129+
_, rNet, _ := net.ParseCIDR(refIPNet)
130+
tIP := net.ParseIP(targetIP)
131+
return rNet.Contains(tIP)
132+
}
133+
134+
// subnetWithinSubnet returns true if a subnet (targetNet) falls within the reference subnet (refIPNet)
135+
func subnetWithinSubnet(refIPNet, targetNet string) bool {
136+
_, rNet, _ := net.ParseCIDR(refIPNet)
137+
tNet, _, _ := net.ParseCIDR(targetNet)
138+
return rNet.Contains(tNet)
139+
}

0 commit comments

Comments
 (0)