将动态格式的日期时间传递给K8s容器配置

时间:2019-10-01 14:00:21

标签: kubernetes containers kubernetes-cronjob

我有一个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 个答案:

答案 0 :(得分:0)

请注意,在您的CronJob中,您不会运行bash或任何其他Shell,而command substitution是一种Shell功能,没有任何功能将无法运行。在您的示例中,仅一个命令my-process在容器中启动,并且由于它不是外壳程序,因此无法执行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涉及。 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 不是shell的命令将无法执行命令替换,这是shell的功能:

$ 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,并且无法执行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

command: ["/bin/sh","-c"]说:

  

-c如果存在-c选项,那么将从第一个非选项参数command_string中读取命令。

所以args基本上意味着运行一个shell并执行以下命令,然后我们使用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 命令的结果

最后我们运行

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim xRg01, xRgSel01, xRg02, xRgSel02 As Range
    Dim xOutApp As Object
    Dim xMailItem As Object
    Dim xMailBody, xFolderPath As String
    'On Error Resume Next
    '---------------------------------
    'get workbook path
    xFolderPath = ActiveWorkbook.Path
    '---------------------------------
    'Deal with first range
    Set xRg01 = Range("D5:D10")
    Set xRgSel01 = Intersect(Target, xRg01)
    If Not xRgSel01 Is Nothing Then
        ActiveWorkbook.Save
        Set xOutApp = CreateObject("Outlook.Application")
        Set xMailItem = xOutApp.CreateItem(0)
        xMailBody = "Hello," & vbCrLf & vbCrLf & "Cell D" & Target.Row & " has been changed, to value [" & Target.Value & "]." & vbCrLf & vbCrLf & "Workbook path:" & xFolderPath
        With xMailItem
            .To = "email@email.com"
            .Subject = "Subject for xRg01"
            .Body = xMailBody
            .Display
        End With
    End If
    '---------------------------------
    'Deal with the second range
    Set xRg02 = Range("D12:D20")
    Set xRgSel02 = Intersect(Target, xRg02)
    If Not xRgSel02 Is Nothing Then
        ActiveWorkbook.Save
        Set xOutApp = CreateObject("Outlook.Application")
        Set xMailItem = xOutApp.CreateItem(0)
        xMailBody = "Hello," & vbCrLf & vbCrLf & "Cell D" & Target.Row & " has been changed, to value [" & Target.Value & "]." & vbCrLf & "Workbook path:" & xFolderPath
        With xMailItem
            .To = "another.email@email.com"
            .Subject = "Subject for xRg02"
            .Body = xMailBody
            .Display
        End With
    End If
    '---------------------------------
        Set xRg01 = Nothing
        Set xRgSel01 = Nothing
        Set xRg02 = Nothing
        Set xRgSel02 = Nothing
        Set xOutApp = Nothing
        Set xMailItem = Nothing
End Sub

使用两个变量。

可以使用其他任何命令完全相同。