如果你想将 k8s 的 pod 从 Completed 状态改为 running 状态,可以执行 “tail -f /dev/null” 的命令
你好,我是Class Act Infrastructure事业部的大塚先生。
我之前在以下文章中描述了使用我的自制DockerImage部署pod时,状态会自动变为Completed并想要解决这个问题的事情。最后发现pod内没有进程是造成这个问题的原因,并在下面的文章中通过在pod内的容器中运行apache2进程来避免这个问题。然而,这个解决方案相当微妙。
而且每次都需要手动访问pod内的容器,进一步增加了微妙性。每次访问都相当麻烦。
这次我将尝试解决这个微妙的问题。
在pod的容器内运行tail -f /dev/null似乎是个不错的选择。我不记得在哪里看到的了,但是为了故意保留进程,对/dev/null使用tail -f似乎是个绝佳的选择?至少比之前我安装和运行apache2要好得多。
关于/dev/null,请参考以下内容。可以将其类比为Windows中的垃圾箱,这样理解应该没错吧?严格来说并不准确。
在使用kubectl run命令部署pod时,同时在容器内执行命令的方法。如果在kubectl run命令的选项中指定”–command”可能会很好。
以下是执行结果。可以看出get pod的输出结果为running。
root@sv-ohtsuka-k8s-master:~# kubectl run --restart=Never --image=shotaohtsuka/deb-ubuntu-image:latest testpod --command -- tail -f /dev/null
pod/testpod created
root@sv-ohtsuka-k8s-master:~# kubectl get pod
NAME READY STATUS RESTARTS AGE
testpod 1/1 Running 0 81s
root@sv-ohtsuka-k8s-master:~# kubectl run --restart=Never --image=shotaohtsuka/deb-ubuntu-image:latest testpod --command -- tail -f /dev/null
pod/testpod created
root@sv-ohtsuka-k8s-master:~# kubectl get pod
NAME READY STATUS RESTARTS AGE
testpod 1/1 Running 0 81s
我看了一下容器中的进程,发现有一个正在运行的tail -f进程。
即使从容器中退出,它仍然保持运行状态。
感觉还不错。
root@sv-ohtsuka-k8s-master:~# kubectl exec -it testpod -- /bin/bash
root@testpod:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 08:02 ? 00:00:00 tail -f /dev/null
root 7 0 0 08:04 pts/0 00:00:00 /bin/bash
root 18 7 0 08:04 pts/0 00:00:00 ps -ef
root@testpod:/# exit
exit
root@sv-ohtsuka-k8s-master:~# kubectl get pod
NAME READY STATUS RESTARTS AGE
testpod 1/1 Running 0 2m6s
使用yaml文件部署pod时,在容器中同时执行命令的方法。这次准备的YAML文件如下:
创建名为deb-ubuntu的Pod,并在内部部署deb-ubuntu-container容器的指示非常简洁。
容器使用的是我自己制作的镜像”shotaohtsuka/deb-ubuntu-image”,它位于Docker Hub上。
在command部分,我们指定了在启动容器时要一起执行的命令。一旦理解了这种写法,就会觉得合理,但一开始可能会有些困惑。如果以”tail -f /dev/null”的方式编写,Pod会报错无法部署。
我们可以把它分解成”tail”、”-f”和”/dev/null”这三个元素进行分隔。
root@sv-ohtsuka-k8s-master:~/k8s_yaml# cat deb-ubuntu.yaml
apiVersion: v1
kind: Pod
metadata:
name: deb-ubuntu
labels:
role: debug
spec:
containers:
- name: deb-ubuntu-container
image: shotaohtsuka/deb-ubuntu-image
command: ['tail', '-f', '/dev/null']
root@sv-ohtsuka-k8s-master:~/k8s_yaml# cat deb-ubuntu.yaml
apiVersion: v1
kind: Pod
metadata:
name: deb-ubuntu
labels:
role: debug
spec:
containers:
- name: deb-ubuntu-container
image: shotaohtsuka/deb-ubuntu-image
command: ['tail', '-f', '/dev/null']
我将根据这个yaml文件部署一个Pod。看起来可以成功启动。
root@sv-ohtsuka-k8s-master:~/k8s_yaml# kubectl create -f deb-ubuntu.yaml
pod/deb-ubuntu created
root@sv-ohtsuka-k8s-master:~/k8s_yaml# kubectl get pod
NAME READY STATUS RESTARTS AGE
deb-ubuntu 1/1 Running 0 63s
我将尝试访问POD内的容器。
看起来没有问题。
root@sv-ohtsuka-k8s-master:~/k8s_yaml# kubectl exec -it deb-ubuntu -c deb-ubuntu-container -- /bin/bash
root@deb-ubuntu:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 08:51 ? 00:00:00 tail -f /dev/null
root 7 0 0 08:53 pts/0 00:00:00 /bin/bash
root 16 7 0 08:53 pts/0 00:00:00 ps -ef

