Search code examples
gogoogle-cloud-platformgoogle-kubernetes-enginekubernetes-pod

How can I get pod external IP from Go code at runtime


Pretty simple question, how can I get the Pod where my current go code is running?

I need it because for some reason, I need to ping directly the Pod's code instead of using my regular endpoint which would be the load balancer.

My current config:

apiVersion: v1
kind: Service
metadata:
  name: web-socket-service-api
spec:
  ports:
    # Port that accepts gRPC and JSON/HTTP2 requests over HTTP.
    - port: 8080
      targetPort: 8080
      protocol: TCP
      name: grpc
    # Port that accepts gRPC and JSON/HTTP2 requests over HTTP.
    - port: 8081
      targetPort: 8081
      protocol: TCP
      name: rest
    # Port that accepts WebSockets.
    - port: 8082
      targetPort: 8082
      protocol: TCP
      name: websocket
  selector:
    app: web-socket-service-api
  type: LoadBalancer
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: web-socket-service-api
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: web-socket-service-api
    spec:
      containers:
        - name: web-socket-service-api
          image: gcr.io/[PROJECT]/web-socket-service-api:latest
          ports:
            - containerPort: 8080
            - containerPort: 8081
            - containerPort: 8082

I tried

/*
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/rest"
*/

func GetContainerIP() string {

    // creates the in-cluster config
    config, err := rest.InClusterConfig()
    if err != nil {
        panic(err.Error())
    }
    // creates the clientset
    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        panic(err.Error())
    }

    log.Println("checking pods")
    pods, err := clientset.CoreV1().Pods("default").List(metav1.ListOptions{})
    if err != nil {
        panic(err.Error())
    }
    b, _ := json.Marshal(pods)
    log.Println(string(b))

    for _, pod := range pods.Items {
        log.Println(pod.Name, pod.Status)
        pod, err := clientset.CoreV1().Pods("default").Get(pod.Name, metav1.GetOptions{})
        if err != nil {
            panic(err.Error())
        }
        log.Println(pod.Status)
    }
    log.Println("checked pods")

    return ""
}

But I sadly got

panic: pods is forbidden: User "system:serviceaccount:default:default" cannot list resource "pods" in API group "" in the namespace "default"

And I couldn't find a way to fix it or any tutorial about it..


Solution

  • I found the answer after a moment, but totally forgot to post it over here!

    Please note that it will crash if you ain't in a Kubernetes env

    import (
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
        "k8s.io/client-go/kubernetes"
        "k8s.io/client-go/rest"
        "os"
        "os/signal"
        "time"
    )
    
    //
    // Pod infos
    //
    
    func GetPodDetails() (IP string, name string) {
    
        // creates the in-cluster config
        config, err := rest.InClusterConfig()
        if err != nil {
            panic(err.Error())
        }
        // creates the clientset
        clientset, err := kubernetes.NewForConfig(config)
        if err != nil {
            panic(err.Error())
        }
    
        IP = ""
        for {
            if IP != "" {
                break
            } else {
                log.Printf("No IP for now.\n")
            }
    
            pods, err := clientset.CoreV1().Pods("default").List(metav1.ListOptions{})
            if err != nil {
                panic(err.Error())
            }
            for _, pod := range pods.Items {
                pod, _ := clientset.CoreV1().Pods("default").Get(pod.Name, metav1.GetOptions{})
                if pod.Name == os.Getenv("HOSTNAME") {
                    IP = pod.Status.PodIP
                }
            }
    
            log.Printf("Waits...\n")
            time.Sleep(1 * time.Second)
        }
    
        name = os.Getenv("HOSTNAME")
        log.Printf("Trying os.Getenv(\"HOSTNAME/IP\"): [%s][%s]\n", name, IP)
    
        return IP, name
    }