From 87fc8b70274aaf45fdfe700cbef74410dd1c7e17 Mon Sep 17 00:00:00 2001 From: D8D Developer Date: Thu, 6 Nov 2025 06:52:31 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20docs(eci):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=8A=A2=E5=8D=A0=E5=BC=8F=E5=AE=9E=E4=BE=8B=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加完整的ECI抢占式实例创建和使用指南 - 包含背景信息、计费方式、回收机制和注意事项 - 提供多种配置示例和YAML模板 - 详细说明释放机制和优雅下线流程 - 涵盖预释放事件处理和Pod状态监控 --- docs/eci.md | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 docs/eci.md diff --git a/docs/eci.md b/docs/eci.md new file mode 100644 index 0000000..db3879a --- /dev/null +++ b/docs/eci.md @@ -0,0 +1,230 @@ +```markdown +# 创建抢占式实例 + +**更新时间:2024-11-19 14:56:45** + +ECI支持抢占式实例,对于短时间运行的Job任务,以及部分扩展性和容错率高的无状态应用,使用抢占式实例可以有效地节约实例使用成本。本文介绍在Kubernetes集群中,如何创建抢占式实例类型的ECI Pod。 + +## 背景信息 + +抢占式实例是一种低成本竞价型实例,您可以对阿里云当前闲置的资源出价,获得资源后运行容器,直到出价低于市场价格或者库存不足等原因导致资源回收。 + +抢占式实例适用于短时间运行的Job任务,以及部分扩展性和容错率高的无状态应用,例如可弹性伸缩的Web站点服务、图像渲染、大数据分析和大规模并行计算等。应用程序的分布度、可扩展性和容错能力越高,越适合使用抢占式实例节省成本和提升吞吐量。更多信息,请参见[什么是抢占式实例](https://help.aliyun.com/zh/eci/user-guide/overview-22)。 + +## 基本概念 + +创建抢占式实例前,您需要了解以下信息: + +### 计费方式 + +抢占式实例的市场价格随供需变化而浮动,您需要在创建抢占式实例时指定出价模式,当指定实例规格的实时市场价格低于出价且库存充足时,就能成功创建抢占式实例。创建成功后,在保护期(默认1小时)内按照成交时的市场价格计费。超过保护期后,按照实时的市场价格计费。 + +> **说明** +> 抢占式实例相对于按量付费实例价格有一定的折扣,实际价格随供求波动,并按实际使用时长进行收费。更多信息,请参见[抢占式实例计费](https://help.aliyun.com/zh/eci/user-guide/billing-overview-4)。 + +### 回收机制 + +超过保护期后,系统每隔5分钟将自动检测一次实例规格的市场价格和库存。如果某一时刻的市场价格高于出价或实例规格库存不足,抢占式实例会被释放。 + +> **说明** +> 资源回收前约3分钟,系统会产生准备释放的事件。 +> +> 资源回收后,实例不再收费,但会保留实例信息,且状态会变更为已过期(Expired)。 + +## 注意事项 + +基于抢占式实例的特点,使用抢占式实例时,请注意以下信息: + +- 选择一个合适的实例规格和一个合理的出价。 +- 您可以通过ECS的OpenAPI接口查询抢占式实例近30天的信息,以便选择实例规格和出价。相关接口如下: + - `DescribeSpotPriceHistory`:查询实例历史价格。 + - `DescribeSpotAdvice`:查询实例平均释放率、平均折扣率等信息。 + +> **重要** +> 您的出价应该足够高,同时充分考虑了市场价格的波动,并且符合您对自身业务评估后的预期。这样才能成功创建抢占式实例,且实例不会因为价格因素被释放,在满足业务需求的同时实现成本节约。 +> +> 使用不受抢占式实例释放影响的存储介质来保存您的重要数据,例如:云盘(关闭随实例释放)、NAS等。 + +## 创建方式 + +支持指定ECS规格,或者指定vCPU和内存来创建抢占式ECI实例: + +### 指定ECS规格 + +计费以指定规格的按量市场价格和实时折扣为准。 + +### 指定vCPU和内存 + +该方式与指定ECS规格方式的效果相同。系统会自动匹配满足规格和价格要求的ECS规格,并以此规格的市场价格作为计费的原始市场价格,即折扣是基于该ECS规格的市场价,而非对应ECI的vCPU和内存的按量价格。 + +该方式仅支持2 vCPU及以上规格,支持指定的vCPU和内存规格如下表所示。如果指定的规格不支持,系统会自动向上规整。 + +| vCPU | 内存(GiB) | +|------|-------------| +| 2 | 2、4、8、16 | +| 4 | 4、8、16、32 | +| 8 | 8、16、32、64 | +| 12 | 12、24、48、96 | +| 16 | 16、32、64、128 | +| 24 | 24、48、96、192 | +| 32 | 32、64、128、256 | +| 52 | 96、192、384 | +| 64 | 128、256、512 | + +## 配置说明 + +您可以在Pod metadata中添加Annotation来创建抢占式实例。相关Annotation如下: + +| Annotation | 示例值 | 是否必选 | 说明 | +|------------|--------|----------|------| +| `k8s.aliyun.com/eci-spot-strategy` | `SpotAsPriceGo` | 是 | 抢占式实例的出价策略。可根据需要配置为:
- `SpotWithPriceLimit`:自定义设置抢占实例价格上限。此时必须通过`k8s.aliyun.com/eci-spot-price-limit`来指定每小时价格上限。
- `SpotAsPriceGo`:系统自动出价,跟随当前市场实际价格。

**重要**:使用`SpotAsPriceGo`策略时,如果对应可用区规格资源紧张,最高价格可能会达到按量价格。 | +| `k8s.aliyun.com/eci-spot-price-limit` | `"0.5"` | 否 | 抢占式实例的每小时价格上限,最多支持精确到小数点后三位。
仅当`k8s.aliyun.com/eci-spot-strategy`设置为`SpotWithPriceLimit`时有效。 | +| `k8s.aliyun.com/eci-spot-duration` | `"0"` | 否 | 抢占式实例的保护期。默认为1,可设置为0,表示无保护期。 | +| `k8s.aliyun.com/eci-spot-fallback` | `"true"` | 否 | 抢占式实例没有库存时,是否自动转为按量付费,以保证实例创建成功。默认为false。 | + +> **重要** +> - Annotation请添加在Pod的metadata下,例如:创建Job时,Annotation需添加在`spec>template>metadata`下。 +> - 仅支持在创建ECI Pod时添加ECI相关Annotation来生效ECI功能,更新ECI Pod时添加或者修改ECI相关Annotation均不会生效。 + +### 示例一:指定ECS规格,采用SpotWithPriceLimit策略 + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: spot-example-1 + annotations: + k8s.aliyun.com/eci-spot-strategy: "SpotWithPriceLimit" + k8s.aliyun.com/eci-spot-price-limit: "0.5" +spec: + containers: + - name: nginx + image: nginx:latest +``` + +### 示例二:指定vCPU和内存,采用SpotAsPriceGo策略 + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: spot-example-2 + annotations: + k8s.aliyun.com/eci-spot-strategy: "SpotAsPriceGo" + k8s.aliyun.com/eci-use-specs: "2-4Gi" +spec: + containers: + - name: nginx + image: nginx:latest +``` + +### 示例三:设置无保护期 + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: spot-example-3 + annotations: + k8s.aliyun.com/eci-spot-strategy: "SpotAsPriceGo" + k8s.aliyun.com/eci-spot-duration: "0" +spec: + containers: + - name: nginx + image: nginx:latest +``` + +### 示例四:设置没有库存时自动转为按量付费 + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: spot-example-4 + annotations: + k8s.aliyun.com/eci-spot-strategy: "SpotAsPriceGo" + k8s.aliyun.com/eci-spot-fallback: "true" +spec: + containers: + - name: nginx + image: nginx:latest +``` + +## 释放说明 + +抢占式实例创建成功后,在保护期内可以正常运行。超出保护期后,如果市场价格高于出价或者资源库存不足,抢占式实例会被释放。您可以通过以下信息了解抢占式实例的释放情况。 + +### 预释放事件 + +抢占式实例在释放前约3分钟,会产生`SpotToBeReleased`事件。 + +> **重要** +> ECI会通过Kubernetes Events事件通知的方式告知您抢占式实例将被释放。在此期间,您可以做一定的处理来确保业务不受实例释放所影响。更多信息,请参见[优雅下线](#优雅下线)。 + +通过`kubectl describe`命令查看Pod详细信息,在返回信息的Events中可以看到预释放事件。示例如下: + +```bash +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Warning SpotToBeReleased 3m32s kubelet, eci Spot ECI will be released in 3 minutes +``` + +通过`kubectl get events`命令查看事件信息,在返回信息中可以看到预释放事件。示例如下: + +```bash +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状态已变更。示例如下: + +```bash +NAME READY STATUS RESTARTS AGE +pi-frmr8 1/1 BidFailed 0 3h5m +``` + +通过`kubectl describe`命令查看Pod详细信息,在返回信息中可以看到Pod状态信息。示例如下: + +```bash +Status: Failed +Reason: BidFailed +Message: The pod is spot instance, and have been released at 2020-04-08T12:36Z +``` + +## 优雅下线 + +抢占式实例在释放前约3分钟,会产生`SpotToBeReleased`事件,同时会将Pod Conditions中的`ContainerInstanceExpired`字段置为`true`。为尽量避免抢占式实例回收导致的业务中断,您可以基于这些通知机制,进行抢占实例的优雅退出和Pod轮转等处理。 + +目前虚拟节点已支持配置ECI抢占式实例优雅下线的功能。您可以为抢占式实例类型的ECI Pod添加`k8s.aliyun.com/eci-spot-release-strategy: api-evict`的Annotation,实现当虚拟节点收到`SpotToBeReleased`事件时,会调用Eviction API来驱逐该抢占式实例。 + +> **重要** +> ACK Virtual Node需要升级到v2.11.0及以上版本,才支持通过Pod Conditions进行抢占实例中断通知以及配置Eviction API来驱逐抢占式实例。更多信息,请参见[ACK Virtual Node](https://help.aliyun.com/zh/ack/ack-virtual-node)。 + +API发起的驱逐将遵从您的PodDisruptionBudget(PDB)和`terminationGracePeriodSeconds`配置。使用API创建Eviction对象,类似于对Pod执行策略控制的DELETE操作。相关流程如下: + +1. **调用API请求** + - 虚拟节点接收到`SpotToBeReleased` Event,调用Eviction API。 + +2. **PDB检查** + - API服务器验证与目标Pod关联的PodDisruptionBudget。 + +3. **驱逐执行** + - 如果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资源。 + +4. **负载Reconcile** + - 如果目标Pod是由控制器(如ReplicaSet、StatefulSet,以及设置了容错的Job、sparkApplication、Workflow)管理的,控制器通常会创建一个新的Pod来替代被驱逐的Pod。 + +> **说明** +> 如果PodDisruptionBudget配置错误,或者调用Eviction API时工作负载存在大量尚未Ready的Pod,则会导致Eviction阻塞。在抢占式实例到期前,如果仍未完成Eviction动作,抢占式实例会被直接释放。 +``` \ No newline at end of file