Skip to content

Commit

Permalink
support to add multiple subnets for a namespace
Browse files Browse the repository at this point in the history
  • Loading branch information
hongzhen-ma committed Jan 14, 2022
1 parent b8b31ae commit 2557c51
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 74 deletions.
32 changes: 11 additions & 21 deletions pkg/controller/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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)
Expand All @@ -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 {
Expand Down Expand Up @@ -171,27 +169,19 @@ 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"
if namespace.Annotations == nil || len(namespace.Annotations) == 0 {
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)
Expand Down
52 changes: 38 additions & 14 deletions pkg/controller/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
}
Expand Down Expand Up @@ -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
}
Expand Down
44 changes: 5 additions & 39 deletions pkg/controller/subnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -839,56 +840,21 @@ 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)
return err
}

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)
}
}
Expand Down

0 comments on commit 2557c51

Please sign in to comment.