How to get another pod name from it's IP? - kubernetes

I have a pod that exposes a port (Server). Other pods (Clients) can communicate with it.
The server can find remote IP and port on a socket (when the client connects to it). I am looking for a way to get the client's pod name (from its IP and port).
I saw a bunch of questions/answers about getting pod names via kubectl. However, I am not sure whether I can do kubectl from within a cluster itself.
I am trying to figure out what is available for something running on the cluster. It's ok if it requires some special privileges. It's more complicated if it requires authentication.

List all the Pods with the List Pods API operation and parse the JSON response for the podIP field (e.g. with jq or some other JSON parsing tool) to find the JSON object of the Pod that has your desired IP address. Then, extract the metadata.name field from this JSON object to get the name of the Pod.
You can do this by either directly using the Kubernetes API (e.g. with curl) or with kubectl (e.g. kubectl get pods -o json | jq ...). In any case, you must include in this request the ServiceAccount token of the ServiceAccount used by the Pod from which you are issuing the request (if you use the Kubernetes API directly, as a Bearer token in the Authorization header, and if you use kubectl with the --token command-line flag).
Regarding authorisation, you need a Role allowing the list verb on the pods resource and a RoleBinding that binds this Role to the ServiceAccount that your Pod is using (by default, Pods use a ServiceAccount named default in their namespace, but you can specify a custom ServiceAccount with the serviceAccountName field of the Pod).

Whatever can be done via kubectl can be done via direct requests to the API server as well. All you need is to have proper ServiceAccount set up for your pod. Once you have it - you use can plenty of libraries dedicated for communication with k8s API server.

Related

kubectl get nodes from pod (NetworkPolicy)

I try to run using Python kubectl to get nodes inside the POD.
How I should set up a Network Policy for this pod?
I tried to connect my namespace to the kube-system namespace, but it was not working.
Thanks.
As per Accessing the API from a Pod:
The recommended way to locate the apiserver within the pod is with the
kubernetes.default.svc DNS name, which resolves to a Service IP which
in turn will be routed to an apiserver.
The recommended way to authenticate to the apiserver is with a service
account credential. By kube-system, a pod is associated with a service account, and a credential (token) for that service account is placed into the filesystem tree of each container in that pod, at /var/run/secrets/kubernetes.io/serviceaccount/token.
All you need is a service account with enough privileges, and use the API server DNS name as stated above. Example:
# Export the token value
export TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
# Use kubectl to talk internally with the API server
kubectl --insecure-skip-tls-verify=true \
--server="https://kubernetes.default.svc:443" \
--token="${TOKEN}" \
get nodes
The Network Policy may be restrictive and prevent this type of call, however, by default, the above should work.

get vs. list in Kubernetes RBAC

