首先来看一下,整个需求的来源:当把应用迁移到 Kubernetes 以后,要如何去保障应用的健康与稳定呢?其实很简单,能够从两个方面来进行加强:html
1,首先是提升应用的可观测性;
2,第二是提升应用的可恢复能力。node
从可观测性上来说,能够在三个方面来去作加强:nginx
1,首先是应用的健康状态上面,能够实时地进行观测;
2,第二个是能够获取应用的资源使用状况;
3,第三个是能够拿到应用的实时日志,进行问题的诊断与分析。web
当出现了问题以后,首先要作的事情是要下降影响的范围,进行问题的调试与诊断。最后当出现问题的时候,理想的情况是:能够经过和 K8s 集成的自愈机制进行完整的恢复。 vim
livenessProbe:[活跃度探测],就是根据用户自定义的规则判断容器是否健康。也叫存活指针,若是 Liveness 指针判断容器不健康,此时会经过 kubelet 杀掉相应的 pod,并根据重启策略来判断是否重启这个容器。若是默认不配置 Liveness 指针,则默认状况下认为它这个探测默认返回是成功的。api
什么是Endpoint?
Endpoint是k8s集群中的一个资源对象,存储在etcd中,用来记录一个service对应的全部pod的访问地址。app
2,Liveness和Readness两种探测机制的使用场景:
Liveness 指针适用场景是支持那些能够从新拉起的应用,而 Readiness 指针主要应对的是启动以后没法当即对外提供服务的这些应用。curl
3,,Liveness和Readness两种探测机制的相同点和不一样点:
相同点是根据探测pod内某个应用或文件,来检查pod的健康情况,不一样点是liveness若是探测失败会重启pod,而readliness则在连续3次探测失败以后,会将pod设置为不可用的状态,并不会重启pod。tcp
4,Liveness 指针和 Readiness 指针支持三种不一样的探测方式:ide
第一种探测方式和第三种很是类似,通常经常使用的是第一和第二种的探测方式。
方法1:使用exec探测方式,查看pod内某个指定的文件是否存在,若是存在则认为状态为健康的,不然会根据设置的重启重启策略重启pod。
###pod的配置文件:
[root@sqm-master yaml]# vim livenss.yaml kind: Pod apiVersion: v1 metadata: name: liveness labels: name: liveness spec: restartPolicy: OnFailure ##定义重启策略,仅在pod对象出现错误时才重启 containers: - name: liveness image: busybox args: - /bin/sh - -c - touch /tmp/test; sleep 30; rm -rf /tmp/test; sleep 300 #建立文件,而且在30秒后将文件进行删除 livenessProbe: #执行活跃度探测 exec: command: - cat #探测/tmp目录下是有test文件,若是有则表明健康,若是没有则执行重启pod策略。 - /tmp/test initialDelaySeconds: 10 #当容器运行多久以后开始探测(单位是s) periodSeconds: 5 #探测频率(单位s),每隔5秒探测一次。
探测机制中其余的可选字段:
- initialDelaySeconds:容器启动后第一次执行探测是须要等待多少秒。
- periodSeconds:执行探测的频率。默认是10秒,最小1秒。
- timeoutSeconds:探测超时时间。默认1秒,最小1秒。
- successThreshold:探测失败后,最少连续探测成功多少次才被认定为成功。默认是1。对于liveness必须是1。最小值是1。
- failureThreshold:探测成功后,最少连续探测失败多少次才被认定为失败。默认是3。最小值是1。
//运行该pod进行测试: [root@sqm-master yaml]# kubectl apply -f livenss.yaml pod/liveness created
//监测pod的状态:
会在容器启动10秒后开始探测,且每5s探测一次。
咱们能够看到pod一直在重启中,从上图看到RESTARTS
的次数已经为7次了,缘由是在启动pod时执行了该命令:
/bin/sh -c "touch /tmp/test; sleep 30; rm -rf /tmp/test; sleep 300"
在容器生命的最初30秒内有一个 /tmp/test 文件,在这30秒内 cat /tmp/test命令会返回一个成功的返回码。但30秒后, cat /tmp/test 将返回失败的返回码,会触发pod的重启策略。
//咱们来查看一下pod的Events信息: [root@sqm-master ~]# kubectl describe pod liveness
从上面的事件中能够发现,探测失败,将重启容器,缘由是在指定的目录下没有发现该文件。
方法2:使用httpGet探测方式,运行一个web服务,探测web网页的根目录下是否有指定的文件,也就等同于 “curl -I 容器ip地址:/healthy”。(这里的目录/,指定的是容器内提供web服务的主目录。)
//pod的yaml文件:
[root@sqm-master yaml]# vim http-livenss.yaml apiVersion: v1 kind: Pod metadata: name: web labels: name: mynginx spec: restartPolicy: OnFailure #定义pod重启策略 containers: - name: nginx image: nginx ports: - containerPort: 80 livenessProbe: #定义探测机制 httpGet: #探测方式为httpGet scheme: HTTP #指定协议 path: /healthy #指定路径下的文件,若是不存在,探测失败 port: 80 initialDelaySeconds: 10 #当容器运行多久以后开始探测(单位是s) periodSeconds: 5 #探测频率(单位s),每隔5秒探测一次 --- apiVersion: v1 #关联一个service对象 kind: Service metadata: name: web-svc spec: selector: name: mynginx ports: - protocol: TCP port: 80 targetPort: 80
httpGet探测方式有以下可选的控制字段:
- host:链接的主机名,默认链接到pod的IP。你可能想在http header中设置”Host”而不是使用IP。
- scheme:链接使用的schema,默认HTTP。
- path: 访问的HTTP server的path。
- httpHeaders:自定义请求的header。HTTP运行重复的header。
- port:访问的容器的端口名字或者端口号。端口号必须介于1和65525之间。
//运行该pod: [root@sqm-master yaml]# kubectl apply -f http-livenss.yaml pod/web created service/web-svc created
##查看pod运行10秒前的状况:
##最开始的10秒该容器是活着的,且返回的状态码为200.
###10秒后当探测机制开始探测时再次查看pod的状况:
//查看的pod的events: [root@sqm-master yaml]# kubectl describe pod web
能够看到返回的状态码为404,表示在网页的根目录下并无找到指定的文件,表示探测失败,且重启4次,状态是completed(完成的状态),说明pod是存在问题的。
2)接下来咱们继续进行检测,使其最终探测成功:
修改pod的配置文件:
[root@sqm-master yaml]# vim http-livenss.yaml
//从新运行pod: [root@sqm-master yaml]# kubectl delete -f http-livenss.yaml pod "web" deleted service "web-svc" deleted [root@sqm-master yaml]# kubectl apply -f http-livenss.yaml pod/web created service/web-svc created
//最终咱们查看pod的状态及Events信息: [root@sqm-master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES web 1/1 Running 0 5s 10.244.1.11 node01 <none> <none>
[root@sqm-master yaml]# kubectl describe pod web Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 71s default-scheduler Successfully assigned default/web to node01 Normal Pulling 71s kubelet, node01 Pulling image "nginx" Normal Pulled 70s kubelet, node01 Successfully pulled image "nginx" Normal Created 70s kubelet, node01 Created container nginx Normal Started 70s kubelet, node01 Started container nginx
能够看到pod的状态时正常运行的。
##测试访问网页头部信息: [root@sqm-master yaml]# curl -I 10.244.1.11
返回的状态码为200,表示这个pod的情况时健康的。
方法1:使用exec探测方式,与iveness相同,探测某个文件是否存在。
//pod的配置文件以下:
[root@sqm-master yaml]# vim readiness.yaml kind: Pod apiVersion: v1 metadata: name: readiness labels: name: readiness spec: restartPolicy: OnFailure containers: - name: readiness image: busybox args: - /bin/sh - -c - touch /tmp/test; sleep 30; rm -rf /tmp/test; sleep 300; readinessProbe: #定义readiness探测方式 exec: command: - cat - /tmp/test initialDelaySeconds: 10 periodSeconds: 5
//运行该pod: [root@sqm-master yaml]# kubectl apply -f readiness.yaml pod/readiness created
//检测pod的状态:
//查看pod的Events: [root@sqm-master yaml]# kubectl describe pod readiness
能够看到找不到该文件,表示探测失败,可是readiness机制与liveness机制不一样,它并不会重启pod,而是连续探测3次失败后,则将容器设置为不可用的状态。
方法二:httpGet方式。
[root@sqm-master yaml]# vim http-readiness.yaml apiVersion: v1 kind: Pod metadata: name: web2 labels: name: web2 spec: containers: - name: web2 image: nginx ports: - containerPort: 81 readinessProbe: httpGet: scheme: HTTP #指定协议 path: /healthy #指定路径,若是不存在,则须要进行建立,不然探测失败 port: 81 initialDelaySeconds: 10 periodSeconds: 5 --- apiVersion: v1 kind: Service metadata: name: web-svc spec: selector: name: web2 ports: - protocol: TCP port: 81 targetPort: 81
//运行pod: [root@sqm-master yaml]# kubectl apply -f http-readiness.yaml pod/web2 created service/web-svc created
//查看pod的状态: [root@sqm-master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES readiness 0/1 Completed 0 37m 10.244.2.12 node02 <none> <none> web 1/1 Running 0 50m 10.244.1.11 node01 <none> <none> web2 0/1 Running 0 2m31s 10.244.1.14 node01 <none> <none>
查看pod的Events信息,经过探测,能够知道pod是不健康的,且http访问失败。
它并不会重启,而是直接将pod设置为不可用的状态。
首先咱们经过explain工具来查看更新使用的字段:
[root@sqm-master ~]# kubectl explain deploy.spec.strategy.rollingUpdate
能够看到在滚动更新的过程当中有两个参数可用:
maxSurge和maxUnavailable的适用场景:
1,若是您但愿在保证系统可用性和稳定性的前提下尽量快地进行升级,能够将 maxUnavailable 设置为 0,同时为 maxSurge 赋予一个较大值。
2,若是系统资源比较紧张,pod 负载又比较低,为了加快升级速度,能够将 maxSurge 设置为 0,同时为 maxUnavailable 赋予一个较大值。须要注意的是,若是 maxSurge 为 0maxUnavailable 为 DESIRED,可能形成整个服务的不可用,此时 RollingUpdate 将退化成停机发布
1)首先咱们建立一个deployment资源对象:
[root@sqm-master ~]# vim app.v1.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: my-web spec: replicas: 10 #定义副本数量为10个 template: metadata: labels: name: my-web spec: containers: - name: my-web image: nginx args: - /bin/sh - -c - touch /usr/share/nginx/html/test.html; sleep 300000; #建立文件,使其在探测时保持pod为健康状态 ports: - containerPort: 80 readinessProbe: #使用readiness机制 exec: command: - cat - /usr/share/nginx/html/test.html initialDelaySeconds: 10 periodSeconds: 10
//运行该pod后,查看pod数量(10个): [root@sqm-master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES my-web-7bbd55db99-2g6tp 1/1 Running 0 2m11s 10.244.2.44 node02 <none> <none> my-web-7bbd55db99-2jdbz 1/1 Running 0 118s 10.244.2.45 node02 <none> <none> my-web-7bbd55db99-5mhcv 1/1 Running 0 2m53s 10.244.1.40 node01 <none> <none> my-web-7bbd55db99-77b4v 1/1 Running 0 2m 10.244.1.44 node01 <none> <none> my-web-7bbd55db99-h888n 1/1 Running 0 2m53s 10.244.2.41 node02 <none> <none> my-web-7bbd55db99-j5tgz 1/1 Running 0 2m38s 10.244.2.42 node02 <none> <none> my-web-7bbd55db99-kjgm2 1/1 Running 0 2m25s 10.244.1.42 node01 <none> <none> my-web-7bbd55db99-kkmh2 1/1 Running 0 2m38s 10.244.1.41 node01 <none> <none> my-web-7bbd55db99-lr896 1/1 Running 0 2m13s 10.244.1.43 node01 <none> <none> my-web-7bbd55db99-rpd8v 1/1 Running 0 2m23s 10.244.2.43 node02 <none>
探测成功,10个副本所有运行。
2)第一次更新:
更新nginx镜像版本,且设置滚动更新策略:
[root@sqm-master yaml]# vim app.v1.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: my-web spec: strategy: #设置滚动更新策略,经过该字段下的rollingUpdate的子属性来设置 rollingUpdate: maxSurge: 3 #指定在滚动更新过程当中最多可建立3个额外的 pod maxUnavailable: 3 #- 指定在滚动更新过程当中最多容许3 pod 不可用 replicas: 10 template: metadata: labels: name: my-web spec: containers: - name: my-web image: 172.16.1.30:5000/nginx:v2.0 #更新的镜像为私有仓库中的镜像nginx:v2.0 args: - /bin/sh - -c - touch /usr/share/nginx/html/test.html; sleep 300000; ports: - containerPort: 80 readinessProbe: exec: command: - cat - /usr/share/nginx/html/test.html initialDelaySeconds: 10 periodSeconds: 10
//执行yaml文件后,查看pod数量: [root@sqm-master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES my-web-7db8b88b94-468zv 1/1 Running 0 3m38s 10.244.2.57 node02 <none> <none> my-web-7db8b88b94-bvszs 1/1 Running 0 3m24s 10.244.1.60 node01 <none> <none> my-web-7db8b88b94-c4xvv 1/1 Running 0 3m38s 10.244.2.55 node02 <none> <none> my-web-7db8b88b94-d5fvc 1/1 Running 0 3m38s 10.244.1.58 node01 <none> <none> my-web-7db8b88b94-lw6nh 1/1 Running 0 3m21s 10.244.2.59 node02 <none> <none> my-web-7db8b88b94-m9gbh 1/1 Running 0 3m38s 10.244.1.57 node01 <none> <none> my-web-7db8b88b94-q5dqc 1/1 Running 0 3m38s 10.244.1.59 node01 <none> <none> my-web-7db8b88b94-tsbmm 1/1 Running 0 3m38s 10.244.2.56 node02 <none> <none> my-web-7db8b88b94-v5q2s 1/1 Running 0 3m21s 10.244.1.61 node01 <none> <none> my-web-7db8b88b94-wlgwb 1/1 Running 0 3m25s 10.244.2.58 node02 <none> <none>
//查看pod的版本信息: [root@sqm-master yaml]# kubectl get deployments. -o wide NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR my-web 10/10 10 10 49m my-web 172.16.1.30:5000/nginx:v2.0 name=my-web
探测成功,10个pod版本所有更新成功。
3)第二次更新:
将镜像版本更新为3.0版本,且设置滚动更新策略。(探测失败)
pod的配置文件以下:
[root@sqm-master yaml]# vim app.v1.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: my-web spec: strategy: rollingUpdate: maxSurge: 3 #定义更新策略,数量依然都是保持3个 maxUnavailable: 3 replicas: 10 #pod数量依然是10个 template: metadata: labels: name: my-web spec: containers: - name: my-web image: 172.16.1.30:5000/nginx:v3.0 #测试镜像版本更新为3.0 args: - /bin/sh - -c - sleep 300000; #不在建立指定文件,使其探测失败 ports: - containerPort: 80 readinessProbe: exec: command: - cat - /usr/share/nginx/html/test.html initialDelaySeconds: 10 periodSeconds: 5
//从新运行pod配置文件: [root@sqm-master yaml]# kubectl apply -f app.v1.yaml deployment.extensions/my-web configured
//查看pod更新后的数量: [root@sqm-master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES my-web-7db8b88b94-468zv 1/1 Running 0 12m 10.244.2.57 node02 <none> <none> my-web-7db8b88b94-c4xvv 1/1 Running 0 12m 10.244.2.55 node02 <none> <none> my-web-7db8b88b94-d5fvc 1/1 Running 0 12m 10.244.1.58 node01 <none> <none> my-web-7db8b88b94-m9gbh 1/1 Running 0 12m 10.244.1.57 node01 <none> <none> my-web-7db8b88b94-q5dqc 1/1 Running 0 12m 10.244.1.59 node01 <none> <none> my-web-7db8b88b94-tsbmm 1/1 Running 0 12m 10.244.2.56 node02 <none> <none> my-web-7db8b88b94-wlgwb 1/1 Running 0 12m 10.244.2.58 node02 <none> <none> my-web-849cc47979-2g59w 0/1 Running 0 3m9s 10.244.1.63 node01 <none> <none> my-web-849cc47979-2lkb6 0/1 Running 0 3m9s 10.244.1.64 node01 <none> <none> my-web-849cc47979-762vb 0/1 Running 0 3m9s 10.244.1.62 node01 <none> <none> my-web-849cc47979-dv7x8 0/1 Running 0 3m9s 10.244.2.61 node02 <none> <none> my-web-849cc47979-j6nwz 0/1 Running 0 3m9s 10.244.2.60 node02 <none> <none> my-web-849cc47979-v5h7h 0/1 Running 0 3m9s 10.244.2.62 node02 <none> <none>
咱们能够看到当前pod的总数量为13个,(包括maxSurge增长额外的数量)由于探测失败,则设置为将3个pod(包括额外的pod)为不可用的状态,但还剩下7个pod可用( 由于maxUnavailable设置为3个),但注意:这7个pod的版本并无更新成功,仍是上一个的版本。
//查看pod的更新后的版本信息: [root@sqm-master yaml]# kubectl get deployments. -o wide NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR my-web 7/10 6 7 58m my-web 172.16.1.30:5000/nginx:v3.0 name=my-web
参数解释:
READY :表示用户的指望值
UP-TO-DATE:表示已更新的
AVAILABLE:表示可用的
咱们能够发现已更新的镜像版本数量为6个(包括额外的3个pod),可是为不可用的状态,可是确保可用的的pod数量为7个,可是版本并无更新。
总结:
描述在滚动更新过程当中,探测机制有什么做用?
若是在公司中须要对某个应用中的pod进行更新操做,若是没有探测机制,不管该pod是否是当你已经作好更新工做准备要进行更新的,它都会将该应用中全部的pod进行更新,这样会形成严重的后果,虽然更新后你发现pod的状态是正常的,为了达到controller manager的指望值,READY的值依然是1/1, 可是pod已是从新生成的pod了,表示pod内的数据将会所有丢失。
若是加上探测机制的话,会探测容器内你指定的文件或其余应用是否存在,若是达到你指定的条件,则探测成功,则会对你的pod进行更新,若是探测失败则会设置pod(容器)为不可用,虽然探测失败的容器不可用了,但至少该模块中还有其余以前版本的pod可用,确保该公司该服务的正常运行。可见探测机制是多么的重要啊。
———————— 本文至此结束,感谢阅读 ————————