Accessing Kubernetes API from OpenShift Pods
How a pod running inside OpenShift can securely talk to the Kubernetes API using its mounted service account token, cluster CA certificate, and RBAC — with curl and Python examples.
By Network Nuts Team · Published 2026-07-14
Every pod running on OpenShift (or any Kubernetes cluster) can talk to the Kubernetes API server directly — no kubeconfig required. The cluster automatically gives each pod an identity through its service account, and everything needed to authenticate is mounted inside the container.
Where the credentials live
When a pod starts, Kubernetes mounts the service account token, the cluster CA certificate, and the current namespace at a well-known path:
/var/run/secrets/kubernetes.io/serviceaccount/token # bearer token
/var/run/secrets/kubernetes.io/serviceaccount/ca.crt # cluster CA cert
/var/run/secrets/kubernetes.io/serviceaccount/namespace # current namespace
Finding the API server
The API server is reachable from every pod through an in-cluster DNS name and injected environment variables:
# DNS name that always resolves to the API server
https://kubernetes.default.svc
# ...or build it from the injected environment variables
echo "https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}"
Calling the API with curl
Combine the token and CA certificate to make an authenticated, TLS-verified request from inside the pod:
APISERVER=https://kubernetes.default.svc
SA=/var/run/secrets/kubernetes.io/serviceaccount
TOKEN=$(cat $SA/token)
NAMESPACE=$(cat $SA/namespace)
curl --cacert $SA/ca.crt \
--header "Authorization: Bearer $TOKEN" \
-X GET "$APISERVER/api/v1/namespaces/$NAMESPACE/pods"
If you get a 403 Forbidden, authentication worked but the service account lacks permission — that is RBAC, covered next.
Granting permissions with RBAC
By default a pod's service account can do almost nothing. Grant exactly what it needs with a Role and a RoleBinding:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: my-project
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: my-project
subjects:
- kind: ServiceAccount
name: default
namespace: my-project
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
On OpenShift you can apply the same objects with oc apply -f role.yaml, or use the shortcuts:
oc create role pod-reader --verb=get,list,watch --resource=pods -n my-project
oc policy add-role-to-user pod-reader -z default --role-namespace=my-project -n my-project
Doing it from application code
Most languages ship an official Kubernetes client that auto-detects the in-cluster config — no manual token handling required. In Python:
from kubernetes import client, config
# Reads the mounted token + CA automatically when running inside a pod
config.load_incluster_config()
v1 = client.CoreV1Api()
for pod in v1.list_namespaced_pod("my-project").items:
print(pod.metadata.name)
Best practices
- Use a dedicated service account per workload instead of
default, so you can scope permissions tightly. - Follow least privilege — grant only the verbs and resources the pod actually needs.
- Never bake tokens into images or environment variables; read them from the mounted path so they rotate automatically.
- Prefer Roles over ClusterRoles unless the workload genuinely needs cluster-wide access.
With the service account token, the cluster CA, and a small RBAC Role, any pod can query and manage Kubernetes resources securely — the foundation for operators, controllers, and in-cluster automation.