如果您的業務為短時服務類型(例如短時Web服務請求等),對業務中斷容忍度較高,可以用完即釋放,不會長時間占用資源,您可以配置Knative Service使用搶占式實例,其價格相較于按量計費的ECS實例更為優惠。通過將Knative與搶占式實例結合使用,您可以在保證服務彈性和響應速度的同時,最大化地利用云計算資源的成本效益,實現更加經濟高效的Serverless架構。
前提條件
已為ACK集群或ACK Serverless集群部署Knative。具體操作,請參見為ACK集群部署Knative、為ACK Serverless集群部署Knative。
名詞解釋
是一種低成本競價型實例,您可以對阿里云當前閑置的資源出價,獲得資源后運行容器,直到出價低于市場價格或者庫存不足等原因導致資源回收。關于搶占式實例的更多信息,請參見什么是搶占式實例。
一款基于Kubernetes的開源Serverless應用編排框架,其目標是制定云原生、跨平臺的Serverless應用編排標準。Knative主要功能包括基于請求的自動彈性、縮容到0、多版本管理、基于流量的灰度發布、函數部署以及事件驅動等。關于Knative的更多信息,請參見ACK Knative概述、ACK Serverless 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
相關文檔
如果您的應用對冷啟動延時較為敏感,推薦您使用保留實例功能,保留一個低規格的突發性能實例,平衡好使用成本和啟動時長,請參見配置保留實例。