Sunday, November 27, 2022
Home SCIENCE How to access your Kubernetes cluster's API from within your pods

How to access your Kubernetes cluster’s API from within your pods

The Kubernetes API is your route to inspect and manage your cluster operations. You can consume the API using the Kubectl CLI, tools like curlor official integration libraries for popular programming languages.

The API is also available to applications within your cluster. Kubernetes pods automatically receive API access and can authenticate using a provided service account. The interactions are done by consuming the injected environment variables and certificate files to make connections from the client of your choice.

Why access the Kubernetes API inside pods?

There are several use cases for API access in the pod. This technique allows applications to dynamically inspect their environment, apply Kubernetes changes, and collect control plane metrics that provide performance insights.

Some organizations build their own tools around Kubernetes. They could implement a special application on the cluster that uses the API to expose additional functionality. Operating from within the cluster can be more secure than making API calls from an external script, since you don’t need to open your environment or share service accounts and authentication tokens.

Using the API client libraries

The easiest and most recommended method of accessing the Kubernetes API from a pod is to use a client library. Fully supported options are available for C, .NET, Go, Haskell, Java, JavaScript, Perl, Python, and Ruby. there are equivalents community-maintained solutions for most other popular programming languages.

The client libraries have built-in support for discovering the cluster environment in which they are running. Each implementation provides a function that you can call that will configure the library to connect to the correct API server.

This is an example of how to list the Pods in your cluster within a Python application:

from kubernetes import client, config
 
config.load_incluster_config()
 
api = client.CoreV1Api()
 
# Perform necessary API interactions
# pods = api.list_pod_for_all_namespaces()

This approach is easy to work with and requires no manual configuration. However, sometimes you won’t be able to use a client library. In those cases, it is still possible to manually access the API using the service account provided by Kubernetes.

Performing Manual API Interactions

To call the API, you need to know two things: the hostname on the cluster you’re exposed to, and the service account token that will authenticate your Pod.

The API hostname is always kubernetes.default.svc. The Kubernetes DNS provider will resolve this name to the control plane API server. Alternatively, you can use the $KUBERNETES_SERVICE_HOST environment variable to discover the IP address of the API server:

$ echo $KUBERNETES_SERVICE_HOST
10.96.0.1

The API is only available over HTTPS. You can find the certificate authority file for your cluster at /var/run/secrets/kubernetes.io/serviceaccount/ca.crt inside your pod. Kubernetes deposits this to the file system every time a new container is created.

You will need to authenticate to accomplish anything useful with the API. Kubernetes creates a new service account for each Pod and provide your token in /var/run/secrets/kubernetes.io/serviceaccount/token. This must be included with each HTTP request as a bearer token in the Authorization headers

Putting it all together, here is an example of how to make a basic Kubernetes API request in the Pod using curl:

$ curl \
  --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
  -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
  
{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "192.168.49.2:8443"
    
  ]

The Kubernetes server has responded with the available API versions. This confirms that a successful connection has been made using the kubernetes.default.svc hostname and service account provided.

RBAC Management

Even if one API request succeeded, most others will be out of bounds if RBAC is enabled for your cluster. Newly created service accounts are not automatically given roles, so your Pod will not be able to request protected API endpoints.

You can resolve this by creating your own role objects and binding them to the service account that is provided to your pods. First create a new Role:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: demo-role
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list"]

Apply it to your cluster with Kubectl:

$ kubectl apply -f role.yaml

Next, bind the role to the service account:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: default
  name: demo-role-binding
subjects:
  - kind: ServiceAccount
    name: default
    apiGroup: ""
roleRef:
  kind: Role
  name: demo-role
  apiGroup: ""

the default the service account is selected as the subject of the role binding. Pods are always provisioned with this service account, scoped to the namespace in which they were created. In this example, the default the namespace is used, but this needs to be changed on the Role and RoleBinding objects if your Pod exists in a different namespace.

Add RoleBinding to your cluster:

$ kubectl apply -f role-binding.yaml

Your Pods will now be able to get and list other Pod Items in the default namespaced You can verify this by making an API request to the namespaced Pods endpoint:

$ curl \
  --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
  -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
  

  "kind": "PodList",
  "apiVersion": "v1"
  ...

Pods can identify their own namespace by reading the /var/run/secrets/kubernetes.io/serviceaccount/namespace proceedings:

$ cat /var/run/secrets/kubernetes.io/serviceaccount/namespace
default

This provides a convenient method of interpolating the active namespace into endpoint URLs:

$ curl \
  --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
  -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
   /var/run/secrets/kubernetes.io/serviceaccount/namespace)/pods

  "kind": "PodList",
  "apiVersion": "v1"
  ...

Choose a different service account

Kubernetes automatically provides Pods with the default service account within your namespace. Optionally, you can inject a different service account by setting the spec.serviceAccountName field in their pods:

apiVersion: v1
kind: Pod
metadata:
  name: demo
spec:
  serviceAccountName: demo-sa

In this example, the Pod will authenticate as the demo-sa tabs You can create this service account manually and link it to the roles you need.

$ kubernetes create serviceaccount demo-sa

The service account must exist in the same namespace as the Pod.

Canceling service account mount

Automatic injection of service accounts is not always desirable. It can be a security hazard, as a successful compromised Pod offers immediate access to your Kubernetes cluster’s API. You can disable service account token mounts with the spec.automountServiceAccountToken Pod manifest field:

apiVersion: v1
kind: Pod
metadata:
  name: demo
spec:
  automountServiceAccountToken: false

Kubernetes will not inject the /var/run/secrets/kubernetes.io/serviceaccount/token proceedings. This will prevent the Pod from authenticating to the Kubernetes API, unless you provide the credentials manually using a different method. This field is also supported for service account objects, making them ineligible to automatically mount to any Pod.

If you use service account mounting, configure the appropriate RBAC policies to restrict the token to your intended use cases. Preventing highly privileged access will decrease the risk of damage should an attacker gain access to your Pod.

Summary

Accessing the Kubernetes API server from within your cluster allows running applications to inspect and modify neighboring workloads. You can add additional features without opening your cluster to external API access.

Official client libraries make it easy to get up and running, if they’re right for your use case. In other situations, you will need to manually make requests to https://kubernetes.default.svc, providing the certificate authority file and service account token that Kubernetes injects into your Pod containers. Regardless of which approach you use, the service account must be properly configured with RBAC role bindings for the Pod to have permission to perform the intended actions.


RELATED ARTICLES

Unearthing everyday life at an ancient site in Greece

As the sun reached its peak, waves of heat rose from the cypress-clad hills around me. The turquoise waters of the Ionian Sea...

Nobel Prize in medicine awarded for research on evolution

This year's Nobel Prize in Physiology or Medicine has been awarded to Swedish scientist Svante Paabo for his discoveries about human evolution.Thomas Perlmann, secretary...

Do you need to report your COVID self-test results?

The latest spike in COVID-19 infections in California may top last winter's tidal wave, health officials say. And judging by the sewage tests,...

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

A Guide to Helping Your Partner Overcome PTSD

If you’re reading this, it’s likely that you have a partner who is suffering from post-traumatic stress disorder...

Technology must allow doctors to be doctors

When my doctor walks into the exam room, I want him to pay attention to me, not the computer. Not only is that...

System outages reported at some public hospitals and health facilities in Singapore

Over the past six weeks, system outages have been reported at some public hospitals and health centers of the National Health Group and the...

Mental health crisis teams are no longer just for cities

Tony Leys and Arielle Zionts NEWTON, Iowa — Jeff White knows what can happen when 911 dispatchers get a call about someone feeling down or...