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

sch*_*cho 58 yaml kubernetes

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

http://kubernetes.io/v1.1/docs/user-guide/configuring-containers.html

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}\""]
Run Code Online (Sandbox Code Playgroud)

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

Tim*_*air 108

command: ["/bin/sh","-c"]
args: ["command one; command two && command three"]
Run Code Online (Sandbox Code Playgroud)

说明:command ["/bin/sh", "-c"]说"运行shell,并执行下列指令".然后将args作为命令传递给shell.在shell脚本中,分号分隔命令,&&如果第一个成功,则有条件地运行以下命令.在上面的例子中,它始终运行command one之后command two,只运行command three,如果command two成功了.

备选方案:在许多情况下,您要运行的某些命令可能是设置要运行的最终命令.在这种情况下,构建自己的Dockerfile可行的方法.特别是看RUN指令.

  • 是的,非常有效,但是,我认为也有很好的用例来扩展 `command`,因为它覆盖了 Dockerfile 的 `Entrypoint` ;) (2认同)
  • @Abdul 这意味着运行作为参数提供的脚本,而不是启动交互式 shell 或从文件加载脚本。 (2认同)
  • 这对我来说毫无意义......`-c` 不是一个参数吗?那么为什么要把它放在“command”而不是“args”中呢?那么为什么不将所有内容都放在“command”中,因为这意味着“command”不必仅包含可执行文件,而且还可以添加参数......为什么还要费力将两者分开呢?为什么 `command: ["/bin/sh", "-c", "command one; command 2 && command Three""]` 不能像您的示例一样工作?如果您必须编写 `command : "/bin/sh"` 然后 `args: ["-c", "..."]` (2认同)

Oli*_*ver 39

我倾向于多行化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:
      - ...
Run Code Online (Sandbox Code Playgroud)

这样做的原因是yaml实际上将" - "之后的所有行连接成一个,并且sh运行一个长字符串"echo starting; ls ...; echo done;".

  • 这非常有效 - 关键是每行上的分号。当命令很多并且与上面的解决方案相比是多行时,这是一个特别好的解决方案。让 git diff 变得轻而易举 (4认同)

blu*_*e10 31

如果你想避免将所有命令连接成一个命令,;或者&&你也可以使用heredoc获得真正的多行脚本:

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

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

   EOF
Run Code Online (Sandbox Code Playgroud)

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


dhu*_*han 30

如果您愿意使用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
Run Code Online (Sandbox Code Playgroud)

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

$ kubectl logs my-pod
Do this
Do that
Run Code Online (Sandbox Code Playgroud)


小智 11

我不确定这个问题是否仍然有效,但由于我没有在上述答案中找到解决方案,我决定把它写下来。

我使用以下方法:

readinessProbe:
  exec:
    command:
    - sh
    - -c
    - |
      command1
      command2 && command3
Run Code Online (Sandbox Code Playgroud)

我知道我的示例与 readinessProbe、livenessProbe 等有关,但怀疑容器命令也是如此。这提供了灵活性,因为它反映了 Bash 中的标准脚本编写。


小智 10

这是运行多行命令的另一种方法。

apiVersion: batch/v1
kind: Job
metadata:
  name: multiline
spec:
  template:
    spec:
      containers:
      - command:
        - /bin/bash
        - -exc
        - |
          set +x
          echo "running below scripts"
          if [[ -f "if-condition.sh" ]]; then
            echo "Running if success"
          else
            echo "Running if failed"
          fi
        name: ubuntu
        image: ubuntu
      restartPolicy: Never
  backoffLimit: 1
Run Code Online (Sandbox Code Playgroud)


sun*_*un2 8

这是另一种方法,即输出日志记录。

apiVersion: v1
kind: Pod
metadata:
  labels:
    type: test
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx
    volumeMounts:
      - name: log-vol
        mountPath: /var/mylog
    command:
        - /bin/sh
        - -c
        - >
            i=0;
            while [ $i -lt 100 ];
            do
             echo "hello $i";
             echo "$i :  $(date)" >> /var/mylog/1.log;
             echo "$(date)" >> /var/mylog/2.log;
             i=$((i+1));
             sleep 1;
            done

  dnsPolicy: ClusterFirst
  restartPolicy: Always
  volumes:
    - name: log-vol
      emptyDir: {}
Run Code Online (Sandbox Code Playgroud)


pis*_*eek 7

恕我直言,最好的选择是使用 YAML 的原生块标量。特别是在这种情况下,折叠样式块。

通过调用,sh -c您可以将参数作为命令传递给您的容器,但是如果您想用换行符优雅地将它们分开,您需要使用folded style block,以便 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
Run Code Online (Sandbox Code Playgroud)

  • 无论如何,使用“kubectl edit”等编辑实时资源是一种反模式,也是一个坏主意。您的运行配置应始终与清单上写入的内容相匹配。这就是声明性配置和版本控制系统的用途。 (7认同)

小智 6

这是我成功的运行

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: busybox
  name: busybox
spec:
  containers:
  - command:
    - /bin/sh
    - -c
    - |
      echo "running below scripts"
      i=0; 
      while true; 
      do 
        echo "$i: $(date)"; 
        i=$((i+1)); 
        sleep 1; 
      done
    name: busybox
    image: busybox
Run Code Online (Sandbox Code Playgroud)