一、Pod 的 initContainers
基本概念:
Init Containers(初始化容器)是 Kubernetes 中的一种特殊类型的容器,它们在应用程序容器启动之前运行。Init Containers 用于执行一些初始化任务,例如设置环境变量、准备配置文件、执行数据库迁移、等待其他服务可用等。Init Containers 完成后,应用程序容器才会启动。
以下是 Init Containers 的一些关键特点和用途:
1. 执行顺序
- Init Containers 按照定义的顺序依次运行。只有在前一个 Init Container 成功完成后,下一个 Init Container 才会开始执行。
- 如果任何一个 Init Container 失败(即退出代码非零),Kubernetes 会重启整个 Pod,直到所有 Init Containers 都成功完成。
2. 资源请求
- Init Containers 可以使用与其他容器相同的资源请求和限制,这意味着你可以在 Init Containers 中指定 CPU 和内存的请求和限制。
3. 安全性
- 由于 Init Containers 在应用程序容器之前运行,因此它们可以用来执行一些敏感操作或配置,而不直接暴露给应用程序容器。
4. 与其他服务的依赖
- Init Containers 可以用来等待其他服务或依赖项(如数据库、消息队列等)在应用程序启动之前就绪。例如,你可以编写一个 Init Container 来等待某个服务的端点可用,然后再启动应用程序容器。
5. 配置管理
- Init Containers 可以用来准备配置文件或环境变量,以供应用程序容器使用。例如,你可能需要从外部服务获取配置数据,并用这些数据生成配置文件。
Init Containers 是 Kubernetes 中非常有用的一个特性,它允许你在应用程序容器启动之前执行一些必要的初始化任务。通过合理使用 Init Containers,你可以确保应用程序在启动时处于一个正确、安全的状态。
原理
Pod能够具有多个容器,应用运行在容器里面,但是它也可能有一个或多个先于应用容器启动的Init容器,Init容器与普通的容器非常像,除了如下两点:
- Init容器总是运行到成功完成为止
- 每个Init容器都必须在下一个Init容器启动之前成功完成
如果Pod的Init容器失败, Kubernetes 会不断地重启该Pod,直到Init容器成功为止。然而,如果Pod对应的restartPolicy为Never,它不会重新启动。
initContainers示例:
apiVersion: v1
kind: Pod
metadata:
name: initc-demo
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: docker.io/busybox
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: docker.io/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;']
我们创建模版资源后查看结果为:
我们查看一下日志:
这个时候我们可以看到因为解析不成功,所以初始化程序卡住了,那么先创建满足第一个解析的service资源:
kind: Service
apiVersion: v1
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
创建完成后我们在查看一下 Pod 的状态:
第一个 init 初始化程序已经成功,这是因为,我们创建名为“myservice”的 SVC 的数据会写到我们内部的DNS(coreDNS) 上,因为可以正常的解析了,所以第一个 init 初始化程序完成,同理我们加入第二个 init 初始化程序的 SVC 后查看 Pod 状态:
kind: Service
apiVersion: v1
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
这个时候我们可以看到,第二个 init 初始化程序已经完成,我们的主容器 Pod 开始初始化,最后成功开始运行。
initContainers特殊说明
1、在 Pod 启动过程中,Init 容器会按顺序在网络和数据卷初始化之后启动。每个容器必须在下一个容器启动之前成功退出。
2、如果由于运行时或失败退出,将导致容器启动失败,它会根据 Pod 的 restartPolicy 指定的策略进行重试。然而,如果 Pod 的 restartPolicy 设置为 Always , Init 容器失败时会使用 RestartPolicy 策略。
3、在所有的Init容器没有成功之前,Pod 将不会变成 Ready 状态。Init 容器的端口将不会在 Service 中进行聚集。正在初始化中的 Pod 处于 Pending 状态,但会将 Initializing 状态设置为 true。
4、如果 Pod 重启,所有 Init 容器必须重新执行。
5、对 Init 容器 spec 的修改被限制在容器 image 字段, 修改其他字段都不会生效。 更改 Init 容器的 image字段,等价于重启该 Pod。
6、Init 容器具有应用容器的所有字段。除了 readinessProbe , 因为Init容器无法定义不同于完成 (completion) 的就绪 (readiness) 之外的其他状态。这会在验证过程中强制执行。
7、在 Pod 中的每个 app 和 Init 容器的名称必须唯一,与任何其它容器共享同个名称,会在验证时抛出错误。