首页 > 解决方案 > 在所有 pod 中运行特定命令

问题描述

我想知道是否可以在所有现有 pod(包括不在默认命名空间中的 pod)中的特定时间运行特定命令(例如:echo "foo")。它就像一个 cronJob,但唯一的区别是我只想在一个地方指定/部署它。这甚至可能吗?

标签: kuberneteskubernetes-pod

解决方案


有可能的。请找到我遵循的步骤,希望对您有所帮助。

首先,创建一个简单的脚本来读取 pod 的名称,exec然后执行命令。

import os, sys
import logging
from datetime import datetime

logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)

dt = datetime.now()
ts = dt.strftime("%d-%m-%Y-%H-%M-%S-%f")

pods = os.popen("kubectl get po --all-namespaces").readlines()

for pod in pods:
    ns = pod.split()[0]
    po = pod.split()[1]

    try:
        h = os.popen("kubectl -n %s exec -i %s sh -- hostname" %(ns, po)).read()
        os.popen("kubectl -n %s exec -i %s sh -- touch /tmp/foo-%s.txt" %(ns, po, ts))
        logging.debug("Executed on %s" %h)
    except Exception as e:
        logging.error(e) 

接下来,Dockerize 上面的脚本,构建和推送。

FROM python:3.8-alpine

ENV KUBECTL_VERSION=v1.18.0

WORKDIR /foo

ADD https://storage.googleapis.com/kubernetes-release/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl .

RUN chmod +x kubectl &&\
    mv kubectl /usr/local/bin

COPY foo.py .

CMD ["python", "foo.py"]

稍后我们将在 CronJob 中使用此图像。你可以看到我已经在 Dockerfile 中安装了 kubectl 来触发 kubectl 命令。但这还不够,我们应该将clusterole和添加clusterrolebinding到运行 CronJob 的服务帐户中。

我创建了一个 nsfoo并将 foo 的默认服务帐户绑定到我创建的集群角色,如下所示。

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: foo
rules:
- apiGroups: [""]
  resources: ["pods", "pods/exec"]
  verbs: ["get", "list", "create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: foo
subjects:
- kind: ServiceAccount
  name: default
  namespace: foo
roleRef:
  kind: ClusterRole
  name: foo
  apiGroup: rbac.authorization.k8s.io

现在服务帐户默认值 foo 有权访问get, list, exec集群中的所有 pod。

最后创建一个 cronjob 来运行任务。

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: foo
spec:
  schedule: "15 9 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: foo
            image: harik8/sof:62177831
            imagePullPolicy: Always
          restartPolicy: OnFailure

登录到 pod 并检查,它应该在/tmp每个 pod 的目录中创建了带有时间戳的文件。

$ kubectl exec -it app-59666bb5bc-v6p2h sh           
# ls -lah /tmp          
-rw-r--r--  1 root root    0 Jun  4 09:15 foo-04-06-2020-09-15-06-792614.txt

日志

error: cannot exec into a container in a completed pod; current phase is Failed
error: cannot exec into a container in a completed pod; current phase is Succeeded
DEBUG:root:Executed on foo-1591262100-798ng

DEBUG:root:Executed on grafana-5f6f8cbf75-jtksp

DEBUG:root:Executed on istio-egressgateway-557dcf8d8-npfnd

DEBUG:root:Executed on istio-ingressgateway-6489d9556d-2dp7j

command terminated with exit code 126
DEBUG:root:Executed on OCI runtime exec failed: exec failed: container_linux.go:349: starting container process caused "exec: \"hostname\": executable file not found in $PATH": unknown

DEBUG:root:Executed on istiod-774777b79-mvmqm

推荐阅读