Is it possible to execute kubectl commands via curl? - kubernetes

is it possible to execute kubectl commands as a curl by simply hitting GKE kube master api for some resources and get json back ?

Kubernetes is an entirely API-based system ,to interact with the Kubernetes API you need a ServiceAccount (obtained through a Cluster Role and a RoleBinding).
Here you can find the documentation for Google Kubernetes Engine API: https://cloud.google.com/kubernetes-engine/docs/reference/rest
Also as side note, might be usefully:
https://kubernetes.io/docs/tasks/administer-cluster/access-cluster-api/#accessing-the-kubernetes-api

Kubernetes is REST API based and can be called via curl.
https://kubernetes.io/docs/tasks/administer-cluster/access-cluster-api/#accessing-the-kubernetes-api
Kubectl internally does curl to Kubernetes API which can be verified via running below command and searching for curl and you can execute the same curl command. In the below example kubectl is using certificate for authentication and executing curl against Kubernetes API.
kubectl get nodes --v=10
curl -k -v -XGET -H "Accept: application/json;as=Table;v=v1beta1;g=meta.k8s.io, application/json" -H "User-Agent: kubectl/v1.17.0 (darwin/amd64) kubernetes/70132b0" 'https://127.0.0.1:32768/api/v1/nodes?limit=500'
But to call Kubernetes REST API you can either use a client certificate or a JWT bearer token. A service account which has a bearer token is the recommended way to communicate to Kubernetes API from a pod.
Kubernetes API.

Related

Kubernetes: How to get other pods' name from within a pod?

I'd like to find out the other pods' name running in the same single-host cluster. All pods are single-application containers. I have pod A (written in Java) that acts as a TCP/IP server and a few other pods (written in C++) connect to the server.
In pod A, I can get IP address of clients (other pods). How do I get their pods' name? I can't run kubectl commands because pod A has no kubectl installed.
Thanks,
You can directly call kube-apiserver with cURL.
First you need to have a serviceaccount binded to clusterrole to be able to send requests to apiserver.
kubectl create clusterrole listpods --verb=get,list,watch --resource=pods
kubectl create clusterrolebinding listpods --clusterrole=listpods --serviceaccount=default:default
Get a shell inside a container
kubectl exec -it deploy/YOUR_DEPLOYMENT -- sh
Define necessary parameters for your cURL, run below commands inside container
APISERVER=https://kubernetes.default.svc
SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace)
TOKEN=$(cat ${SERVICEACCOUNT}/token)
CACERT=${SERVICEACCOUNT}/ca.crt
Send pods list request to apiserver
curl -s -k -H "Authorization: Bearer $TOKEN" -H 'Accept: application/json' $APISERVER/api/v1/pods | jq "[ .items[] | .metadata.name ]"
Done ! It will return you a json list of "kubectl get pods"
For more examples, you can check OpenShift RestAPI Reference. Also, if you are planning to do some programmatic stuff, I advice you to checkout official kubernetes-clients.
Credits for jq improvement to #moonkotte

Minikube: kubectl doesn't use provided token permissions

Using minikube, when running the following command:
kubectl -v=11 --kubeconfig /dev/null --insecure-skip-tls-verify -s http://localhost:8001 --token "invalid" -n namespace get pods
I have an answer when I don't want one. And I don't know how it was authorized. Moreover, if I use a valid token with specific rights, these are not used.
kubectl --token=$TOKEN doesn't run with the permissions of the token doesn't answer my question as I specified to used /dev/null as a config file.
Any idea ?
I will try to summarize the answer I provided in the comments.
The question was: Why does running kubectl -s http://localhost:8001 --kubeconfig /dev/null --token <invalid_token> (where :8001 is a port opened by kubectl proxy) repoonds as if I was authorized, when it shouldn't beacause I set all possible authorization options to null or incorrect values?
The answer is that kubectl proxy opens a port and handles all authorization for you so you dont have to. Now to access REST api of kubernetes all you need to do is to use curl localhost:8001/.... No tokens and certificates.
Because you are already authorized with kubectl proxy, using kubectl and pointing it to localhost:8001 is causing that it won't need to authorize and you won't need any tokens to access k8s.
As an alternative you can check what happens when you run the same but instead of connecting through kubectl proxy you use kubernetes port directly.
You mentioned that you are using minikube so by default that would be port 8443
$ kubectl --kubeconfig /dev/null -s https://$(minikube ip):8443 --token "invalid" --insecure-skip-tls-verify get pods
error: You must be logged in to the server (Unauthorized)
As you see now it works as expected.

