How to connect to microk8s API through Python Kubernetes client?

7/13/2019

I'm trying to connect to my microk8s Kubernetes cluster which is listening on port 16443 with the Python Kubernetes client:

#!/usr/bin/python3

import kubernetes
from kubernetes import client
from kubernetes.client import ApiClient


def setup_cluster():
    configuration = kubernetes.client.configuration.Configuration()
    configuration.host = "https://localhost:16443"
    #configuration.cert_file = "ca.crt"
    #configuration.key_file = "ca.key"
    configuration.api_key["authorization"] = "[the token which I got from kubectl -n kube-system describe secret default-token-abc123]"

    api_client = ApiClient(configuration=configuration)

    v1 = client.CoreV1Api(api_client=api_client)

    print("Listing pods with their IPs:")
    ret = v1.list_pod_for_all_namespaces(watch=False)
    for i in ret.items:
        print("%s\t%s\t%s" % (i.status.pod_ip, i.metadata.namespace, i.metadata.name))


if __name__ == "__main__":
    setup_cluster()

If I set none of the fields cert_file, key_file or api_key of the configuration in the example, the connection fails due to

Traceback (most recent call last):
  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/kubernetes_python_port_ignored.py", line 26, in <module>
    setup_cluster()
  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/kubernetes_python_port_ignored.py", line 20, in setup_cluster
    ret = v1.list_pod_for_all_namespaces(watch=False)
  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/venv/lib/python3.7/site-packages/kubernetes/client/apis/core_v1_api.py", line 13630, in list_pod_for_all_namespaces
    (data) = self.list_pod_for_all_namespaces_with_http_info(**kwargs)
  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/venv/lib/python3.7/site-packages/kubernetes/client/apis/core_v1_api.py", line 13724, in list_pod_for_all_namespaces_with_http_info
    collection_formats=collection_formats)
  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/venv/lib/python3.7/site-packages/kubernetes/client/api_client.py", line 334, in call_api
    _return_http_data_only, collection_formats, _preload_content, _request_timeout)
  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/venv/lib/python3.7/site-packages/kubernetes/client/api_client.py", line 168, in __call_api
    _request_timeout=_request_timeout)
  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/venv/lib/python3.7/site-packages/kubernetes/client/api_client.py", line 355, in request
    headers=headers)
  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/venv/lib/python3.7/site-packages/kubernetes/client/rest.py", line 231, in GET
    query_params=query_params)
  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/venv/lib/python3.7/site-packages/kubernetes/client/rest.py", line 205, in request
    headers=headers)
  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/venv/lib/python3.7/site-packages/urllib3/request.py", line 68, in request
    **urlopen_kw)
  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/venv/lib/python3.7/site-packages/urllib3/request.py", line 89, in request_encode_url
    return self.urlopen(method, url, **extra_kw)
  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/venv/lib/python3.7/site-packages/urllib3/poolmanager.py", line 326, in urlopen
    response = conn.urlopen(method, u.request_uri, **kw)
  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/venv/lib/python3.7/site-packages/urllib3/connectionpool.py", line 670, in urlopen
    **response_kw)
  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/venv/lib/python3.7/site-packages/urllib3/connectionpool.py", line 670, in urlopen
    **response_kw)
  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/venv/lib/python3.7/site-packages/urllib3/connectionpool.py", line 670, in urlopen
    **response_kw)
  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/venv/lib/python3.7/site-packages/urllib3/connectionpool.py", line 641, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/venv/lib/python3.7/site-packages/urllib3/util/retry.py", line 399, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='localhost', port=16443): Max retries exceeded with url: /api/v1/pods?watch=False (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)')))

If I specify the api_key as shown in the code above I get

  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/venv/lib/python3.7/site-packages/urllib3/util/retry.py", line 399, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='localhost', port=16443): Max retries exceeded with url: /api/v1/pods?watch=False (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)')))

I tried setting some certificates like ca.crt and ca.key from /var/snap/microk8s/current/certs as shown, but this then fails due to

  File "/home/richter/examples/kubernetes-python/kubernetes-python-port-ignored/venv/lib/python3.7/site-packages/urllib3/util/retry.py", line 399, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='localhost', port=16443): Max retries exceeded with url: /api/v1/pods?watch=False (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)')))

