diff --git a/pkg/controller/namespace.go b/pkg/controller/namespace.go index fef927e3f24..8d0738301a3 100644 --- a/pkg/controller/namespace.go +++ b/pkg/controller/namespace.go @@ -71,6 +71,10 @@ func (c *Controller) enqueueUpdateNamespace(old, new interface{}) { klog.Warningf("no logical switch annotation for ns %s", newNs.Name) c.addNamespaceQueue.Add(newNs.Name) } + + if newNs.Annotations != nil && newNs.Annotations[util.LogicalSwitchAnnotation] != "" && !reflect.DeepEqual(oldNs.Annotations, newNs.Annotations) { + c.addNamespaceQueue.Add(newNs.Name) + } } func (c *Controller) runAddNamespaceWorker() { @@ -120,8 +124,8 @@ func (c *Controller) handleAddNamespace(key string) error { } namespace := orinamespace.DeepCopy() - var ls, cidr string - var excludeIps []string + var ls string + var lss []string subnets, err := c.subnetsLister.List(labels.Everything()) if err != nil { klog.Errorf("failed to list subnets %v", err) @@ -131,18 +135,12 @@ func (c *Controller) handleAddNamespace(key string) error { for _, s := range subnets { for _, ns := range s.Spec.Namespaces { if ns == key { - ls = s.Name - cidr = s.Spec.CIDRBlock - excludeIps = s.Spec.ExcludeIps - break + lss = append(lss, s.Name) } } - if ls != "" { - break - } } - if ls == "" { + if lss == nil { // If NS does not belong to any custom VPC, then this NS belongs to the default VPC vpc, err := c.vpcsLister.Get(c.config.ClusterRouter) if err != nil { @@ -171,10 +169,7 @@ func (c *Controller) handleAddNamespace(key string) error { klog.Errorf("failed to get default subnet %v", err) return err } - ls = subnet.Name - cidr = subnet.Spec.CIDRBlock - excludeIps = subnet.Spec.ExcludeIps - + lss = append(lss, subnet.Name) } op := "replace" @@ -182,16 +177,11 @@ func (c *Controller) handleAddNamespace(key string) error { op = "add" namespace.Annotations = map[string]string{} } else { - if namespace.Annotations[util.LogicalSwitchAnnotation] == ls && - namespace.Annotations[util.CidrAnnotation] == cidr && - namespace.Annotations[util.ExcludeIpsAnnotation] == strings.Join(excludeIps, ",") { + if namespace.Annotations[util.LogicalSwitchAnnotation] == strings.Join(lss, ",") { return nil } } - - namespace.Annotations[util.LogicalSwitchAnnotation] = ls - namespace.Annotations[util.CidrAnnotation] = cidr - namespace.Annotations[util.ExcludeIpsAnnotation] = strings.Join(excludeIps, ",") + namespace.Annotations[util.LogicalSwitchAnnotation] = strings.Join(lss, ",") if _, err = c.config.KubeClient.CoreV1().Namespaces().Patch(context.Background(), key, types.JSONPatchType, generatePatchPayload(namespace.Annotations, op), metav1.PatchOptions{}, ""); err != nil { klog.Errorf("patch namespace %s failed %v", key, err) diff --git a/pkg/controller/pod.go b/pkg/controller/pod.go index 56f07471d6a..941135a4ed1 100644 --- a/pkg/controller/pod.go +++ b/pkg/controller/pod.go @@ -897,11 +897,16 @@ func needAllocateSubnets(pod *v1.Pod, nets []*kubeovnNet) []*kubeovnNet { } func (c *Controller) getPodDefaultSubnet(pod *v1.Pod) (*kubeovnv1.Subnet, error) { - var subnetName string + var subnet *kubeovnv1.Subnet + var err error // 1. check annotation subnet lsName, lsExist := pod.Annotations[util.LogicalSwitchAnnotation] if lsExist { - subnetName = lsName + subnet, err = c.subnetsLister.Get(lsName) + if err != nil { + klog.Errorf("failed to get subnet %v", err) + return nil, err + } } else { ns, err := c.namespacesLister.Get(pod.Namespace) if err != nil { @@ -914,18 +919,35 @@ func (c *Controller) getPodDefaultSubnet(pod *v1.Pod) (*kubeovnv1.Subnet, error) return nil, err } - subnetName = ns.Annotations[util.LogicalSwitchAnnotation] - if subnetName == "" { - err = fmt.Errorf("namespace %s default logical switch is not found", pod.Namespace) - klog.Error(err) - return nil, err - } - } + subnetNames := ns.Annotations[util.LogicalSwitchAnnotation] + for _, subnetName := range strings.Split(subnetNames, ",") { + if subnetName == "" { + err = fmt.Errorf("namespace %s default logical switch is not found", pod.Namespace) + klog.Error(err) + return nil, err + } + subnet, err = c.subnetsLister.Get(subnetName) + if err != nil { + klog.Errorf("failed to get subnet %v", err) + return nil, err + } - subnet, err := c.subnetsLister.Get(subnetName) - if err != nil { - klog.Errorf("failed to get subnet %v", err) - return nil, err + switch subnet.Spec.Protocol { + case kubeovnv1.ProtocolIPv4: + fallthrough + case kubeovnv1.ProtocolDual: + if subnet.Status.V4AvailableIPs == 0 { + klog.V(3).Infof("there's no available ips for subnet %v, try next subnet", subnet.Name) + continue + } + case kubeovnv1.ProtocolIPv6: + if subnet.Status.V6AvailableIPs == 0 { + klog.Infof("there's no available ips for subnet %v, try next subnet", subnet.Name) + continue + } + } + break + } } return subnet, nil } @@ -1228,7 +1250,9 @@ func appendCheckStatefulSetPodToDel(c *Controller, pod *v1.Pod) (bool, error) { klog.Errorf("failed to get namespace %s, %v", pod.Namespace, err) return false, err } - if podNs.Annotations[util.LogicalSwitchAnnotation] != "" && pod.Annotations[util.LogicalSwitchAnnotation] != "" && strings.TrimSpace(podNs.Annotations[util.LogicalSwitchAnnotation]) != strings.TrimSpace(pod.Annotations[util.LogicalSwitchAnnotation]) { + + subnetNames := podNs.Annotations[util.LogicalSwitchAnnotation] + if subnetNames != "" && pod.Annotations[util.LogicalSwitchAnnotation] != "" && !util.ContainsString(strings.Split(subnetNames, ","), strings.TrimSpace(pod.Annotations[util.LogicalSwitchAnnotation])) { klog.Infof("ns %s annotation subnet is %s, which is inconstant with subnet for pod %s, delete pod", pod.Namespace, podNs.Annotations[util.LogicalSwitchAnnotation], pod.Name) return true, nil } diff --git a/pkg/controller/subnet.go b/pkg/controller/subnet.go index 3aaa21cac78..828b0a1aa7f 100644 --- a/pkg/controller/subnet.go +++ b/pkg/controller/subnet.go @@ -735,7 +735,8 @@ func (c *Controller) handleDeleteLogicalSwitch(key string) (err error) { if annotations == nil { continue } - if annotations[util.LogicalSwitchAnnotation] == key { + + if util.ContainsString(strings.Split(annotations[util.LogicalSwitchAnnotation], ","), key) { c.enqueueAddNamespace(ns) } } @@ -839,48 +840,13 @@ func (c *Controller) reconcileSubnet(subnet *kubeovnv1.Subnet) error { func (c *Controller) reconcileNamespaces(subnet *kubeovnv1.Subnet) error { var err error - // 1. unbind from previous subnet - subnets, err := c.subnetsLister.List(labels.Everything()) - if err != nil { - return err - } - - namespaceMap := map[string]bool{} - for _, ns := range subnet.Spec.Namespaces { - namespaceMap[ns] = true - } - - for _, orisub := range subnets { - if orisub.Name == subnet.Name || len(orisub.Spec.Namespaces) == 0 { - continue - } - sub := orisub.DeepCopy() - - changed := false - reservedNamespaces := []string{} - for _, ns := range sub.Spec.Namespaces { - if namespaceMap[ns] { - changed = true - } else { - reservedNamespaces = append(reservedNamespaces, ns) - } - } - if changed { - sub.Spec.Namespaces = reservedNamespaces - _, err = c.config.KubeOvnClient.KubeovnV1().Subnets().Update(context.Background(), sub, metav1.UpdateOptions{}) - if err != nil { - klog.Errorf("failed to unbind namespace from subnet %s, %v", sub.Name, err) - return err - } - } - } - // 2. add annotations to bind namespace + // 1. add annotations to bind namespace for _, ns := range subnet.Spec.Namespaces { c.addNamespaceQueue.Add(ns) } - // 3. update unbind namespace annotation + // 2. update unbind namespace annotation namespaces, err := c.namespacesLister.List(labels.Everything()) if err != nil { klog.Errorf("failed to list namespaces, %v", err) @@ -888,7 +854,7 @@ func (c *Controller) reconcileNamespaces(subnet *kubeovnv1.Subnet) error { } for _, ns := range namespaces { - if ns.Annotations != nil && ns.Annotations[util.LogicalSwitchAnnotation] == subnet.Name && !namespaceMap[ns.Name] { + if ns.Annotations != nil && util.ContainsString(strings.Split(ns.Annotations[util.LogicalSwitchAnnotation], ","), subnet.Name) { c.addNamespaceQueue.Add(ns.Name) } }