通过&&掌舵

时间:2020-01-29 20:40:41

标签: kubernetes-helm

我为Django应用程序提供了以下Helm Job,以运行迁移并收集静态文件:

apiVersion: batch/v1
kind: Job
metadata:
  name: django-app-job
  labels:
    app.kubernetes.io/name: django-app-job
    helm.sh/chart: django-app
    app.kubernetes.io/instance: staging-admin
    app.kubernetes.io/managed-by: Tiller
  annotations:
    "helm.sh/hook": pre-install,pre-upgrade
    "helm.sh/hook-weight": "1"
    "helm.sh/hook-delete-policy": hook-succeeded,hook-failed
spec:
  template:
    metadata:
      labels:
        app.kubernetes.io/name: django-app-job
        app.kubernetes.io/instance: foobar
    spec:
      restartPolicy: OnFailure
      containers:
        - name: django-app
          command:
          - "/bin/bash"
          - "-c"
          - "python3 ./manage.py migrate"
          - "&&"
          - "python3 ./manage.py collectstatic --noinput"

但这仅执行迁移以更新数据库模式,但从不运行collect static。即使迁移运行正常。这项工作不会失败,因为如果升级失败,那升级就不会失败。

但是如果我将命令更改为此:

      containers:
        - name: django-app
          command:
          - "/bin/bash"
          - "-c"
          - "python3 ./manage.py migrate && python3 ./manage.py collectstatic --noinput"

现在,作业将运行迁移并收集静态数据。这两个命令有什么区别?

1 个答案:

答案 0 :(得分:2)

从根本上来说,所有Unix命令实际上都是按单词序列执行的。通常情况下,shell会为您将命令行分割成多个单词,但是在Kubernetes清单中,您必须一次手动指定一个单词。

在您的示例中,Bourne shell sh -c option仅读取下一个单词,并应用正常的shell规则将其作为命令执行。如果该命令碰巧使用了$1之类的变量,则所有剩余的单词都将用作位置参数。

您可以在本地Shell的Kubernetes外部进行演示,使用引号强制Shell分解所需的单词:

# Option one
'/bin/sh' '-c' 'echo foo' '&&' 'echo bar'
# Prints "foo"

# Option two
'/bin/sh' '-c' 'echo foo && echo bar'
# Prints "foo", "bar"

经常出现的一个技巧是使用YAML block scalars在多行中编写单个字符串,从而提供类似于shell脚本的内容,但实际上并非如此。

command: ['/bin/sh', '-c']
args: >-
  python3 ./manage.py migrate
  &&
  python3 ./manage.py collectstatic --noinput