7.2. 在部署 pod 前使用初始容器来执行任务
Red Hat OpenShift Service on AWS 提供了 init 容器,它们是在应用程序容器之前运行的专用容器,可以包含不出现在应用程序镜像中的工具或设置脚本。
7.2.1. 了解初始容器
您可以在部署 pod 的其余部分之前,使用初始容器资源来执行任务。
pod 可以同时包含初始容器和应用程序容器。借助初始容器,您可以重新整理设置脚本和绑定代码。
初始容器可以:
- 包含并运行出于安全考虑而不应包括在应用容器镜像中的实用程序。
- 包含不出现在应用程序镜像中的设置的实用程序或自定义代码。例如,不需要仅仅为了在设置过程中使用 sed、awk、python 或 dig 等工具而使用 FROM 从其他镜像生成一个镜像。
- 使用 Linux 命名空间,以便使用与应用程序容器不同的文件系统,如访问应用程序容器无法访问的 Secret。
各个初始容器必须成功完成,然后下一个容器才能启动。因此,初始容器提供了一种简单的方法来阻止或延迟应用程序容器的启动,直至满足一定的前提条件。
例如,您可以通过如下一些方式来使用初始容器:
通过类似以下示例的 shell 命令,等待创建服务:
for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; done; exit 1
通过类似以下示例的命令,从 Downward API 将此 Pod 注册到远程服务器:
$ curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d ‘instance=$()&ip=$()’
-
通过类似
sleep 60
的命令,等待一段时间后再启动应用程序容器。 - 将一个 git 存储库克隆到卷中。
- 将值放在配置文件中,并且运行模板工具为主应用程序容器动态生成配置文件。例如,将 POD_IP 值放在配置中,并且使用 Jinja 生成主应用程序配置文件。
如需更多信息,请参阅 Kubernetes 文档。
7.2.2. 创建初始容器
下例概述了一个包含两个初始容器的简单 Pod。一个用于等待 myservice
,另一个用于等待 mydb
。两个容器完成后,pod 都会启动。
流程
为初始容器创建 pod:
创建一个类似以下示例的 YAML 文件:
apiVersion: v1 kind: Pod metadata: name: myapp-pod labels: app: myapp spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: myapp-container image: registry.access.redhat.com/ubi9/ubi:latest command: ['sh', '-c', 'echo The app is running! && sleep 3600'] securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] initContainers: - name: init-myservice image: registry.access.redhat.com/ubi9/ubi:latest command: ['sh', '-c', 'until getent hosts myservice; do echo waiting for myservice; sleep 2; done;'] securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] - name: init-mydb image: registry.access.redhat.com/ubi9/ubi:latest command: ['sh', '-c', 'until getent hosts mydb; do echo waiting for mydb; sleep 2; done;'] securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL]
创建 pod:
$ oc create -f myapp.yaml
查看 pod 的状态:
$ oc get pods
输出示例
NAME READY STATUS RESTARTS AGE myapp-pod 0/1 Init:0/2 0 5s
pod 状态
Init:0/2
表示它正在等待这两个服务。
创建
myservice
服务。创建一个类似以下示例的 YAML 文件:
kind: Service apiVersion: v1 metadata: name: myservice spec: ports: - protocol: TCP port: 80 targetPort: 9376
创建 pod:
$ oc create -f myservice.yaml
查看 pod 的状态:
$ oc get pods
输出示例
NAME READY STATUS RESTARTS AGE myapp-pod 0/1 Init:1/2 0 5s
pod 状态
Init:1/2
表示它正在等待一个服务,本例中为mydb
服务。
创建
mydb
服务:创建一个类似以下示例的 YAML 文件:
kind: Service apiVersion: v1 metadata: name: mydb spec: ports: - protocol: TCP port: 80 targetPort: 9377
创建 pod:
$ oc create -f mydb.yaml
查看 pod 的状态:
$ oc get pods
输出示例
NAME READY STATUS RESTARTS AGE myapp-pod 1/1 Running 0 2m
pod 状态表示它不再等待服务并运行。