在集群中的特定容器上执行命令。从另一个容器
Posted
技术标签:
【中文标题】在集群中的特定容器上执行命令。从另一个容器【英文标题】:Execute a command on a particular container in cluster. From another container 【发布时间】:2018-05-14 09:08:16 【问题描述】:在 kubernetes 中,我有一个容器 X。我想运行一个 cronjob,它在容器 X 中执行一个命令。
我有以下想法:
-
使用 busybox 容器运行 cronjob,
在busybox容器中执行一个脚本,它将:
-
确定必须执行的 pod 名称,
运行 curl,类似:
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
这里的动态值是:
我的命名空间 my_pod_name my_sh_command my_container_name我知道我可能应该使用令牌来访问 kubernetes API,但我不知道如何在 curl 中获取/使用该令牌。
是否可以使用curl
和 kubernetes API 来做到这一点?如果是,怎么做?
我想做这件奇怪的事情是有原因的。我有一个已编译的应用程序,可以识别 CLI 命令。我想运行一个特定的 CLI 命令,而无需通过 Web 服务器路由公开 CLI,随后将通过 k8s 服务访问该命令。
【问题讨论】:
【参考方案1】:您的一般方法(从容器内调用 Kubernetes API 上的 pod/exec
端点)对我来说似乎完全有效。总的来说,我认为需要考虑两个方面:1)如何使用 curl
与 Kubernetes API 进行通信,以及 2)如何在 Pod 中针对 API 进行身份验证。
使用curl
访问 Kubernetes API
一般来说,Kubernetes API 可以通过curl
轻松调用。但是,exec
端点是该规则的一个例外,因为 API 服务器将该端点上的连接升级为 SPDY 连接,curl
不支持这种连接(该主题甚至有一个discussion in the Kubernetes issue tracker)。出于这个原因,我建议使用 kubectl(正如 @sfgroups 已经建议的那样)或使用其中一个客户端 SDK(例如,Go 或 Python 的)。
验证来自 Pod 内的 exec
调用
如果您在 Pod(或任何客户端 SDK,甚至 curl)中使用 kubectl,则需要针对 API 服务器进行身份验证。为此,您的 Pod 需要与 服务帐户 相关联,并且该服务帐户需要被授权调用 /pods/pod/exec
端点。这是如何工作的,很大程度上取决于您的集群配置:
在许多集群配置中,默认情况下,您的 Pod 可能已经与服务帐户关联(具有足够的授权)。在 Pod 中,您将在 /var/run/secrets/kubernetes.io/serviceaccount
目录中找到凭据。 kubectl
和常见的客户端 SDK 都会自动找到这个目录,允许它们“正常工作”而无需任何额外配置。使用 curl,您需要从该目录中的 token
文件中提取身份验证令牌,并在 Authorization: Bearer <token>
标头中使用它。
如果您的 Pod 是使用 automountServiceAccountToken: false
属性创建的,则它可能没有收到服务帐户令牌。
如果您的集群配置为to use RBAC,您的 Pod 可能仍与一个 Service Account 关联,但该帐户可能无权在其他 Pod 中执行命令。要授予访问权限,您可以创建自己的角色来授予所需的权限,然后创建服务帐户和 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
然后,使用 PodSpec 中的 serviceAccountName: cron
属性将您的 cron runner pod 与新创建的服务帐户相关联。
【讨论】:
【参考方案2】:我认为我们不能使用 curl 命令触发。另一种选择是在 pod 上安装 kubectl 并使用 kubectl exec 命令运行脚本。
./kubectl exec <POD> -- <script>
【讨论】:
以上是关于在集群中的特定容器上执行命令。从另一个容器的主要内容,如果未能解决你的问题,请参考以下文章