如何设置多个命令在一个 yaml 文件与 Kubernetes?

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

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}\""]

如果我想运行多个命令,如何做?

235365 次浏览
command: ["/bin/sh","-c"]
args: ["command one; command two && command three"]

解释: command ["/bin/sh", "-c"]说“运行一个 shell,执行以下指令”。然后将参数作为命令传递给 shell。在 shell 脚本中,分号分隔命令,如果第一个命令成功,则 &&有条件地运行以下命令。在上面的例子中,它总是运行 command onecommand two,并且只有在 command two成功的情况下才运行 command three

备选: 在许多情况下,您想要运行的一些命令可能正在设置要运行的最终命令。在这种情况下,构建您自己的 文件夹是可行的方法。特别要注意 快跑指令。

如果你愿意使用一个卷和一个配置图,你可以 挂载 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

我的偏好是多行的参数,这是最简单和最容易阅读。此外,脚本可以改变而不影响图像,只需要重新启动吊舱。例如,对于 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 start; ls... ; echo done;”。

如果您希望避免将所有命令与 ;&&连接成单个命令,您还可以使用 herdoc 获得真正的多行脚本:

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


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


EOF

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

另一个可能的选择是,当秘密以卷的形式呈现给吊舱时,可以使用它们:

秘密例子:

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

亚穆提取物:

....
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

我知道很多人会说这不是秘密的用途,但这是一种选择。

恕我直言,最好的选择是使用 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

这就是我的成功之路

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

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

我使用以下方法:

readinessProbe:
exec:
command:
- sh
- -c
- |
command1
command2 && command3

我知道我的示例与 readinessExplorer、 livenessExplorer 等相关,但是怀疑容器命令也是同样的情况。这提供了灵活性,因为它反映了用 Bash 编写的标准脚本。

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

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

这里还有一种方法可以做到这一点,即使用输出日志记录。

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: {}