diff --git a/docs/os-issues.md b/docs/os-issues.md index 81ebcbc53e2..cbe3b9e2059 100644 --- a/docs/os-issues.md +++ b/docs/os-issues.md @@ -62,6 +62,7 @@ notes](https://coreos.com/releases/). | Issues | | ------ | | [#591](https://github.com/vmware-tanzu/antrea/issues/591) | +| [#1516](https://github.com/vmware-tanzu/antrea/issues/1516) | If your K8s Nodes are running Photon OS 3.0, you may see error messages in the antrea-agent logs like this one: `"Received bundle error msg: [...]"`. These @@ -94,3 +95,21 @@ the Pod network: ``` iptables -A INPUT -i antrea-gw0 -j ACCEPT ``` + +### Pod Traffic Shaping + +Antrea provides support for Pod [Traffic Shaping](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/#support-traffic-shaping) +by leveraging the open-source [bandwidth plugin](https://github.com/containernetworking/plugins/tree/master/plugins/meta/bandwidth) +maintained by the CNI project. This plugin requires the following Kernel +modules: `ifb`, `sch_tbf` and `sch_ingress`. It seems that at the moment Photon +OS 3.0 is built without the `ifb` Kernel module, which you can confirm by +running `modprobe --dry-run ifb`: an error would indicate that the module is +indeed missing. Without this module, Pods with the +`kubernetes.io/egress-bandwidth` annotation cannot be created successfully. Pods +with no traffic shaping annotation, or which only use the +`kubernetes.io/ingress-bandwidth` annotation, can still be created successfully +as they do not require the creation of an `ifb` device. + +If Photon OS is patched to enable `ifb`, we will update this documentation to +reflect this change, and include information about which Photon OS version can +support egress traffic shaping. diff --git a/test/e2e/bandwidth_test.go b/test/e2e/bandwidth_test.go index 088451237e2..ed01e0e81da 100644 --- a/test/e2e/bandwidth_test.go +++ b/test/e2e/bandwidth_test.go @@ -109,6 +109,8 @@ func TestPodTrafficShaping(t *testing.T) { // Test is flaky on dual-stack clusters: https://github.com/vmware-tanzu/antrea/issues/1543. // So we disable it except for IPv4 single-stack clusters for now. skipIfIPv6Cluster(t) + nodeName := masterNodeName() + skipIfMissingKernelModule(t, nodeName, []string{"ifb", "sch_tbf", "sch_ingress"}) data, err := setupTest(t) if err != nil { t.Fatalf("Error when setting up test: %v", err) @@ -138,7 +140,7 @@ func TestPodTrafficShaping(t *testing.T) { t.Run(tt.name, func(t *testing.T) { clientPodName := fmt.Sprintf("client-a-%d", i) serverPodName := fmt.Sprintf("server-a-%d", i) - if err := data.createPodOnNode(clientPodName, masterNodeName(), perftoolImage, nil, nil, nil, nil, false, func(pod *v1.Pod) { + if err := data.createPodOnNode(clientPodName, nodeName, perftoolImage, nil, nil, nil, nil, false, func(pod *v1.Pod) { pod.Annotations = map[string]string{ "kubernetes.io/egress-bandwidth": fmt.Sprintf("%dM", tt.clientEgressBandwidth), } @@ -149,7 +151,7 @@ func TestPodTrafficShaping(t *testing.T) { if err := data.podWaitForRunning(defaultTimeout, clientPodName, testNamespace); err != nil { t.Fatalf("Error when waiting for the perftest client Pod: %v", err) } - if err := data.createPodOnNode(serverPodName, masterNodeName(), perftoolImage, nil, nil, nil, []v1.ContainerPort{{Protocol: v1.ProtocolTCP, ContainerPort: iperfPort}}, false, func(pod *v1.Pod) { + if err := data.createPodOnNode(serverPodName, nodeName, perftoolImage, nil, nil, nil, []v1.ContainerPort{{Protocol: v1.ProtocolTCP, ContainerPort: iperfPort}}, false, func(pod *v1.Pod) { pod.Annotations = map[string]string{ "kubernetes.io/ingress-bandwidth": fmt.Sprintf("%dM", tt.serverIngressBandwidth), } diff --git a/test/e2e/fixtures.go b/test/e2e/fixtures.go index de73a763094..99131a17b4c 100644 --- a/test/e2e/fixtures.go +++ b/test/e2e/fixtures.go @@ -70,6 +70,21 @@ func skipIfNotIPv6Cluster(tb testing.TB) { } } +func skipIfMissingKernelModule(tb testing.TB, nodeName string, requiredModules []string) { + for _, module := range requiredModules { + // modprobe with "--dry-run" does not require root privileges + cmd := fmt.Sprintf("modprobe --dry-run %s", module) + rc, stdout, stderr, err := RunCommandOnNode(nodeName, cmd) + if err != nil { + tb.Skipf("Skipping test as modprobe could not be run to confirm the presence of module '%s': %v", module, err) + } + if rc != 0 { + tb.Skipf("Skipping test as modprobe exited with an error when trying to confirm the presence of module '%s' - stdout: %s - stderr: %s", module, stdout, stderr) + } + } + tb.Logf("The following modules have been found on Node '%s': %v", nodeName, requiredModules) +} + func ensureAntreaRunning(tb testing.TB, data *TestData) error { tb.Logf("Applying Antrea YAML") if err := data.deployAntrea(); err != nil {