使用自己创建的Docker镜像部署到Kubernetes中的Pod后,出现了变为”Completed”状态的问题

你好。
我是Kuraasujakuto股份有限公司基础设施业务部的大塚。

在这篇文章中,我想记录一下使用DockerHub上自己制作的镜像文件,在kubernetes环境中部署pod的方法,以及在部署完成后状态自动变为”Completed”导致无法与pod连接(exec)的原因和解决方案。由于我正在重新学习中,所以无法保证所写内容是否真正原因。请仅供参考。

Pod是什么意思?

我引用了官方网站的内容。

Pod是可在Kubernetes内部创建和管理的计算的最小部署单元。Pod这个名字与鲸群或豌豆荚等表达方式有相似的含义,表示一个或多个容器的组合,具有共享存储和网络资源,并且具有有关容器执行方式的规范。

请提供一篇关于研究心理健康的最新文献。

 

在以下的视频内容中,使用了”pod就像是一个虚拟主机”这样的表达,如果很难理解pod的概念,可以将其想象为虚拟主机,这样可能更容易理解。实际上,在k8s中,每个pod都被分配了一个veth(≒虚拟网络接口),这也让我更容易理解。在部署虚拟主机(即pod)上部署容器与使用docker是一样的。

 

kubernetes.drawio.png
kubernetes-ページ2.drawio.png

我会把这些图形排列在一起。我认为红色虚线部分表示几乎相等。

kubernetes-ページ3.drawio.png

这次要使用的自制Docker镜像

这是按照以下步骤创建的。容器通常不包含用于调试等的命令,如ping、traceroute等,需要时需要安装。但是考虑到这一点过于麻烦,于是我决定创建一个专门用于这些命令的容器映像。

首先,在docker环境中,基于ubuntu 22.04映像部署一个容器。

进入部署好的容器,使用exec命令执行apt update和apt upgrade。

root@docker:~# docker run --name deb-ubuntu -itd ubuntu:22.04 
c83adeb801759ad124b4cea3b650d2775c6ff2174f42d12ec6e0f10385f3d516 
root@docker:~# docker ps 
CONTAINER ID   IMAGE                    COMMAND                  CREATED         STATUS         PORTS                                                                                            NAMES 
c83adeb80175   ubuntu:22.04             "/bin/bash"              4 seconds ago   Up 3 seconds                                                                                                    deb-ubuntu 
c03147d2f83c   httpd:latest             "httpd-foreground"       5 hours ago     Up 5 hours     80/tcp                                                                                           httpd.1.t5zt9glbr4tlgjofhcozjz7bi 
521b69dd00e9   nginx:latest             "/docker-entrypoint.…"   36 hours ago    Up 36 hours    80/tcp                                                                                           my-nginx.3.hux0zd2goc6974s25n4vvafcj 
8240d0af95a3   portainer/portainer-ce   "/portainer"             7 days ago      Up 36 hours    0.0.0.0:8000->8000/tcp, :::8000->8000/tcp, 0.0.0.0:9000->9000/tcp, :::9000->9000/tcp, 9443/tcp   portainer

root@docker:~# docker exec -it deb-ubuntu /bin/bash 
root@c83adeb80175:/# apt update
root@c83adeb80175:/# apt upgrade

然后按照以下顺序执行命令:
依次安装ping、ip、vi、traceroute、nslookup、curl、systemctl命令。

root@c83adeb80175:/# apt-get install iputils-ping net-tools
root@c83adeb80175:/# apt-get install iproute2
root@c83adeb80175:/# apt-get install vim
root@c83adeb80175:/# apt-get install traceroute
root@c83adeb80175:/# apt-get install dnsutils
root@c83adeb80175:/# apt-get install curl
root@c83adeb80175:/# apt-get install systemctl

将这个容器制作成镜像,并推送到Docker Hub。