关于如何在2023/5/13后追加到yaml文件的描述方式。以下是另一种在spec.containers.command中进行编写的方式,请添加并整理。
命令中将所有内容写在一个地方。这与上述所写的是一样的。
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-patt01
labels:
role: debug
spec:
containers:
- name: ubuntu-patt01
image: ubuntu:latest
command: [ "tail", "-f", "/dev/null" ]
将所有内容都写在命令行中的2号模式
用与模式①相同的方式写如下则意思相同。
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-patt02
labels:
role: debug
spec:
containers:
- name: ubuntu-patt02
image: ubuntu:latest
command:
- "tail"
- "-f"
- "/dev/null"
将第三种模式分为命令和参数进行编写。args是”arguments”的缩写。
“arguments”在英语中意味着”参数”。(顺便说一下,”argument”则意味着”争论”,完全不同,所以要注意)
明确指明tail命令的参数是”-f”和”/dev/null”,我个人认为这样是最清晰易懂的。
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-patt03
labels:
role: debug
spec:
containers:
- name: ubuntu-patt03
image: ubuntu:latest
command: [ "tail" ]
args: ["-f", "/dev/null" ]
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-patt01
labels:
role: debug
spec:
containers:
- name: ubuntu-patt01
image: ubuntu:latest
command: [ "tail", "-f", "/dev/null" ]
将所有内容都写在命令行中的2号模式
用与模式①相同的方式写如下则意思相同。
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-patt02
labels:
role: debug
spec:
containers:
- name: ubuntu-patt02
image: ubuntu:latest
command:
- "tail"
- "-f"
- "/dev/null"
将第三种模式分为命令和参数进行编写。args是”arguments”的缩写。
“arguments”在英语中意味着”参数”。(顺便说一下,”argument”则意味着”争论”,完全不同,所以要注意)
明确指明tail命令的参数是”-f”和”/dev/null”,我个人认为这样是最清晰易懂的。
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-patt03
labels:
role: debug
spec:
containers:
- name: ubuntu-patt03
image: ubuntu:latest
command: [ "tail" ]
args: ["-f", "/dev/null" ]
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-patt02
labels:
role: debug
spec:
containers:
- name: ubuntu-patt02
image: ubuntu:latest
command:
- "tail"
- "-f"
- "/dev/null"
“arguments”在英语中意味着”参数”。(顺便说一下,”argument”则意味着”争论”,完全不同,所以要注意)
明确指明tail命令的参数是”-f”和”/dev/null”,我个人认为这样是最清晰易懂的。
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-patt03
labels:
role: debug
spec:
containers:
- name: ubuntu-patt03
image: ubuntu:latest
command: [ "tail" ]
args: ["-f", "/dev/null" ]
无论选择哪一个都是一样的,但当描述时输出会稍有不同。
Containers:
ubuntu-patt01:
Container ID: containerd://86b23d6d5ee178076af2d40f1d6c76a76c02104c48528122ea3d4708adcae95f
Image: ubuntu:latest
Image ID: docker.io/library/ubuntu@sha256:dfd64a3b4296d8c9b62aa3309984f8620b98d87e47492599ee20739e8eb54fbf
Port: <none>
Host Port: <none>
Command:
tail
-f
/dev/null
Containers:
ubuntu-patt02:
Container ID: containerd://af4fe19da11ebb001c634b299fb199d847a7b252efe4bba8c99710e7c02da4ab
Image: ubuntu:latest
Image ID: docker.io/library/ubuntu@sha256:dfd64a3b4296d8c9b62aa3309984f8620b98d87e47492599ee20739e8eb54fbf
Port: <none>
Host Port: <none>
Command:
tail
-f
/dev/null
Containers:
ubuntu-patt03:
Container ID: containerd://529af4be73e216a3984e8c7e98bdb29262cdbef6b2be5be7ca74002723635146
Image: ubuntu:latest
Image ID: docker.io/library/ubuntu@sha256:dfd64a3b4296d8c9b62aa3309984f8620b98d87e47492599ee20739e8eb54fbf
Port: <none>
Host Port: <none>
Command:
tail
Args:
-f
/dev/null