存活探针

Kubernetes可以通过存活探针(liveness probe)检查容器是否存活。如果探测失败,Kubernetes将定期执行探针并重新启动容器。

官方文档请见:https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/

存活探针分为三种:

  • exec:在容器内执行任意命令,并检查命令的退出状态码,为0则成功,否则失败。
  • httpGet:执行http get请求,http code大于等于200并且小于400表示成功,否则失败。
  • tcp:尝试与指定端口建立socket连接,建立成功则探测成功,否则失败。

exec探针

从官网复制个yaml,但是要将image从k8s.gcr.io/busybox更改为busybox。

-> [root@kube0.vm] [~] cat exec-liveness.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5

运行然后30秒后查看

-> [root@kube0.vm] [~] k create -f exec-liveness.yaml
pod/liveness-exec created -> [root@kube0.vm] [~] k describe po liveness-exec
.......
Liveness: exec [cat /tmp/healthy] delay=5s timeout=1s period=5s #success=1 #failure=3
.......
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned default/liveness-exec to kube1.vm
Normal Pulling <invalid> kubelet, kube1.vm Pulling image "busybox"
Normal Pulled <invalid> kubelet, kube1.vm Successfully pulled image "busybox"
Normal Created <invalid> kubelet, kube1.vm Created container liveness
Normal Started <invalid> kubelet, kube1.vm Started container liveness
Warning Unhealthy <invalid> (x3 over <invalid>) kubelet, kube1.vm Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
Normal Killing <invalid> kubelet, kube1.vm Container liveness failed liveness probe, will be restarted

前30秒,/tmp/healthy是存在的,探针返回成功。30秒后,因为/tmp/healthy不存在了,所以一直失败,直到失败3次后重启。

livenessProbe下的字段

这时候kubectl explain po.spec.containers.livenessProbe就派上了用场。

  • exec:exec探针配置
  • httpGet:httpGet探针配置
  • tcpSocket:tcpSocket探针配置
  • initialDelaySeconds:初始延迟时间,在此时间内不进行探测,给程序预留启动时间。
  • periodSeconds:探测周期,默认10s
  • timeoutSeconds:超时时间,默认1s
  • failureThreshold:被认为失活的最小连续失败次数,默认3次
  • successThreshold:失败后被认为存活的最小连续成功次数,默认为1次。

这些参数在上面的kubectl describe的结果中的Liveness字段有:

exec [cat /tmp/healthy] delay=5s timeout=1s period=5s #success=1 #failure=3

注意事项

  • 一定要检查程序的内部,而没有外界因素影响。

    例如,当服务器无法连接到数据库时,前端服务的探针不应返回失败。因为问题在数据库,重启前端服务也无法解决问题。
  • 无须再探针中实现重试
  • 探针要轻量

ReplicationController

ReplicationController是一种Kubernetes资源,可以确保他的pod始终处于运行状态。

ReplicationController描述文件分为三大部分:

  • label selector(标签选择器):用于确定ReplicationController管理哪些pod
  • replica count(副本个数):指定运行pod的数量
  • pod template(pod模板):用于创建pod

ReplicationController的目的就是创建和管理若干个pod副本,它会持续监控正在运行的pod列表,保证标签选择器匹配的pod数量与副本个数一致。如果少于副本数量,就要根据pod模板创建新的副本;如果多余副本数量,就要删除多余的pod。

数量少的原因可能是:

  • 增加了副本个数
  • pod所在的工作节点出现故障
  • pod的标签更改了,导致pod与ReplicationController的标签选择器不再匹配了。此时,如果它不被任何ReplicationController的标签选择器匹配,它就称为一个孤儿了。

数量多的原因可能是:

  • 减少了副本个数
  • 新建的pod与该ReplicationController的标签选择器匹配
  • 已存在的pod标签修改后与该ReplicationController的标签选择器匹配

nginx-rc.yaml

API服务器会检查模板中的标签是否与selector匹配,如果不匹配是无法创建的。可以不指定selector,它会根据模板中的labels自动配置。

