diff --git a/test/e2e/framework/network/utils.go b/test/e2e/framework/network/utils.go index a2febeab5f8..2b7778e7d0e 100644 --- a/test/e2e/framework/network/utils.go +++ b/test/e2e/framework/network/utils.go @@ -45,7 +45,6 @@ import ( e2epod "k8s.io/kubernetes/test/e2e/framework/pod" e2epodoutput "k8s.io/kubernetes/test/e2e/framework/pod/output" e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper" - e2essh "k8s.io/kubernetes/test/e2e/framework/ssh" imageutils "k8s.io/kubernetes/test/utils/image" netutils "k8s.io/utils/net" ) @@ -1099,101 +1098,6 @@ func httpGetNoConnectionPoolTimeout(url string, timeout time.Duration) (*http.Re return client.Get(url) } -// TestUnderTemporaryNetworkFailure blocks outgoing network traffic on 'node'. Then runs testFunc and returns its status. -// At the end (even in case of errors), the network traffic is brought back to normal. -// This function executes commands on a node so it will work only for some -// environments. -func TestUnderTemporaryNetworkFailure(ctx context.Context, c clientset.Interface, ns string, node *v1.Node, testFunc func(ctx context.Context)) { - host, err := e2enode.GetSSHExternalIP(node) - if err != nil { - framework.Failf("Error getting node external ip : %v", err) - } - controlPlaneAddresses := framework.GetControlPlaneAddresses(ctx, c) - ginkgo.By(fmt.Sprintf("block network traffic from node %s to the control plane", node.Name)) - defer func() { - // This code will execute even if setting the iptables rule failed. - // It is on purpose because we may have an error even if the new rule - // had been inserted. (yes, we could look at the error code and ssh error - // separately, but I prefer to stay on the safe side). - ginkgo.By(fmt.Sprintf("Unblock network traffic from node %s to the control plane", node.Name)) - for _, instanceAddress := range controlPlaneAddresses { - UnblockNetwork(ctx, host, instanceAddress) - } - }() - - framework.Logf("Waiting %v to ensure node %s is ready before beginning test...", resizeNodeReadyTimeout, node.Name) - if !e2enode.WaitConditionToBe(ctx, c, node.Name, v1.NodeReady, true, resizeNodeReadyTimeout) { - framework.Failf("Node %s did not become ready within %v", node.Name, resizeNodeReadyTimeout) - } - for _, instanceAddress := range controlPlaneAddresses { - BlockNetwork(ctx, host, instanceAddress) - } - - framework.Logf("Waiting %v for node %s to be not ready after simulated network failure", resizeNodeNotReadyTimeout, node.Name) - if !e2enode.WaitConditionToBe(ctx, c, node.Name, v1.NodeReady, false, resizeNodeNotReadyTimeout) { - framework.Failf("Node %s did not become not-ready within %v", node.Name, resizeNodeNotReadyTimeout) - } - - testFunc(ctx) - // network traffic is unblocked in a deferred function -} - -// BlockNetwork blocks network between the given from value and the given to value. -// The following helper functions can block/unblock network from source -// host to destination host by manipulating iptable rules. -// This function assumes it can ssh to the source host. -// -// Caution: -// Recommend to input IP instead of hostnames. Using hostnames will cause iptables to -// do a DNS lookup to resolve the name to an IP address, which will -// slow down the test and cause it to fail if DNS is absent or broken. -// -// Suggested usage pattern: -// -// func foo() { -// ... -// defer UnblockNetwork(from, to) -// BlockNetwork(from, to) -// ... -// } -func BlockNetwork(ctx context.Context, from string, to string) { - framework.Logf("block network traffic from %s to %s", from, to) - iptablesRule := fmt.Sprintf("OUTPUT --destination %s --jump REJECT", to) - dropCmd := fmt.Sprintf("sudo iptables --insert %s", iptablesRule) - if result, err := e2essh.SSH(ctx, dropCmd, from, framework.TestContext.Provider); result.Code != 0 || err != nil { - e2essh.LogResult(result) - framework.Failf("Unexpected error: %v", err) - } -} - -// UnblockNetwork unblocks network between the given from value and the given to value. -func UnblockNetwork(ctx context.Context, from string, to string) { - framework.Logf("Unblock network traffic from %s to %s", from, to) - iptablesRule := fmt.Sprintf("OUTPUT --destination %s --jump REJECT", to) - undropCmd := fmt.Sprintf("sudo iptables --delete %s", iptablesRule) - // Undrop command may fail if the rule has never been created. - // In such case we just lose 30 seconds, but the cluster is healthy. - // But if the rule had been created and removing it failed, the node is broken and - // not coming back. Subsequent tests will run or fewer nodes (some of the tests - // may fail). Manual intervention is required in such case (recreating the - // cluster solves the problem too). - err := wait.PollUntilContextTimeout(ctx, time.Millisecond*100, time.Second*30, false, func(ctx context.Context) (bool, error) { - result, err := e2essh.SSH(ctx, undropCmd, from, framework.TestContext.Provider) - if result.Code == 0 && err == nil { - return true, nil - } - e2essh.LogResult(result) - if err != nil { - framework.Logf("Unexpected error: %v", err) - } - return false, nil - }) - if err != nil { - framework.Failf("Failed to remove the iptable REJECT rule. Manual intervention is "+ - "required on host %s: remove rule %s, if exists", from, iptablesRule) - } -} - // WaitForService waits until the service appears (exist == true), or disappears (exist == false) func WaitForService(ctx context.Context, c clientset.Interface, namespace, name string, exist bool, interval, timeout time.Duration) error { err := wait.PollUntilContextTimeout(ctx, interval, timeout, true, func(ctx context.Context) (bool, error) { diff --git a/test/e2e/framework/util.go b/test/e2e/framework/util.go index b727fbe7322..04f6ecaccd6 100644 --- a/test/e2e/framework/util.go +++ b/test/e2e/framework/util.go @@ -56,11 +56,6 @@ import ( netutils "k8s.io/utils/net" ) -const ( - // TODO(justinsb): Avoid hardcoding this. - awsMasterIP = "172.20.0.9" -) - // DEPRECATED constants. Use the timeouts in framework.Framework instead. const ( // PodListTimeout is how long to wait for the pod to be listable. @@ -678,38 +673,6 @@ func GetNodeExternalIPs(node *v1.Node) (ips []string) { return } -// getControlPlaneAddresses returns the externalIP, internalIP and hostname fields of control plane nodes. -// If any of these is unavailable, empty slices are returned. -func getControlPlaneAddresses(ctx context.Context, c clientset.Interface) ([]string, []string, []string) { - var externalIPs, internalIPs, hostnames []string - - // Populate the internal IPs. - eps, err := c.CoreV1().Endpoints(metav1.NamespaceDefault).Get(ctx, "kubernetes", metav1.GetOptions{}) - if err != nil { - Failf("Failed to get kubernetes endpoints: %v", err) - } - for _, subset := range eps.Subsets { - for _, address := range subset.Addresses { - if address.IP != "" { - internalIPs = append(internalIPs, address.IP) - } - } - } - - // Populate the external IP/hostname. - hostURL, err := url.Parse(TestContext.Host) - if err != nil { - Failf("Failed to parse hostname: %v", err) - } - if netutils.ParseIPSloppy(hostURL.Host) != nil { - externalIPs = append(externalIPs, hostURL.Host) - } else { - hostnames = append(hostnames, hostURL.Host) - } - - return externalIPs, internalIPs, hostnames -} - // GetControlPlaneNodes returns a list of control plane nodes func GetControlPlaneNodes(ctx context.Context, c clientset.Interface) *v1.NodeList { allNodes, err := c.CoreV1().Nodes().List(ctx, metav1.ListOptions{}) @@ -737,30 +700,6 @@ func GetControlPlaneNodes(ctx context.Context, c clientset.Interface) *v1.NodeLi return &cpNodes } -// GetControlPlaneAddresses returns all IP addresses on which the kubelet can reach the control plane. -// It may return internal and external IPs, even if we expect for -// e.g. internal IPs to be used (issue #56787), so that we can be -// sure to block the control plane fully during tests. -func GetControlPlaneAddresses(ctx context.Context, c clientset.Interface) []string { - externalIPs, internalIPs, _ := getControlPlaneAddresses(ctx, c) - - ips := sets.NewString() - switch TestContext.Provider { - case "gce": - for _, ip := range externalIPs { - ips.Insert(ip) - } - for _, ip := range internalIPs { - ips.Insert(ip) - } - case "aws": - ips.Insert(awsMasterIP) - default: - Failf("This test is not supported for provider %s and should be disabled", TestContext.Provider) - } - return ips.List() -} - // PrettyPrintJSON converts metrics to JSON format. func PrettyPrintJSON(metrics interface{}) string { output := &bytes.Buffer{}