官方:https://kubernetes.io/zh/docs/concepts/workloads/pods/pod-lifecycle/
探针是由 kubelet 对容器执行的定期诊断:
ExecAction:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
TCPSocketAction:对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的。
HTTPGetAction:对指定的端口和路径上的容器的 IP 地址执行 HTTP Get 请求。如果响应的状态码大于等于200 且小于 400,则诊断被认为是成功的。
每次探测都将获得以下三种结果之一:
成功:容器通过了诊断。
失败:容器未通过诊断。
未知:诊断失败,因此不会采取任何行动。
Kubelet 可以选择是否执行在容器上运行的三种探针执行和做出反应:
重启策略:PodSpec 中有一个 restartPolicy 字段,可能的值为 Always、OnFailure 和 Never。默认为 Always。
kubelet 使用存活探测器来知道什么时候要重启容器。 例如,存活探测器可以捕捉到死锁(应用程序在运行,但是无法继续执行后面的步骤)
(1)存活探针的定义
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: myapp:v1
args: ## 当容器启动时,执行的命令,,新建文件/tmp/healthy,30s后删除,休眠600s
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe: ## 存活探测 /tmp/healthy是否存在
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5 ## 告诉kubelet在执行第一次探测前应该等待 5 秒
periodSeconds: 5 ## 指定了kubelet每5秒执行一次存活探测
应用资源清单文件:kubectl create -f live.yml
kubelet 在容器内执行命令cat /tmp/healthy来进行探测。如果命令执行成功并且返回值为0,kubelet就会认为这个容器是健康存活的;如果这个命令返回非 0值,kubelet会杀死这个容器并重新启动它
(1)在 30 秒内,查看 Pod 的事件:
kubectl get pod -w
kubectl describe pod liveness-exec
(2)30s后:查看pod的信息
kubectl get pod
kubectl describe pod liveness-exec
(3)容器重启30s后,再次执行命令cat /tmp/healthy来进行探测,失败,会再次重启
kubectl describe pod liveness-exec
kubectl delete -f live.yml
kubelet 使用就绪探测器可以知道容器什么时候准备好了并可以开始接受请求流量, 当一个 Pod 内的所有容器都准备好了,才能把这个 Pod 看作就绪了。 这种信号的一个用途就是控制哪个 Pod 作为 Service 的后端。 在 Pod 还没有准备好的时候,会从 Service 的负载均衡器中被剔除的
下面这个例子同时使用就绪和存活探测器
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: myapp:v1
## kubelet会在容器启动5秒后进行第一次存活探测,尝试连接myapp容器的80端口,如果存活探测失败,这个容器会被重新启动
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 5
periodSeconds: 5
## kubelet会在容器启动3秒后发送第一个就绪探测,判断hello.html是否存在;如果探测成功,这个Pod会被标记为就绪状态,kubelet将继续每隔3秒运行一次检测
readinessProbe:
httpGet:
path: /hello.html ## 文件不存在
port: 80
initialDelaySeconds: 3
periodSeconds: 3
(1)应用文件:kubectl create -f live.yml
kubectl get pod
kubectl describe pod liveness-exec
,Ready失败(2)进入容器的交互环境,使就绪的条件成立:kubectl exec liveness-exec -it -- sh
kubectl get pod
kubectl describe pod liveness-exec
使用 TCP 套接字进行存活探测。 kubelet 会尝试在指定端口和容器建立套接字链接。 如果能建立连接,这个容器就被看作是健康的,如果不能则这个容器就被看作是有问题的
(1)应用文件:kubectl create -f live.yml
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: myapp:v1
## 存活探测:kubelet在容器启动5秒后进行第一次存活探测。尝试连接liveness容器的8080 端口。 如果存活探测失败,这个容器会被重新启动。
livenessProbe:
tcpSocket:
port: 8080 ## 端口错误
initialDelaySeconds: 5
periodSeconds: 5 ## 5s执行一次
## kubelet在容器启动3秒后发送第一个就绪探测。判断myapp默认页面hostname.html是否存在,尝试连接liveness的80端口。如果探测成功,这个Pod会被标记为就绪状态,kubelet将继续每隔3秒运行一次检测
readinessProbe:
httpGet:
path: /hostname.html
port: 80
initialDelaySeconds: 3
periodSeconds: 3 ### 3s探测一次
(2)查看pod的详细信息:kubectl get pod
kubectl describe pod liveness-exec
,存活检测失败,容器重启kubectl get pod
,发现pod一直处于就绪状态kubectl describe pod liveness-exec
,存活检测失败后容器重启除了应用容器,Pod 还可以包含在 Pod 启动期间运行的 Init 容器
每个 Pod 中可以包含多个容器, 应用运行在这些容器里面,同时 Pod 也可以有一个或多个先于应用容器启动的 Init 容器。
Init 容器与普通的容器非常像,除了如下两点:
它们总是运行到完成。
每个都必须在下一个启动之前成功完成。
(1)Init 容器可以包含一些安装过程中应用容器中不存在的实用工具或个性化代码。
(2)Init 容器可以安全地运行这些工具,避免这些工具导致应用镜像的安全性降低。应用镜像的创建者和部署者可以各自独立工作,而没有必要联合构建一个单独的应用镜像。
(3)Init 容器能以不同于Pod内应用容器的文件系统视图运行。因此,Init容器可具有访问 Secrets 的权限,而应用容器不能够访问。
(4)由于 Init 容器必须在应用容器启动之前运行完成,因此 Init 容器提供了一种机制来阻塞或延迟应用容器的启动,直到满足了一组先决条件。一旦前置条件满足,Pod内的所有的应用容器会并行启动。
kubernetes中的service是一种逻辑概念。它定义了一个pod逻辑集合以及访问它们的策略,service与pod的关联同样是通过label完成的。service的目标是提供一种桥梁,他会为访问者提供一个固定的访问IP地址,用于在访问时重定向到相应的后端,这可以使一些非kubernetes原生应用程序,在无需为kubernetes编写特定代码的前提下轻松访问后端
kubectl run demo --image=busyboxplus -it
kubectl attach demo -it
nslookup myservice ## 不能解析myservice
vim service.yml
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- protocol: TCP ## 协议
port: 80
targetPort: 80
kubectl create -f service.yml
kubectl get all
kubectl describe svc myservice
kubectl attach demo -it
nslookup myservice
下面的例子定义了一个具有 Init 容器的简单 Pod。只有Init的myservicet容器启动完成,Pod 将启动 spec 节中的应用容器
(1)编辑文件:vim 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"]
## 只要nslookup myservice.default.svc.cluster.local不成功解析就会一直执行这一句
(2)创建pod:kubectl create -f init.yml
kubectl get pod
,init未完成kubectl logs myapp-pod init-myservice
,出错的原因是nslookup myservice.default.svc.cluster.local未解析,myservicet容器启动完成
(3)创建myservers的:kubectl create -f service.yml
,能解析myservers
kubectl get svc
kubectl get pod
,Init的myservicet容器启动完成,Pod 将启动 spec 节中的应用容器kubectl logs myapp-pod init-myservice
,myservice可以正常解析