What is the difference between the get and list RBAC verbs?
All I could find in the the documentation is this:
"get (for individual resources), list (for collections, including full object content)", which I find severely lacking. Is list a superset of get, meaning if you have list permissions can you fetch all the information from get and more? While we're at it, what about watch? Does it only give permissions to read the change stream but not full object?
In practice, you can get all of the information you'd normally get out of get calls through list calls. However, having permission to list a resource doesn't mean get calls will work. You still have to use list calls and extract the information that way.
watch is a special verb that gives you permission to see updates on resources in real time. Having watch access without list or get is not very helpful because you won't be able to view the resource after it updates. Through kubectl, I was unable to watch a resource without having the get access to that resource.
To play around with these roles, I'd recommend messing around with roles in a Kubernetes cluster on Katacoda.
Initial setup to make roles and grant them to (fake) users:
kubectl create role deployment-getter --verb=get --resource=deployment
kubectl create role deployment-lister --verb=list --resource=deployment
kubectl create role deployment-watcher --verb=watch --resource=deployment
kubectl create rolebinding only-get --role=deployment-getter --user=only-get
kubectl create rolebinding only-list --role=deployment-lister--user=only-list
kubectl create rolebinding only-watch --role=deployment-watcher--user=only-list
kubectl run nginx --image=nginx # Make a resource to look at
Then you can run kubectl commands as one of the special users to see what limited RBAC permissions look like.
For example, the following commands show that we can only list resources with the list verb.
kubectl get deployment --as list-only # Prints out nginx deployment
kubectl get deployment --as get-only # RBAC error
kubectl get deployment --as watch-only # RBAC error
And this example shows that we can only get resources with the get verb (but you can get similar information by listing resources too).
kubectl get deployment nginx --as get-only -o yaml
# apiVersion: extensions/v1beta1
# kind: Deployment
# ...
kubectl get deployment nginx --as list-only -o yaml # RBAC error
kubectl get deployment --as list-only -o yaml
# apiVersion: v1
# kind: List
# items:
# - apiVersion: extensions/v1beta1
# kind: Deployment
# ...
The get, list, and watch RBAC verbs grant permissions for different Kubernetes API operations.
You can see the corresponding API operations for each object in the Kubernetes API reference, for example, here for the Deployment.
Here are some examples:
get
If you have the get permissions on the Deployment resource, you are allowed to execute the following API request:
GET /apis/apps/v1/namespaces/{namespace}/deployments/{name}
It returns the manifest of a specific Deployment.
list
If you have the list permission, you are allowed to execute these API requests:
GET /apis/apps/v1/namespaces/{namespace}/deployments
GET /apis/apps/v1/deployments
They both return a list of manifests of Deployments. The former, of all Deployments in a specific namespace, and the latter of all Deployments across all namespaces.
watch
If you have the watch permission, you are allowed to execute these API requests:
GET /apis/apps/v1/deployments?watch=true
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments?watch=true
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments/{name} [DEPRECATED]
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments [DEPRECATED]
GET /apis/apps/v1/watch/deployments [DEPRECATED]
They open a streaming connection that returns you the full manifest of a Deployment whenever it changes (or when a new one is created).
Note that the latter three API endpoints are deprecated, and you should use the endpoints for the list operation with a watch=true parameter instead. However, this still triggers the watch API operation and not list.
Note 1
Commands like kubectl get, kubectl list, etc. just executes these API requests under the hood. For experimentation, you can execute these API requests directly.
For example, first do:
kubectl proxy
And then:
curl localhost:8001/apis/apps/v1/deployments?watch=true
Or, you can also use this (doesn't require kubectl proxy):
kubectl get --raw="/apis/apps/v1/deployments?watch=true"
Note 2
In general, the permission don't imply each other. For example, if you have list permissions, it doesn't mean you can do get or watch requests, and if you have watch permissions, it doesn't mean you can do get or list requests.
Note 3
If you have only watch permissions (but not get and list), you can't watch with kubectl (kubectl get deployment -w) because kubectl makes a get and list request, respectively, before the watch request (to get the resource versions of the watched resources).
More examples in this answer.

Get IP addresses of all k8s pods from within a container

I have a service called my-service with an endpoint called refreshCache. my-service is hosted on multiple servers, and occasionally I want an event in my-service on one of the servers to trigger refreshCache on my-service on all servers. To do this I manually maintain a list of all the servers that host my-service, pull that list, and send a REST request to <server>/.../refreshCache for each server.
I'm now migrating my service to k8s. Similarly to before, where I was running refreshCache on all servers that hosted my-service, I now want to be able to run refreshCache on all the pods that host my-service. Unfortunately I cannot manually maintain a list of pod IPs, as my understanding is that IPs are ephemeral in k8s, so I need to be able to dynamically get the IPs of all pods in a node, from within a container in one of those pods. Is this possible?
Note: I'm aware this information is available with kubectl get endpoints ..., however kubectl will not be available within my container.
For achieving this the best way would be to use a K8s config inside the pod.
For this the K8s Client can help. Here is an example python script that can be used to get pods and their metadata from inside the pod.
from kubernetes import client, config
def trigger_refresh_cache():
# it works only if this script is run by K8s as a POD
config.load_incluster_config()
v1 = client.CoreV1Api()
print("Listing pods with their IPs:")
ret = v1.list_pod_for_all_namespaces(label_selector='app=my-service')
for i in ret.items:
print("%s\t%s\t%s" %
(i.status.pod_ip, i.metadata.namespace, i.metadata.name))
# Rest of the logic goes here to trigger endpoint
Here the method load_incluster_config() is used which loads the kubeconfig inside pod via the service account attached to that pod.
You don't need kubectl to access the Kubernetes API. You can do it with any tool that can make HTTP requests.
The Kubernetes API is a simple HTTP REST API, and all the authentication information that you need is present in the container if it runs as a Pod in the cluster.
To get the Endpoints object named my-service from within a container in the cluster, you can do:
curl -k -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
https://kubernetes.default.svc:443/api/v1/namespaces/{namespace}/endpoints/my-service
Note: replace {namespace} with the namespace of the my-service Endpoints resource.
And to extract the IP addresses of the returned JSON, you could pipe the output to a tool like jq:
... | jq -r '.subsets[].addresses[].ip'
Note that the Pod from which you are executing this needs read permissions for the Endpoints resource, otherwise the API request is denied.
You can do this with a ClusterRole, ClusterRoleBinding, and Service Account (you need to set this up only once):
kubectl create sa endpoint-reader
kubectl create clusterrole endpoint-reader --verb=get,list --resource=endpoints
kubectl create clusterrolebinding endpoint-reader --serviceaccount=default:endpoint-reader --clusterrole=endpoint-reader
Then, use the endpoint-reader ServiceAccount for the Pod from which you want to execute the above curl command by specifying it in the pod.spec.serviceAccountName field.
Granting permissions for any other API operations (i.e. combinations of verbs and resources) works in the same way.

How to get creator information about particular resource from kubectl get or describe command

I want to know who create pod from kubectl get or describe command.
Can I insert this field into Pod? or Custom Resource Definition?
Please help.
when I access to kubernetes cluster as user 'Alice' and create pod 'sample-pod'
I want to see as follows when exec 'kubectl get pod sample-pod' command.
NAME READY STATUS RESTARTS AGE CREATEUSER
sample-pod 1/1 Running 0 10s Alice
I assume that the information about authenticated Kubernetes users is not included in the general API reference list for Pod core schema objects. Therefore, it's not possible to retrieve user data from Pod specification. Actually, you might try to use Service accounts that granted to manage Kubernetes API via RBAC mechanism, in that way you can create a particular SA in namespace related to a specific user, and use it for any resource Kubernetes creation purpose. Although the information about SA name for specific resource propagated through .spec.serviceAccountName field in relevant object configuration template, you can invoke it using custom-columns= option in kubectl get command:
kubectl get pods -o custom-columns=NAME:.metadata.name,SERVICE_ACCOUNT:.spec.serviceAccountName
kubectl get pods -n -o yaml will give the pod definition. you can edit and use it for deploying pods.

How to make a service can access via the service proxy running at the master in kubernetes

How to make a service can access via the service proxy running at the master in kubernetes ?
like service of kube-ui or fluentd-elasticsearch in example. can access the url: http://[masterIP:post]/api/v1/proxy/namespaces/kube-system/services/kube-ui/
I can not access http://[masterIP:post]/api/v1/proxy/namespaces/test/services/myweb, when I create a service in the test namespace named myweb.
So how to do ?
If you're trying to access it from a pod running in the cluster, you're best off just accessing the service directly. Services are made available using DNS within the cluster. If your pod is in the same namespace as the service, you should be able to access it simply using its name, e.g. at myweb in this case. If your pod is in a different namespace, you can hit it at pod-name.namespace, e.g. myweb.test in this case.
If you're trying to access it from outside the cluster, then you shouldn't need to do anything different than you do for the default services. If you're unable to access it in the same way, it's likely that your service doesn't have any pods backing it, or that those pods aren't working. You can check which pods are backing your service using kubectl get endpoints myweb --namespace=test. If that's empty, then you should make sure you've scheduled the pods that are meant to implement the service, and if so, that their labels are correct.
You might find the documentation on services useful.