如果您的业务为短时服务类型(例如短时Web服务请求等),对业务中断容忍度较高,可以用完即释放,不会长时间占用资源,您可以配置Knative Service使用抢占式实例,其价格相较于按量计费的ECS实例更为优惠。通过将Knative与抢占式实例结合使用,您可以在保证服务弹性和响应速度的同时,最大化地利用云计算资源的成本效益,实现更加经济高效的Serverless架构。
前提条件
已在集群中部署Knative,请参见部署Knative。
名词解释
实现原理及功能优势
在Knative中,Serverless工作负载的管理主要通过Knative Service实现。Knative Service可以基于请求自动扩缩容Pod。如果需要使用抢占式实例,只需要配置相应的Pod注解即可。虚拟节点(Virtual Node)会根据Pod的注解自动申请对应的ECI资源规格。当前虚拟节点提供了抢占式实例自动替换能力,可以更加自动化地使用抢占式实例。
Knative结合抢占式实例的优势:
Serverless场景:短时Web服务请求,资源随时使用,用完即释放,不会长时间占用资源。
优雅下线的天然适配:在虚拟节点实现自动替换过程中,需要先删除Pod,然后工作负载控制器再创建新的抢占式实例,这就要求业务容器具备优雅下线的能力。而在Knative中会为每个Pod设置1个queue-proxy Sidecar容器,在删除Pod时,会先触发queue-proxy容器等待请求处理完成,然后再删除业务容器。
成本敏感:对于使用Knative且关心成本的用户,使用抢占式实例更具吸引力。
结合Knative配置抢占式实例及示例
配置抢占式实例
仅支持在创建ECI Pod时添加以下Annotation来使ECI功能生效,更新ECI Pod时添加或者修改ECI相关Annotation均不会生效。
在Service中添加Annotation来配置抢占式实例的相关Annotation如下:
Annotation | 示例值 | 是否必选 | 说明 |
k8s.aliyun.com/eci-spot-strategy | SpotAsPriceGo | 是 | 抢占式实例的出价策略。可根据需要配置为:
|
k8s.aliyun.com/eci-spot-price-limit | "0.5" | 否 | 抢占式实例的每小时价格上限,最多支持精确到小数点后三位。 仅当 |
k8s.aliyun.com/eci-spot-duration | "1" | 否 | 抢占式实例的保护期。默认值为1,可设置为0。0表示无保护期。 |
k8s.aliyun.com/eci-spot-fallback | "true" | 否 | 抢占式实例没有库存时,是否自动转为按量付费,以保证实例创建成功。默认为 |
示例一:指定ECS规格,采用SpotWithPriceLimit策略
以下YAML示例可创建一个ecs.c6规格的抢占式实例。
创建时,如果没有满足规格和价格上限要求的库存,则创建失败。
创建后,可以稳定使用1小时,超出1小时保护期后,如果某一时刻的市场价格高于出价或实例规格库存不足,抢占式实例会被释放。
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld-go
spec:
template:
metadata:
labels:
alibabacloud.com/eci: "true"
annotations:
k8s.aliyun.com/eci-use-specs : "ecs.c6.large" # 指定ECS实例规格。
k8s.aliyun.com/eci-spot-strategy: "SpotWithPriceLimit" # 采用自定义设置价格上限的策略。
k8s.aliyun.com/eci-spot-price-limit: "0.25" # 设置每小时价格上限。
spec:
containers:
- env:
- name: TARGET
value: "Knative"
image: registry.cn-hangzhou.aliyuncs.com/knative-sample/helloworld-go:73fbdd56
示例二:设置没有库存时自动转为按量付费
以下YAML示例可创建一个ecs.c6规格的抢占式实例。
创建时,如果有满足规格和价格上限要求的库存,则会创建一个抢占式实例。创建后,可以稳定使用1小时,超出1小时保护期后,如果某一时刻的市场价格高于出价或实例规格库存不足,抢占式实例会被释放。
创建时,如果没有满足规格和价格上限要求的库存,则会创建一个按量付费的实例。创建后,系统不会主动释放实例。实例创建成功后,您可以通过
kubectl describe pod
命令查看对应Pod的事件来确认是否转为按量付费实例,如果看到SpotDegraded事件,则表明已转为按量付费实例。
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld-go
spec:
template:
metadata:
labels:
alibabacloud.com/eci: "true"
annotations:
k8s.aliyun.com/eci-use-specs : "ecs.c6.large" # 指定ECS实例规格。
k8s.aliyun.com/eci-spot-strategy: "SpotWithPriceLimit" # 采用自定义设置价格上限的策略。
k8s.aliyun.com/eci-spot-price-limit: "0.05" # 设置每小时价格上限。
k8s.aliyun.com/eci-spot-fallback: "true" # 当抢占式实例没有库存时,自动转为按量付费。
spec:
containers:
- env:
- name: TARGET
value: "Knative"
image: registry.cn-hangzhou.aliyuncs.com/knative-sample/helloworld-go:73fbdd56
步骤一:为Knative Service配置抢占式实例
为尽可能降低计算资源成本,您可以为Knative Service配置k8s.aliyun.com/eci-spot-strategy
注解,这样服务会优先使用抢占式实例(ECI Spot实例),这类实例的价格相较于按需实例更为优惠。
然而,实例在市场价格高于出价或实例规格库存不足时会被回收,这可能导致服务中断。为了避免这种情况影响业务连续性,您可以同时设置k8s.aliyun.com/eci-spot-fallback: "true"
注解,在抢占式实例因资源不足无法继续使用时,配置了该注解的Knative Service会自动回退到使用按需实例,从而确保服务的稳定运行和连续性。这样既能有效节约成本,又能兼顾服务可靠性。
登录容器服务管理控制台,在左侧导航栏选择集群。
在集群列表页面,单击目标集群名称,然后在左侧导航栏,选择 。
在Knative页面的服务管理页签下,选择命名空间为default,然后单击使用模板创建,单击示例模板右侧的下拉列表,选择自定义,将以下示例代码粘贴至模板,最后单击创建,创建一个名为helloworld-go的Knative服务。
apiVersion: serving.knative.dev/v1 kind: Service metadata: name: helloworld-go spec: template: metadata: labels: alibabacloud.com/eci: "true" annotations: k8s.aliyun.com/eci-use-specs : "ecs.c6.large" # 指定ECS实例规格。 k8s.aliyun.com/eci-spot-strategy: "SpotAsPriceGo" # 采用自定义设置价格上限的策略。 k8s.aliyun.com/eci-spot-duration: "1" # 设置无保护期。默认为1,单位:h。您可以在创建实例时根据实际需求指定保护期时长。 k8s.aliyun.com/eci-spot-fallback: "true" # 当抢占式实例没有库存时,自动转为按量付费。 spec: containers: - env: - name: TARGET value: "Knative" image: registry-vpc.{REGION-ID}.aliyuncs.com/knative-samples/helloworld-go:160e4dc8 # {REGION-ID}为对应集群所在的地域,如cn-hangzhou。
以上YAML示例可创建一个ecs.c6规格的抢占式实例。
创建时,如果没有满足规格要求的库存,则创建失败。
创建后,可以稳定使用1小时,在此期间内,即使市场价格高于出价,实例也不会被释放。超出1小时保护期后,如果某一时刻的市场价格高于出价或者因为资源库存不足,抢占式实例有可能会被阿里云自动释放。此时,通过
k8s.aliyun.com/eci-spot-fallback: "true"
设置,当抢占式实例因任何原因无法获取或被释放时,系统会自动转为按量付费实例以确保服务可用性。
(可选)步骤二:配置抢占式实例的优雅下线
使用限制
虚拟节点组件ACK Virtual Node需要升级到v2.11.0及以上,才支持通过Pod Conditions来进行抢占实例中断通知以及配置Eviction API来驱逐抢占式实例。关于ACK Virtual Node的更多信息,请参见ACK Virtual Node。
抢占式实例中断通知
抢占式实例会在中断前3分钟发出SpotToBeReleased Event,同时会更新Pod Conditions的ContainerInstanceExpired
字段为true
。
Pod的Conditions字段和Events字段显示如下。
配置抢占式实例到期的优雅处理方式
为了尽量避免ECI抢占式实例回收导致的业务中断,虚拟节点提供了可配置的ECI抢占式实例优雅下线的功能。您可以为抢占型Pod配置annotationsk8s.aliyun.com/eci-spot-release-strategy: api-evict
。那么当虚拟节点接收到SpotToBeReleased Event
时,则会调用Eviction API来驱逐该抢占式实例。API发起的驱逐将遵从您的PodDisruptionBudgets
和terminationGracePeriodSeconds
配置。使用API创建Eviction对象,类似于对Pod执行策略控制的DELETE
操作。
调用API请求:虚拟节点接收到SpotToBeReleased Event,调用Eviction API。
PDB检查:API服务器验证与目标Pod关联的PodDisruptionBudget。
驱逐执行:如果API服务器允许驱逐,Pod将按照如下方式删除。
API服务器中的Pod资源会更新删除时间戳,之后API服务器会认为此Pod资源将被终止。 此Pod资源还会标记上配置的宽限期。
本地运行状态的Pod所处的节点上的kubelet注意到Pod资源被标记为终止,并开始优雅停止本地Pod。
当kubelet停止Pod时,控制面从Endpoint和EndpointSlice对象中移除该Pod。因此,控制器不再将此Pod视为有用对象。
Pod的宽限期到期后,kubelet强制终止本地Pod。
kubelet告诉API服务器删除Pod资源。
API服务器删除Pod资源。
在Knative场景下,每个Service的Pod中包含一个queue-proxy Sidecar容器。在删除Pod时,queue-proxy会首先等待所有正在进行的请求处理完成,以保证服务的连续性和数据完整性,最后才会停止业务容器,从而实现平滑的Pod缩容或更新操作。
释放说明
抢占式实例创建成功后,在保护期内可以正常运行。超出保护期后,如果市场价格高于出价或者资源库存不足,抢占式实例会被释放。您可以通过以下信息了解抢占式实例的释放情况。
预释放事件
抢占式实例在释放前约5分钟,会产生SpotToBeReleased事件。
重要ECI会通过Kubernetes Events事件通知的方式告知您抢占式实例将被释放,在此期间,您可以做一定的处理来确保业务不受实例释放所影响。
通过
kubectl describe
命令查看Pod详细信息,在返回信息的Events中可以看到预释放事件。示例如下:Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning SpotToBeReleased 3m32s kubelet, eci Spot ECI will be released in 3 minutes
通过
kukubectl get events
命令查看事件信息,在返回信息中可以看到预释放事件。示例如下:LAST SEEN TYPE REASON OBJECT MESSAGE 3m39s Warning SpotToBeReleased pod/pi-frmr8 Spot ECI will be released in 3 minutes
释放后Pod状态
抢占式实例释放后,实例信息仍会保留,状态变更为Failed,Failed原因为BidFailed。
通过
kubectl get pod
命令查看Pod信息,在返回信息中可以看到Pod状态已变更。示例如下:NAME READY STATUS RESTARTS AGE pi-frmr8 1/1 BidFailed 0 3h5m
通过
kubectl describe
命令查看Pod详细信息,在返回信息中可以看到Pod状态信息。示例如下:Status: Failed Reason: BidFailed Message: The pod is spot instance, and have been released at 2020-04-08T12:36Z
相关文档
如果您的应用对冷启动延时较为敏感,推荐您使用保留实例功能,保留一个低规格的突发性能实例,平衡好使用成本和启动时长,请参见配置保留实例。