一、初始化容器
初始化容器(init container)即应用程序的主容器启动之前需要运行的容器,常用于为主容器执行一些预置的操作,它们具有两种典型特征:
1)初始化容器必须运行完成直至结束,若某个初始化容器运行失败,那么Kubernetes需要重启此容器直到它成功启动
2)每个初始化容器都必须按定义顺序的串行的来运行
有不少的场景都需要在应用容器启动之前进行部分初始化操作,例如,等待其他关联组件服务可用、基于环境变量或配置模板为应用程序生成配置文件、从配置中心获取配置等;初始化容器的典型应用需求具体包含如下几种:
1)用于运行特定的工具程序,出于安全等方面的原因,这些程序不适用于包含在主容器镜像中
2)提供主容器镜像中不具备的工具程序或自定义代码
3)为容器镜像的构建和部署人员提供了分离、独立工作的途径,使得他们不必协同起来制作单个镜像文件
4)初始化容器和主容器处于不同的文件系统视图中,因此可以分别安全地使用敏感数据,例如Secrets资源
5)初始化容器要先于应用容器串行启动并运行完成,因此可用于延后应用容器的启动直至其依赖的条件得到满足
二、初始化容器实验
1)编写初始化容器yaml文件
]# cat init-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: init-pod
labels:
app: myapp
spec:
containers:
- name: init-conta
image: ikubernetes/myapp:v1
imagePullPolicy: IfNotPresent
initContainers:
- name: init-something
image: busybox
command: ['sh','-c','sleep 10']
2)创建Pod
]# kubectl apply -f init-pod.yaml
pod/init-pod created
3)观察集群中Pod的资源变化
]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
init-pod 0/1 Pending 0 0s
init-pod 0/1 Pending 0 0s
init-pod 0/1 Init:0/1 0 0s
init-pod 0/1 Init:0/1 0 19s
init-pod 0/1 PodInitializing 0 29s
init-pod 1/1 Running 0 30s
]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
init-pod 0/1 Init:0/1 0 16s <none> node1 <none> <none>
]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
init-pod 1/1 Running 0 42s 10.244.1.39 node1 <none> <none>
可以看到是先启动初始化容器的,待30秒之后再启动主容器,容器状态变为Running
4)查看Pod的详细信息
]# kubectl describe pods init-pod
Name: init-pod
Namespace: default
Priority: 0
Node: node1/172.16.2.101
Start Time: Sat, 01 Aug 2020 15:38:04 +0800
Labels: app=myapp
Annotations: Status: Running
IP: 10.244.1.39
IPs:
IP: 10.244.1.39
Init Containers:
init-something:
Container ID: docker://f182b594a2541af05052a9fc5558c3b46c75e745135cd239962ae3e794efac71
Image: busybox
Image ID: docker-pullable://busybox@sha256:4f47c01fa91355af2865ac10fef5bf6ec9c7f42ad2321377c21e844427972977
Port: <none>
Host Port: <none>
Command:
sh
-c
sleep 10
State: Terminated
Reason: Completed
Exit Code: 0
Started: Sat, 01 Aug 2020 15:38:23 +0800
Finished: Sat, 01 Aug 2020 15:38:33 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-47pch (ro)
Containers:
init-conta:
Container ID: docker://5e883576bc8b3b7fe1f19c6057c8c7c9f386a1f19f98c469811d2e91c350365c
Image: ikubernetes/myapp:v1
Image ID: docker-pullable://ikubernetes/myapp@sha256:9c3dc30b5219788b2b8a4b065f548b922a34479577befb54b03330999d30d513
Port: <none>
Host Port: <none>
State: Running
Started: Sat, 01 Aug 2020 15:38:34 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-47pch (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-47pch:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-47pch
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned default/init-pod to node1
Normal Pulling <invalid> kubelet, node1 Pulling image "busybox"
Normal Pulled <invalid> kubelet, node1 Successfully pulled image "busybox"
Normal Created <invalid> kubelet, node1 Created container init-something
Normal Started <invalid> kubelet, node1 Started container init-something
Normal Pulled <invalid> kubelet, node1 Container image "ikubernetes/myapp:v1" already present on machine
Normal Created <invalid> kubelet, node1 Created container init-conta
Normal Started <invalid> kubelet, node1 Started container init-conta
从此Pod的详细信息中Init、Event字段中可以看出,先启动了busybox容器并在30秒之后正常退出了,然后再去启动init-pod
三、Pod生命周期钩子函数
生命周期钩子函数(lifecycle hook)是编程语言(如Angular)中常用的生命周期管理的组件,它实现了程序运行周期中关键时刻的可见性,并赋予用户为此采取某种行为的能力。类似地,容器生命周期钩子使它能够感知其自身生命周期管理中的事件,并在相应的时刻到来时运行由用户指定的处理程序代码。Kubernetes为容器提供了两种生命周期钩子:
1)postStart:于容器创建完成之后立即运行的钩子处理器(handler),不过Kubernetes无法确保它一定会于容器中ENTRYPOINT之前运行
2)preStop:于容器终止操作之前立即运行的钩子处理器,它以同步的方式调用,因此在其完成之前会阻塞删除容器的操作的调用
钩子处理器的实现方式有"Exec"和"HTTP"两种,前一种在钩子事件触发时直接在当前容器中运行由用户定义的命令,后一种则是在当前容器中向某URL发起HTTP请求。
四、钩子函数实验
1)编写钩子函数yaml文件
]# cat lifecycle.yml
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
labels:
app: myapp
release: dev
spec:
containers:
- name: lifecycle-demo-container
image: ikubernetes/myapp:v1
imagePullPolicy: IfNotPresent
lifecycle:
postStart:
exec:
command: ["/bin/sh","-c","echo 'lifecycle hooks handle' > /tmp/test.txt"]
preStop:
exec:
command: ["/usr/sbin/nginx","-s","quit"]
2)进入容器查看测试文件
# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
lifecycle-demo 1/1 Running 0 62s 10.244.1.40 node1 <none> <none>
/ # cat /tmp/test.txt
lifecycle hooks handle
可以看到有此文件,说明容器启动后执行了启动的钩子函数
3)退出Pod
]# kubectl delete -f lifecycle.yml
pod "lifecycle-demo" deleted