Skip to content

Commit

Permalink
avoid Pod IP to be the same with node internal IP
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangzujian committed Aug 23, 2021
1 parent 85b5723 commit 8906e45
Show file tree
Hide file tree
Showing 6 changed files with 778 additions and 258 deletions.
18 changes: 17 additions & 1 deletion pkg/controller/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,22 @@ func (c *Controller) handleAddNode(key string) error {
return err
}

subnets, err := c.subnetsLister.List(labels.Everything())
if err != nil {
klog.Errorf("failed to list subnets: %v", err)
return err
}

nodeIP := util.GetNodeInternalIP(*node)
for _, subnet := range subnets {
if subnet.Spec.Vlan == "" && subnet.Spec.Vpc == util.DefaultVpc && util.CIDRContainIP(subnet.Spec.CIDRBlock, nodeIP) {
msg := fmt.Sprintf("internal IP address of node %s is in CIDR of subnet %s, this may result in network issues", node.Name, subnet.Name)
klog.Warning(msg)
c.recorder.Eventf(&v1.Node{ObjectMeta: metav1.ObjectMeta{Name: node.Name, UID: types.UID(node.Name)}}, v1.EventTypeWarning, "NodeAddressConflictWithSubnet", msg)
break
}
}

providerNetworks, err := c.providerNetworksLister.List(labels.Everything())
if err != nil && !k8serrors.IsNotFound(err) {
klog.Errorf("failed to list provider networks: %v", err)
Expand Down Expand Up @@ -241,7 +257,7 @@ func (c *Controller) handleAddNode(key string) error {
return err
}
} else {
v4IP, v6IP, mac, err = c.ipam.GetRandomAddress(portName, c.config.NodeSwitch)
v4IP, v6IP, mac, err = c.ipam.GetRandomAddress(portName, c.config.NodeSwitch, nil)
if err != nil {
klog.Errorf("failed to alloc random ip addrs for node %v, err %v", node.Name, err)
return err
Expand Down
55 changes: 54 additions & 1 deletion pkg/controller/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -878,14 +878,67 @@ func (c *Controller) getPodAttachmentNet(pod *v1.Pod) ([]*kubeovnNet, error) {
return result, nil
}

func (c *Controller) validatePodIP(podName, subnetName, ipv4, ipv6 string) (bool, bool, error) {
subnet, err := c.subnetsLister.Get(subnetName)
if err != nil {
klog.Errorf("failed to get subnet %s: %v", subnetName, err)
return false, false, err
}

if subnet.Spec.Vlan == "" && subnet.Spec.Vpc == util.DefaultVpc {
nodes, err := c.nodesLister.List(labels.Everything())
if err != nil {
klog.Errorf("failed to list nodes: %v", err)
return false, false, err
}

for _, node := range nodes {
if nodeIP := util.GetNodeInternalIP(*node); nodeIP != "" {
msg := fmt.Sprintf("IP address (%s) assigned to pod %s is the same with internal IP address of node %s, reallocating...", nodeIP, podName, node.Name)
if nodeIP == ipv4 {
klog.Error(msg)
return false, true, nil
}
if nodeIP == ipv6 {
klog.Error(msg)
return true, false, nil
}
}
}
}

return true, true, nil
}

func (c *Controller) acquireAddress(pod *v1.Pod, podNet *kubeovnNet) (string, string, string, error) {
key := fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)
macStr := pod.Annotations[fmt.Sprintf(util.MacAddressAnnotationTemplate, podNet.ProviderName)]

// Random allocate
if pod.Annotations[fmt.Sprintf(util.IpAddressAnnotationTemplate, podNet.ProviderName)] == "" &&
pod.Annotations[fmt.Sprintf(util.IpPoolAnnotationTemplate, podNet.ProviderName)] == "" {
return c.ipam.GetRandomAddress(key, podNet.Subnet.Name)
var skippedAddrs []string
for {
ipv4, ipv6, mac, err := c.ipam.GetRandomAddress(key, podNet.Subnet.Name, skippedAddrs)
if err != nil {
return "", "", "", err
}

ipv4OK, ipv6OK, err := c.validatePodIP(pod.Name, podNet.Subnet.Name, ipv4, ipv6)
if err != nil {
return "", "", "", err
}
if ipv4OK && ipv6OK {
return ipv4, ipv6, mac, nil
}

if !ipv4OK {
skippedAddrs = append(skippedAddrs, ipv4)
}
if !ipv6OK {
skippedAddrs = append(skippedAddrs, ipv6)
}
}
}

// Static allocate
Expand Down
4 changes: 4 additions & 0 deletions pkg/ipam/ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ func (a IP) Add(num int64) IP {
return IP(util.BigInt2Ip(big.NewInt(0).Add(util.Ip2BigInt(string(a)), big.NewInt(num))))
}

func (a IP) Sub(num int64) IP {
return IP(util.BigInt2Ip(big.NewInt(0).Sub(util.Ip2BigInt(string(a)), big.NewInt(num))))
}

func (ipr IPRange) IPExist(ip IP) bool {
return (ipr.Start.LessThan(ip) || ipr.Start.Equal(ip)) &&
(ipr.End.GreaterThan(ip) || ipr.End.Equal(ip))
Expand Down
22 changes: 13 additions & 9 deletions pkg/ipam/ipam.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,21 @@ func NewIPAM() *IPAM {
}
}

func (ipam *IPAM) GetRandomAddress(podName string, subnetName string) (string, string, string, error) {
func (ipam *IPAM) GetRandomAddress(podName, subnetName string, skippedAddrs []string) (string, string, string, error) {
ipam.mutex.RLock()
defer ipam.mutex.RUnlock()
if subnet, ok := ipam.Subnets[subnetName]; !ok {

subnet, ok := ipam.Subnets[subnetName]
if !ok {
return "", "", "", NoAvailableError
} else {
v4IP, v6IP, mac, err := subnet.GetRandomAddress(podName)
klog.Infof("allocate v4 %s v6 %s mac %s for %s", v4IP, v6IP, mac, podName)
return string(v4IP), string(v6IP), mac, err
}

v4IP, v6IP, mac, err := subnet.GetRandomAddress(podName, skippedAddrs)
klog.Infof("allocate v4 %s v6 %s mac %s for %s", v4IP, v6IP, mac, podName)
return string(v4IP), string(v6IP), mac, err
}

func (ipam *IPAM) GetStaticAddress(podName string, ip, mac string, subnetName string) (string, string, string, error) {
func (ipam *IPAM) GetStaticAddress(podName, ip, mac, subnetName string) (string, string, string, error) {
ipam.mutex.RLock()
defer ipam.mutex.RUnlock()
if subnet, ok := ipam.Subnets[subnetName]; !ok {
Expand Down Expand Up @@ -96,10 +98,10 @@ func checkAndAppendIpsForDual(ips []IP, podName string, subnet *Subnet) ([]IP, e
var err error
if util.CheckProtocol(string(ips[0])) == kubeovnv1.ProtocolIPv4 {
newIps = ips
_, ipAddr, _, err = subnet.getV6RandomAddress(podName)
_, ipAddr, _, err = subnet.getV6RandomAddress(podName, nil)
newIps = append(newIps, ipAddr)
} else if util.CheckProtocol(string(ips[0])) == kubeovnv1.ProtocolIPv6 {
ipAddr, _, _, err = subnet.getV4RandomAddress(podName)
ipAddr, _, _, err = subnet.getV4RandomAddress(podName, nil)
newIps = append(newIps, ipAddr)
newIps = append(newIps, ips...)
}
Expand All @@ -116,6 +118,8 @@ func (ipam *IPAM) ReleaseAddressByPod(podName string) {
}

func (ipam *IPAM) AddOrUpdateSubnet(name, cidrStr string, excludeIps []string) error {
excludeIps = util.ExpandExcludeIPs(excludeIps, cidrStr)

ipam.mutex.Lock()
defer ipam.mutex.Unlock()

Expand Down

0 comments on commit 8906e45

Please sign in to comment.