如何使用Kubernetes在一个Yaml文件中设置多个命令?


91

在此官方文档中,它可以在yaml配置文件中运行命令:

https://kubernetes.io/docs/tasks/configure-pod-container/

apiVersion: v1
kind: Pod
metadata:
  name: hello-world
spec:  # specification of the pod’s contents
  restartPolicy: Never
  containers:
  - name: hello
    image: "ubuntu:14.04"
    env:
    - name: MESSAGE
      value: "hello world"
    command: ["/bin/sh","-c"]
    args: ["/bin/echo \"${MESSAGE}\""]

如果我要运行多个命令,该怎么办?

Answers:


144
command: ["/bin/sh","-c"]
args: ["command one; command two && command three"]

说明:command ["/bin/sh", "-c"]说“运行shell,并执行下列指令”。然后将args作为命令传递到外壳。在shell脚本中,分号分隔命令,并&&在第一个成功的情况下有条件地运行以下命令。在上面的示例中,它始终运行,command one后跟command two,并且仅在以下command three情况下运行command two成功了。

替代方法:在许多情况下,您要运行的某些命令可能设置了要运行的最终命令。在这种情况下,构建自己的Dockerfile是必经之路。看看运行特别指令。


1
是的,非常有效,但是,我认为也有一些很好的用例可以扩展,command因为它覆盖了Dockerfile Entrypoint;)
Michael Hausenblas

1
关于如何在容器生命周期中做到这一点的任何想法?它没有参数
大约

1
@aclokay,您可以仅将参数指定为其他命令字符串。容器中命令和参数之间的分隔只是为了使覆盖参数更容易。它们在功能上是等效的。
蒂姆·阿克莱尔

-c在这里做什么?
阿卜杜勒

1
@Abdul意味着运行作为参数提供的脚本,而不是启动交互式Shell或从文件加载脚本。
蒂姆·阿克莱尔

68

我的首选是对args进行多行处理,这是最简单且最容易阅读的。此外,可以更改脚本而不会影响图像,只需要重新启动Pod。例如,对于mysql转储,容器规范可能是这样的:

containers:
  - name: mysqldump
    image: mysql
    command: ["/bin/sh", "-c"]
    args:
      - echo starting;
        ls -la /backups;
        mysqldump --host=... -r /backups/file.sql db_name;
        ls -la /backups;
        echo done;
    volumeMounts:
      - ...

之所以起作用,是因为yaml实际上将“-”之后的所有行连接为一个,并且sh运行了一个长字符串“ echo starting; ls ...; echo done;”。


很好,但是当您请求使用kubectl进行编辑时,它将再次在一行中。:)
sekrett

@sekrett哦,不!:(
aclokay

1
效果很好-关键是每行上的分号。当命令很多并且与上述解决方案多行时,这是一个特别好的解决方案。使git diff
变得

这就是我想要的。使用环境变量作为此解决方案的参数很好地工作。
吴敬鹏

1美丽的,再加上多行命令很好地工作:command: ['/bin/bash', '-c'] args: - exec &> /path/to/redirected/program.output;`蟒/ program.py``--key1 = val1``--key2 = val2``--key3 = val3`
nelsonspbr

44

如果您愿意使用Volume和ConfigMap,则可以将ConfigMap数据作为脚本安装,然后运行该脚本:

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-configmap
data:
  entrypoint.sh: |-
    #!/bin/bash
    echo "Do this"

    echo "Do that"
---
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: "ubuntu:14.04"
    command:
    - /bin/entrypoint.sh
    volumeMounts:
    - name: configmap-volume
      mountPath: /bin/entrypoint.sh
      readOnly: true
      subPath: entrypoint.sh
  volumes:
  - name: configmap-volume
    configMap:
      defaultMode: 0700
      name: my-configmap

这会稍微清理您的pod规范,并允许执行更复杂的脚本。

$ kubectl logs my-pod
Do this
Do that

1
非常酷,但是我认为使用内联脚本更为简单,只需使用多行语法即可。我在一个单独的答案中显示。
奥利弗

当我需要使用双引号怎么办?例如,假设以下命令:printf'%s @%s \ n'“ $(
echo'user

15

如果你想避免连接的所有命令到一个单一的命令;或者&&你也可以使用定界符得到真正的多行脚本:

command: 
 - sh
 - "-c"
 - |
   /bin/bash <<'EOF'

   # Normal script content possible here
   echo "Hello world"
   ls -l
   exit 123

   EOF

这对于运行现有的bash脚本很方便,但缺点是需要一个内部和一个外壳实例来设置heredoc。


2

恕我直言,最好的选择是使用YAML的本机块标量。具体地,在这种情况下,折叠样式块。

通过调用,sh -c您可以将参数作为命令传递给容器,但是如果您想用换行符将其优雅地分开,则需要使用折叠样式块,这样YAML就会知道将换行符转换为空格,从而有效地连接命令。

一个完整的工作示例:

apiVersion: v1
kind: Pod
metadata:
  name: myapp
  labels:
    app: myapp
spec:
  containers:
  - name: busy
    image: busybox:1.28
    command: ["/bin/sh", "-c"]
    args:
    - >
      command_1 &&
      command_2 &&
      ... 
      command_n

0

这是使用kubernetes在一个YAML文件中传递多个命令和参数的方法:

# Write your commands here
command: ["/bin/sh", "-c"]
# Write your multiple arguments in args
args: ["/usr/local/bin/php /var/www/test.php & /usr/local/bin/php /var/www/vendor/api.php"]

yaml文件中的完整容器阻止:

    containers:
      - name: widc-cron # container name
        image: widc-cron # custom docker image
        imagePullPolicy: IfNotPresent # advisable to keep
        # write your command here
        command: ["/bin/sh", "-c"]
        # You can declare multiple arguments here, like this example
        args: ["/usr/local/bin/php /var/www/tools/test.php & /usr/local/bin/php /var/www/vendor/api.php"]
        volumeMounts: # to mount files from config-map generator
          - mountPath: /var/www/session/constants.inc.php
            subPath: constants.inc.php
            name: widc-constants

0

只是为了带来另一个可能的选择,可以使用机密,因为这些机密将它们作为卷呈现给豆荚:

秘密范例:

apiVersion: v1
kind: Secret 
metadata:
  name: secret-script
type: Opaque
data:
  script_text: <<your script in b64>>

Yaml提取物:

....
containers:
    - name: container-name
      image: image-name
      command: ["/bin/bash", "/your_script.sh"]
      volumeMounts:
        - name: vsecret-script
          mountPath: /your_script.sh
          subPath: script_text
....
  volumes:
    - name: vsecret-script
      secret:
        secretName: secret-script

我知道许多人会争辩说这不是必须使用的秘密,而是一种选择。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.