StatefulSet和Deployment的区别
- Deployment应用于无状态应用;StatefulSet应用于有状态应用。
- Deployment的Pod之间没有顺序;StatefulSet的Pod部署、扩展、更新、删除都要有顺序。
- Deployment的所有pod共享存储;StatefulSet的每个pod都有自己存储,所以都用volumeClaimTemplates,为每个pod都生成一个自己的存储,保存自己的状态。
- Deployment的pod名字包含随机数字;StatefulSet的pod名字始终是固定的。
- Deployment的Service都有ClusterIP,可以负载均衡;StatefulSet的Service没有ClusterIP,是Headless Service,所以无法负载均衡,返回的都是pod名,所以pod名字都必须固定,StatefulSet在Headless Service的基础上又为StatefulSet控制的每个Pod副本创建了一个DNS域名:
$(podname).(headless server name).namespace.svc.cluster.local
。
DaemonSet
DaemonSet控制器确保集群中的每一个Node只运行一个特定的Pod副本,实现系统级的后台任务,也具有标签选择器。
也可以指定部分满足条件的Node运行一个Pod副本,比如监控具有ssd存储的Node节点。
常用来部署一些集群的日志、监控或者其他系统管理应用。典型的应用包括:
- 日志收集,比如fluentd、logstash等。
- 系统监控,比如Prometheus Node Exporter、collectd、New Relic agent、Ganglia gmond等。
- 系统程序,比如kube-proxy、kube-dns、Glusterd、Ceph等。
DaemonSet的示例如下所示:
前提:
# 列出所用的节点 kubectl get node # 给节点名为minikube的节点添加 disk=ssd 标签 kubectl label node minikube disk=ssd 复制代码
下面创建一个模拟运行ssd-monitor 监控器进程的 DaemonSet, 该进程每5 秒会将 “SSD OK” 打印到标准输出。它将运行 一个基于 luksa/ssd-monitor 容器镜像的单容器 pod。 该 pod 的实例将在每个具有disk=ssd 标签的节点上创建。
apiVersion: apps/v1beta2 kind: DaemonSet metadata: name: ssd-monitor spec: selector: matchLabels: app: ssd-monitor template: metadata: labels: app: ssd-monitor spec: nodeSelector: disk: ssd containers: - name: main image: luksa/ssd-monitor 复制代码
Job
到目前为止, 我们只谈论了需要持续运行的 pod
。 你会遇到只想运行完成工作后就终止任务的清况。 ReplicationController 、 ReplicaSet和 DaemonSet 会持续运行任务, 永远达不到完成态。 这些 pod 中的进程在退出时会重新启动。 但是在一个可完成的任务中, 其进程终止后, 不应该再重新启动。
Job控制器用于配置Pod对象运行一次性任务,容器中的进程在正常运行结束后不会进行重启,而是将Pod对象置于“Completed”状态。若容器中的进程因为错误而终止,则需要配置确定是否要重启。
Job控制器对象主要有两种:
- 单工作队列地串行式Job:多个一次性的作业方式串行执行多次作业,直到满足期望的次数
- 多工作队列的并行式Job:多个工作队列并行运行多个一次性作业
配置项:
- completions:总的执行的作业数
- parallelism:作业执行的并行度
- activeDeadlineSeconds:最大活动时间长度,超出此时长的作业将被终止
- backoffLimit:将作业标记为失败状态之前的重试次数,默认为6
- ttlSecondsAfterFinished:Completed的job默认不会清理。此配置项设置当job完成后的保留xx秒就自动清理这个job。当ttl controller清理job的时候是级联删除的,会把这个job下的pod一并删除。如果设置为0,job会被立即删除。如果不指定,job则不会被删除。
Job的示例如下所示:
定义了一个Job类型的资源,它将运行luksa/batch-job镜像,该镜像调用 一个运行120秒的进程,然后退出。
apiVersion: batch/v1 kind: Job metadata: name: batch-job spec: completions: 5 parallelism: 2 activeDeadlineSeconds: 100 backoffLimit: 5 ttlSecondsAfterFinished: 100 template: metadata: labels: app: batch-job spec: restartPolicy: OnFailure containers: - name: main image: luksa/batch-job 复制代码
上面没有指定pod选择器,它将根据pod模板中的标签进行创建。
说明:
在一个pod的定义中,可以指定在容器中运行的进程结束时,Kubernetes应该做什么?
这是通过pod配置的属性restartPolicy完成的,默认为Always。Job类型的资源pod不能使用默认策略,因为它们不是要无限期地运行。因此,需要明确地将重启策略设置为OnFailure或Never。此设置防止容器在完成任务时重新启动。
CronJob
CronJob控制器执行周期性任务作业,控制其运行的时间点及重复运行的方式,类似于Linux操作系统的周期性任务作业计划的方式控制其运行的时间点和重复运行的方式。
配置项:
- jobTemplate:Job控制器模板。
- schedule:Cron格式的作业调度运行的时间点。
- concurrencyPolicy:并发执行策略,用于定义前一次作业尚未完成时如何执行下一此任务。默认是Allow,即允许前后Job,甚至是属于同一个CrontJob的更多Job同时运行。如果设置为Forbid则禁止前后两个Job同时运行,如果前一个尚未结束,后一个不会启动(跳过),如果设置为Replace,则后一个Job会替代前一个Job,即终止前一个,启动后一个。
- failedJobHistoryLimit:为失败的任务执行保留的历史记录数,默认是1。
- successfulJobsHistoryLimit:为成功的任务执行保留的历史记录数,默认是3。
- startingDeadlineSeconds:因各种原因缺乏执行作业的时间点所导致的启动作业错误的超时时长,会被记入错误历史记录
- suspend:是否挂起后续的任务执行,默认是false。
CronJob的示例如下所示:
定义了一个CronJob类型的资源每15分钟运行一次批处理任务。
apiVersion: batch/v1beta1 kind: CronJob metadata: name: batch-job-every-fifteen-minutes spec: schedule: "0,15,30,45 * * * *" jobTemplate: spec: template: metadata: labels: app: periodic-batch-job spec: restartPolicy: OnFailure containers: - name: main image: luksa/batch-job 复制代码
配置时间表如下图所示:
时间表从左到右包含以下五个条目:
- 分钟
- 小时
- 每月中的第几天
- 月
- 星期几
了解调度Job如何运行
你可能发生 Job或Pod创建并运行得相对较晚的情况。你可能对这项作业有很高的要求,任务开始不能落后于预定的时间过多。
在这种情况下,可以通过指定CronJob规范中的startingDeadlineSeconds
字段来指定截止日期。
apiVersion: batch/v1beta1 kind: CronJob spec: schedule: "0,15,30,45 * * * *" startingDeadlineSeconds: 15 复制代码
Pod 最迟必须在预定时间15秒后开始运行, 假如作业运行的时间应该是10:30:00
。如果因为任何原因10:30:15
不启动,任务将不会运行,并将显示为Failed。
在正常情况下,CronJob总是为schedule中配置的每个执行创建一个 Job, 但可能会同时创建两个Job, 或者根本没有建。 为了解决第一个问题,你的任务应该是幕等的(多次(而不是一次)运行不会得到不希望的结果)。 对于第二个问题,请确保下一个任务运行完成本应该由上一次(错过的) 运行完成的任何工作。
HorizontalPodAutoscaler(HPA)
应用的资源使用率通常都有高峰和低谷的时候,如何削峰填谷,提高集群的整体资源利用率,让Service中的Pod 个数自动调整呢?这就有赖于Horizontal Pod Autoscaling了,顾名思义,使Pod水平自动缩放(按照期望的pod的cpu或内存来自动伸缩pod数量)。
apiVersion: autoscaling/v1 # 资源类型是HPA kind: HorizontalPodAutoscaler metadata: name: hpa-test namespace: test spec: # 最大副本数 maxReplicas: 10 # 最小副本数 minReplicas: 3 scaleTargetRef: apiVersion: apps/v1beta1 kind: Deployment # 监控名为deploy-test的Deployment name: deploy-test # cpu 阈值 CPU大于80会自动创建pod来分担服务压力,小于80则减少pod数量 targetCPUUtilizationPercentage: 80 复制代码
基于多个Pod度量的自动伸缩(例如: CPU使用率和每秒查询率[QPS])的计算也并不复杂。 Autoscaler单独计算每个度量的副本数, 然后取最大值(例如:如果需要4个pod达到目标CPU使用率, 以及需要3个pod来达到目标QPS, 那么Autoscaler 将扩展到4个pod) 。
总结
我们通常将应用分为无状态应用、有状态应用、守护型应用、批处理应用这四种。Kubernetes针对各种类型的应用设计了相应的控制器。本文简单介绍了这几种控制器的不同用途。
控制器 | 用途 |
Deployment | 无状态应用 |
StatefulSet | 有状态应用 |
DaemonSet | 守护进程应用 |
Job & CronJob | 批处理作业 |