func (plugin *kubenetNetworkPlugin) setup(namespace string, name string, id kubecontainer.ContainerID, pod *api.Pod) error { // Bring up container loopback interface if _, err := plugin.addContainerToNetwork(plugin.loConfig, "lo", namespace, name, id); err != nil { return err } // Hook container up with our bridge res, err := plugin.addContainerToNetwork(plugin.netConfig, network.DefaultInterfaceName, namespace, name, id) if err != nil { return err } if res.IP4 == nil { return fmt.Errorf("CNI plugin reported no IPv4 address for container %v.", id) } ip4 := res.IP4.IP.IP.To4() if ip4 == nil { return fmt.Errorf("CNI plugin reported an invalid IPv4 address for container %v: %+v.", id, res.IP4) } // Put the container bridge into promiscuous mode to force it to accept hairpin packets. // TODO: Remove this once the kernel bug (#20096) is fixed. // TODO: check and set promiscuous mode with netlink once vishvananda/netlink supports it if plugin.hairpinMode == componentconfig.PromiscuousBridge { output, err := plugin.execer.Command("ip", "link", "show", "dev", BridgeName).CombinedOutput() if err != nil || strings.Index(string(output), "PROMISC") < 0 { _, err := plugin.execer.Command("ip", "link", "set", BridgeName, "promisc", "on").CombinedOutput() if err != nil { return fmt.Errorf("Error setting promiscuous mode on %s: %v", BridgeName, err) } } } // The first SetUpPod call creates the bridge; get a shaper for the sake of // initialization shaper := plugin.shaper() ingress, egress, err := bandwidth.ExtractPodBandwidthResources(pod.Annotations) if err != nil { return fmt.Errorf("Error reading pod bandwidth annotations: %v", err) } if egress != nil || ingress != nil { if err := shaper.ReconcileCIDR(fmt.Sprintf("%s/32", ip4.String()), egress, ingress); err != nil { return fmt.Errorf("Failed to add pod to shaper: %v", err) } } plugin.podIPs[id] = ip4.String() // Open any hostports the pod's containers want runningPods, err := plugin.getRunningPods() if err != nil { return err } if err := plugin.hostportHandler.OpenPodHostportsAndSync(pod, BridgeName, runningPods); err != nil { return err } return nil }
func (plugin *kubenetNetworkPlugin) SetUpPod(namespace string, name string, id kubecontainer.ContainerID) error { pod, ok := plugin.host.GetPodByName(namespace, name) if !ok { return fmt.Errorf("pod %q cannot be found", name) } ingress, egress, err := bandwidth.ExtractPodBandwidthResources(pod.Annotations) if err != nil { return fmt.Errorf("Error reading pod bandwidth annotations: %v", err) } // Can't set up pods if we don't have a PodCIDR yet if plugin.netConfig == nil { return fmt.Errorf("Kubenet needs a PodCIDR to set up pods") } runtime, ok := plugin.host.GetRuntime().(*dockertools.DockerManager) if !ok { return fmt.Errorf("Kubenet execution called on non-docker runtime") } netnsPath, err := runtime.GetNetNS(id) if err != nil { return fmt.Errorf("Kubenet failed to retrieve network namespace path: %v", err) } rt := buildCNIRuntimeConf(name, namespace, id, netnsPath) if err != nil { return fmt.Errorf("Error building CNI config: %v", err) } glog.V(3).Infof("Calling cni plugins to add container to network with cni runtime: %+v", rt) res, err := plugin.cniConfig.AddNetwork(plugin.netConfig, rt) if err != nil { return fmt.Errorf("Error adding container to network: %v", err) } if res.IP4 == nil { return fmt.Errorf("CNI plugin reported no IPv4 address for container %v.", id) } plugin.podCIDRs[id] = res.IP4.IP.String() // The first SetUpPod call creates the bridge; ensure shaping is enabled if plugin.shaper == nil { plugin.shaper = bandwidth.NewTCShaper(BridgeName) if plugin.shaper == nil { return fmt.Errorf("Failed to create bandwidth shaper!") } plugin.shaper.ReconcileInterface() } if egress != nil || ingress != nil { ipAddr, _, _ := net.ParseCIDR(plugin.podCIDRs[id]) if err = plugin.shaper.ReconcileCIDR(fmt.Sprintf("%s/32", ipAddr.String()), egress, ingress); err != nil { return fmt.Errorf("Failed to add pod to shaper: %v", err) } } return nil }
func (plugin *kubenetNetworkPlugin) SetUpPod(namespace string, name string, id kubecontainer.ContainerID) error { pod, ok := plugin.host.GetPodByName(namespace, name) if !ok { return fmt.Errorf("pod %q cannot be found", name) } ingress, egress, err := bandwidth.ExtractPodBandwidthResources(pod.Annotations) if err != nil { return fmt.Errorf("Error reading pod bandwidth annotations: %v", err) } if err := plugin.Status(); err != nil { return fmt.Errorf("Kubenet cannot SetUpPod: %v", err) } runtime, ok := plugin.host.GetRuntime().(*dockertools.DockerManager) if !ok { return fmt.Errorf("Kubenet execution called on non-docker runtime") } netnsPath, err := runtime.GetNetNS(id) if err != nil { return fmt.Errorf("Kubenet failed to retrieve network namespace path: %v", err) } rt := buildCNIRuntimeConf(name, namespace, id, netnsPath) if err != nil { return fmt.Errorf("Error building CNI config: %v", err) } if err = plugin.addContainerToNetwork(id, rt); err != nil { return err } // The first SetUpPod call creates the bridge; ensure shaping is enabled if plugin.shaper == nil { plugin.shaper = bandwidth.NewTCShaper(BridgeName) if plugin.shaper == nil { return fmt.Errorf("Failed to create bandwidth shaper!") } plugin.ensureBridgeTxQueueLen() plugin.shaper.ReconcileInterface() } if egress != nil || ingress != nil { ipAddr, _, _ := net.ParseCIDR(plugin.podCIDRs[id]) if err = plugin.shaper.ReconcileCIDR(fmt.Sprintf("%s/32", ipAddr.String()), egress, ingress); err != nil { return fmt.Errorf("Failed to add pod to shaper: %v", err) } } return nil }
func getBandwidth(pod *kapi.Pod) (string, string, error) { ingress, egress, err := kbandwidth.ExtractPodBandwidthResources(pod.Annotations) if err != nil { return "", "", fmt.Errorf("failed to parse pod bandwidth: %v", err) } var ingressStr, egressStr string if ingress != nil { ingressStr = fmt.Sprintf("%d", ingress.Value()) } if egress != nil { egressStr = fmt.Sprintf("%d", egress.Value()) } return ingressStr, egressStr, nil }
// cleanupBandwidthLimits updates the status of bandwidth-limited containers // and ensures that only the appropriate CIDRs are active on the node. func (kl *Kubelet) cleanupBandwidthLimits(allPods []*api.Pod) error { if kl.shaper == nil { return nil } currentCIDRs, err := kl.shaper.GetCIDRs() if err != nil { return err } possibleCIDRs := sets.String{} for ix := range allPods { pod := allPods[ix] ingress, egress, err := bandwidth.ExtractPodBandwidthResources(pod.Annotations) if err != nil { return err } if ingress == nil && egress == nil { glog.V(8).Infof("Not a bandwidth limited container...") continue } status, found := kl.statusManager.GetPodStatus(pod.UID) if !found { // TODO(random-liu): Cleanup status get functions. (issue #20477) s, err := kl.containerRuntime.GetPodStatus(pod.UID, pod.Name, pod.Namespace) if err != nil { return err } status = kl.generateAPIPodStatus(pod, s) } if status.Phase == api.PodRunning { possibleCIDRs.Insert(fmt.Sprintf("%s/32", status.PodIP)) } } for _, cidr := range currentCIDRs { if !possibleCIDRs.Has(cidr) { glog.V(2).Infof("Removing CIDR: %s (%v)", cidr, possibleCIDRs) if err := kl.shaper.Reset(cidr); err != nil { return err } } } return nil }
// setup sets up networking through CNI using the given ns/name and sandbox ID. // TODO: Don't pass the pod to this method, it only needs it for bandwidth // shaping and hostport management. func (plugin *kubenetNetworkPlugin) setup(namespace string, name string, id kubecontainer.ContainerID, pod *v1.Pod) error { // Bring up container loopback interface if _, err := plugin.addContainerToNetwork(plugin.loConfig, "lo", namespace, name, id); err != nil { return err } // Hook container up with our bridge res, err := plugin.addContainerToNetwork(plugin.netConfig, network.DefaultInterfaceName, namespace, name, id) if err != nil { return err } if res.IP4 == nil { return fmt.Errorf("CNI plugin reported no IPv4 address for container %v.", id) } ip4 := res.IP4.IP.IP.To4() if ip4 == nil { return fmt.Errorf("CNI plugin reported an invalid IPv4 address for container %v: %+v.", id, res.IP4) } // Explicitly assign mac address to cbr0. If bridge mac address is not explicitly set will adopt the lowest MAC address of the attached veths. // TODO: Remove this once upstream cni bridge plugin handles this link, err := netlink.LinkByName(BridgeName) if err != nil { return fmt.Errorf("failed to lookup %q: %v", BridgeName, err) } macAddr, err := generateHardwareAddr(plugin.gateway) if err != nil { return err } glog.V(3).Infof("Configure %q mac address to %v", BridgeName, macAddr) err = netlink.LinkSetHardwareAddr(link, macAddr) if err != nil { return fmt.Errorf("Failed to configure %q mac address to %q: %v", BridgeName, macAddr, err) } // Put the container bridge into promiscuous mode to force it to accept hairpin packets. // TODO: Remove this once the kernel bug (#20096) is fixed. // TODO: check and set promiscuous mode with netlink once vishvananda/netlink supports it if plugin.hairpinMode == componentconfig.PromiscuousBridge { output, err := plugin.execer.Command("ip", "link", "show", "dev", BridgeName).CombinedOutput() if err != nil || strings.Index(string(output), "PROMISC") < 0 { _, err := plugin.execer.Command("ip", "link", "set", BridgeName, "promisc", "on").CombinedOutput() if err != nil { return fmt.Errorf("Error setting promiscuous mode on %s: %v", BridgeName, err) } } // configure the ebtables rules to eliminate duplicate packets by best effort plugin.syncEbtablesDedupRules(macAddr) } plugin.podIPs[id] = ip4.String() // The host can choose to not support "legacy" features. The remote // shim doesn't support it (#35457), but the kubelet does. if !plugin.host.SupportsLegacyFeatures() { return nil } // The first SetUpPod call creates the bridge; get a shaper for the sake of // initialization shaper := plugin.shaper() ingress, egress, err := bandwidth.ExtractPodBandwidthResources(pod.Annotations) if err != nil { return fmt.Errorf("Error reading pod bandwidth annotations: %v", err) } if egress != nil || ingress != nil { if err := shaper.ReconcileCIDR(fmt.Sprintf("%s/32", ip4.String()), egress, ingress); err != nil { return fmt.Errorf("Failed to add pod to shaper: %v", err) } } // Open any hostports the pod's containers want activePods, err := plugin.getActivePods() if err != nil { return err } newPod := &hostport.ActivePod{Pod: pod, IP: ip4} if err := plugin.hostportHandler.OpenPodHostportsAndSync(newPod, BridgeName, activePods); err != nil { return err } return nil }
func (plugin *kubenetNetworkPlugin) SetUpPod(namespace string, name string, id kubecontainer.ContainerID) error { plugin.mu.Lock() defer plugin.mu.Unlock() start := time.Now() defer func() { glog.V(4).Infof("SetUpPod took %v for %s/%s", time.Since(start), namespace, name) }() pod, ok := plugin.host.GetPodByName(namespace, name) if !ok { return fmt.Errorf("pod %q cannot be found", name) } ingress, egress, err := bandwidth.ExtractPodBandwidthResources(pod.Annotations) if err != nil { return fmt.Errorf("Error reading pod bandwidth annotations: %v", err) } if err := plugin.Status(); err != nil { return fmt.Errorf("Kubenet cannot SetUpPod: %v", err) } // Bring up container loopback interface if _, err := plugin.addContainerToNetwork(plugin.loConfig, "lo", namespace, name, id); err != nil { return err } // Hook container up with our bridge res, err := plugin.addContainerToNetwork(plugin.netConfig, network.DefaultInterfaceName, namespace, name, id) if err != nil { return err } if res.IP4 == nil || res.IP4.IP.String() == "" { return fmt.Errorf("CNI plugin reported no IPv4 address for container %v.", id) } plugin.podCIDRs[id] = res.IP4.IP.String() // Put the container bridge into promiscuous mode to force it to accept hairpin packets. // TODO: Remove this once the kernel bug (#20096) is fixed. // TODO: check and set promiscuous mode with netlink once vishvananda/netlink supports it if plugin.hairpinMode == componentconfig.PromiscuousBridge { output, err := plugin.execer.Command("ip", "link", "show", "dev", BridgeName).CombinedOutput() if err != nil || strings.Index(string(output), "PROMISC") < 0 { _, err := plugin.execer.Command("ip", "link", "set", BridgeName, "promisc", "on").CombinedOutput() if err != nil { return fmt.Errorf("Error setting promiscuous mode on %s: %v", BridgeName, err) } } } // The first SetUpPod call creates the bridge; ensure shaping is enabled if plugin.shaper == nil { plugin.shaper = bandwidth.NewTCShaper(BridgeName) if plugin.shaper == nil { return fmt.Errorf("Failed to create bandwidth shaper!") } plugin.ensureBridgeTxQueueLen() plugin.shaper.ReconcileInterface() } if egress != nil || ingress != nil { ipAddr, _, _ := net.ParseCIDR(plugin.podCIDRs[id]) if err = plugin.shaper.ReconcileCIDR(fmt.Sprintf("%s/32", ipAddr.String()), egress, ingress); err != nil { return fmt.Errorf("Failed to add pod to shaper: %v", err) } } return nil }
func (plugin *kubenetNetworkPlugin) SetUpPod(namespace string, name string, id kubecontainer.ContainerID) error { plugin.mu.Lock() defer plugin.mu.Unlock() start := time.Now() defer func() { glog.V(4).Infof("SetUpPod took %v for %s/%s", time.Since(start), namespace, name) }() pod, ok := plugin.host.GetPodByName(namespace, name) if !ok { return fmt.Errorf("pod %q cannot be found", name) } // try to open pod host port if specified hostportMap, err := plugin.openPodHostports(pod) if err != nil { return err } if len(hostportMap) > 0 { // defer to decide whether to keep the host port open based on the result of SetUpPod defer plugin.syncHostportMap(id, hostportMap) } ingress, egress, err := bandwidth.ExtractPodBandwidthResources(pod.Annotations) if err != nil { return fmt.Errorf("Error reading pod bandwidth annotations: %v", err) } if err := plugin.Status(); err != nil { return fmt.Errorf("Kubenet cannot SetUpPod: %v", err) } // Bring up container loopback interface if _, err := plugin.addContainerToNetwork(plugin.loConfig, "lo", namespace, name, id); err != nil { return err } // Hook container up with our bridge res, err := plugin.addContainerToNetwork(plugin.netConfig, network.DefaultInterfaceName, namespace, name, id) if err != nil { return err } if res.IP4 == nil { return fmt.Errorf("CNI plugin reported no IPv4 address for container %v.", id) } ip4 := res.IP4.IP.IP.To4() if ip4 == nil { return fmt.Errorf("CNI plugin reported an invalid IPv4 address for container %v: %+v.", id, res.IP4) } plugin.podIPs[id] = ip4.String() // Put the container bridge into promiscuous mode to force it to accept hairpin packets. // TODO: Remove this once the kernel bug (#20096) is fixed. // TODO: check and set promiscuous mode with netlink once vishvananda/netlink supports it if plugin.hairpinMode == componentconfig.PromiscuousBridge { output, err := plugin.execer.Command("ip", "link", "show", "dev", BridgeName).CombinedOutput() if err != nil || strings.Index(string(output), "PROMISC") < 0 { _, err := plugin.execer.Command("ip", "link", "set", BridgeName, "promisc", "on").CombinedOutput() if err != nil { return fmt.Errorf("Error setting promiscuous mode on %s: %v", BridgeName, err) } } } // The first SetUpPod call creates the bridge; get a shaper for the sake of // initialization shaper := plugin.shaper() if egress != nil || ingress != nil { ipAddr := plugin.podIPs[id] if err := shaper.ReconcileCIDR(fmt.Sprintf("%s/32", ipAddr), egress, ingress); err != nil { return fmt.Errorf("Failed to add pod to shaper: %v", err) } } plugin.syncHostportsRules() return nil }
func (plugin *kubenetNetworkPlugin) SetUpPod(namespace string, name string, id kubecontainer.ContainerID) error { plugin.mu.Lock() defer plugin.mu.Unlock() start := time.Now() defer func() { glog.V(4).Infof("TearDownPod took %v for %s/%s", time.Since(start), namespace, name) }() pod, ok := plugin.host.GetPodByName(namespace, name) if !ok { return fmt.Errorf("pod %q cannot be found", name) } ingress, egress, err := bandwidth.ExtractPodBandwidthResources(pod.Annotations) if err != nil { return fmt.Errorf("Error reading pod bandwidth annotations: %v", err) } if err := plugin.Status(); err != nil { return fmt.Errorf("Kubenet cannot SetUpPod: %v", err) } runtime, ok := plugin.host.GetRuntime().(*dockertools.DockerManager) if !ok { return fmt.Errorf("Kubenet execution called on non-docker runtime") } netnsPath, err := runtime.GetNetNS(id) if err != nil { return fmt.Errorf("Kubenet failed to retrieve network namespace path: %v", err) } rt := buildCNIRuntimeConf(name, namespace, id, netnsPath) if err != nil { return fmt.Errorf("Error building CNI config: %v", err) } if err = plugin.addContainerToNetwork(id, rt); err != nil { return err } // Put the container bridge into promiscuous mode to force it to accept hairpin packets. // TODO: Remove this once the kernel bug (#20096) is fixed. // TODO: check and set promiscuous mode with netlink once vishvananda/netlink supports it if plugin.hairpinMode == componentconfig.PromiscuousBridge { output, err := plugin.execer.Command("ip", "link", "show", "dev", BridgeName).CombinedOutput() if err != nil || strings.Index(string(output), "PROMISC") < 0 { _, err := plugin.execer.Command("ip", "link", "set", BridgeName, "promisc", "on").CombinedOutput() if err != nil { return fmt.Errorf("Error setting promiscuous mode on %s: %v", BridgeName, err) } } } // The first SetUpPod call creates the bridge; ensure shaping is enabled if plugin.shaper == nil { plugin.shaper = bandwidth.NewTCShaper(BridgeName) if plugin.shaper == nil { return fmt.Errorf("Failed to create bandwidth shaper!") } plugin.ensureBridgeTxQueueLen() plugin.shaper.ReconcileInterface() } if egress != nil || ingress != nil { ipAddr, _, _ := net.ParseCIDR(plugin.podCIDRs[id]) if err = plugin.shaper.ReconcileCIDR(fmt.Sprintf("%s/32", ipAddr.String()), egress, ingress); err != nil { return fmt.Errorf("Failed to add pod to shaper: %v", err) } } return nil }