root@docker:~# docker login
Authenticating with existing credentials...
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
root@docker:~# docker commit deb-ubuntu deb-ubuntu-image
sha256:7afcd01fe171f2e55cc8b1286f8359503fb120e65ff8fae4c181fc0065e642b3
root@docker:~# docker image ls
REPOSITORY                     TAG       IMAGE ID       CREATED         SIZE
deb-ubuntu-image               latest    7afcd01fe171   6 seconds ago   263MB
root@docker:~# docker tag deb-ubuntu-image shotaohtsuka/deb-ubuntu-image:latest
root@docker:~# docker image ls
REPOSITORY                      TAG       IMAGE ID       CREATED         SIZE
deb-ubuntu-image                latest    7afcd01fe171   4 minutes ago   263MB
shotaohtsuka/deb-ubuntu-image   latest    7afcd01fe171   4 minutes ago   263MB
root@docker:~# docker push shotaohtsuka/deb-ubuntu-image
Using default tag: latest
The push refers to repository [docker.io/shotaohtsuka/deb-ubuntu-image]
e3c2f7fb5b3e: Pushed
b93c1bd012ab: Mounted from shotaohtsuka/my-django-image
latest: digest: sha256:83ede37b63b9d5962404f55629388daab6f0439a0daf5a80bd6f919c04810610 size: 741
2023043001.png

将自己创建的 DockerImage 部署到 Kubernetes 中。

或许使用yaml文件来部署Pod是一个流行的选项,但这次我们不会用到它。我们将使用kubectl run命令进行部署。实际要输入的命令如下:
通过指定–restart=Never来部署Pod,然后指定docker镜像。暂时似乎会去询问hub。根据配置,也可能不进行询问吗?
在部署Pod之后,检查状态发现已完成…

root@sv-ohtsuka-k8s-master:~# kubectl run --restart=Never --image=shotaohtsuka/deb-ubuntu-image:latest testpod
pod/testpod created
root@sv-ohtsuka-k8s-master:~# kubectl get pod
NAME      READY   STATUS      RESTARTS   AGE
nginx     1/1     Running     0          4h5m
testpod   0/1     Completed   0          6s

在这种情况下,即使尝试指定Pod进行连接,也会被拒绝。
是的,因为它没有运行。所以下面是执行的结果。在指定Pod之后,使用-c选项指定了Pod中的容器。

root@sv-ohtsuka-k8s-master:~# kubectl exec -it testpod -c testpod -- /bin/bash
error: cannot exec into a container in a completed pod; current phase is Succeeded

我来查看pod的详细信息。
要进行确认,请使用describe命令。
无法特别确认是否有错误。

root@sv-ohtsuka-k8s-master:~# kubectl describe pod testpod
Name:         testpod
Namespace:    default
Priority:     0
Node:         sv-ohtsuka-k8s-master/172.19.0.223
Start Time:   Sun, 30 Apr 2023 02:55:56 +0000
Labels:       run=testpod
Annotations:  cni.projectcalico.org/podIP:
              cni.projectcalico.org/podIPs:
Status:       Succeeded
IP:           10.1.114.84
IPs:
  IP:  10.1.114.84
