pod生命周期
1. 简介
- Pod 可以包含多个容器,应用运行在这些容器里面,同时 Pod 也可以有一个或多个先于应用容器启动的 Init 容器。
- Init 容器与普通的容器非常像,除了如下两点:
它们总是运行到完成。
Init 容器不支持 Readiness,因为它们必须在 Pod 就绪之前运行完成,每个 Init 容器必须运行成功,下一个才能够运行。
- 如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止。然而,如果 Pod 对应的 restartPolicy 值为 Never,它不会重新启动。
- Init 容器能做什么?
Init 容器可以包含一些安装过程中应用容器中不存在的实用工具或个性化代码。
Init 容器可以安全地运行这些工具,避免这些工具导致应用镜像的安全性降低。
应用镜像的创建者和部署者可以各自独立工作,而没有必要联合构建一个单独的应用镜像。
Init 容器能以不同于Pod内应用容器的文件系统视图运行。因此,Init容器可具有访问 Secrets 的权限,而应用容器不能够访问。
由于 Init 容器必须在应用容器启动之前运行完成,因此 Init 容器提供了一种机制来阻塞或延迟应用容器的启动,直到满足了一组先决条件。一旦前置条件满足,Pod内的所有的应用容器会并行启动。
- 探针 是由 kubelet 对容器执行的定期诊断:
ExecAction:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
TCPSocketAction:对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的。
HTTPGetAction:对指定的端口和路径上的容器的 IP 地址执行 HTTP Get 请求。如果响应的状态码大于等于200 且小于 400,则诊断被认为是成功的。
每次探测都将获得以下三种结果之一:
成功:容器通过了诊断。
失败:容器未通过诊断。
未知:诊断失败,因此不会采取任何行动
- Kubelet 可以选择是否执行在容器上运行的三种探针执行和做出反应:
livenessProbe:指示容器是否正在运行。如果存活探测失败,则 kubelet 会杀死容器,并且容器将受到其 重启策略 的影响。如果容器不提供存活探针,则默认状态为 Success。
readinessProbe:指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与 Pod 匹配的所有 Service 的端点中删除该 Pod 的 IP 地址。初始延迟之前的就绪状态默认为 Failure。如果容器不提供就绪探针,则默认状态为 Success。
startupProbe: 指示容器中的应用是否已经启动。如果提供了启动探测(startup probe),则禁用所有其他探测,直到它成功为止。如果启动探测失败,kubelet 将杀死容器,容器服从其重启策略进行重启。如果容器没有提供启动探测,则默认状态为成功Success。
- 重启策略
PodSpec 中有一个 restartPolicy 字段,可能的值为 Always、OnFailure 和 Never。默认为 Always。
- Pod 的生命
一般Pod 不会消失,直到人为销毁他们,这可能是一个人或控制器。
建议创建适当的控制器来创建 Pod,而不是直接自己创建 Pod。因为单独的 Pod 在机器故障的情况下没有办法自动复原,而控制器却可以。
三种可用的控制器:
1.使用 Job 运行预期会终止的 Pod,例如批量计算。Job 仅适用于重启策略为 OnFailure 或 Never 的 Pod。
2.对预期不会终止的 Pod 使用 ReplicationController、ReplicaSet 和 Deployment ,例如 Web 服务器。 ReplicationController 仅适用于具有 restartPolicy 为 Always 的 Pod。
3.提供特定于机器的系统服务,使用 DaemonSet 为每台机器运行一个 Pod
2.示例
2.1 livenessProbe
[root@server2 ~]# vim live.yml ##编辑示例文件
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: busyboxplus
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 2
periodSeconds: 3
[root@server2 ~]# kubectl create -f live.yml ##创建
[root@server2 ~]# kubectl get pod ##查看创建的pod,执行成功不会报错。执行错误会一直重启,知道成功
NAME READY STATUS RESTARTS AGE
demo 1/1 Running 0 6h30m
liveness-exec 1/1 Running 0 16s
[root@server2 ~]# kubectl delete -f live.yml
pod "liveness-exec" deleted
[root@server2 ~]# cat live.yml
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: myapp:v1
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 2
periodSeconds: 3
[root@server2 ~]# kubectl create -f live.yml
[root@server2 ~]# kubectl describe pod liveness-exec ##查看详细信息,发现启动成功
2.2 readinessPeobe
[root@server2 ~]# kubectl delete -f live.yml
pod "liveness-exec" deleted
[root@server2 ~]# vim live.yml
[root@server2 ~]# cat live.yml
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: myapp:v1
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 2
periodSeconds: 3
readinessProbe:
httpGet:
path: /test.html ##没有这个文件就一直请求服务
port: 80
initialDelaySeconds: 3
periodSeconds: 3
[root@server2 ~]# kubectl create -f live.yml
pod/liveness-exec created
[root@server2 ~]# kubectl get pod ##发现一直没有准备好
NAME READY STATUS RESTARTS AGE
demo 1/1 Running 0 6h53m
liveness-exec 0/1 Running 0 5m9s
[root@server2 ~]# kubectl exec -it liveness-exec -- sh ##通过命令行的方式添加test.html文件
/ # cd usr/share/nginx/
/usr/share/nginx # ls
html
/usr/share/nginx # cd html/
/usr/share/nginx/html # ls
50x.html index.html
/usr/share/nginx/html # touch test.html
/usr/share/nginx/html # ls
50x.html index.html test.html
[root@server2 ~]# kubectl get pod ##发现准备好了
NAME READY STATUS RESTARTS AGE
demo 1/1 Running 0 6h53m
liveness-exec 1/1 Running 0 5m9s
2.3 使用init容器的情况initContainers
2.3.1 书写一个测试使用的service
[root@server2 ~]# vim service.yml
[root@server2 ~]# cat service.yml ##创建一个service
---
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 80
[root@server2 ~]# kubectl create -f service.yml
service/myservice created
[root@server2 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d2h
myservice ClusterIP 10.111.239.47 <none> 80/TCP 8s
[root@server2 ~]# kubectl describe svc myservice
Name: myservice
Namespace: default
Labels: <none>
Annotations: <none>
Selector: <none>
Type: ClusterIP
IP Families: <none>
IP: 10.111.239.47
IPs: 10.111.239.47
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: <none> ##没有任何pod
Session Affinity: None
Events: <none>
##测试解析myservice
[root@server2 ~]# kubectl attach demo -it
Defaulting container name to demo.
Use 'kubectl describe pod/demo -n default' to see all of the containers in this pod.
If you don't see a command prompt, try pressing enter.
/ # nslookup myservice
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: myservice
Address 1: 10.111.239.47 myservice.default.svc.cluster.local ##可以解析到myservice
/ # nslookup mydb
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
nslookup: can't resolve 'mydb' ##解析不到mydb
/ #
2.3.2 测试
[root@server2 ~]# vim init.yml
[root@server2 ~]# cat init.yml
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: myapp:v1
initContainers:
- name: init-myservice
image: busyboxplus
command: ['sh', '-c', "until nslookup myservice.default.svc.cluster.local; do echo waiting for myservice; sleep 2; done"] #先搜索myservice,搜索成功之后执行containers
[root@server2 ~]# kubectl delete -f service.yml ##删除myservice服务
service "myservice" deleted
[root@server2 ~]# kubectl create -f init.yml ##创建pod
pod/myapp-pod created
[root@server2 ~]# kubectl get pod ##查看pod,发现初始化失败
NAME READY STATUS RESTARTS AGE
demo 1/1 Running 1 7h21m
myapp-pod 0/1 Init:0/1 0 8s
[root@server2 ~]# kubectl create -f service.yml
service/myservice created
[root@server2 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
demo 1/1 Running 1 7h23m
myapp-pod 1/1 Running 0 2m
[root@server2 ~]# kubectl delete -f init.yml ##实验做完之后删除,保证环境的纯净
pod "myapp-pod" deleted