apiVersion: v1
kind: ReplicationController
metadata:
name: nginx-rc
spec:
replicas: 3 # 副本数量
selector: # pod选择器,决定RC的操作对象
app: nginx
template: # pod模板
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80

使用ReplicationController

创建ReplicationController

-> [root@kube0.vm] [~] k create -f nginx-rc.yaml
replicationcontroller/nginx-rc created

查看pod,确实新建了3个pod。

-> [root@kube0.vm] [~] k get po --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-rc-2c47w 0/1 ContainerCreating 0 5s app=nginx
nginx-rc-jrcl2 0/1 ContainerCreating 0 5s app=nginx
nginx-rc-qgchh 0/1 ContainerCreating 0 5s app=nginx

查看ReplicationController,rc是ReplicationController的简写。

-> [root@kube0.vm] [~] k get rc
NAME DESIRED CURRENT READY AGE
nginx-rc 3 3 3 5m58s

查看详情

-> [root@kube0.vm] [~] k describe rc nginx-rc
Name: nginx-rc
Namespace: default
Selector: app=nginx
Labels: app=nginx
Annotations: <none>
Replicas: 3 current / 3 desired # 当前数量、期望数量
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed # 各种状态下的数量
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 7m26s replication-controller Created pod: nginx-rc-2c47w
Normal SuccessfulCreate 7m26s replication-controller Created pod: nginx-rc-jrcl2
Normal SuccessfulCreate 7m26s replication-controller Created pod: nginx-rc-qgchh

可以搞一些破坏,比如更改、删除pod的标签,或者干脆删除pod。ReplicationController会因为当前数量与期望数量不符而创建新的副本。

控制器如何创建的pod

控制器通过创建一个新的副本代替被删除的副本时,它并没有对删除本身做出反应,而是针对由此产生的状态——副本数量不足做出反应。

虽然控制器会立即受到pod被删除的通知,但这并不是它创建新副本的原因。该通知会触发控制器检查实际的副本数量并采取相应措施。

kubectl edit

kubectl edit rc nginx-rc可以在编辑器中打开nginx-rc的yaml配置,修改在保存后会立刻做出改变。

-> [root@kube0.vm] [~] k edit rc nginx-rc
replicationcontroller/nginx-rc edited
通过KUBE_EDITOR环境变量可以指定用什么编辑器打开。

kubectl scale

可以使用kubectl scale命令进行扩缩容。

-> [root@kube0.vm] [~] k scale rc nginx-rc --replicas=6
replicationcontroller/nginx-rc scaled

以上操作会修改spec.replicas字段,就像通过kubectl edit修改一样。

删除ReplicationController

使用 kubectl delete 删除ReplicationController时,pod也会被删除。但由于pod是被ReplicationController创建的而不是它的组成部分,所以可以通过指定--cascade=false而不删除pod。

注意事项

  • pod永远不会被重新安置到另一个节点。
  • 虽然一个pod没有绑定在ReplicationController上,但该pod在metadata.ownerReferences引用它。

ReplicaSet

ReplicationController最终将要被弃用,代替它的是ReplicaSet。它们的行为完全相同,但是ReplicaSet的选择器更具有表达力。

nginx-rs.yaml

让我们来看一个ReplicaSet的描述文件:

apiVersion: apps/v1	# api版本与ReplicationController不同
kind: ReplicaSet
metadata:
name: nginx-rs
spec:
replicas: 3
selector: # ReplicaSet的pod选择器有matchLabels和matchExpressions,与ReplicationController的是相似的,但更强大
matchLabels:
app: nginx
template: # 模板内容是一致的
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80

主要区别在于pod选择器。ReplicaSet的创建于ReplicationController一样,缩写是rs,就不再赘叙了。

matchExpressions

上面描述文件的选择器使用matchExpressions可以改为:

  selector:
matchExpressions:
- key: app
operator: In
values:
- nginx

每个表达式都必须包含key、operator(运算符),有可能包含values(取决于运算符),运算符有以下四种:

  • In:Label的值必须与values中的一个相等
  • NotIn:Label的值不能与values中的任何一个相等
  • Exists:Pod必须包含一个指定名称的标签,values无所谓
  • DoesNotExists:Pod不得包含指定名称的标签,values不能指定

