Pod 遵循一个预定义的生命周期,起始于 Pending 阶段,如果至少其中有一个主要容器正常启动,则进入 Running,之后取决于 Pod 中是否有容器以失败状态结束而进入 Succeeded 或者 Failed 阶段。
Pod 在其生命周期中只会被调度一次。 一旦 Pod 被调度(分派)到某个节点,Pod 会一直在该节点运行,直到 Pod 停止或者被终止。
Pod可以包含多个容器,应用运行在这些容器里面,同时 Pod 也可以有一个或多个先于应用容器启动的 Init 容器。
Init 容器与普通的容器非常像,但是:
1、它们总是运行到完成。
2、 Init 容器不支持 Readiness,因为它们必须在 Pod 就绪之前运行完成,每个 Init 容器必须运行成功,下一个才能够运行。
如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止。然而,如果 Pod 对应的 restartPolicy 值为 Never,它不会重新启动。
1、Init 容器可以包含一些安装过程中应用容器中不存在的实用工具或个性化代码。
2、Init 容器可以安全地运行这些工具,避免这些工具导致应用镜像的安全性降低。
3、应用镜像的创建者和部署者可以各自独立工作,而没有必要联合构建一个单独的应用镜像。
4、Init 容器能以不同于Pod内应用容器的文件系统视图运行。因此,Init容器可具有访问 Secrets 的权限,而应用容器不能够访问。
5、由于 Init 容器必须在应用容器启动之前运行完成,因此 Init容器提供了一种机制来阻塞或延迟应用容器的启动,直到满足了一组先决条件。一旦前置条件满足,Pod内的所有的应用容器会并行启动。
1、首先需要一个镜像文件pause为pod提供了基础的初始化环境
用阿里云镜像拉取一个busyboxplus镜像
docker pull radial/busyboxplus
2、新建编辑资源清单文件init.yaml,设置生成主容器myapp-container前需要运行两个init初始化容器
apiVersion: v1
kind: Pod
metadata:
name: pod-example
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busyboxplus
command: ['sh','-c','echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busyboxplus
command: ['sh','-c',"until nslookup myservice.default.svc.sluster.local; do echo waiting for myservice; sleep 2; done"]
- name: init-mydb
image: busyboxplus
command: ['sh','-c',"until nslookup mydb.default.svc.sluster.local; do echo waiting for myservice; sleep 2; done"]
可以看到我们的init容器因为没有满足条件所以没有启动,每个init初始化容器必须成功运行并退出后,主容器才能成功运行,因此pod一直未就绪。
3、修改刚才的资源清单,加上满足init容器的条件
apiVersion: v1
kind: Pod
metadata:
name: pod-example
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busyboxplus
command: ['sh','-c','echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busyboxplus
command: ['sh','-c',"until nslookup myservice.default.svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
- name: init-mydb
image: busyboxplus
command: ['sh','-c',"until nslookup mydb.default.svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
---
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
探针 是由 kubelet 对容器执行的定期诊断:
ExecAction:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
TCPSocketAction:对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的。
HTTPGetAction:对指定的端口和路径上的容器的 IP 地址执行 HTTP Get 请求。如果响应的状态码大于等于200且小于400,则诊断被认为是成功的。
每次探测都将获得以下三种结果之一:
成功:容器通过了诊断。
失败:容器未通过诊断。
未知:诊断失败,因此不会采取任何行动。
livenessProbe存活探针:
指示容器是否正在运行。如果存活探测失败,则 kubelet 会杀死容器,并且容器将受到其 重启策略的影响。如果容器不提供存活探针,则默认状态为 Success。
1、编辑资源清单文件pod.yaml,设置在生成pod时使用存活探针探测容器的8080端口是否开放,从而指示容器是否正在运行
[root@server2 pod] cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-example
spec:
containers:
- name: myapp
image: myapp:v1
imagePullPolicy: IfNotPresent
livenessProbe: 探针部分
tcpSocket:
port: 8080 探针检测部分
initialDelaySeconds: 1
periodSeconds: 3
timeoutSeconds: 1
2、读取资源清单创建pod,查看Pod信息可以在状态中看到新建的容器无法成功运行,这是因为我们在文件中指定使用myapp镜像创建容器,myapp容器默认开放的是80端口,8080端口没有开放,存活探针探测到后认为容器未在运行,k8s会杀死容器,并且容器将受到其重启策略的影响
3、如果将我们的探测端口改为80端口,那么探针就可以检测到了.
[root@server2 pod] cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-example
spec:
containers:
- name: myapp
image: myapp:v1
imagePullPolicy: IfNotPresent
livenessProbe: 探针部分
tcpSocket:
port: 80 检测80端口是否开启
initialDelaySeconds: 1
periodSeconds: 3
timeoutSeconds: 1
readinessProbe就绪探针:
指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与 Pod 匹配的所有 Service的端点中删除该 Pod 的 IP 地址。初始延迟之前的就绪状态默认为 Failure。如果容器不提供就绪探针,则默认状态为 Success。
1、增加就绪探针
探测/test.hml是否存在,如果不存在则会显示容器没有就绪
[root@server2 pod] cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-example
spec:
containers:
- name: myapp
image: myapp:v1
imagePullPolicy: IfNotPresent
readinessProbe: 存活谭政
httpGet:
path: /test.html
port: 80
initialDelaySeconds: 1
periodSeconds: 3
timeoutSeconds: 1
2、结果查看
因为文件不存在,所以探测不到,pod显示的是没有就绪。但curl访问容器分配到的ip可以看到生成容器所使用的镜像的默认发布页面,这说明容器实际上已就绪,只是显示未就绪。
3、设置标签
删除刚才的pod,加上容器的标签设置
可以查看到当前的标签为myapp
4、新建svc.yaml
新建文件的内容是:将标签为myapp的Pod提供统一的对外访问80接口
应用服务资源清单svc.yaml后,结果发现service创建成功,但此时查看服务的详细信息发现该服务无后端pod。这是因为就绪探针持续运行,当容器没有就绪,svc不会暴露出去,没有能够提供访问的后端。
5、连接进入pod,在容器默认发布路径下创建指定test.html文件,
就绪探针检测到后指示容器就绪,此时查看服务的详细信息发现该服务有了后端pod
startupProbe启动探针: 指示容器中的应用是否已经启动。如果提供了启动探测(startup probe),则禁用所有其他探测,直到它成功为止。如果启动探测失败,kubelet将杀死容器,容器服从其重启策略进行重启。如果容器没有提供启动探测,则默认状态为成功Success。
实际中,为了防止存活探针误杀正在启动的容器,一般可以给容器配置一个启动探针,启动探针检测成功后才能继续执行存活检测。
比如可以进行如下配置:
startupProbe:
httpGet:
path: /test.html
port: 80
failureThreshold: 30
periodSeconds: 10