Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

K8s client library for KEDA #3265

Closed
Willzy-x opened this issue Jun 22, 2022 · 14 comments
Closed

K8s client library for KEDA #3265

Willzy-x opened this issue Jun 22, 2022 · 14 comments
Labels
feature-request All issues for new features that have not been committed to needs-discussion

Comments

@Willzy-x
Copy link

Proposal

Hi, could you provide a Python library for KEDA just like this:
kubernetes-client-python

Use-Case

I am currently deploying a series of deployments and auto scalers. kubernetes-client-python helps me to deployment a dozen of deployments easily by executing Python scripts. However, there's no client libraries for KEDA. So I cannot deploy scalers for each deployment automatically using Python scripts.

Anything else?

No response

@Willzy-x Willzy-x added feature-request All issues for new features that have not been committed to needs-discussion labels Jun 22, 2022
@zroubalik
Copy link
Member

Are you willing to contribute and maintain this?

@JorTurFer
Copy link
Member

JorTurFer commented Jun 23, 2022

Can't you just use the dynamic client to provide the needed manifests for KEDA? I mean, we don't change them really often, maybe it's enough if you use it. AFAI can see, it's supported and you can find som examples in the repo

Creating and maintaining those libraries could be hard job and IMO dynamic client could fill your requirements. (But if you are willing to do it, I agree with it)

@Willzy-x
Copy link
Author

Hi, I managed to do it by sending API calls directly. I think maybe more details about KEDA's API should be listed in the documents. So, people can customize their deployment jobs.

@JorTurFer
Copy link
Member

I don't get your point, do you mean to expose the OpenAPI json in the docs for instance? To avoid the direct calls, you can use the dynamic client in python

@aslanpour
Copy link

I usually use build a helm chart (e.g., for the ScaleObjects) and customize the deployment through the helm chart in Python, if no client library is available.

@JorTurFer
Copy link
Member

the point is that you don't need client library, you can simply use the dynamic client and give the json, but reusing all the authentication stuffs from the k8s-client

@Willzy-x
Copy link
Author

Hi, I'm actually new to K8S. Do you mean this procedure?

    # fetching the service api
    api = client.resources.get(api_version="v1", kind="Service")

    name = "frontend-service"

    service_manifest = {
        "apiVersion": "v1",
        "kind": "Service",
        "metadata": {"labels": {"name": name}, "name": name, "resourceversion": "v1"},
        "spec": {
            "ports": [
                {"name": "port", "port": 80, "protocol": "TCP", "targetPort": 80}
            ],
            "selector": {"name": name},
        },
    }

Like I just relace api version and kind in api = client.resources.get(api_version="v1", kind="Service") with KEDA's?

@JorTurFer
Copy link
Member

You can check the examples in the python k8s client https://github.com/kubernetes-client/python/tree/master/examples/dynamic-client

@Willzy-x
Copy link
Author

Yea, I copied that code snippet from service.py under this directory. So, like I can use

api = client.resources.get(api_version="keda.sh/v1alpha1", kind="scaledobjects")

and this will discover KEDA's API automatically and avoid directly calling API /apis/keda.sh/v1alpha1/namespaces/{namespace}/scaledobjects?

If that's not the case, I think we cannot avoid calling APIs.

@JorTurFer
Copy link
Member

I guess that it could work 🤔
I have never used the dynamic client with python, but based on the samples, seems like that yes.
Doesn't it work?

@Willzy-x
Copy link
Author

Yes, it worked. Thank you very much!

@ccfreeman
Copy link

ccfreeman commented Dec 22, 2023

I am facing a related issue I believe. I'm using the Python dynamic client to identify keda.sh/v1alpha1 and then to create a ScaledObject resource, but am facing some issues with versioning.

# This code is within a pod on the cluster
config.load_incluster_config()
dynamic_client = dynamic.DynamicClient(client=api_client.ApiClient())
dynamic_api: dynamic.Resource = dynamic_client.resources.get(
    api_version="keda.sh/v1alpha1", kind="ScaledObject"
)
body = {
    "apiVersion:": "keda.sh/v1alpha1",
    "kind": "ScaledObject",
    "metadata": {
        "name": "blah",
        "namespace": "foo",
    },
    "spec": { 
        ...
    },
} # dict repr of the form for the ScaledObject
dynamic_api.create(body=body, namespace="foo")

When I execute this in the cluster, it returns

{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"the API version in the data () does not match the expected API version (keda.sh/v1alpha1)","reason":"BadRequest","code":400}

This json body includes the API version field with keda.sh/v1alpha1, and matches the yaml body I successfully use through Helm. Everything looks good to me, but the version seems to be stripped out of the data (I presume this is the body of the request). Nothing in the code looks like it's doing this (client code just serializes the body I give it and passes it as the POST body).

@Willzy-x how did you end up solving this? I'm wondering if I'm missing some extra fields here.

Thanks!

@prabhatkgupta
Copy link

prabhatkgupta commented Jan 21, 2024

I was also facing a similar issue, I needed to fetch the ScaledObject resource, modify it, and then patch the changes.

Kubernetes version: 1.25
Python: 3.9
Keda API version: keda.sh/v1alpha1

The following code can be used as a working template with Dynamic object handling in K8s

# import required packages
from kubernetes import dynamic, client
# create dynamic client and pass api_client as parameter, resource_client will be used to interact with cluster
your_api_client = client.ApiClient()
your_dynamic_client = dynamic.DynamicClient(your_api_client)
resource_client = your_dynamic_client.resources.get(api_version="keda.sh/v1alpha1", kind="ScaledObject")
# fetch ScaledObject resource using dynamic_client
sample_response = resource_client.get(name=scaledobject_name, namespace=namespace)
# modify fields of sample_response
{Your custom code}
# Patch the ScaledObject resource
resource_client.patch(namespace=namespace, name=scaledobject_name, body=api_response, content_type="application/merge-patch+json")

@prabhatkgupta
Copy link

@ccfreeman you can refer to above solution ^^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request All issues for new features that have not been committed to needs-discussion
Projects
Status: Done
Development

No branches or pull requests

6 participants