Containers:
  testpod:
    Container ID:   containerd://c30fae9c825ad5e791395b9f3cff36379db8b726c55c2ecb9a6bd22ad94fef60
    Image:          shotaohtsuka/deb-ubuntu-image:latest
    Image ID:       docker.io/shotaohtsuka/deb-ubuntu-image@sha256:83ede37b63b9d5962404f55629388daab6f0439a0daf5a80bd6f919c04810610
    Port:           <none>
    Host Port:      <none>
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Sun, 30 Apr 2023 02:55:58 +0000
      Finished:     Sun, 30 Apr 2023 02:55:58 +0000
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-l6qnh (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             False
  ContainersReady   False
  PodScheduled      True
Volumes:
  kube-api-access-l6qnh:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  7s    default-scheduler  Successfully assigned default/testpod to sv-ohtsuka-k8s-master
  Normal  Pulling    7s    kubelet            Pulling image "shotaohtsuka/deb-ubuntu-image:latest"
  Normal  Pulled     6s    kubelet            Successfully pulled image "shotaohtsuka/deb-ubuntu-image:latest" in 1.245030855s (1.245046541s including waiting)
  Normal  Created    5s    kubelet            Created container testpod
  Normal  Started    5s    kubelet            Started container testpod

当部署将-it选项添加到部署pod时,可以访问该pod。但是,如果pod退出,状态仍将变为“完成”。请记住,在pod内运行ps命令并记住输出结果。

root@sv-ohtsuka-k8s-master:~# kubectl run testpod -it --restart=Never --image=shotaohtsuka/deb-ubuntu-image 
If you don't see a command prompt, try pressing enter.
root@testpod:/# apt-get install apache2
root@testpod:/# service apache2 start 
 * Starting Apache httpd web server apache2                                                                                                                                              AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 10.1.114.80. Set the 'ServerName' directive globally to suppress this message 
 * 
root@testpod:/# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 03:14 pts/0    00:00:00 /bin/bash
root          10       1  0 03:14 pts/0    00:00:00 ps -ef
root@testpod:/# exit 
exit 
E0429 23:02:16.688728 3188213 v2.go:105] EOF 
root@sv-ohtsuka-k8s-master:~# kubectl get pod 
NAME      READY   STATUS      RESTARTS   AGE 
nginx     1/1     Running     0          20m 
testpod   0/1     Completed   0          4m16s

为什么pod的状态会自动变为”Completed”?

为了验证标题的内容,我将部署一个用于nginx的Pod。
我认为从nginx镜像部署Pod后,状态会变为running。

root@sv-ohtsuka-k8s-master:~# kubectl run --restart=Never --image=nginx:latest nginx
pod/nginx created
root@sv-ohtsuka-k8s-master:~# kubectl get pod
NAME      READY   STATUS      RESTARTS   AGE
testpod   0/1     Completed   0          14m
nginx     1/1     Running     0          6s

在这种状态下,您可以使用exec命令访问Pod内的容器。
在这里也应该使用ps命令。默认情况下,没有安装ps命令,所以需要安装一下。
由于这是一个nginx容器,所以当然会运行nginx进程。
与上述不同的是,即使从Pod中退出,它也不会转为“完成”状态,而会保持在“运行”状态。

root@sv-ohtsuka-k8s-master:~# kubectl exec -it nginx -c nginx -- /bin/bash
root@nginx:/# apt update
root@nginx:/# apt upgrade
root@nginx:/# apt-get install procps
root@nginx:/# ps -ef 
UID          PID    PPID  C STIME TTY          TIME CMD 
root           1       0  0 22:41 ?        00:00:00 nginx: master process nginx -g daemon off; 
nginx         29       1  0 22:41 ?        00:00:00 nginx: worker process 
nginx         30       1  0 22:41 ?        00:00:00 nginx: worker process 
nginx         31       1  0 22:41 ?        00:00:00 nginx: worker process 
nginx         32       1  0 22:41 ?        00:00:00 nginx: worker process 
root          45       0  0 22:43 pts/0    00:00:00 /bin/bash 
root         818      45  0 22:44 pts/0    00:00:00 ps -ef
root@nginx:/# exit 
exit
root@sv-ohtsuka-k8s-master:~# kubectl get pod 
NAME      READY   STATUS      RESTARTS   AGE 
testpod   0/1     Completed   0          9m21s 
nginx     1/1     Running     0          5m30s

我的结论是【使用自己制作的Docker镜像部署的Pod,由于没有运行的进程,所以状态变为”Completed”】。我将展示出ps命令的输出结果。可能会有人说“即使在使用自制的镜像部署的Pod上也有运行的进程啊!”但是输出结果中显示的两个进程是连接到Pod的进程(/bin/bash)和执行的命令本身的进程(ps -ef)。因此,一旦退出该Pod,Pod中运行的进程数量将变为0,Kubernetes会自作主张地认为“不需要运行了!”并将其状态自动变为Completed。而与此同时,Nginx方面还会有除/bin/bash和ps -ef之外的其他运行进程,所以即使从该Pod退出,状态也不会变为Completed,而是会保持在running状态。

