将动态格式化的日期时间传递给 K8s 容器配置
Posted
技术标签:
【中文标题】将动态格式化的日期时间传递给 K8s 容器配置【英文标题】:Pass in Dynamic Formatted Datetime to K8s Container Config 【发布时间】:2020-01-30 20:14:53 【问题描述】:我有一个CronJob
,它在 Kubernetes 的容器中运行一个进程。
此过程采用由--since
和--until
标志定义的时间窗口。此时间窗口需要在容器启动时间(触发 cron 时)定义,并且是当前时间的函数。运行此过程的示例如下:
$ my-process --since=$(date -v -1H +"%Y-%m-%dT%H:%M:%SZ") --until=$(date -v +1H +"%Y-%m-%dT%H:%M:%SZ")
因此,对于上面的示例,我希望时间窗口从 1 小时前到未来 1 小时。 Kubernetes 中有没有办法将格式化的日期时间作为命令参数传递给进程?
我正在尝试做的一个示例是以下配置:
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: my-process
spec:
schedule: "*/2 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: my-process
image: my-image
args:
- my-process
- --since=$(date -v -1H +"%Y-%m-%dT%H:%M:%SZ")
- --until=$(date -v +1H +"%Y-%m-%dT%H:%M:%SZ")
执行此操作时,文字字符串 "$(date -v -1H +"%Y-%m-%dT%H:%M:%SZ")"
将作为 --since
标志传入。
这样的事情可能吗?如果是这样,我该怎么做?
【问题讨论】:
【参考方案1】:请注意,在您的CronJob
中,您不会运行bash
或任何其他shell,而command substitution
是一种shell 功能,没有它将无法工作。在您的示例中,容器中仅启动了一个命令 my-process
,并且由于它不是 shell,因此无法执行 command substitution
。
这个:
$ my-process --since=$(date -v -1H +"%Y-%m-%dT%H:%M:%SZ") --until=$(date -v +1H +"%Y-%m-%dT%H:%M:%SZ")
会正常工作,因为它是在 shell
中启动的,因此它可以利用 command substitution
等 shell 功能
一件事:date -v -1H +"%Y-%m-%dT%H:%M:%SZ"
在bash shell
中没有正确扩展,默认GNU/Linux
date
实现。其中-v
选项无法识别,所以我猜你是在MacOSX
或某种BSD
系统上使用它。在下面的示例中,我将使用适用于 Debian
的日期版本。
所以在GNU/Linux
上测试它会是这样的:
date --date='-1 hour' +"%Y-%m-%dT%H:%M:%SZ"
出于测试目的,我尝试使用来自this 示例的简单CronJob 进行了一些修改:
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: debian
env:
- name: FROM
value: $(date --date="-1 hour" +"%Y-%m-%dT%H:%M:%SZ")
- name: TILL
value: $(date --date="+1 hour" +"%Y-%m-%dT%H:%M:%SZ")
args:
- /bin/sh
- -c
- date; echo from $(FROM) till $(TILL)
restartPolicy: OnFailure
它工作正常。下面可以看到CronJob
执行的结果:
$ kubectl logs hello-1569947100-xmglq
Tue Oct 1 16:25:11 UTC 2019
from 2019-10-01T15:25:11Z till 2019-10-01T17:25:11Z
除了使用environment variables 的示例之外,我还使用以下代码对其进行了测试:
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: debian
args:
- /bin/sh
- -c
- date; echo from $(date --date="-1 hour" +"%Y-%m-%dT%H:%M:%SZ") till $(date --date="+1 hour" +"%Y-%m-%dT%H:%M:%SZ")
restartPolicy: OnFailure
正如您在此处看到的,command substitution
也可以正常工作:
$ kubectl logs hello-1569949680-fk782
Tue Oct 1 17:08:09 UTC 2019
from 2019-10-01T16:08:09Z till 2019-10-01T18:08:09Z
它可以正常工作,因为在这两个示例中首先我们在容器中生成bash shell
,然后随后它运行其他命令,就像它的参数一样简单的echo
。您可以使用my-process
命令代替echo
,只需在一行中提供它的所有参数,如下所示:
args:
- /bin/sh
- -c
- my-process --since=$(date -v -1H +"%Y-%m-%dT%H:%M:%SZ") --until=$(date -v +1H +"%Y-%m-%dT%H:%M:%SZ")
此示例不起作用,因为没有涉及 shell
。 echo
不是 shell 的命令将无法执行作为 shell 功能的命令替换:
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: debian
args:
- /bin/echo
- from $(date --date="-1 hour" +"%Y-%m-%dT%H:%M:%SZ") till $(date --date="+1 hour" +"%Y-%m-%dT%H:%M:%SZ")
restartPolicy: OnFailure
结果将是一个文字字符串:
$ kubectl logs hello-1569951180-fvghz
from $(date --date="-1 hour" +"%Y-%m-%dT%H:%M:%SZ") till $(date --date="+1 hour" +"%Y-%m-%dT%H:%M:%SZ")
这与您的命令类似,例如 echo
不是 shell
并且它无法执行 command substitution
。
总结一下:解决方案是将您的命令包装为 shell 参数。在前两个示例中,echo
命令与其他命令一起作为 shell 参数传递。
也许在下面的例子中可以更清楚地看到它,但语法有点不同:
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: debian
command: ["/bin/sh","-c"]
args: ["FROM=$(date --date='-1 hour' +'%Y-%m-%dT%H:%M:%SZ'); TILL=$(date --date='+1 hour' +'%Y-%m-%dT%H:%M:%SZ') ;echo from $FROM till $TILL"]
restartPolicy: OnFailure
man bash
说:
-c 如果存在 -c 选项,则从第一个非选项参数 command_string 中读取命令。
所以command: ["/bin/sh","-c"]
基本上意味着运行一个shell 并执行以下命令,然后我们使用args
将其传递给它。在bash
中,命令应该用分号;
分隔,以便它们独立运行(无论执行先前的命令/命令的结果如何,都会执行后续命令)。
在以下片段中:
args: ["FROM=$(date --date='-1 hour' +'%Y-%m-%dT%H:%M:%SZ'); TILL=$(date --date='+1 hour' +'%Y-%m-%dT%H:%M:%SZ') ;echo from $FROM till $TILL"]
我们向/bin/sh -c
提供三个单独的命令:
FROM=$(date --date='-1 hour' +'%Y-%m-%dT%H:%M:%SZ')
将FROM
环境变量设置为date --date='-1 hour' +'%Y-%m-%dT%H:%M:%SZ'
命令的执行结果,
TILL=$(date --date='+1 hour' +'%Y-%m-%dT%H:%M:%SZ')
将TILL
环境变量设置为date --date='+1 hour' +'%Y-%m-%dT%H:%M:%SZ'
命令的执行结果
最后我们运行
echo from $FROM till $TILL
使用这两个变量。
任何其他命令都可以做到这一点。
【讨论】:
以上是关于将动态格式化的日期时间传递给 K8s 容器配置的主要内容,如果未能解决你的问题,请参考以下文章