三.kubernetes核心资源
3.深入解读Pod资源
3.1-k8s核心资源pod介绍
3.1.1-Pod是什么?
Pod 是 Kubernetes 中的最小调度单元,k8s 是通过定义一个 Pod 的资源,然后在 Pod 里面运行容
器,容器需要指定一个镜像,这样就可以用来运行具体的服务。一个 Pod 封装一个容器(也可以封装多
个容器),Pod 里的容器共享存储、网络等。也就是说,应该把整个 pod 看作虚拟机,然后每个容器相当
于运行在虚拟机的进程。Pod 是需要调度到 k8s 集群的工作节点来运行的,具体调度到哪个节点,是根据 scheduler 调度器实 现的。
3.1.2-Pod如何管理多个容器
Pod 中可以同时运行多个容器。同一个 Pod 中的容器会自动的分配到同一个 node 上。同一个 Pod 中 的容器共享资源、网络环境,它们总是被同时调度,在一个 Pod 中同时运行多个容器是一种比较高级的 用法,只有当你的容器需要紧密配合协作的时候才考虑用这种模式。例如,你有一个容器作为 web 服务 器运行,需要用到共享的 volume,有另一个“sidecar”容器来从远端获取资源更新这些文件。
一些 Pod 有 init 容器和应用容器。 在应用程序容器启动之前,运行初始化容器。
3.1.3-Pod网络
Pod 是有 IP 地址的,每个 pod 都被分配唯一的 IP 地址(IP 地址是靠网络插件 calico、flannel、
weave 等分配的),POD 中的容器共享网络名称空间,包括 IP 地址和网络端口。 Pod 内部的容器可以使
用 localhost 相互通信。 Pod 中的容器也可以通过网络插件 calico 与其他节点的 Pod 通信。
3.1.4-Pod存储
创建 Pod 的时候可以指定挂载的存储卷。 POD 中的所有容器都可以访问共享卷,允许这些容器共享 数据。 Pod 只要挂载持久化数据卷,Pod 重启之后数据还是会存在的。
3.1.5-Pod启动方式
Pod 是 Kubernetes 中最基本的部署调度单元,可以包含 container,逻辑上表示某种应用的一个 实例。例如一个 web 站点应用由前端、后端及数据库构建而成,这三个组件将运行在各自的容器中,那 么我们可以创建包含三个 container 的 pod。
master 节点:kubectl -> kube-api -> kubelet -> CRI 容器环境初始化
第一步: 客户端提交创建 Pod 的请求,可以通过调用 API Server 的 Rest API 接口,也可以通过 kubectl 命令行 工具。如 kubectl apply -f filename.yaml(资源清单文件)
第二步: apiserver 接收到 pod 创建请求后,会将 yaml 中的属性信息(metadata)写入 etcd。
第三步: apiserver 触发 watch 机制准备创建 pod,信息转发给调度器 scheduler,调度器使用调度算法选择 node,调度器将 node 信息给 apiserver,apiserver 将绑定的 node 信息写入 etcd 调度器用一组规则过滤掉不符合要求的主机。比如 Pod 指定了所需要的资源量,那么可用资源比 Pod 需 要的资源量少的主机会被过滤掉。 scheduler 查看 k8s api ,类似于通知机制。 首先判断:pod.spec.Node == null? 若为 null,表示这个 Pod 请求是新来的,需要创建;因此先进行调度计算,找到最“闲”的 node。 然后将信息在 etcd 数据库中更新分配结果:pod.spec.Node = nodeA (设置一个具体的节点) ps:同样上述操作的各种信息也要写到 etcd 数据库中中
第四步: apiserver 又通过 watch 机制,调用 kubelet,指定 pod 信息,调用 Docker API 创建并启动 pod 内的容 器。
第五步: 创建完成之后反馈给 kubelet, kubelet 又将 pod 的状态信息给 apiserver, apiserver 又将 pod 的状态信息写入 etcd。
kubelet提交create pod请求→apiserver收到将属性写入etcd→同时触发watch信息传入schedule→schedule选择node传回apiserver→apiserver将绑定的node信息写入etcd,过滤不符合的→etcd更新分配结果,apiserver通过wath调用kubelet,指定pod信息→传入Docker API启动容器→返回kubelet返回apiserver返回etcd写入
3.1.6-Pod资源清单详细解读
通过 kubectl explain 查看定义 Pod 资源包含哪些字段。
apiVersion: v1 #*版本号,如v1
kind: Pod #*资源类型,如Pod
metadata: #元数据
name: string #Pod名字
namespace: string #所属命名空间
labels: #自定义标签
- name: string #两个都是自定义名字
annotation: #自定义注释列表
- name: string
spec: #*描述pod的
containers: #*定义容器的,必须字段
- name: #*必须,容器名字
image: #*定义所需的镜像
imagePullPolicy: #*Always 不管本地有无,重新拉取;Never 从不拉取;IfNotPresent
command: #容器启动命令,不写用打包时候的
args: #容器启动命令参数列表
workingDir: #容器工作目录
volumeMounts: #挂载到容器内部的存储卷配置
- name: string #共享存储卷的名称
mountPath: string #存储卷在容器内的绝对路径
readOnly: boolean #是否为只读
ports: #*端口
- name: string #端口名字
containerPort: int #*必须,容器暴露的端口
hostIP: int #将服务暴露到宿主机端口时,指定宿主机IP
hostPort: int #映射到的宿主机端口
protocol: int #协议,TCP UDP
env: #运行前的环境变量
- name: string #环境变量名称
value: string #环境变量值
resources: #资源限制和请求设置
limits: #资源限制设置
cpu: string #cpu限制 单位为core数
memory: string #内存限制 单位M G
requests: #资源请求设置
cpu: string #cpu请求,容器启动初始可用量
memory: string #内存请求,容器启动初始可用量
livenessProbe: #对Pod内容器健康检查,探测无响应则重启:exec,httpGet,tcpSocket三选一
exec: #检查方式为exec
command: #定制命令或脚本
httpGet: #需指定Path和port
path: #url
port: #端口
host: #要连接的主机名,默认为 Pod IP,可以在 http request head 中设置 host
scheme: #用于连接 host 的协议,默认为 HTTP。
HttpHeaders: #自定义 HTTP 请求 headers,HTTP 允许重复 headers。
- name:
value:
tcpSocket:
port:
initialDelaySeconds: 0 #容器启动后首次探测时间,单位s
timeoutSeconds: 0 #等待响应超时时间,单位S,默认1S
periodSeconds: 0 #周期性,单位S,默认10S一次
successThreshold: 0
failureThreshold: 0
securityContext:
privileged: false
restartPolicy: #重启策略,Always,OnFailure以非0退出就重启,Nerver不重启
nodeSelector: key:value #调度到指定labels的node
imagePullSecrets: #Pull镜像使用的secret名称
- name: string
hostNetwork: false #是否使用宿主机网络模式
volumes: #定义共享存储卷
- name: string
emptyDir: {} #类型为emptyDir与Pod同生命周期的零时目录,默认的
hostPath: #挂载到宿主机的哪个目录
secret: #类型为secret的存储卷,挂载集群与定义的secre对象到容器内部
screname: string
items:
- key: string
path: string
configMap: #类型为configMap的
name: string
items:
- key:string
path: string
3.1.7-自定义Pod创建
apiVersion: v1 #api 版本 kind: Pod #创建的资源 metadata: name: tomcat-test #Pod 的名字 namespace: default #Pod 所在的名称空间 labels: app: tomcat #Pod 具有的标签 spec: containers: - name: tomcat-java #Pod 里容器的名字 ports: - containerPort: 8080 #容器暴露的端口 image: docker.io/library/tomcat:latest #容器使用的镜像 imagePullPolicy: IfNotPresent #镜像拉取策略
3.1.8-kubectl对pod的使用
kubctl logs pod-name #查看POD日志
kubectl logs pod-name -c container-name #查看pod内指定容器日志
kubctl exec -it pod-name -- /bin/bash #进入容器
kubctl exec -it pod-name -c container-name -- /bin/bash #进入Pod内指定容器
kubctl run podname --image=docker.io/library/name:latest --image-pull-policy='IfNotPresent' --port=xx #命令启动
3.1.9-Pod的常见状态和重启策略
#常见的Pod状态
挂起(Pending)
#我们在请求创建 pod 时,条件不满足,调度没有完成,没有任何一个节点能满足调度条件,已经创建了 pod 但是没有适合它运行的节点叫做挂起,调度没有完成,处于 pending的状态会持续一段时间:包括调度 Pod 的时间和通过网络下载镜像的时间。
运行中(Running)
#Pod 已经绑定到了一个节点上,Pod 中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态。
成功(Succeeded)
#Pod 中的所有容器都被成功终止,并且不会再重启。
失败(Failed)
#Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止。
未知(Unknown)
#未知状态,所谓 pod 是什么状态是 apiserver 和运行在 pod 节点的 kubelet 进行通信获取状态信息的,如果节点之上的 kubelet 本身出故障,那么 apiserver 就连不上kubelet,得不到信息了,就会看 Unknown
Evicted 状态
#出现这种情况,多见于系统内存或硬盘资源不足,可 df-h 查看 docker 存储所在目录的资源使用情况,如果百分比大于 85%,就要及时清理下资源,尤其是一些大文件、docker 镜像。
CrashLoopBackOff
#容器曾经启动了,但可能又异常退出了
Error 状态
#Pod 启动过程中发生了错误
3.2-命名空间
3.2.1-什么是命名空间
Kubernetes 支持多个虚拟集群,它们底层依赖于同一个物理集群。 这些虚拟集群被称为命名空
间。
命名空间 namespace 是 k8s 集群级别的资源,可以给不同的用户、租户、环境或项目创建对应的命
名空间,例如,可以为 test、devlopment、production 环境分别创建各自的命名空间。
命名空间适用于存在很多跨多个团队或项目的用户的场景。对于只有几到几十个用户的集群,根本 不需要创建或考虑命名空间。
3.2.2-命名空间的使用
#创建命名空间
kubctl create ns name
#切换默认查看的命名空间
kubectl config set-context --current --namespace=kube-system
#查看哪些资源属于命名空间级
kubectl api-resources --namespaced=true
3.2.3-命名空间的资源限制
配置该项后,创建的Pod必须设置资源限制,否则失败
version: v1 kind: ResourceQuota metadata: name: mem-cpu-quota namespace: test spec: hard: requests.cpu: "2" requests.memory: 2Gi limits.cpu: "4" limits.memory: 4Gi #所有容器的请求总额不得超过2cpu 2gi内存,限额4cpu 4gi内存
#设置上面后,pod.spec.containers 需要添加resources
spec:
containers:
- name:
resources:
memeory:
cpu:
limits:
memory:
cpu:
3.3-标签lables
3.3.1-什么是标签
标签其实就一对 key/value ,被关联到对象上,比如 Pod,标签的使用我们倾向于能够表示对象的特 殊特点,就是一眼就看出了这个 Pod 是干什么的,标签可以用来划分特定的对象(比如版本,服务类型 等),标签可以在创建一个对象的时候直接定义,也可以在后期随时修改,每一个对象可以拥有多个标 签,但是,key 值必须是唯一的。创建标签之后也可以方便我们对资源进行分组管理。如果对 pod 打标 签,之后就可以使用标签来查看、删除指定的 pod。 在 k8s 中,大部分资源都可以打标签。
3.3.2-标签的命令使用
#对已经存在的pod打标签
kubectl label pods name key=value
#查看pod标签
kubectl get pods name --show-labels
#列出pod标签key值是app的pod,L显示value值
kubectl get pods -l app
3.4-Node节点选择器
3.4.1-什么是node选择器
我们在创建 pod 资源的时候,pod 会根据 schduler 进行调度,那么默认会调度到随机的一个工作 节点,如果我们想要 pod 调度到指定节点或者调度到一些具有相同特点的 node 节点,可以使用 pod 中的 nodeName 或者 nodeSelector 字段指定要调度到的 node 节点
#spec.nodeName 直接指定主机
spec:
nodeName: hostname
#spec.nodeSelector 通过标签选择
spec:
nodeSelector:
key: value
3.5-亲和性-Pod主动权
3.5.1-node节点亲和性
#给node打标签
kubctl label nodes nodename key=value
#node 节点亲和性调度:nodeAffinity pods.spec.affinity pods.spec.affinity.nodeAffinity
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution: #尽量满足,不是必要,软亲和
requiredDuringSchedulingIgnoredDuringExecution: #必须满足,硬条件,硬亲和
nodeSelectorTerms:
- matchExperssions: #匹配表达式 选其一
- key:
values:
- matchFields: #匹配字段
- key:
values:
operator: #做等值选择还是不等值选择
#示例-硬性检查当前节点中有任意一个节点拥有 zone 标签的值是 foo 或者 bar,就可以把 pod 调度到这个 node 节点的 foo 或者 bar 标签上的节点上
apiversion: v1
kind: Pod
metadata:
name: pod-node-affinity-test
namespace: default
labels:
app: myapp
spec:
containers:
- name: myapp
image: docker.io/library/nginx:latest
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: zone
operator: In
values:
- foo
- bar
3.5.2-Pod节点亲和性
pod自身有podaffinity和podAntiAffinity两种表达形式
podaffinity:pod 和 pod 更倾向腻在一起,把相近的 pod 结合到相近的位置,如同一区域,同一
机架,这样的话 pod 和 pod 之间更好通信,比方说有两个机房,这两个机房部署的集群有 1000 台
主机,那么我们希望把 nginx 和 tomcat 都部署同一个地方的 node 节点上,可以提高通信效率;
podunaffinity:pod 和 pod 更倾向不腻在一起,如果部署两套程序,那么这两套程序更倾向于反
亲和性,这样相互之间不会有影响。
#spec.affinity.podAffinity
spec:
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution: #软
requiredDuringSchedulingIgnoredDuringExecution: #硬
- labelSelector: #
matchExpressions:
- {key: app2,operator: In, values: ["myapp2"]}
- matchLabels:
topologyKey: kubernetes.io/hostname #位置拓扑的键,必须字段node的labels
namespace: #labelSelector选择的资源在那个ns里面,通过这个指定,不指定为当前pod的
#实例-Pod-1
apiVersion: v1
kind: Pod
metadata:
name: pod-one
labels:
app2: myapp2
spec:
containers:
- name: pod-podaffinity-test-1
image: docker.io/library/nginx:latest
--- #pod-2
apiVersion: v1
kind: Pod
metadata:
name: pod-two
labels:
app3: myapp3
spec:
containers:
- name: pod-podaffinity-test-busybox-2
image: docker.io/library/busybox:latest
imagePullPolicy: IfNotPresent
command: ["sh","-c","sleep 3600"]
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution: #硬
- labelSelectoy:
matchExpressions:
- {key: app2,operator: In, values: ["myapp2"]}
topologyKey: kubernetes.io/hostname
#上面表示创建的 pod-2 必须与拥有 app2=myapp2 标签的 pod 在一个节点上
3.5.3-Pod节点的反亲和性
和亲和性相反,定义的pod与限制的内容唱反调。远离其
#亲和性的代码spec.affinity.podAffinity 改成podAntiAffinity
3.6-污点,容忍度-node主动权
3.6.1-什么是污点和容忍度
给了节点选则的主动权,我们给节点打一个污点,不容忍的 pod 就运行不上来,污点就是定义在节点上的键值属性数据,可以定决定拒绝那些 pod;
taints 是键值数据,用在节点上,定义污点;
tolerations 是键值数据,用在 pod 上,定义容忍度,能容忍哪些污点
pod 亲和性是 pod 属性;但是污点是节点的属性,污点定义在 nodeSelector 上
3.6.2-污点的定义
kubectl describe nodes master1 |grep Taints #查看node的污点
kubectl describe pods kube-apiserver-master1 -n kube-system |grep Tolerations #查看node的容忍度
#taints 的 effect 用来定义对 pod 对象的排斥等级
NoSchedule:
#仅影响 pod 调度过程,当 pod 能容忍这个节点污点,就可以调度到当前节点,后来这个节点的污点改了,加了一个新的污点,使得之前调度的 pod 不能容忍了,那这个 pod 会怎么处理,对现存的 pod 对象不产生影响
NoExecute:
#既影响调度过程,又影响现存的 pod 对象,如果现存的 pod 不能容忍节点后来加的污点,这个 pod就会被驱逐
PreferNoSchedule:
#最好不,也可以,是 NoSchedule 的柔性版本
---
#在 pod 对象定义容忍度的时候支持两种操作:
1.等值密钥:key 和 value 上完全匹配
2.存在性判断:key 和 effect 必须同时匹配,value 可以是空
在 pod 上定义的容忍度可能不止一个,在节点上定义的污点可能多个,需要琢个检查容忍度和污
点能否匹配,每一个污点都能被容忍,才能完成调度,如果不能容忍怎么办,那就需要看 pod 的
容忍度了
3.6.3-污点容忍度的示例
#将node2当成生产环境专用,如果pod没有容忍度,则不会在此node节点调度 注意:有pod的会被撵走
kubectl taint node node2 node-type=production:NoSchedule
#pod-1 pod.spec.tolerations
spec:
tolerations: #容忍度
- key: "node-type"
value: "production"
effect: "NoSchedule"
operatoy: "Equal" #equal等值匹配,上3值必须完全匹配;Exists为只要对应的键是存在即可
3.7-Pod的生命周期-Init容器和主容器
3.7.1-Pod的删除过程
#pod 在整个生命周期中有非常多的用户行为:
#1、初始化容器完成初始化
#2、主容器启动后可以做启动后钩子
#3、主容器结束前可以做结束前钩子
#4、在主容器运行中可以做一些健康检测,如 liveness probe,readness probe
#优雅的删除资源对象
#当用户删除包含Pod资源的对象(RC,deployment等),K8s为了让应用程序完成正在处理的请求后,再关闭软件;k8s提供了两种信息通知:
默认: #K8S 通知 node 执行 docker stop 命令,docker 会先向容器中 PID 为 1 的进程发送系统信号 SIGTERM,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认超时时间(30s),会继续发送 SIGKILL 的系统信号强行 kill 掉进程。
Pod生命周期(利用PreStop回调函数): #它执行在发送终止信号之前。 默认情况下,所有的删除操作的优雅退出时间都在 30 秒以内。kubectl delete 命令支持--grace-period=的选项,以运行用户来修改默认值。0 表示删除立即执行,并且立即从 API 中删除 pod。在节点上,被设置了立即结束的的 pod,仍然会给一个很短的优雅退出时间段,才会开始被强制杀死。
3.7.2-什么是Init容器?
Pod 里面可以有一个或者多个容器,部署应用的容器可以称为主容器,在创建 Pod 时候,Pod 中 可以有一个或多个先于主容器启动的 Init 容器,这个 init 容器就可以成为初始化容器,初始化容 器一旦执行完,它从启动开始到初始化代码执行完就退出了,它不会一直存在,所以在主容器启 动之前执行初始化,初始化容器可以有多个,多个初始化容器是要串行执行的,先执行初始化容 器 1,在执行初始化容器 2 等,等初始化容器执行完初始化就退出了,然后再执行主容器,主容器 一退出,pod 就结束了,主容器退出的时间点就是 pod 的结束点,它俩时间轴是一致的;
Init 容器就是做初始化工作的容器。可以有一个或多个,如果多个按照定义的顺序依次执行,只 有所有的初始化容器执行完后,主容器才启动。由于一个 Pod 里的存储卷是共享的,所以 Init Container 里产生的数据可以被主容器使用到,Init Container 可以在多种 K8S 资源里被使用 到,如 Deployment、DaemonSet, StatefulSet、Job 等,但都是在 Pod 启动时,在主容器启动前 执行,做初始化工作。
Init 容器与普通的容器区别是:
1、Init 容器不支持 Readiness,因为它们必须在 Pod 就绪之前运行完成
2、每个 Init 容器必须运行成功,下一个才能够运行
3、如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止,然
而,如果 Pod 对应的 restartPolicy 值为 Never,它不会重新启动。
#spec.initContainers
spec:
initContainers:
- name:
image:
command: ['sh','-c','']
3.7.3-主容器钩子lifecycle
容器钩子:
初始化容器启动之后,开始启动主容器,在主容器启动之前有一个 post start hook(容器启动后 钩子)和 pre stop hook(容器结束前钩子),无论启动后还是结束前所做的事我们可以把它放两 个钩子,这个钩子就表示用户可以用它来钩住一些命令,来执行它,做开场前的预设,结束前的 清理,如 awk 有 begin,end,和这个效果类似;
postStart: #该钩子在容器被创建后立刻触发,通知容器它已经被创建。如果该钩子对应的 hook handler 执行失败,则该容器会被杀死,并根据该容器的重启策略决定是否要重启该容器,这个钩子不需要传递任何参数。
preStop: #该钩子在容器被删除前触发,其所对应的 hook handler 必须在删除该容器的请求发送给 Docker daemon 之前完成。在该钩子对应的 hook handler 完成后不论执行的结果如何,Docker daemon 会发送一个 SGTERN 信号量给 Docker daemon 来删除该容器,这个钩子不需要传递任何参数。
#示例spec.containers.lifecycle
spec:
containers:
- name:
lifecycle:
postStart:
exec:
command:
- "cp"
- "/start.jar"
- "/app"
prestop:
httpGet:
host: master.com
path: /waring
port: 80
scheme: HTTP
#定义了一个Pod,包含一个java web容器。启动成功后复制start.jar,终止前,HTTP请求到监控发送警告
3.7.4-Pod存活性探测 livenessProbe 和就绪性探测 readinessProbe
livenessProbe:存活性探测:
#许多应用程序经过长时间运行,最终过渡到无法运行的状态,除了重启,无法恢复。通常情况下,K8S 会发现应用程序已经终止,然后重启应用程序 pod。有时应用程序可能因为某些原因(后端服务故障等)导致暂时无法对外提供服务,但应用软件没有终止,导致 K8S 无法隔离有故障的pod,调用者可能会访问到有故障的 pod,导致业务不稳定。K8S 提供 livenessProbe 来检测容器是否正常运行,并且对相应状况进行相应的补救措施。如果容器配置中没有配置livenessProbe,Kubelet 将认为存活探针探测一直为成功状态。
readinessProbe:就绪性探测:
#在没有配置 readinessProbe 的资源对象中,pod 中的容器启动完成后,就认为 pod 中的应用程序可以对外提供服务,该 pod 就会加入相对应的 service,对外提供服务。但有时一些应用程序启动后,需要较长时间的加载才能对外服务,如果这时对外提供服务,执行结果必然无法达到预期效果,影响用户体验。比如使用 tomcat 的应用程序来说,并不是简单地说 tomcat 启动成功就可以对外提供服务的,还需要等待 spring 容器初始化,数据库连接上等等。当探测成功后才使 Pod 对外提供网络访问,设置容器 Ready 状态为 true,如果探测失败,则设置容器的Ready 状态为 false。
两种探针都支持下面三种探测方法:
1、ExecAction:在容器中执行指定的命令,如果执行成功,退出码为 0 则探测成功。
2、TCPSocketAction:通过容器的 IP 地址和端口号执行 TCP 检 查,如果能够建立 TCP 连接,
则表明容器健康。
3、HTTPGetAction:通过容器的 IP 地址、端口号及路径调用 HTTP Get 方法,如果响应的状态码
大于等于 200 且小于 400,则认为容器健康
探测结果:
1、Success:表示通过检测。
2、Failure:表示未通过检测。
3、Unknown:表示检测没有正常进行。
区别:
是一个是用于探测应用的存活,一个是判断是否对外提供流量的条件。
#pod.spec.containers.livenessProbe readinessProbe
spec:
containers:
livenessProbe:
initialDelaySeconds: #Pod 启动后首次进行检查的等待时间,单位“秒”
periodSeconds: #检查间隔时间。默认10S
timeoutSeconds: #等待超时时间,默认1s
successThreshold: #连续探测几次成功,默认1,最小1
failureThreshold: #探测失败重试次数,重试一定次数后认定为失败。默认3,最小1
readinessProbe:
区别:
#ReadinessProbe 和 livenessProbe 可以使用相同探测方式,只是对 Pod 的处置方式不同: readinessProbe 当检测失败后,将 Pod 的 IP:Port 从对应的 EndPoint 列表中删除。 livenessProbe 当检测失败后,将杀死容器并根据 Pod 的重启策略来决定作出对应的措施。
3.7.5-Pod探针使用示例-livenessProbe
#通过exec
apiVersion: v1
kind: Pod
metadata:
name: liveness-exec
labels:
test: liveness
spec:
containers:
- name: liveness
image: docker.io/library/busybox:latest
args: #创建探测文件
- /bin/sh
- -c
- touch /root/healthy; sleep 30; rm -rf /root/healthy; sleep 600
livenessProbe:
initialDelaySeconds: 10
periodSeconds: 5
exec:
command:
- cat
- /root/healthy
#容器在初始化后,在root创建healthy文件,睡眠30S后,删除。存活探针延迟10S后,cat输入该文件,能成功执行则为成功。后30文件不见后,kubernetes会根据pod设置的重启策略来判断是否重启pob
#通过http
apiVersion: v1
kind: Pod
metadata:
name: liveness-http
labels:
test: liveness
spec:
containers:
- name: liveness-http
image: docker.io/library/nginx:latest
livenessProbe:
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 80
path: /
#启动一个nginx。存活探针可以使用 HTTPGet 方式向服务发起请求;如果探测失败,则会杀死 Pod 进行重启操作。推荐java web项目任何大于或等于 200 且小于 400 的代码表示探测成功。
#通过tcp
apiVersion: v1
kind: Pod
metadata:
name: liveness-tcp
labels:
test: liveness
spec:
containers:
- name: liveness-tcp
image: docker.io/library/nginx:latest
livenessProbe:
initialDelaySeconds: 15
periodSeconds: 20
tcpSocket:
port: 80
#启动一个nginx尝试连接容器的 80 端口,如果连接失败则将杀死 Pod 重启容器。
3.7.6-Pod探针使用示例-readinessProbe
#区别:是一个是用于探测应用的存活,一个是判断是否对外提供流量的条件
apiVersion: v1
kind: Pod
metadata:
name: readiness
labels:
test: readiness
spec:
containers:
- name: readiness-springboot
image: docker.io/gazgeek/springboot-helloworld
ports:
- name: server
containerPort: 8080
readinessProbe:
initialDelaySeconds: 20
periodSeconds: 5
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 8080
---
apiVersion: v1
kind: Service
metadata:
name: springboot
labels:
app: springboot
spec:
type: NodePort
ports:
- name: server
port: 8080
targetPort: 8080
nodePort: 31888
selector:
test: readiness
#设置 ReadinessProbe 探测 SpringBoot 项目的 8080 端口如果探测成功则代表内部程序以及启动,就开放对外提供接口访问,否则内部应用没有成功启动,暂不对外提供访问,直到就绪探针探测成功。
3.7.7-Pod-ReadinessProbe + LivenessProbe 配合使用示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: springboot-live-read
labels:
test: liveread
spec:
replicas: 1
selector:
matchLabels:
test: liveread
template:
metadata:
name: springboot-live-read-pod
labels:
test: liveread
spec:
containers:
- name: springboot-live-read
image: docker.io/gazgeek/springboot-helloworld
ports:
- name: server
containerPort: 8080
livenessProbe:
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 8080
readinessProbe:
initialDelaySeconds: 20
periodSeconds: 5
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 8080
---
apiVersion: v1
kind: Service
metadata:
name: springboot
labels:
app: springboot
spec:
type: NodePort
ports:
- name: server
port: 8080
targetPort: 8080
nodePort: 31888
selector:
test: liveread