从零开始学习k8s-06容器初始化
背景
以往我们在使用Dockerfile
构建容器的时候,都会在CMD
命令下写一些脚本来初始化容器必要的数据。那么在使用Pod
的时候,会有这类需求,容器启动会有一些必要条件,这个条件可以在容器初始化的过程中把这部分数据放到容器中(当然,通过pod
的生命周期回调函数也可以做。)
学习
我们依然使用官方的例子。目前我这里使用官方的例子跑的时候有一些异常,因此我小改了一下yaml
文件,具体的内容如下。
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: workdir
mountPath: /usr/share/nginx/html
initContainers:
- name: install
image: nginx
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/message"]
volumeMounts:
- name: workdir
mountPath: "/usr"
dnsPolicy: Default
volumes:
- name: workdir
emptyDir: {}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
我们可以看到,在创建的开始会有一个Init
的阶段
kubectl get pods
NAME READY STATUS RESTARTS AGE
init-demo 0/1 Init:0/1 0 4s
kubectl get pods
NAME READY STATUS RESTARTS AGE
init-demo 0/1 PodInitializing 0 8s
kubectl get pods
NAME READY STATUS RESTARTS AGE
init-demo 1/1 Running 0 10s
2
3
4
5
6
7
8
9
10
11
这个时候,是在创建init
容器,以及执行init
容器的命令。
当init完毕之后,就会变成Running
状态,这里就表明容器创建成功了。
在创建成功之后我们进入容器内部查看这个信息。
kubectl exec -it init-demo -- /bin/bash
Defaulted container "nginx" out of: nginx, install (init)
cd /usr/share/nginx/html/
init-demo:/usr/share/nginx/html# ls
message
init-demo:/usr/share/nginx/html# cat message
Hello from the postStart handler
2
3
4
5
6
7
可以看到我们在init
阶段写入/usr
路径下的文件已经在我们的主容器查看到了。
规则解析
在这个yaml
文档中,我们定义了两个容器,其中install
容器是init
容器,而nginx
容器是主容器。
k8s
在调度的时候,会优先执行init
容器的内容,之后再执行主容器的内容。
可以看到目前我们的init
容器和主容器同时挂载了usr
,init
容器在启动的时候写了一个文件到挂载的路径上。那么主容器启动的时候,则会在这个路径上存在这个文件,就可以在主容器上发布。
多个Init容器
如果为一个 Pod 指定了多个 Init 容器,这些容器会按顺序逐个运行。 每个 Init 容器必须运行成功,下一个才能够运行。当所有的 Init 容器运行完成时, Kubernetes 才会为 Pod 初始化应用容器并像平常一样运行。
与普通容器的不同之处
Init 容器支持应用容器的全部字段和特性,包括资源限制、数据卷和安全设置。 然而,Init 容器对资源请求和限制的处理稍有不同,在下面资源节有说明。
同时 Init 容器不支持
lifecycle
、livenessProbe
、readinessProbe
和startupProbe
, 因为它们必须在 Pod 就绪之前运行完成。
进一步思考
Pod
在设计的时候设计成多容器的模式,实际上就是为了支持辅助应用(helper applications),以协助主应用(primary application)。 辅助应用的典型例子是数据抽取,数据推送和代理。
官方给出了一些init
容器的使用思路
Init 容器可以包含一些安装过程中应用容器中不存在的实用工具或个性化代码。 例如,没有必要仅为了在安装过程中使用类似
sed
、awk
、python
或dig
这样的工具而去FROM
一个镜像来生成一个新的镜像。
Init 容器可以安全地运行这些工具,避免这些工具导致应用镜像的安全性降低。
应用镜像的创建者和部署者可以各自独立工作,而没有必要联合构建一个单独的应用镜像。
Init 容器能以不同于 Pod 内应用容器的文件系统视图运行。因此,Init 容器可以访问 应用容器不能访问的 Secret 的权限。
由于 Init 容器必须在应用容器启动之前运行完成,因此 Init 容器 提供了一种机制来阻塞或延迟应用容器的启动,直到满足了一组先决条件。 一旦前置条件满足,Pod 内的所有的应用容器会并行启动。