Pod是K8s调度的最小单元,但是Pod可能因为资源不足、集群崩溃等被驱逐。Controller Manage会管理Pod,完成Pod自愈、滚动升级等操作,通过Deployment这种资源完成Pod维护。
一个Deployment可以包含一个或多个Pod副本,每个Pod副本的角色相同,所以系统会自动为Deployment的多个Pod副本分发请求。
Deployment集成了上线部署、滚动升级、创建副本、恢复上线的功能,在某种程度上,Deployment实现无人值守的上线,大大降低了上线过程的复杂性和操作风险。
Deployment关注的是应用的部署和管理,负责创建和更新Pod。
Service关注的是网络访问和服务的发现,提供统一的网络入口和负载均衡。
在实际应用中,通常先创建Deployment来定义应用的需求,然后创建Service来暴露应用的服务。
示例:创建一个名为nginx的Deployment负载,使用nginx:latest镜像创建两个Pod,每个Pod占用100m core CPU、200Mi内存。
从这个定义中可以看到
Deployment的名称为nginx;
spec.replicas定义了Pod的数量,即这个Deployment控制2个Pod;
spec.selector是Label Selector(标签选择器),表示这个Deployment会选择Label为app=nginx的Pod;
spec.template是Pod的定义,内容与Pod中的定义完全一致。
将上面Deployment的定义保存到deployment.yaml文件中,使用kubectl创建这个Deployment。
使用kubectl get查看Deployment和Pod,可以看到READY值为2/2,前一个2表示当前有2个Pod运行,后一个2表示期望有2个Pod,AVAILABLE为2表示有2个Pod是可用的。
$ kubectl create -f deployment.yaml
deployment.apps/nginx created$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 2/2 2 2 4m5s
删除Pod后,Deployment会重新拉起一个新的Pod。
两个后缀中前面一部分是相同的,都是7f98958cdf,这是因为Deployment不是直接控制Pod的,Deployment是通过ReplicaSet的控制器控制Pod,通过命令可以查询ReplicaSet,其中rs是ReplicaSet的缩写。
ReplicaSet的名称为nginx-7f98958cdf,后缀-7f98958cdf也是随机生成的。
Deployment控制ReplicaSet,ReplicaSet控制Pod。
通过Describe也可以查询到ReplicaSet信息。
Deployment的两种升级策略:
Deployment可以通过maxSurge和maxUnavailable两个参数控制升级过程中同时重新创建Pod的比例,这在很多时候是非常有用,配置如下所示。
spec:
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
回滚也称为回退,即当发现升级出现问题时,让应用回到老的版本。Deployment可以非常方便的回滚到老版本。
Deployment之所以能如此容易的做到回滚,是因为Deployment是通过ReplicaSet控制Pod的,升级后之前ReplicaSet都一直存在,Deployment回滚做的就是使用之前的ReplicaSet再次把Pod创建出来。Deployment保存ReplicaSet的数量可使用revisionHistoryLimit参数限制,默认值10。
无状态就是每个服务状态信息一致,有状态就是服务信息不一致,请求需要路由到某一个特定的服务器,应用中每个部分的角色不同(即分工不同),比如数据库有主备、Pod之间有依赖。
在Kubernetes中部署有状态应用对Pod有如下要求:
Kubernetes提供了StatefulSet来解决这个问题,其具体如下:
headless不分配clusterIP
解析service的DNS,返回所有Pod的地址和DNS(statefulSet部署的Pod才有DNS)
普通的service,只能通过解析service的DNS返回service的ClusterIP。
创建Statefulset需要一个Headless Service用于Pod访问。
执行如下命令创建Headless Service。
创建完成后可以查询Service。
执行创建命令
命令执行后,查询一下StatefulSet和Pod,可以看到Pod的名称后缀从0开始到2,逐个递增。
此时如果手动删除nginx-1这个Pod,然后再次查询Pod,可以看到StatefulSet重新创建了一个名称相同的Pod,通过创建时间5s可以看出nginx-1是刚刚创建的。
进入容器查看容器的hostname,可以看到同样是nginx-0、nginx-1和nginx-2。
同时可以看一下StatefulSet创建的PVC,可以看到这些PVC,都以“PVC名称-StatefulSet名称-编号”的方式命名,并且处于Bound状态。
Headless Service使用DNS,给每个Pod固定域名,即使ip变化也不影响访问。
使用pvc做持久化存储。
图1 StatefulSet的Pod重建过程
批量处理短暂的一次性任务,仅执行一次任务,保证一个或多个Pod结束。Job管理的Pod根据用户设置成功的任务完成就自动退出。
计算π到2000位并打印输出。Job结束需要运行50个Pod,这个示例中就是打印π 50次,并行运行5个Pod,Pod如果失败最多重试5次。
根据completions和parallelism的设置,可以将Job划分为以下几种类型。
CronJob的格式从前到后就是:
如 "0,15,30,45 * * * * " ,前面逗号隔开的是分钟,后面第一个* 表示每小时,第二个 * 表示每个月的哪天,第三个表示每月,第四个表示每周的哪天。
如果您想要每个月的第一天里面每半个小时执行一次,那就可以设置为" 0,30 * 1 * * " 如果您想每个星期天的3am执行一次任务,那就可以设置为 "0 3 * * 0"。
运行在节点上,有且仅有一个Pod,非常适合一些系统层面的应用,例如日志收集、资源监控等,这类应用需要每个节点都运行,且不需要太多实例。
Deployment或StatefulSet中的replicas参数,因为是每个节点固定一个。nodeSelector,指定了只在有“daemon=need”的节点上才创建Pod,如下图所示,DaemonSet只在指定标签的节点上创建Pod。如果需要在每一个节点上创建Pod可以删除该标签。
创建DaemonSet
查询发现nginx-daemonset没有Pod创建。
这是因为节点上没有daemon=need这个标签,使用如下命令可以查询节点的标签。