★自作イメージでデプロイしたpod
root@testpod:/# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 03:14 pts/0    00:00:00 /bin/bash
root          10       1  0 03:14 pts/0    00:00:00 ps -ef

★nginxイメージでデプロイしたpod
root@nginx:/# ps -ef 
UID          PID    PPID  C STIME TTY          TIME CMD 
root           1       0  0 22:41 ?        00:00:00 nginx: master process nginx -g daemon off; 
nginx         29       1  0 22:41 ?        00:00:00 nginx: worker process 
nginx         30       1  0 22:41 ?        00:00:00 nginx: worker process 
nginx         31       1  0 22:41 ?        00:00:00 nginx: worker process 
nginx         32       1  0 22:41 ?        00:00:00 nginx: worker process 
root          45       0  0 22:43 pts/0    00:00:00 /bin/bash 
root         818      45  0 22:44 pts/0    00:00:00 ps -ef

从这个猜测中,如果想要将从自己创建的镜像部署的pod保持在运行状态,只需在pod中运行任何一个进程即可判断它是一个良好的环境,即使退出也可以。
有很多方法,如使用nohup等,但本次我们暂时将在pod中安装apache2并启动服务来尝试。
需要注意的是,在启动apache2进程后,如果退出会导致进程消失,因此如果在teraterm等工具上连接,请点击右上角的“X”以退出。

root@sv-ohtsuka-k8s-master:~# kubectl run testpod -it --restart=Never --image=shotaohtsuka/deb-ubuntu-image 
If you don't see a command prompt, try pressing enter. 
root@testpod:/# apt-get install apache2 
root@testpod:/# service apache2 start 
 * Starting Apache httpd web server apache2                                                                                                                                              AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 10.1.114.80. Set the 'ServerName' directive globally to suppress this message 
 * 
root@testpod:/# ps -ef 
UID          PID    PPID  C STIME TTY          TIME CMD 
root           1       0  0 22:58 pts/0    00:00:00 /bin/bash 
root         558       1  0 23:01 ?        00:00:00 /usr/sbin/apache2 -k start 
www-data     561     558  0 23:01 ?        00:00:00 /usr/sbin/apache2 -k start 
www-data     562     558  0 23:01 ?        00:00:00 /usr/sbin/apache2 -k start 
root         619       1  0 23:01 pts/0    00:00:00 ps -ef 
★このタイミングでteratermの「×」を押してexit out

在这个时间点上,再次尝试连接到Kubernetes环境并确认接入Pod的状态,会发现状态已经固定为运行中。

root@sv-ohtsuka-k8s-master:~# kubectl get pod 
NAME      READY   STATUS    RESTARTS   AGE 
nginx     1/1     Running   0          27m 
testpod   1/1     Running   0          86s

如果情况是这样的,你可以使用”exec”进入这个容器并安全退出。

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 23:08 pts/0    00:00:00 /bin/bash 
root         551       1  0 23:09 ?        00:00:00 /usr/sbin/apache2 -k start 
www-data     554     551  0 23:09 ?        00:00:00 /usr/sbin/apache2 -k start 
www-data     555     551  0 23:09 ?        00:00:00 /usr/sbin/apache2 -k start 
root         613       0  0 23:12 pts/1    00:00:00 /bin/bash 
root         622     613  0 23:12 pts/1    00:00:00 ps -ef 
root@testpod:/# exit
root@sv-ohtsuka-k8s-master:~# kubectl get pod 
NAME      READY   STATUS    RESTARTS   AGE 
nginx     1/1     Running   0          30m 
testpod   1/1     Running   0          4m19s
bannerAds