DaemonSet

DaemonSet与ReplicaSet的不同在于,DaemonSet可以让pod在集群的每个节点上运行,有且只有一个。

如果节点下线,DaemonSet不会在其他地方重建pod;如果集群新加入了一个节点,DaemonSet会立刻部署一个新的pod。如果有人删除了pod,DaemonSet会建立一个新的。

这些pod通常用于执行系统级别或基础结构相关的工作,如日志收集和资源监控。典型的例子就是Kubernetes自己的kube-proxy。

如果想让DaemonSet只在特定节点运行pod,需要通过pod模板中的nodeSelector属性指定。

DaemonSet中没有期望副本数的概念,它不需要。因为它的工作是确保有一个匹配它选择器的pod在节点上运行。

nginx-ds.yaml

可能这里用继续用nginx作为例子不太恰当,但目前我们关注的重点是DaemonSet,继续吧。。。

apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-ds
spec: # 去掉了replicas,因为不需要
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
nodeSelector: # 添加了一个节点的标签选择器,选择只部署地区在在北京的节点上
region: "beijing"
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80

创建DaemonSet

先给kube1.vm打个标签

-> [root@kube0.vm] [~] k label node kube1.vm region=beijing
node/kube1.vm labeled -> [root@kube0.vm] [~] k get node -L region
NAME STATUS ROLES AGE VERSION REGION
kube0.vm Ready master 40h v1.17.3
kube1.vm Ready <none> 40h v1.17.3 beijing
kube2.vm Ready <none> 40h v1.17.3

提交描述文件

-> [root@kube0.vm] [~] k create -f nginx-ds.yaml
daemonset.apps/nginx-ds created -> [root@kube0.vm] [~] k get ds,po -o wide
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR
daemonset.apps/nginx-ds 1 1 1 1 1 region=beijing 52s nginx nginx app=nginx NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-ds-5z95c 1/1 Running 0 52s 10.244.1.24 kube1.vm <none> <none>

给kube2.vm也打个标签

-> [root@kube0.vm] [~] k label node kube2.vm region=beijing
node/kube2.vm labeled -> [root@kube0.vm] [~] k get ds,po -o wide
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR
daemonset.apps/nginx-ds 2 2 1 2 1 region=beijing 113s nginx nginx app=nginx NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-ds-5z95c 1/1 Running 0 113s 10.244.1.24 kube1.vm <none> <none>
pod/nginx-ds-b46lb 0/1 ContainerCreating 0 3s <none> kube2.vm <none> <none>

Job

Job可以运行一种pod,在该pod内的进程成功结束时,不再重启。一旦任务完成,pod就被认为处于完成状态。

比如可以使用在将一些数据导出到其他地方,这个工作可能会持续几个小时。

我们基于busybox镜像,sleep一段时间用于模拟这个操作。

job.yaml

apiVersion: batch/v1
kind: Job
metadata:
name: job
spec:
template: # 没有指定selector,会根据pod标签中自动创建
metadata:
labels:
app: job
spec:
restartPolicy: OnFailure # 执行遇到异常则重启,默认为Always。
containers:
- name: sleepbusybox
image: busybox
command: ["/bin/sh","-c","sleep 60;echo this is busybox"]

restartPolicy表示pod的重启策略,默认Always,其他两项为OnFailure和Never。

运行查看

创建job

-> [root@kube0.vm] [~] k create -f job.yaml
job.batch/job created

60秒内查看:

-> [root@kube0.vm] [~] k get job,pod
NAME COMPLETIONS DURATION AGE
job.batch/job 0/1 14s 14s NAME READY STATUS RESTARTS AGE
pod/job-4sfv4 1/1 Running 0 14s

60秒后查看:

-> [root@kube0.vm] [~] k get job,pod
NAME COMPLETIONS DURATION AGE
job.batch/job 1/1 68s 71s NAME READY STATUS RESTARTS AGE
pod/job-4sfv4 0/1 Completed 0 71s

使用jsonpath获取 pod name 查看log

