ECI支持搶占式實例,對于短時間運行的Job任務,以及部分擴展性和容錯率高的無狀態應用,使用搶占式實例可以有效地節約實例使用成本。本文介紹在Kubernetes集群中,如何創建搶占式實例類型的ECI Pod。
背景信息
搶占式實例是一種低成本競價型實例,您可以對阿里云當前閑置的資源出價,獲得資源后運行容器,直到出價低于市場價格或者庫存不足等原因導致資源回收。
搶占式實例適用于短時間運行的Job任務,以及部分擴展性和容錯率高的無狀態應用,例如可彈性伸縮的Web站點服務、圖像渲染、大數據分析和大規模并行計算等。應用程序的分布度、可擴展性和容錯能力越高,越適合使用搶占式實例節省成本和提升吞吐量。更多信息,請參見什么是搶占式實例。
基本概念
創建搶占式實例前,您需要了解以下信息:
計費方式
搶占式實例的市場價格隨供需變化而浮動,您需要在創建搶占式實例時指定出價模式,當指定實例規格的實時市場價格低于出價且庫存充足時,就能成功創建搶占式實例。創建成功后,在保護期(默認1小時)內按照成交時的市場價格計費。超過保護期后,按照實時的市場價格計費。
說明搶占式實例相對于按量付費實例價格有一定的折扣,實際價格隨供求波動,并按實際使用時長進行收費。更多信息,請參見搶占式實例計費。
回收機制
超過保護期后,系統每隔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 | 是 | 搶占式實例的出價策略。可根據需要配置為:
|
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策略
apiVersion: batch/v1
kind: Job
metadata:
name: test
spec:
template:
metadata:
labels:
app: perl
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:
- name: pi
image: registry.cn-shanghai.aliyuncs.com/eci_open/perl:5
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
以上YAML示例可創建一個ecs.c6規格的搶占式實例。
創建時,如果沒有滿足規格和價格上限要求的庫存,則創建失敗。
創建后,可以穩定使用1小時,超出1小時保護期后,如果某一時刻的市場價格高于出價或實例規格庫存不足,搶占式實例會被釋放。
示例二:指定vCPU和內存,采用SpotAsPriceGo策略
通過pod.spec.resources指定vCPU和內存規格
apiVersion: batch/v1 kind: Job metadata: name: test spec: template: metadata: labels: app: perl alibabacloud.com/eci: "true" annotations: k8s.aliyun.com/eci-spot-strategy: "SpotAsPriceGo" #采用系統自動出價,跟隨當前市場實際價格 spec: containers: - name: pi image: registry.cn-shanghai.aliyuncs.com/eci_open/perl:5 command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] resources: limits: #指定pi容器的vCPU為2 vCPU,內存為4 GiB cpu: 2000m memory: 4096Mi restartPolicy: Never
通過Annotation指定vCPU和內存規格
apiVersion: batch/v1 kind: Job metadata: name: test spec: template: metadata: labels: app: perl alibabacloud.com/eci: "true" annotations: k8s.aliyun.com/eci-use-specs : "2-4Gi" #指定vCPU和內存,僅支持2 vCPU及以上規格 k8s.aliyun.com/eci-spot-strategy: "SpotAsPriceGo" #采用系統自動出價,跟隨當前市場實際價格 spec: containers: - name: pi image: registry.cn-shanghai.aliyuncs.com/eci_open/perl:5 command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] restartPolicy: Never
以上YAML示例可創建一個2 vCPU,4 GiB內存的搶占式實例。
創建時,如果沒有滿足規格要求的庫存,則創建失敗。
創建后,可以穩定使用1小時,超出1小時保護期后,如果某一時刻的市場價格高于出價或實例規格庫存不足,搶占式實例會被釋放。
示例三:設置無保護期
apiVersion: batch/v1
kind: Job
metadata:
name: test
spec:
template:
metadata:
labels:
app: perl
alibabacloud.com/eci: "true"
annotations:
k8s.aliyun.com/eci-use-specs : "2-4Gi" #指定vCPU和內存,僅支持2 vCPU及以上規格
k8s.aliyun.com/eci-spot-strategy: "SpotAsPriceGo" #采用系統自動出價,跟隨當前市場實際價格
k8s.aliyun.com/eci-spot-duration: "0" #設置無保護期
spec:
containers:
- name: pi
image: registry.cn-shanghai.aliyuncs.com/eci_open/perl:5
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
以上YAML示例可創建一個2 vCPU,4 GiB內存的搶占式實例。
創建時,如果沒有滿足規格要求的庫存,則創建失敗。
創建后,沒有穩定使用的保護期,只要某一時刻的市場價格高于出價或實例規格庫存不足,搶占式實例就會被釋放。
示例四:設置沒有庫存時自動轉為按量付費
apiVersion: batch/v1
kind: Job
metadata:
name: test
spec:
template:
metadata:
labels:
app: perl
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:
- name: pi
image: registry.cn-shanghai.aliyuncs.com/eci_open/perl:5
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
以上YAML示例可創建一個ecs.c6規格的搶占式實例。
創建時,如果有滿足規格和價格上限要求的庫存,則會創建一個搶占式實例。創建后,可以穩定使用1小時,超出1小時保護期后,如果某一時刻的市場價格高于出價或實例規格庫存不足,搶占式實例會被釋放。
創建時,如果沒有滿足規格和價格上限要求的庫存,則會創建一個按量付費的實例。創建后,系統不會主動釋放實例。
實例創建成功后,您可以通過
kubectl describe pod
命令查看對應Pod的事件來確認是否轉為按量付費實例,如果看到SpotDegraded事件,則表明已轉為按量付費實例。
釋放說明
搶占式實例創建成功后,在保護期內可以正常運行。超出保護期后,如果市場價格高于出價或者資源庫存不足,搶占式實例會被釋放。您可以通過以下信息了解搶占式實例的釋放情況。
預釋放事件
搶占式實例在釋放前約3分鐘,會產生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
優雅下線
搶占式實例在釋放前約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。
API發起的驅逐將遵從您的PodDisruptionBudget(PDB)和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資源。
負載Reconcile
如果目標Pod是由控制器(如ReplicaSet、StatefulSet,以及設置了容錯的Job、sparkApplication、Workflow)管理的,控制器通常會創建一個新的Pod來替代被驅逐的Pod。
如果PodDisruptionBudget配置錯誤,或者調用Eviction API時工作負載存在大量尚未Ready的Pod, 則會導致Eviction阻塞。在搶占式實例到期前,如果仍未完成Eviction動作,搶占式實例會被直接釋放。