cloudandheat / ch-k8s-lbaas

Flexible Loadbalancer-as-a-Service controller for Kubernetes
Apache License 2.0
9 stars 7 forks source link

lbaas-controller leaks floating IP addresses #28

Open expektorans opened 2 years ago

expektorans commented 2 years ago

I've put lbaas under a bit of stress and could observe that it started to "leak" FIPs. "Leak" is here defined as "floating IPs that are allocated by lbaas to an OS project but are no longer actively used by it"

expektorans commented 2 years ago

This is my hack-ish stress script which wasn't cleaned up in any way.

#!/usr/bin/env python3

from functools import partial
from kubernetes import client, config, utils, watch, dynamic
from kubernetes.client import api_client
from threading import Thread
import random
import time

def task(name, port):
    svc_manifest = {
        "apiVersion": "v1",
        "kind": "Service",
        "metadata": {
            "labels": {
            "app": "nginx"
            },
            "name": name
        },
        "spec": {
            "ports": [
            {
                "port": port,
                "protocol": "TCP",
                "targetPort": 80
            }
            ],
            "selector": {
            "app": "nginx"
            },
            "type": "LoadBalancer"
        },
    }

    # Creating a dynamic client
    c = dynamic.DynamicClient(
        api_client.ApiClient(configuration=config.load_kube_config())
    )

    api = c.resources.get(api_version="v1", kind="Service")
    try:
        api.get(name=name, namespace="default")
        api.delete(name=name, namespace="default")
    except:
        print("Nothing to do")

    while True:
        api.create(body=svc_manifest, namespace="default")
        time.sleep(random.randint(0, 20))
        while True:
            svc = api.get(name=name, namespace="default")
            if svc["status"].get('loadBalancer', {}).get('ingress', []):
                print(f"Got an IP")
                break
            time.sleep(random.randint(0, 20))
        print("Deleting")
        time.sleep(random.randint(0, 20))
        api.delete(name=name, namespace="default")

def main():
    config.load_kube_config()
    for i,p in enumerate([80, 81, 80, 81, 80]):
        Thread(target=partial(task, name=f"nginx-{i}", port=p)).start()

if __name__ == '__main__':
    main()