-> [root@kube0.vm] [~] k logs $(k get po --selector=app=job --output=jsonpath={.items..metadata.name})
this is busybox

completions与parallelism

job描述文件下的spec有两个字段:

  • completions:job要确保完成多少个pod,默认为1。
  • parallelism:最多并行运行多少个pod,默认为1。

job-batch.yaml

apiVersion: batch/v1
kind: Job
metadata:
name: job-batch
spec:
completions: 5
parallelism: 2
template:
# 与job.yaml相同

activeDeadlineSeconds

job.spec.activeDeadlineSeconds属性来限制Job在集群中的存活时间,超过此值,所有的pod都被终止。Job的status变为 type: Failed,reason: DeadlineExceeded

CronJob

与Linux的crontab类似,使pod可以在特定时间运行,或者周期运行。

cronjob.yaml

这个描述文件是个套娃。。

CronJob包含job的模板,也就是jobTemplate;job里还包含pod的模板,也就是template。

schedule字段中的值是"分 小时 每月第几天 月份 星期几",详情请参考Linux crontab。

apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: cron-job
spec:
schedule: "*/3 * * * * " # 每三分钟运行一次
jobTemplate: # job的模板
spec:
template: # pod的模板
metadata:
labels:
app: job-in-cron
spec:
restartPolicy: OnFailure
containers:
- name: sleepbusybox
image: busybox
command: ["/bin/sh","-c","sleep 60;echo this is busybox"]

运行

创建cron-job

-> [root@kube0.vm] [~] k create -f cronjob.yaml
cronjob.batch/cron-job created

等了几分钟

-> [root@kube0.vm] [~] k get all
NAME READY STATUS RESTARTS AGE
pod/cron-job-1590053040-pqhhh 0/1 Completed 0 97s NAME COMPLETIONS DURATION AGE
job.batch/cron-job-1590053040 1/1 68s 97s NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cronjob.batch/cron-job */3 * * * * False 0 105s 4m39s

又等了几分钟

-> [root@kube0.vm] [~] k get all
NAME READY STATUS RESTARTS AGE
pod/cron-job-1590053040-pqhhh 0/1 Completed 0 3m4s
pod/cron-job-1590053220-whflp 0/1 ContainerCreating 0 3s NAME COMPLETIONS DURATION AGE
job.batch/cron-job-1590053040 1/1 68s 3m4s
job.batch/cron-job-1590053220 0/1 3s 3s NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cronjob.batch/cron-job */3 * * * * False 1 12s 6m6s

可以看到就当前的描述文件而言,cron-job每次创建一个job,job创建一个pod的运行。

startingDeadlineSeconds

cronjob.spec.startingDeadlineSeconds规定pod必须预定时间之后的startingDeadlineSeconds秒内运行,超过此时间则不运行,并将其显示未Failed。

小结

  • 使用存活探针检查容器是否存活。
  • ReplicationController创建并管理Pod,但并不是绑定关系。它始终保持期望数量的副本正在运行。
  • ReplicationController将被弃用,ReplicaSet拥有更强的标签选择器。
  • DaemonSet会在每个节点上保持运行有且只有一个Pod,可以通过nodeSelector让其只在特定节点运行。
  • Job创建Pod运行完成后,Pod为为Completed状态。completions与parallelism指定需要完成的数量与并行度。
  • restartPolicy:默认Always,还有OnFailure、Never。
  • CronJob创建Job,Job创建Pod。
  • 命令:edit、scale

