Kubernetes
client-go
self-pod
Kubernetes API
Go programming

How to get self pod with kubernetes client-go

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

If a Go application running in Kubernetes wants to fetch its own Pod object with client-go, it needs two pieces of information: the pod name and the namespace. The Kubernetes API does not provide a magical “give me myself” endpoint, so the usual pattern is to inject that identity into the container with the downward API and then query the Pod normally.

That pattern is more reliable than guessing from hostnames or listing every pod and trying to match one. Once the pod name and namespace are available inside the container, the lookup code is straightforward.

Inject Pod Identity With the Downward API

The cleanest approach is to set environment variables from Pod fields.

yaml
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4  name: my-app
5spec:
6  replicas: 1
7  selector:
8    matchLabels:
9      app: my-app
10  template:
11    metadata:
12      labels:
13        app: my-app
14    spec:
15      serviceAccountName: my-app
16      containers:
17        - name: app
18          image: my-app:latest
19          env:
20            - name: POD_NAME
21              valueFrom:
22                fieldRef:
23                  fieldPath: metadata.name
24            - name: POD_NAMESPACE
25              valueFrom:
26                fieldRef:
27                  fieldPath: metadata.namespace

Now the container has explicit knowledge of its own pod identity. That is better than relying on HOSTNAME, which often matches the pod name but is a convention rather than the clearest contract.

Use In-Cluster Config and Read the Pod

Inside the cluster, create an in-cluster client and then fetch the Pod by name.

go
1package main
2
3import (
4    "context"
5    "fmt"
6    "log"
7    "os"
8
9    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10    "k8s.io/client-go/kubernetes"
11    "k8s.io/client-go/rest"
12)
13
14func main() {
15    podName := os.Getenv("POD_NAME")
16    namespace := os.Getenv("POD_NAMESPACE")
17
18    if podName == "" || namespace == "" {
19        log.Fatal("missing POD_NAME or POD_NAMESPACE")
20    }
21
22    config, err := rest.InClusterConfig()
23    if err != nil {
24        log.Fatal(err)
25    }
26
27    clientset, err := kubernetes.NewForConfig(config)
28    if err != nil {
29        log.Fatal(err)
30    }
31
32    pod, err := clientset.CoreV1().Pods(namespace).Get(
33        context.Background(),
34        podName,
35        metav1.GetOptions{},
36    )
37    if err != nil {
38        log.Fatal(err)
39    }
40
41    fmt.Println("Running in pod:", pod.Name)
42    fmt.Println("Node:", pod.Spec.NodeName)
43}

This is the normal client-go read path. There is nothing special about self lookup once you know the object's name and namespace.

Give the Service Account Permission

The pod's service account must be allowed to read Pod objects in its namespace.

yaml
1apiVersion: rbac.authorization.k8s.io/v1
2kind: Role
3metadata:
4  name: pod-reader
5  namespace: prod
6rules:
7  - apiGroups: [""]
8    resources: ["pods"]
9    verbs: ["get"]

And bind it:

yaml
1apiVersion: rbac.authorization.k8s.io/v1
2kind: RoleBinding
3metadata:
4  name: pod-reader-binding
5  namespace: prod
6subjects:
7  - kind: ServiceAccount
8    name: my-app
9roleRef:
10  apiGroup: rbac.authorization.k8s.io
11  kind: Role
12  name: pod-reader

Without this, the client code may work locally against a broad kubeconfig but fail in-cluster with an authorization error.

You could list pods by label and try to infer which one is current, but that is slower, noisier, and less reliable. If the pod already knows its own identity through the downward API, a direct Get is simpler and produces less API traffic.

The same logic applies to reading the namespace from mounted service-account files versus injecting it directly. The downward API makes the dependency explicit.

Common Pitfalls

The biggest mistake is assuming HOSTNAME is always the right pod identifier and building logic around that assumption instead of injecting explicit metadata.

Another issue is forgetting the namespace. Pod names are only unique within a namespace, so both pieces are needed for a direct lookup.

A third problem is missing RBAC permissions for pods/get, which causes the code to fail only after deployment.

Summary

  • There is no special self-pod endpoint in client-go; fetch the pod normally by name and namespace.
  • Use the downward API to inject metadata.name and metadata.namespace into the container.
  • Use rest.InClusterConfig() and clientset.CoreV1().Pods(namespace).Get(...) for the lookup.
  • Grant the service account get permission on pods.
  • Prefer explicit pod identity injection over guessing from hostnames or scanning pod lists.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.