From 45b00710cfc9e2b77e42bc297ab15908ab7dfa12 Mon Sep 17 00:00:00 2001 From: Zhao Congqi <52371592+zcq98@users.noreply.github.com> Date: Mon, 15 Jan 2024 10:58:59 +0800 Subject: [PATCH] support vip dual stack (#3617) Signed-off-by: zcq98 Co-authored-by: zcq98 --- pkg/controller/pod.go | 83 ++++++++++++++++++++++++++++--------------- pkg/controller/vip.go | 17 +++++---- 2 files changed, 65 insertions(+), 35 deletions(-) diff --git a/pkg/controller/pod.go b/pkg/controller/pod.go index ea674ac2bd9..803ffbc3f66 100644 --- a/pkg/controller/pod.go +++ b/pkg/controller/pod.go @@ -2013,42 +2013,67 @@ func getPodType(pod *v1.Pod) string { } func (c *Controller) getVirtualIPs(pod *v1.Pod, podNets []*kubeovnNet) map[string]string { - vipsMap := make(map[string]string) - if aaps := pod.Annotations[util.AAPsAnnotation]; aaps != "" { - for _, vipName := range strings.Split(aaps, ",") { - vip, err := c.virtualIpsLister.Get(vipName) - if err != nil { - klog.Errorf("failed to get vip %s, %v", vipName, err) - continue - } - if vip.Spec.Namespace != pod.Namespace || vip.Status.V4ip == "" { - continue - } - subnet, err := c.subnetsLister.Get(vip.Spec.Subnet) - if err != nil { - klog.Errorf("failed to get subnet %s, %v", vip.Spec.Subnet, err) - continue - } - key := fmt.Sprintf("%s.%s", subnet.Name, subnet.Spec.Provider) - if vips, exists := vipsMap[key]; exists { - vipsMap[key] = strings.Join([]string{vips, vip.Status.V4ip}, ",") - } else { - vipsMap[key] = vip.Status.V4ip - } + vipsListMap := make(map[string][]string) + var vipNamesList []string + for _, vipName := range strings.Split(strings.TrimSpace(pod.Annotations[util.AAPsAnnotation]), ",") { + if !util.ContainsString(vipNamesList, vipName) { + vipNamesList = append(vipNamesList, vipName) + } + } + for _, vipName := range vipNamesList { + vip, err := c.virtualIpsLister.Get(vipName) + if err != nil { + klog.Errorf("failed to get vip %s, %v", vipName, err) + continue + } + if vip.Spec.Namespace != pod.Namespace || (vip.Status.V4ip == "" && vip.Status.V6ip == "") { + continue + } + subnet, err := c.subnetsLister.Get(vip.Spec.Subnet) + if err != nil { + klog.Errorf("failed to get subnet %s, %v", vip.Spec.Subnet, err) + continue + } + key := fmt.Sprintf("%s.%s", subnet.Name, subnet.Spec.Provider) + vipsList := vipsListMap[key] + if vipsList == nil { + vipsList = []string{} } + + // ipam will ensure the uniqueness of VIP + if util.IsValidIP(vip.Status.V4ip) { + vipsList = append(vipsList, vip.Status.V4ip) + } + if util.IsValidIP(vip.Status.V6ip) { + vipsList = append(vipsList, vip.Status.V6ip) + } + + vipsListMap[key] = vipsList } for _, podNet := range podNets { - key := fmt.Sprintf("%s.%s", podNet.Subnet.Name, podNet.ProviderName) - vip := pod.Annotations[fmt.Sprintf(util.PortVipAnnotationTemplate, podNet.ProviderName)] - if vip == "" { + vipStr := pod.Annotations[fmt.Sprintf(util.PortVipAnnotationTemplate, podNet.ProviderName)] + if vipStr == "" { continue } - if vips, exists := vipsMap[key]; exists { - vipsMap[key] = strings.Join([]string{vips, vip}, ",") - } else { - vipsMap[key] = vip + key := fmt.Sprintf("%s.%s", podNet.Subnet.Name, podNet.ProviderName) + vipsList := vipsListMap[key] + if vipsList == nil { + vipsList = []string{} + } + + for _, vip := range strings.Split(vipStr, ",") { + if util.IsValidIP(vip) && !util.ContainsString(vipsList, vip) { + vipsList = append(vipsList, vip) + } } + + vipsListMap[key] = vipsList + } + + vipsMap := make(map[string]string) + for key, vipsList := range vipsListMap { + vipsMap[key] = strings.Join(vipsList, ",") } return vipsMap } diff --git a/pkg/controller/vip.go b/pkg/controller/vip.go index b7e098d611d..f754fd3d211 100644 --- a/pkg/controller/vip.go +++ b/pkg/controller/vip.go @@ -46,7 +46,8 @@ func (c *Controller) enqueueUpdateVirtualIP(oldObj, newObj interface{}) { oldVip.Spec.MacAddress != newVip.Spec.MacAddress || oldVip.Spec.ParentMac != newVip.Spec.ParentMac || oldVip.Spec.ParentV4ip != newVip.Spec.ParentV4ip || - oldVip.Spec.V4ip != newVip.Spec.V4ip { + oldVip.Spec.V4ip != newVip.Spec.V4ip || + oldVip.Spec.V6ip != newVip.Spec.V6ip { klog.Infof("enqueue update vip %s", key) c.updateVirtualIPQueue.Add(key) } @@ -216,7 +217,7 @@ func (c *Controller) handleAddVirtualIP(key string) error { } klog.V(3).Infof("handle add vip %s", key) vip := cachedVip.DeepCopy() - var sourceV4Ip, v4ip, v6ip, mac, subnetName string + var sourceV4Ip, sourceV6Ip, v4ip, v6ip, mac, subnetName string subnetName = vip.Spec.Subnet if subnetName == "" { return fmt.Errorf("failed to create vip '%s', subnet should be set", key) @@ -228,12 +229,15 @@ func (c *Controller) handleAddVirtualIP(key string) error { } portName := ovs.PodNameToPortName(vip.Name, vip.Spec.Namespace, subnet.Spec.Provider) sourceV4Ip = vip.Spec.V4ip - if sourceV4Ip != "" { - v4ip, v6ip, mac, err = c.acquireStaticIPAddress(subnet.Name, vip.Name, portName, sourceV4Ip) + sourceV6Ip = vip.Spec.V6ip + ipStr := util.GetStringIP(sourceV4Ip, sourceV6Ip) + if ipStr != "" { + v4ip, v6ip, mac, err = c.acquireStaticIPAddress(subnet.Name, vip.Name, portName, ipStr) } else { // Random allocate v4ip, v6ip, mac, err = c.acquireIPAddress(subnet.Name, vip.Name, portName) } + if err != nil { klog.Error(err) return err @@ -420,11 +424,12 @@ func (c *Controller) handleUpdateVirtualParents(key string) error { return err } // only pods in the same namespace as vip are allowed to use aap - if cachedVip.Status.V4ip == "" || cachedVip.Spec.Namespace == "" { + if (cachedVip.Status.V4ip == "" && cachedVip.Status.V6ip == "") || cachedVip.Spec.Namespace == "" { return nil } // add new virtual port if not exist - if err = c.OVNNbClient.CreateVirtualLogicalSwitchPort(cachedVip.Name, cachedVip.Spec.Subnet, cachedVip.Status.V4ip); err != nil { + ipStr := util.GetStringIP(cachedVip.Status.V4ip, cachedVip.Status.V6ip) + if err = c.OVNNbClient.CreateVirtualLogicalSwitchPort(cachedVip.Name, cachedVip.Spec.Subnet, ipStr); err != nil { klog.Errorf("create virtual port with vip %s from logical switch %s: %v", cachedVip.Name, cachedVip.Spec.Subnet, err) return err }