I'm using microk8s 1.15.0 (695) on Ubuntu 19.04 with Python 3.7 and Kubernetes Python client 10.0.0.

-- Karl Richter
kubernetes
kubernetes-python-client
microk8s
python

3 Answers

12/2/2019

This works for AWS EKS cluster:

import boto3
import kubernetes
import os
import base64

eks = boto3.client('eks')

eks_cluster_name = os.environ['EKS_CLUSTER_NAME']
eks_api_key = os.environ['EKS_API_KEY']

eksresponse = eks.describe_cluster(
    name=eks_cluster_name
)

ca_file = open("/tmp/ca.crt", "wb")
n = ca_file.write(base64.b64decode(eksresponse['cluster']['certificateAuthority']['data']))
ca_file.close()

configuration = kubernetes.client.Configuration()

configuration.ssl_ca_cert = '/tmp/ca.crt'
configuration.api_key['authorization'] = eks_api_key
configuration.api_key_prefix['authorization'] = 'Bearer'
configuration.host = eksresponse['cluster']['endpoint']

api_instance = kubernetes.client.CoreV1Api(kubernetes.client.ApiClient(configuration))

api_response = api_instance.list_pod_for_all_namespaces()
for i in api_response.items:
    print(i.metadata.name)
-- Artsiom Sinitsa
Source: StackOverflow

7/14/2019

Your SSL verification is failing the TLS checks. The easiest and quickest fix is to set your Kube config to skip tls-verify because you are using a single node.

clusters:
- cluster:  
    server: https://127.0.0.1:16443
    insecure-skip-tls-verify: true
-- WiththeWind
Source: StackOverflow

7/24/2019

you need to pass path to ca.crt file at configuration.ssl_ca_cert = 'ca.crt'.

configuration = kubernetes.client.Configuration()
configuration.ssl_ca_cert = 'ca.crt' #<<< look here>>>
configuration.api_key['authorization'] = 'ZXXXXXXXXXXdw=='
configuration.api_key_prefix['authorization'] = 'Bearer'
configuration.host = 'https://aaaaaaaaaaaaaaa.gr7.us-east-1.eks.amazonaws.com'

other options are important as well or else you can use default kubeconfig location by adding following line in your code.

config.load_kube_config()

Generally we can authenticate our client in different ways here i will give example for two ways.

  1. By using default location of config file at ~/.kube/config.

If you are using this method make sure you have, config file at ~/.kube/config

If there is no file present at this location, use kubectl config view to get the content of config file and save it to config file and place that file at ~/.kube/config

Example for first case:

following code will give you listofpods in default namespace

from kubernetes import client, config

#<<<observe below line of code >>>
#uses default config file loccated at ~/.kube/config
config.load_kube_config()

v1 = client.CoreV1Api()
print("Listing pods with their IPs:")
ret = v1.list_pod_for_all_namespaces(watch=False)
for i in ret.items:
    print("%s\t%s\t%s" % (i.status.pod_ip, i.metadata.namespace, i.metadata.name))

res = v1.list_namespaced_pod(namespace='default',watch=False)
for i in res.items:
    print("%s\t%s\t%s" % (i.status.pod_ip, i.metadata.namespace, i.metadata.name))
  1. By defining certs and bearer token.

Example for second case

This code lists names of namespaces

import kubernetes.client

<<<pay attention here next five lines of code>>>
configuration = kubernetes.client.Configuration()
configuration.ssl_ca_cert = 'ca.crt'
configuration.api_key['authorization'] = 'ZXXXXXXXXXXdw=='
configuration.api_key_prefix['authorization'] = 'Bearer'
configuration.host = 'https://aaaaaaaaaaaaaaa.gr7.us-east-1.eks.amazonaws.com'

api_instance = kubernetes.client.CoreV1Api(kubernetes.client.ApiClient(configuration))

api_response = api_instance.list_namespace()
for i in api_response.items:
    print(i.metadata.name)

for more info refer official GitHub repository for examples

refer: my answer to similar problem

-- naveen kumar
Source: StackOverflow