In a kubernetes I have a container X. I'd like to run a cronjob, that executes a command within a container X.
I have the following idea in mind:
from within busybox container execute a script that will:
run curl, something like:
curl https://35.187.120.184/api/v1/namespaces/my_namespace/pods/my_pod_name/exec?command=my_sh_command&container=my_container_name&stdin=true&stdout=true&tty=true
Dynamic values here are:
I know I should probably use a token to access kubernetes API, but I can't figure out how to obtain / use that token in curl.
Is it possible to do that using curl
and kubernetes API? If yes, how?
There's a reason I want to do this weird thing. I have a compiled app, that recognizes CLI commands. I want to run a particular CLI command, without the hassle of exposing the CLI via a web-server route, that'd be subsequently accessed via k8s service.
I don't think we can trigger using curl command. one other option is to install the kubectl on the pod and use kubectl exec command to run the script.
./kubectl exec <POD> -- <script>
Your general approach (calling the {pod}/exec
endpoint on the Kubernetes API from within your container) seems totally valid to me. In general, I see two aspects to consider, here: 1) how to use curl
to communicate with the Kubernetes API, and 2) how to authenticate against the API from within a Pod.
curl
for Kubernetes API accessIn general, the Kubernetes API is easily callable via curl
. However, the exec
endpoint is an exception to that rule, since the API server upgrades connections on that endpoint to an SPDY connection, which is not supported by curl
(there even is a discussion in the Kubernetes issue tracker on that topic). For that reason, I'd recommend using kubectl (as already suggested by @sfgroups) or using one of the client SDKs (like for example, the Go or Python ones).
exec
calls from within a PodIf you are using kubectl from within a Pod (or any of the client SDKs, or even curl, for that matter), you will need to authenticate against the API server. For this, your Pod needs to be associated with a Service Account, and that Service Account needs to be authorized to call the /pods/{pod}/exec
endpoint. How this works, is largely dependent on your cluster configuration:
In many cluster configurations, your Pod may have already been associated with a Service Account (with sufficient authorization) by default. In the Pod, you will find the credentials in the /var/run/secrets/kubernetes.io/serviceaccount
directory. Both kubectl
and the common client SDKs will find this directory automatically, allowing them to "just work" without any additional configuration. Using curl, you will need to extract the authentication token from the token
file within that directory and use it in an Authorization: Bearer <token>
header.
Your Pod may not have received a Service Account token, if it was created with the automountServiceAccountToken: false
property.
If your cluster is configured to use RBAC, your Pod may still be associated with a Service Account, but that account may not be authorized to execute commands in other Pods. To grant access, you can create your own Role that grants the required rights, and then create a Service Account and a RoleBinding:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-exec
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
- apiGroups: [""]
resources: ["pods/exec]
verbs: ["create"]
---
kind: ServiceAccount
apiVersion: v1
metadata:
name: cron
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: cron
subjects:
- kind: ServiceAccount
name: cron
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-exec
apiGroup: rbac.authorization.k8s.io
Then, use the serviceAccountName: cron
attribute in your PodSpec to associate your cron runner pod with the newly created Service Account.