持续集成部署-k8s-高级调度-InitC:初始化容器的概念和使用

持续集成部署-k8s-高级调度-InitC:初始化容器的概念和使用

1. Init Container(初始化容器)是什么?

Kubernetes中,Init Container(初始化容器)是一种特殊类型的容器,它在Pod中的其他容器之前运行。Init Container用于在主容器启动之前执行一些初始化任务,例如配置文件的下载、数据库的初始化等。

Init Container与普通容器一样,但它们具有以下几个特点:

  • 顺序执行:在同一个Pod中,所有的Init Container会按照定义的顺序依次执行,只有当前Init Container成功退出(即返回状态码为0)后,下一个Init Container才会开始执行。
  • 容器间共享文件系统卷:Init Container可以与其他容器共享相同的卷(volume),使它们能够访问相同的文件或配置信息。
  • 生命周期独立:Init Container的生命周期与Pod中的其他容器是独立的。它们可以在主容器正在运行时继续执行,也可以在主容器结束后继续执行。

2. Init Container 的简单使用

新建配置文件:init-container.yaml

apiVersion: v1
kind: Pod
metadata:
  name: init-container-pod
spec:
  containers:
    - name: main-container-nginx
      image: nginx:1.7.9
      # 主容器的定义

  initContainers:
    - name: init-container-1
      image: busybox:latest
      command: ['sh', '-c', 'echo Init Container 1']
      # 第一个Init Container的定义

    - name: init-container-2
      image: busybox:latest
      command: ['sh', '-c', 'echo Init Container 2']
      # 第二个Init Container的定义

在上面的示例中,我们定义了一个Pod,其中包含一个名为 main-container-nginx的主容器和两个Init Container:init-container-1init-container-2。它们将按照定义的顺序依次执行。

每个Init Containerk可以使用不同的镜像(这里使用了Busybox镜像),并通过command字段指定了要执行的命令。在这个示例中,Init Container只是打印一些文本信息。

当Pod启动时,Kubernetes将首先创建并运行init-container-1,待其成功退出后,再创建并运行init-container-2。最后,Kubernetes会创建并运行main-container-nginx

接着我们操作下看下执行的流程:kubectl create -f init-container.yaml

[root@docker-54 jobs]# kubectl create -f init-container.yaml 
pod/init-container-pod created
[root@docker-54 jobs]# 
[root@docker-54 jobs]# kubectl get po
NAME                           READY   STATUS      RESTARTS        AGE
init-container-pod             0/1     Init:0/2    0               6s
[root@docker-54 jobs]# 
[root@docker-54 jobs]# kubectl get po
NAME                           READY   STATUS      RESTARTS        AGE
init-container-pod             0/1     Init:1/2    0               6s
[root@docker-54 jobs]# 
[root@docker-54 jobs]# kubectl get po
NAME                           READY   STATUS             RESTARTS        AGE
init-container-pod             0/1     PodInitializing    0               6s
[root@docker-54 jobs]# 
[root@docker-54 jobs]# kubectl get po
NAME                           READY   STATUS     RESTARTS        AGE
init-container-pod             1/1     Running    0               6s
[root@docker-54 jobs]# 

可以看到,Pod 创建成功后,READY显示 0/1表示未就绪状态,并且STATUS显示有两个 Init Container 在初始化,然后等待初始化完成后,容器状态变为 Running;

接着看下描述事件的内容:

[root@docker-54 jobs]# kubectl describe po  init-container-pod 
Name:         init-container-pod
Namespace:    default
...
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  87s   default-scheduler  Successfully assigned default/init-container-pod to docker-56
  Normal  Pulling    87s   kubelet            Pulling image "busybox:latest"
  Normal  Pulled     48s   kubelet            Successfully pulled image "busybox:latest" in 39.045941073s
  Normal  Created    48s   kubelet            Created container init-container-1
  Normal  Started    48s   kubelet            Started container init-container-1
  Normal  Pulling    47s   kubelet            Pulling image "busybox:latest"
  Normal  Pulled     16s   kubelet            Successfully pulled image "busybox:latest" in 31.46613887s
  Normal  Created    16s   kubelet            Created container init-container-2
  Normal  Started    16s   kubelet            Started container init-container-2
  Normal  Pulled     15s   kubelet            Container image "nginx:1.7.9" already present on machine
  Normal  Created    15s   kubelet            Created container main-container-nginx
  Normal  Started    14s   kubelet            Started container main-container-nginx
[root@docker-54 jobs]# 

可以看到,首先是任务调度到 docker-56 节点上,然后拉取了 "busybox:latest"的镜像,这里有两个 Init Container 但是用了同一个版本的镜像,却拉取了两次,就有点神奇了。

这是因为当Pod被调度到节点上并开始执行时,Kubernetes会按顺序为每个Init Container创建一个容器实例。每个容器实例需要从镜像仓库中拉取镜像,以便在节点上运行。

所以,在上面示例中,第一个Init Container(init-container-1)在开始时拉取了busybox:latest镜像,然后在成功退出后,第二个Init Container(init-container-2)也会拉取相同的镜像。这是因为每个Init Container都是独立的,它们之间没有共享镜像的缓存。

主容器(main-container-nginx)则是另一个独立的容器,它使用的是不同的镜像(nginx:1.7.9)。由于该镜像已经存在于节点上,所以在事件信息中显示为Container image "nginx:1.7.9" already present on machine,表示不需要再次拉取该镜像。

接着看下节点上容器的执行情况:

[root@docker-56 ~]# docker ps -a | grep init
8962da1d4913   84581e99d807                                                              "nginx -g 'daemon of…"   11 minutes ago   Up 11 minutes                         k8s_main-container-nginx_init-container-pod_default_c8984746-7c8e-4724-82da-4bb7376ec560_0
d29abaa670cd   busybox                                                                   "sh -c 'echo Init Co…"   11 minutes ago   Exited (0) 11 minutes ago             k8s_init-container-2_init-container-pod_default_c8984746-7c8e-4724-82da-4bb7376ec560_0
1cc8c7423c64   busybox                                                                   "sh -c 'echo Init Co…"   12 minutes ago   Exited (0) 12 minutes ago             k8s_init-container-1_init-container-pod_default_c8984746-7c8e-4724-82da-4bb7376ec560_0
[root@docker-56 ~]# docker logs -f --tail 20 k8s_init-container-1_init-container-pod_default_c8984746-7c8e-4724-82da-4bb7376ec560_0
Init Container 1
[root@docker-56 ~]# 

确实可以看到,这里运行了三个容器,Init Container 执行完成,已经是停止的状态了,并且查看对应 Init Container 的日志,也是可以正常看到的。

使用Init Container可以实现一些初始化任务,确保主容器在启动之前具备所需的条件。例如,可以使用Init Container下载配置文件初始化数据库执行数据迁移等操作。

需要注意的是,如果Init Container失败退出(即返回状态码非零),Kubernetes将会重启整个Pod,以便重新执行Init Container主容器。因此,在编写Init Container时,应确保其能够处理错误情况,并保证在正常情况下能够成功退出。

猜你喜欢

转载自blog.csdn.net/linmengmeng_1314/article/details/134748835