Kubernetes学习笔记(二):部署托管的Pod -- 存活探针、ReplicationController、ReplicaSet、DaemonSet、Job、CronJob的更多相关文章

  1. Kubernetes 学习笔记(一):基础概念

    个人笔记,仅本人查阅使用,不保证正确. 零.微服务 微服务架构专注于应用解耦合,通过将应用彻底地组件化和服务化,每个微服务只包含一个非常小的功能,比如权限管理.日志收集等等.由这一组微服务组合起来,提 ...

  2. Kubernetes学习笔记(八):Deployment--声明式的升级应用

    概述 本文核心问题是:如何升级应用. 对于Pod的更新有两种策略: 一是删除全部旧Pod之后再创建新Pod.好处是,同一时间只会有一个版本的应用存在:缺点是,应用有一段时间不可用. 二是先创建新Pod ...

  3. amazeui学习笔记二(进阶开发1)--项目结构structure

    amazeui学习笔记二(进阶开发1)--项目结构structure 一.总结 1.项目结构:是说的amazeui在github上面的项目结构,二次开发amazeui用 二.项目结构structure ...

  4. WPF的Binding学习笔记(二)

    原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的 ...

  5. AJax 学习笔记二(onreadystatechange的作用)

    AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...

  6. [Firefly引擎][学习笔记二][已完结]卡牌游戏开发模型的设计

    源地址:http://bbs.9miao.com/thread-44603-1-1.html 在此补充一下Socket的验证机制:socket登陆验证.会采用session会话超时的机制做心跳接口验证 ...

  7. JMX学习笔记(二)-Notification

    Notification通知,也可理解为消息,有通知,必然有发送通知的广播,JMX这里采用了一种订阅的方式,类似于观察者模式,注册一个观察者到广播里,当有通知时,广播通过调用观察者,逐一通知. 这里写 ...

  8. java之jvm学习笔记二(类装载器的体系结构)

    java的class只在需要的时候才内转载入内存,并由java虚拟机的执行引擎来执行,而执行引擎从总的来说主要的执行方式分为四种, 第一种,一次性解释代码,也就是当字节码转载到内存后,每次需要都会重新 ...

  9. Java IO学习笔记二

    Java IO学习笔记二 流的概念 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 程序中的输入输 ...

随机推荐

  1. Test Test...

    标题: Test(一级标题) Test(二级标题) Test(三级标题) 列表: test(列表) Alpha Beta Gamma test 2 Delte Epsilon 链接: 点兔成金斐波那契 ...

  2. Scala教程之:深入理解协变和逆变

    文章目录 函数的参数和返回值 可变类型的变异 在之前的文章中我们简单的介绍过scala中的协变和逆变,我们使用+ 来表示协变类型:使用-表示逆变类型:非转化类型不需要添加标记. 假如我们定义一个cla ...

  3. weblogic创建域

    一.webLogic服务域创建 https://blog.csdn.net/github_38922197/article/details/75097320

  4. Java多线程并发系列之闭锁(Latch)和栅栏(CyclicBarrier)

    JAVA并发包中有三个类用于同步一批线程的行为,分别是闭锁(Latch),信号灯(Semaphore)和栅栏(CyclicBarrier).本贴主要说明闭锁(Latch)和栅栏(CyclicBarri ...

  5. 限流 - Guava RateLimiter

    2019独角兽企业重金招聘Python工程师标准>>> 限流 限流的目的是通过对并发访问/请求进行限速或者一个时间窗口内的的请求进行限速来保护系统,一旦并发访问/请求达到限制速率或者 ...

  6. 短视频sdk:选择一个靠谱的短视频SDK 你需要了解这些

    2017 年,短视频成为了内容创业的新风口,各种短视频 App 如雨后春笋般先后上线.随着互联网内容消费升级,视频越来越像文字.图片一样,成为每一个 App 不可或缺的一部分. 为了能够更好地聚焦于业 ...

  7. Codeforce 1155D Beautiful Array(DP)

    D. Beautiful Array You are given an array aa consisting of nn integers. Beauty of array is the maxim ...

  8. tomcat 在linux下启动时找不到JDK

    方案一.  修改bashrc (转载: https://www.cnblogs.com/hongzg1982/articles/2101792.html)  $ vim ~/.bashrc #加入JA ...

  9. HTTP请求头中的X-Forwarded-For介绍

    概述 我们在做nginx方向代理的时候,为了记录整个代理过程,我们往往会在配置文件中加上如下配置: location ^~ /app/download/ { ... proxy_set_header ...

  10. andorid jar/库源码解析之okio

    目录:andorid jar/库源码解析 Okio: 作用: 说白了,就是一个IO库,基于java原生io.来进行操作,内部做了优化,简洁,高效.所以受到了一部分人的喜欢和使用 栗子: 读写文件. p ...