资源request和limit
K8S通过Request和Limit两个抽象概念来给Pod申请资源与配额:
(1)Request是资源预估申请,由K8s调度决策是否能够满足申请,如有资源则保证供给,如果资源资源不足则显示等待状态。
(2)Limit是容器资源限额:
内存超额 > OOMKill相关的容器
CPU超额 > 限制使用量(throttling)
(3)Request <= Limit
(4)管理员还可配置名字空间级别的配额(ResourceQuota/LimitRange)
statefulset和deployment
官方给出的建议是,如果你部署的应用满足以下一个或多个部署需求,则建议使用StatefulSet。
- 稳定的、唯一的网络标识。
- 稳定的、持久的存储。
- 有序的、优雅的部署和伸缩。
- 有序的、优雅的删除和停止。
- 有序的、自动的滚动更新。
稳定的主要是针对Pod发生re-schedule后仍然要保持之前的网络标识和持久化存储。
这里所说的网络标识包括hostname、集群内DNS中该Pod对应的A Record,并不能保证Pod re-schedule之后IP不变。
要想保持Pod IP不变,我们可以借助稳定的Pod hostname定制IPAM获取固定的Pod IP。
借助StatefulSet的
稳定的唯一的网络标识
特性,我们能比较轻松的实现Pod的固定IP需求。然后如果使用Deployment,那么将会复杂的多,你需要考虑滚动更新的过程中的参数控制(maxSurge、maxUnavailable)、每个应用的IP池预留造成的IP浪费等等问题。
1、不需额外数据依赖或者状态维护的部署,或者replicas是1,优先考虑使用Deployment;
2、单纯的要做数据持久化,防止pod宕掉重启数据丢失,那么使用pv/pvc就可以了;
3、要打通app之间的通信,而又不需要对外暴露,使用headlessService即可;
4、需要使用service的负载均衡,不要使用StatefulSet,尽量使用clusterIP类型,用serviceName做转发;
5、有多replicas,且需要挂载多个pv且每个pv的数据是不同的,因为pod和pv之间是 一 一对应的,如果某个pod挂掉再重启,还需要连接之前的pv,不能连到别的pv上,考虑使用StatefulSet
6、deployment重启后pod的名称是变化的,statefulset重启后pod名称不变,从这方面考虑的话,若要求pod名称固化(重启后名称固定),就使用statefulset。
7、采取使用volumeClaimTemplates,只能是statefulset。deployment不支持。
8、statefulset的headless-service,如果使用StatefulSet,spec.serviceName需要指向headlessServiceName,且不能省略指定步骤。
官方文档要求headlessService必须在创建StatefulSet之前创建完成。官方要求要在创建StatefulSet之前创建好headlessService,是为了让pod启动时能自动对应到service上。之所以要指定一个headlessService,是因为admin可以给StatefulSet创建多个、多种类型的service,k8s不知道要用哪个service的名称当作集群内域名的一部分。
经过测试,如果没有也不会影响pod运行(pod还是running状态),只是不能拥有一个stable-network-id 集群内部不能访问到这个服务(如果这个服务不需要被发现,只需要去发现其他服务,则serviceName随便写一个也行)
Deployment类型则不能有此参数,否则报错。
9、deployment service都有ClusterIP,可以负载均衡。
statefulset service没有ClusterIP,是headlessservice,所以无法负载均衡,返回的都是pod名,所以pod名字都必须固定,StatefulSet在Headless Service的基础上又为StatefulSet控制的每个Pod副本创建了一个DNS域名:$(podname).(headless server name).namespace.svc.cluster.local
statefulset和deployment扩缩容的不同
- 当部署有N个副本的StatefulSet应用时,严格按照index从0到N-1的递增顺序创建,下一个Pod创建必须是前一个Pod Ready为前提。
- 当删除有N个副本的StatefulSet应用时,严格按照index从N-1到0的递减顺序删除,下一个Pod删除必须是前一个Pod shutdown并完全删除为前提。
- 当扩容StatefulSet应用时,每新增一个Pod必须是前一个Pod Ready为前提。
- 当缩容StatefulSet应用时,每删除一个Pod必须是前一个Pod shutdown并成功删除为前提。
- 注意StatefulSet的pod.Spec.TerminationGracePeriodSeconds不要设置为0。
statefulset和deployment的更新策略
StatefulSet的更新策略(由.spec.updateStrategy.type
指定)支持以下两种:
- OnDelete,删除重建,含义同Deployment的OnDelete策略。
- RollingUpdate,滚动更新,过程也跟Deployment大致相同,区别在于:
- 相当于Deployment的maxSurge=0,maxUnavailable=1(其实StatefulSet是不存在这两个配置的)
- 滚动更新的过程是有序的(逆序),index从N-1到0逐个依次进行,并且下一个Pod创建必须是前一个Pod Ready为前提,下一个Pod删除必须是前一个Pod shutdown并完全删除为前提。
- 支持部分实例滚动更新,部分不更新,通过
.spec.updateStrategy.rollingUpdate.partition
来指定一个index分界点。- 所有ordinal大于等于partition指定的值的Pods将会进行滚动更新。
- 所有ordinal小于partition指定的值得Pods将保持不变。即使这些Pods被recreate,也会按照原来的pod template创建,并不会更新到最新的版本。
- 特殊地,如果partition的值大于StatefulSet的期望副本数N,那么将不会触发任何Pods的滚动更新。
deployment的更新策略(spec.strategy.type:更新deployment的方式,默认是RollingUpdate)
平滑升级,可以理解为“灰度策略的一种”,服务不中断。
- Recreate:重建,先删除旧的Pod,在创建新的Pod
- RollingUpdate:滚动更新,可以指定maxSurge和maxUnavailable
- maxUnavailable:指定在回滚或更新时最大不可用的Pod的数量,可选字段,默认25%,可以设置成数字或百分比,如果该值为0,那么maxSurge就不能0
- maxSurge:可以超过期望值(replicas)的最大Pod数,可选字段,默认为25%,可以设置成数字或百分比,如果该值为0,那么maxUnavailable不能为0