14.Init 容器
Init 容器
该特性在自containers
数组一起来指定。此前
本文讲解
理解Init 容器
Pod 能够具有多个容器,应用运行在容器里面,但是它也可能有一个或多个先于应用容器启动的
Init 容器总是运行到成功完成为止。- 每个
Init 容器都必须在下一个Init 容器启动之前成功完成。
如果restartPolicy
为
指定容器为initContainers
字段,以containers
数组。status.initContainerStatuses
字段中以容器状态数组的格式返回(类似 status.containerStatuses
字段
与普通容器的不同之处
如果为一个
Init 容器能做什么?
因为
- 它们可以包含并运行实用工具,但是出于安全考虑,是不建议在应用程序容器镜像中包含这些实用工具的。
- 它们可以包含使用工具和定制化代码来安装,但是不能出现在应用程序镜像中。例如,创建镜像没必要
FROM
另一个镜像,只需要在安装过程中使用类似sed
、awk
、python
或dig
这样的工具。 - 应用程序镜像可以分离出创建和部署的角色,而没有必要联合它们构建一个单独的镜像。
Init 容器使用Linux Namespace ,所以相对应用程序容器来说具有不同的文件系统视图。因此,它们能够具有访问Secret 的权限,而应用程序容器则不能。- 它们必须在应用程序容器启动之前运行完成,而应用程序容器是并行运行的,所以
Init 容器能够提供了一种简单的阻塞或延迟应用容器的启动的方法,直到满足了一组先决条件。
示例
下面列举了
-
等待一个
Service 创建完成,通过类似如下shell 命令:for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; exit 1
-
将
Pod 注册到远程服务器,通过在命令中调用API ,类似如下:curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'
-
在启动应用容器之前等一段时间,使用类似
sleep 60
的命令。 -
克隆
Git 仓库到数据卷。 -
将配置值放到配置文件中,运行模板工具为主应用容器动态地生成配置文件。例如,在配置文件中存放
POD_IP 值,并使用Jinja 生成主应用配置文件。
更多详细用法示例,可以在
使用Init 容器
下面是myservice
启动,第二个等待 mydb
启动。一旦这两个
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
annotations:
pod.beta.kubernetes.io/init-containers: '[
{
"name": "init-myservice",
"image": "busybox",
"command": ["sh", "-c", "until nslookup myservice; do echo waiting for myservice; sleep 2; done;"]
},
{
"name": "init-mydb",
"image": "busybox",
"command": ["sh", "-c", "until nslookup mydb; do echo waiting for mydb; sleep 2; done;"]
}
]'
spec:
containers:
- name: myapp-container
image: busybox
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
这是spec
中:
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox
command: ["sh", "-c", "echo The app is running! && sleep 3600"]
initContainers:
- name: init-myservice
image: busybox
command:
[
"sh",
"-c",
"until nslookup myservice; do echo waiting for myservice; sleep 2; done;",
]
- name: init-mydb
image: busybox
command:
[
"sh",
"-c",
"until nslookup mydb; do echo waiting for mydb; sleep 2; done;",
]
注意:版本兼容性问题
1.5 版本的语法在1.6 和1.7 版本中仍然可以使用,但是我们推荐使用1.6 版本的新语法。Kubernetes 1.8 以后的版本只支持新语法。在Kubernetes 1.6 版本中,Init 容器在API 中新建了一个字段。虽然期望使用beta 版本的annotation ,但在未来发行版将会被废弃掉。
下面的mydb
和 myservice
两个
kind: Service
apiVersion: v1
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
---
kind: Service
apiVersion: v1
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
这个
$ kubectl create -f myapp.yaml
pod "myapp-pod" created
$ kubectl get -f myapp.yaml
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:0/2 0 6m
$ kubectl describe -f myapp.yaml
Name: myapp-pod
Namespace: default
[...]
Labels: app=myapp
Status: Pending
[...]
Init Containers:
init-myservice:
[...]
State: Running
[...]
init-mydb:
[...]
State: Waiting
Reason: PodInitializing
Ready: False
[...]
Containers:
myapp-container:
[...]
State: Waiting
Reason: PodInitializing
Ready: False
[...]
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
16s 16s 1 {default-scheduler } Normal Scheduled Successfully assigned myapp-pod to 172.17.4.201
16s 16s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulling pulling image "busybox"
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulled Successfully pulled image "busybox"
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Created Created container with docker id 5ced34a04634; Security:[seccomp=unconfined]
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Started Started container with docker id 5ced34a04634
$ kubectl logs myapp-pod -c init-myservice # Inspect the first init container
$ kubectl logs myapp-pod -c init-mydb # Inspect the second init container
一旦我们启动了 mydb
和 myservice
这两个myapp-pod
被创建:
$ kubectl create -f services.yaml
service "myservice" created
service "mydb" created
$ kubectl get -f myapp.yaml
NAME READY STATUS RESTARTS AGE
myapp-pod 1/1 Running 0 9m
这个例子非常简单,但是应该能够为我们创建自己的
具体行为
在restartPolicy
指定的策略进行重试。然而,如果restartPolicy
设置为RestartPolicy
策略。
在所有的Ready
状态。Pending
状态,但应该会将 Initializing
状态设置为
如果
对
因为EmptyDirs
文件中的代码,应该对输出文件可能已经存在做好准备。
readinessProbe
,因为
在activeDeadlineSeconds
,在容器上使用 livenessProbe
,这样能够避免
在
资源
为
-
在所有
Init 容器上定义的,任何特殊资源请求或限制的最大值,是 有效初始请求/ 限制 -
Pod 对资源的有效请求/ 限制要高于:- 所有应用容器对某个资源的请求
/ 限制之和 - 对某个资源的有效初始请求
/ 限制
- 所有应用容器对某个资源的请求
-
基于有效请求
/ 限制完成调度,这意味着Init 容器能够为初始化预留资源,这些资源在Pod 生命周期过程中并没有被使用。 -
Pod 的 有效QoS 层,是Init 容器和应用容器相同的QoS 层。
基于有效
Pod 重启的原因
- 用户更新
PodSpec 导致Init 容器镜像发生改变。应用容器镜像的变更只会重启应用容器。 Pod 基础设施容器被重启。这不多见,但某些具有root 权限可访问Node 的人可能会这样做。- 当
restartPolicy
设置为Always ,Pod 中所有容器会终止,强制重启,由于垃圾收集导致Init 容器完整的记录丢失。
支持与兼容性
spec.initContainers
字段来支持spec.initContainers
字段也被加入到