文章目录
k8s-Pod
pod 是k8s 中可以调度的最小单位
每个Pod中都可以包含一个或者多个容器,这些容器可以分为两类:
-
用户程序所在的容器,数量可多可少
-
Pause容器,这是每个Pod都会有的一个根容器,它的作用有两个:
-
可以以它为依据,评估整个Pod的健康状态
-
可以在根容器上设置Ip地址,其它容器都此Ip(Pod IP),以实现Pod内部的网路通信
-
pod 配置文件详解
yaml 格式
sh
apiVersion: v1 # api 文档版本
kind: Pod # 资源对象类型,也可以配置为像Deployment、StatefulSet这一类的对象
metadata: # Pod 相关的元数据,用于描述 Pod 的数据
name: nginx-demo # Pod 的名称
labels: # 定义 Pod 的标签
type: app # 自定义 label 标签,名字为 type,值为 app
test: 1.0.0 # 自定义 label 标签,描述 Pod 版本号
namespace: 'default' # 命名空间的配置
spec: # 期望 Pod 按照这里面的描述进行创建
containers: # 对于 Pod 中的容器描述
- name: nginx # 容器的名称
image: nginx:1.7.9 # 指定容器的镜像
imagePullPolicy: IfNotPresent # 镜像拉取策略,指定如果本地有就用本地的,如果没有就拉取远程的
command: # 指定容器启动时执行的命令
- nginx
- -g
- 'daemon off;' # nginx -g 'daemon off;'
workingDir: /usr/share/nginx/html # 定义容器启动后的工作目录
ports:
- name: http # 端口名称
containerPort: 80 # 描述容器内要暴露什么端口
protocol: TCP # 描述该端口是基于哪种协议通信的
env: # 环境变量
- name: JVM_OPTS # 环境变量名称
value: '-Xms128m -Xmx128m' # 环境变量的值
resources:
requests: # 最少需要多少资源
cpu: 100m # 限制 cpu 最少使用 0.1 个核心
memory: 128Mi # 限制内存最少使用 128兆
limits: # 最多可以用多少资源
cpu: 200m # 限制 cpu 最多使用 0.2 个核心
memory: 256Mi # 限制 最多使用 256兆
restartPolicy: OnFailure # 重启策略,只有失败的情况才会重启
pod 生命周期
在整个生命周期中,Pod会出现5种状态(相位),分别如下:
- 挂起(Pending):apiserver已经创建了pod资源对象,但它尚未被调度完成或者仍处于下载镜像的过程中
- 运行中(Running):pod已经被调度至某节点,并且所有容器都已经被kubelet创建完成
- 成功(Succeeded):pod中的所有容器都已经成功终止并且不会被重启
- 失败(Failed):所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非0值的退出状态
- 未知(Unknown):apiserver无法正常获取到pod对象的状态信息,通常由网络通信失败所导致
pod 探针
探针是容器内应用的监测机制,根据不同的探针来判断容器应用当前的状态,根据生命周期图可以看出探针目前存在三种类型
类型 | 描述 | 作用阶段 |
---|---|---|
StartupProbe | 1.16 版本新增的探针,用于判断应用程序是否已经启动了。 | 容器启动阶段 |
LivenessProbe | 用于探测容器中的应用是否运行,如果探测失败,kubelet 会根据配置的重启策略进行重启,若没有配置,默认就认为容器启动成功,不会执行重启策略。 | 容器运行过程中 |
ReadinessProbe | 用于探测容器内的程序是否健康,它的返回值如果返回 success,那么就认为该容器已经完全启动,并且该容器是可以接收外部流量的 | 容器启动之后检测 |
注:
当配置了 startupProbe 后,会先禁用其他探针,直到 startupProbe 成功后,其他探针才会继续。
三种探针的探测方式都是支持,httpGet tcpSocket 和 exec 三种方式。按需使用
StartupProbe
- 使用场景:用于指示容器中的应用是否已经启动。在容器启动初期,某些长时间运行的任务(如加载大型数据集)可能会导致容器在应用实际可用之前无法响应其他探针。在这种情况下,StartupProbe可以用来避免误判容器为失败状态。
- 配置示例:对于需要执行长时间初始化任务的容器,我们可以配置一个StartupProbe,在容器启动初期禁用其他探针,直到初始化任务完成并且容器可以响应其他探针检查为止。
sh
startupProbe:
httpGet:
path: /api/startup
port: 80
host: 127.0.0.1 #主机地址
scheme: HTTP #支持的协议,http或者https
initialDelaySeconds: 60 # 初始化时间
timeoutSeconds: 2 # 超时时间
successThreshold: 1 # 检查 1 次成功就表示成功
failureThreshold: 2 # 监测失败 2 次就表示失败
LivenessProbe
- 使用场景:用于检测容器是否仍在运行。如果容器不再响应探针,Kubernetes将重新启动该容器。
- 配置示例:对于Web应用程序容器,我们可以配置一个HTTP GET请求的LivenessProbe,定期向容器的某个健康检查端点发送请求。如果容器无法响应这些请求,Kubernetes将认为容器已经死亡,并尝试重新启动它。
sh
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30 # 容器启动后等待30秒再开始执行探针检查
periodSeconds: 10 # 每10秒执行一次探针检查
ReadinessProbe
- 使用场景:用于检测容器是否已准备好接收请求。如果容器未就绪,Kubernetes将不会将其添加到Service的后端Endpoint中,从而确保不会向未就绪的容器发送流量。
- 配置示例:对于数据库容器,我们可以配置一个TCP连接的ReadinessProbe,检查数据库是否已启动并可以接受连接。只有当数据库容器就绪时,Web应用程序容器才能开始与其交互。
sh
readinessProbe:
exec:
command:
- sh
- init.sh # 用来检查数据库是否初始化
探针使用建议
为容器配置探针(LivenessProbe、ReadinessProbe 和 StartupProbe)时,需要根据应用程序的特性和需求来合理设置参数。以下是一些建议,帮助您配置这些探针的参数:
- initialDelaySeconds(初始延迟秒数)
- LivenessProbe:设置为应用程序启动并初始化所需的时间。例如,如果应用程序需要加载大量数据或执行长时间的初始化操作,应相应增加这个值。
- ReadinessProbe:同样考虑应用程序的启动和初始化时间,但还要考虑到它是否准备好接收流量。通常,这个值可能会稍大于 LivenessProbe 的初始延迟。
- StartupProbe:如果应用程序在启动初期需要执行长时间的任务,StartupProbe 的初始延迟应设置为足够长的时间,以确保这些任务完成。
- periodSeconds(执行探测的频率)
- 根据应用程序的健康检查需求和资源消耗来设置。较短的周期可以更快速地检测到问题,但也会增加 Kubernetes API 服务器的负载和容器的资源消耗。
- 对于关键服务,可能需要更频繁的探测以确保其可用性。
- 考虑到集群规模和资源限制,避免设置过短的周期。
- timeoutSeconds(超时时间)
- 设置为探针等待响应的合理时间。如果应用程序的响应时间较长,应相应增加这个值。
- 避免设置过短的超时时间,以免因为网络延迟或短暂的负载高峰而导致不必要的探针失败。
- failureThreshold(连续探测失败的次数)
- 根据应用程序的稳定性和容错能力来设置。对于更稳定的服务,可以设置较高的失败阈值。
- 如果应用程序偶尔出现短暂的不稳定状态,增加失败阈值可以减少不必要的重启或流量移除。
- successThreshold(连续探测成功的次数)
- 对于 ReadinessProbe 和 StartupProbe,这个参数决定了容器在多少次连续成功探测后才能被标记为就绪或启动完成。
- 根据应用程序的特性和需求来设置。如果应用程序需要多次成功的健康检查来确保稳定性,可以增加这个值。
- 其他注意事项
- 在生产环境中,建议通过实际测试和观察来调整这些参数,以确保它们与应用程序的实际行为相匹配。
- 考虑到集群的整体性能和资源消耗,避免为所有容器设置过于严格的探针参数。
- 根据应用程序的日志和监控数据来分析和优化探针配置。
总之,合理配置探针参数需要综合考虑应用程序的特性、集群规模、资源限制以及业务需求等多个因素。通过不断测试和调整,您可以找到最适合您应用程序的探针配置。
初始化容器
初始化容器是在pod的主容器启动之前要运行的容器,主要是做一些主容器的前置工作,它具有两大特征:
- 初始化容器必须运行完成直至结束,若某初始化容器运行失败,那么kubernetes需要重启它直到成功完成
- 初始化容器必须按照定义的顺序执行,当且仅当前一个成功之后,后面的一个才能运行
初始化容器有很多的应用场景,下面列出的是最常见的几个:
- 提供主容器镜像中不具备的工具程序或自定义代码
- 初始化容器要先于应用容器串行启动并运行完成,因此可用于延后应用容器的启动直至其依赖的条件得到满足
sh
apiVersion: v1
kind: Pod
metadata:
name: pod-initcontainer
namespace: dev
spec:
containers:
- name: main-container
image: nginx:1.7.9
imagePullPolicy: IfNotPresent
ports:
- name: nginx-port
containerPort: 80
initContainers: # 初始化容器执行操作 执行完之后才会启动主容器
- name: test-mysql
image: busybox:1.30
command: ['sh', '-c', 'until ping 172.26.25.71 -c 1 ; do echo waiting for mysql...; sleep 2; done;']
- name: test-redis
image: busybox:1.30
command: ['sh', '-c', 'until ping 172.26.25.71 -c 1 ; do echo waiting for reids...; sleep 2; done;']
钩子函数
pod 生命周期中,有两个钩子函数,PreStart 和 PreStop,
-
PreStart 在主容器创建之后执行,如果失败,就会重启容器(PreStart使用频率少,因为与有init 和 startupprobe 都处于容器启动前阶段,并且使用不当会与startupprobe 冲突)
-
PreStop 在主容器销毁之前执行,执行完成之后终止容器(用来在容销毁前,在注册中心下线,清理/销毁 数据)
同样钩子处理器支持 exec tcpScoke httpGet 三种方式.下面以PreStop 为例, 配置在containers: 下
sh
lifecycle:
preStop:
exec:
command:
- sh
- -c
- 'sleep 20; kill pgrep java'
执行preStop 时,pod 会处于Termination 状态挂起
但是需要注意,由于 k8s 默认给 pod 的停止宽限时间为 30s,如果我们停止操作会超过 30s 时,不要光设置 sleep 50,还要将 terminationGracePeriodSeconds: 30 也更新成更长的时间,否则 k8s 最多只会在这个时间的基础上再宽限几秒,不会真正等待 50s