kubernetes restart all the pods using REST api

I need to update all the pods(rolling updates), with env variable changes
I am not using kubectl, but using REST api.
Right not i am deleting the service and pods; And then recreating both services and pods. (It usually take around minutes, and there is downtime). Wanted similar with rolling update, without downtime.
If you want to restart all pod attached to a deployment, then you can do that by running
$ curl -k --data '{"spec":{"template":{"metadata":{"annotations":{"kubectl.kubrnetes.io/restartedAt":"'"$(date +%Y-%m-%dT%T%z)"'"}}}}}' -XPATCH -H "Accept: application/json, */*" -H "Content-Type: application/strategic-merge-patch+json" localhost:8001/apis/extensions/v1beta1/namespaces/default/deployments/mydeployment
Use deployment instead of pods.
Deployment has DeploymentStrategy , maxUnavailable, maxSurge using which you can achieve zero downtime upgrade.
For changing env just change it the deployment yaml and apply it to the cluster. It will rollout the deployment without any downtime.
Kubectl internally calls rest api exposed by Kubernetes API Server. You could check what rest call being sent by kubectl by increasing the verbosity. Once you know the rest api being called you could call those apis as well.
kubectl rollout restart deployment/frontend -v=10

Rollout restart statefulset using kubectl proxy

I have started kubectl proxy from within my pods and am able to access kubernetes APIs. I have a need to restart my statefulset.
Using kubectl, I would done this:
kubectl rollout restart statefulset my-statefulset
However, I would like to do this using the REST APIs. For instance, I can delete my pods, using this:
curl -XDELETE localhost:8080/api/v1/namespaces/default/pods
Is there any equivalent REST endpoint that I can use to rollout restart a statefulset?
I run your command kubectl rollout restart statefulset my-statefulset --v 10 and notice the output logs.
I figured out kubectl makes a patch request when I apply above command. And I am able to do that patch request using curl like following
curl -k --data '{"spec":{"template":{"metadata":{"annotations":{"kubectl.kubrnetes.io/restartedAt":"'"$(date +%Y-%m-%dT%T%z)"'"}}}}}'\
-XPATCH -H "Accept: application/json, */*" -H "Content-Type: application/strategic-merge-patch+json"\
localhost:8080/apis/apps/v1/namespaces/default/statefulsets/my-statefulset

Kubernetes Engine API delete pod

I need to delete POD on my GCP kubernetes cluster. Actually in Kubernetes Engine API documentation I can find only REST api's for: projects.locations.clusters.nodePools, but nothing for PODs.
The GKE API is used to manage the cluster itself on an infrastructure level. To manage Kubernetes resources, you'd have to use the Kubernetes API. There are clients for various languages, but of course you can also directly call the API.
Deleting a Pod from within another or the same Pod:
PODNAME=ubuntu-xxxxxxxxxx-xxxx
curl https://kubernetes/api/v1/namespaces/default/pods/$PODNAME \
-X DELETE -k \
-H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
From outside, you'd have to use the public Kubernetes API server URL and a valid token. Here's how you get those using kubectl:
APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
TOKEN=$(kubectl get secret $(kubectl get serviceaccount default -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 --decode )
Here's more official information on accessing the Kubernetes API server.