Execute a command on a particular container in cluster. From another container

11/30/2017

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:

  1. run a cronjob using busybox container,
  2. from within busybox container execute a script that will:

    1. determine the pod name where the execution must happen,
    2. 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:

      • my_namespace
      • my_pod_name
      • my_sh_command
      • my_container_name

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.

-- gmile
api
cron
curl
kubernetes

2 Answers

11/30/2017

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>
-- sfgroups
Source: StackOverflow

11/30/2017

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.

Using curl for Kubernetes API access

In 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).

Authenticating exec calls from within a Pod

If 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:

  1. 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.

  2. 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.

-- helmbert
Source: StackOverflow