Search code examples
pythonkubernetesdigital-oceankubeconfig

How to operate a Kubernetes cluster on Digitalocean from Python?


the question

I am running a Kubernetes cluster in Digitalocean and I want to connect to it from certain Python app, in order to retrieve information about running services. I am able to setup the connection from my local (where kubeconfig created using doctl is present), however how to create a kubeconfig when the app is deployed (using Docker)?

current state

So far the connection I use looks like this, the issue is with load_kube_config, because in my container there is not kubeconfig.

import kubernetes as k8s
from kubernetes.client.rest import ApiException


def init_k8s():
    """
    Init connection to k8s cluster
    :return:
    """
    # Load the Kubernetes configuration
    k8s.config.load_kube_config()

    # Configure the Digital Ocean API access token
    configuration = k8s.client.Configuration()
    configuration.host = 'https://api.digitalocean.com'
    # configuration.verify_ssl = True
    # configuration.debug = False
    configuration.api_key = {'access-token': DO_API_SECRET}

possible options

Please note, I am using Digitalocean Applications for build and run. This limits some options, as seen below.

💡 create kubeconfig during docker build

One idea, is to create kubeconfig during build of the container, running

doctl auth init -t the-secret-token
doctl kubernetes cluster kubeconfig save 1c08efb9-xxx-yyy

The only issue might with exposing certain variable during build.

❌ map existing kubeconfig to the container

One possible option will be to somehow map the existing kubeconfig into the container during runtime. Unfortunately I have no option to do this (it's deployed over Digitalocean Apps, not Kubernetes or so)

❌ copy existing kubeconfig during build

Also not possible due to point above - I am building the app in DO Apps and there is no option to copy the kubeconfig.

❌ create base docker image

Create a new docker image containing the kubeconfig and use it as base image during the app build is one possible approach. However merging my secrets (kubeconfig) into an image which needs to be in public Docker registry is not possible

✅ create kubeconfig during app runtime - THIS WORKS

The most optimal approach, so far, is to create a kubeconfig file during app runtime using doctl API (or lib like this). I am currently trying to figure out this way.

I am gonna dig and try more and more options. I will be glad for any help 🙏


Solution

  • I have finally figured out a way, how to do it using Digitalocean API. Note that

    • DO_API_SECRET is API key generated on digital ocean
    • DO_API_URL is digitalocean base api URL, right now it's https://api.digitalocean.com/v2
    • K8S_CLUSTER_ID - is the internal cluster id, I have copied mine from the browser URL and looks like 1c08ef14-zzzz-xxxx-aaa-qqqq
    • It is a good idea to remove the tempfile after it's loaded
    def get_kubeconfig():
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {DO_API_SECRET}",
        }
    
        response = requests.get(
            f"{DO_API_URL}/kubernetes/clusters/{K8S_CLUSTER_ID}/kubeconfig",
            headers=headers,
        )
    
        kubeconfig_content = response.text
    
        # Generate a temporary kubeconfig file
        kubeconfig_path = tempfile.mkstemp()[1]
        with open(kubeconfig_path, "w") as kubeconfig_file:
            kubeconfig_file.write(kubeconfig_content)
    
        return kubeconfig_path
    
    path = get_kubeconfig()
    k8s.config.load_kube_config(path)