Knative和AI結合提供了快速部署、高彈性和低成本的技術優勢,適用于需要頻繁調整計算資源的AI應用場景,例如模型推理等。您可以通過Knative Pod部署AI模型推理任務,配置自動擴縮容、靈活分配GPU資源等功能,提高AI推理服務能力和GPU資源利用率。
加速模型部署
為了保證Knative Serving部署的AI模型推理服務實現快速的伸縮能力,應避免將AI模型打包到容器鏡像中。當AI模型和容器鏡像打包在一起時,容器的大小會顯著地增大,從而減緩容器的部署速度。此外,當AI模型被打包在容器內時,AI模型的版本將與容器鏡像版本綁定,增加了版本控制的復雜性。
為避免上述問題,推薦您將AI模型的數據加載到對象存儲OSS、文件存儲NAS等外部介質中,并通過PVC掛載到Knative服務Pod中。同時,可使用分布式數據集編排和加速引擎Fluid來加速對AI模型的讀取和加載過程(參見JindoFS加速OSS文件訪問、EFC加速NAS或CPFS文件訪問等相關文檔),實現大模型的秒級加載。
前提條件
步驟一:定義數據集
當您將AI模型存放在對象存儲OSS時,可以使用Dataset來聲明OSS上的數據集,并使用JindoRuntime執行緩存任務。
apiVersion: v1
kind: Secret
metadata:
name: access-key
stringData:
fs.oss.accessKeyId: your_ak_id # 請替換為訪問OSS所用的access key ID。
fs.oss.accessKeySecret: your_ak_skrt # 請替換為訪問OSS所用的access key secret。
---
apiVersion: data.fluid.io/v1alpha1
kind: Dataset
metadata:
name: oss-data
spec:
mounts:
- mountPoint: "oss://{Bucket}/{path-to-model}" # 請替換為模型所在的OSS Bucket以及存儲路徑。
name: xxx
path: "{path-to-model}" # 根據程序加載模型的路徑,替換該處的模型存儲路徑。
options:
fs.oss.endpoint: "oss-cn-beijing.aliyuncs.com" # 請替換為實際的OSS endpoint地址。
encryptOptions:
- name: fs.oss.accessKeyId
valueFrom:
secretKeyRef:
name: access-key
key: fs.oss.accessKeyId
- name: fs.oss.accessKeySecret
valueFrom:
secretKeyRef:
name: access-key
key: fs.oss.accessKeySecret
accessModes:
- ReadOnlyMany
---
apiVersion: data.fluid.io/v1alpha1
kind: JindoRuntime
metadata:
name: oss-data
spec:
replicas: 2
tieredstore:
levels:
- mediumtype: SSD
volumeType: emptyDir
path: /mnt/ssd0/cache
quota: 100Gi
high: "0.95"
low: "0.7"
fuse:
properties:
fs.jindofsx.data.cache.enable: "true"
args:
- -okernel_cache
- -oro
- -oattr_timeout=7200
- -oentry_timeout=7200
- -ometrics_port=9089
cleanPolicy: OnDemand
步驟二:掛載PVC實現加速效果
聲明Dataset和JindoRuntime后,系統會自動創建同名PVC,將PVC掛載到Knative服務中即可實現加速效果。
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: sd-backend
spec:
template:
spec:
containers:
- image: <YOUR-IMAGE> # 請將<YOUR-IMAGE>替換為您的鏡像名稱。
name: image-name
ports:
- containerPort: xxx
protocol: TCP
volumeMounts:
- mountPath: /data/models # 根據程序加載模型的路徑,替換moutPath。
name: data-volume
volumes:
- name: data-volume
persistentVolumeClaim:
claimName: oss-data # 掛載和Dataset同名的PVC。
步驟三:通過鏡像緩存實現秒級加載
除AI模型本身之外,也需要考慮容器鏡像大小對Knative服務的影響。運行AI模型的服務容器往往需要打包CUDA、pytorch-gpu等一系列依賴,導致其容器鏡像大小顯著增加。當使用ECI Pod部署Knative AI模型推理服務時,建議使用ImageCache來加速鏡像的拉取過程,ImageCache能夠為ECI Pod提供鏡像緩存功能,通過提前緩存鏡像來顯著加速鏡像拉取時間、實現秒級鏡像拉取,參見使用ImageCache加速創建ECI Pod。
apiVersion: eci.alibabacloud.com/v1
kind: ImageCache
metadata:
name: imagecache-ai-model
annotations:
k8s.aliyun.com/eci-image-cache: "true" # 開啟鏡像緩存復用。
spec:
images:
- <YOUR-IMAGE>
imageCacheSize:
25 # 鏡像緩存大小,單位GiB。
retentionDays:
7 # 鏡像緩存保留時間。
優雅關閉容器
為了確保正在進行的請求不會突然終止,容器應在收到SIGTERM信號時啟動正常關閉。
收到SIGTERM信號后,如果應用程序使用HTTP探測,則設置容器為非就緒狀態,防止將新的請求轉發給正在關閉的容器。
在關閉過程中,Knative的queue-proxy可能仍在將請求轉發到容器。建議將
timeoutSeconds
參數應該設置為最長預期處理請求響應時間的1.2倍左右,以確保所有請求可以在容器終止之前完成。例如,如果最長的請求響應時間需要10秒,建議將timeoutSeconds
參數設置為12秒。apiVersion: serving.knative.dev/v1 kind: Service metadata: name: helloworld-go namespace: default spec: template: spec: timeoutSeconds: 12
并發參數配置
通過正確配置并發參數,您可以顯著提升Knative服務的性能和響應速度。這些設置可以幫助您的應用程序更有效地處理高并發請求負載,從而提高整體的服務質量和用戶體驗。
并發硬限制:硬限制是強制上限。如果并發達到硬限制,多余的請求將被緩沖,并且必須等待,直到有足夠的可用資源來執行請求。
并發軟限制:軟限制是有針對性的限制,而不是嚴格的約束。在類似請求突然爆發的情況下,可能會超過該值。
目標使用率:相較于直接修改
target
,調整目標使用率autoscaling.knative.dev/target-utilization-percentage
提供了更直觀的并發級別管理方式。將此配置接近 100% 可以實現最高效的并發處理。
更多詳細說明及實例,請參見并發數配置介紹。
自動彈性擴縮容
在對自動彈性進行調整之前,首先需定義優化目標,例如減少延遲、最大限度地降低成本或適應尖峰流量模式。然后測量Pod在預期場景下啟動所需的時間。例如,部署單個Pod可能與同時部署多個Pod具有不同的方差和平均啟動時間。這些指標為自動彈性配置提供了基準。
更多參數信息及配置說明,請參見基于流量請求數實現服務自動擴縮容。
擴縮容模式
自動彈性有兩種模式,穩定模式(Stable Mode)和恐慌模式(Panic Mode),每種模式都有單獨的窗口。穩定模式用于一般操作,而恐慌模式默認情況下具有更短的窗口,用于在流量突發時快速擴容Pod。
穩定模式窗口
通常為了保持穩定的擴縮容行為,穩定窗口應該比平均Pod啟動時間長,推薦設置為平均時間的2倍。
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/window: "40s"
恐慌模式窗口
恐慌窗口是穩定窗口的百分比。其主要功能是管理突然的、意外的流量高峰。
此配置容易導致過度擴容,尤其當Pod啟動時間較長時。請謹慎配置。
如果穩定窗口設置為30秒,恐慌窗口配置為10%,則系統將使用3秒的數據來判斷是否進入恐慌縮放模式。如果Pod通常需要30秒才能啟動,則系統可能會在新Pod仍在上線時繼續擴容,從而可能導致過度擴容Pod。
在調整其他參數并確保縮放行為穩定之前,避免對恐慌窗口進行微調,尤其是當考慮到恐慌窗口的值短于或等同于Pod啟動時間的情形。若穩定窗口為平均Pod啟動時間的兩倍,可以考慮將恐慌窗口值設定為50%,以此作為平衡正常和高峰流量模式的起點。
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld
namespace: default
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/panic-window-percentage: "20.0"
恐慌模式閾值是傳入流量與服務容量的比率。根據流量的尖峰和可接受的延遲水平來調整此值。初始值為200%或更高,直到縮放行為穩定。服務運行一段時間之后,可以考慮進一步調整。
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld
namespace: default
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/panic-threshold-percentage: "150.0"
彈性速率
為了更好地響應流量模式,可以通過調整擴容和縮容速率來控制系統的彈性。默認配置通常能夠滿足大部分需求,但在特定場景下可能需要進行相應的調整。在調整速率之前需要觀察當前情況,并優先在測試環境中進行更改和驗證,以評估其影響。如果遇到擴縮容問題,請檢查與擴容和縮容速率相關的參數,如穩定窗口和恐慌窗口等。
擴容速率
除非遇到特定問題,否則擴容速率通常不需要修改。例如,如果同時對多個Pod進行擴容,可能由于需等待資源的分配,導致啟動時間延長,則需要調整擴容速率。如果觀察到頻繁擴縮,可能還需要考慮調整其他相關參數,如穩定窗口或者恐慌窗口大小,以優化伸縮行為。
apiVersion: v1
kind: ConfigMap
metadata:
name: config-autoscaler
namespace: knative-serving
data:
max-scale-up-rate: "500.0"
縮容速率
縮容速率最初應設置為平均Pod啟動時間或更長。默認值通常足以滿足大多數使用情況,但如果重點在于優化成本,可以考慮調高速率,以便在流量高峰后更快地縮容。
縮容率是一個乘數,例如,值N/2將允許系統在彈性周期結束時將Pod數量縮減至當前數量的一半。對于Pod數量較少的服務,較低的縮容率有助于保持Pod數量更加平滑,避免頻繁地伸縮造成的波動,從而提高系統穩定性。
apiVersion: v1
kind: ConfigMap
metadata:
name: config-autoscaler
namespace: knative-serving
data:
max-scale-down-rate: "4.0"
延遲縮容
可以通過指定延遲縮容的時間窗口,避免新請求進入時頻繁擴縮容,導致響應延遲的問題。
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld-go
namespace: default
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/scale-down-delay: "2m" // 表示延遲 2 分鐘縮容
擴縮容邊界
這些參數與業務的規模和可用資源高度相關。
下限
autoscaling.knative.dev/min-scale
控制每個修訂版應具有的最小副本數。Knative將保持不少于此數量的副本。對于那些使用率不高但需要保持始終可用的服務,將該值設置為1可以確保至少有一個副本始終運行。對于可能會有大量突發流量的服務,應將此值設定高于1以提高應對能力。如果希望服務能夠在無流量時縮減到零副本,可將該值設置為0。
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld
namespace: default
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/min-scale: "0"
上限
autoscaling.knative.dev/max-scale
不應超過可用資源。使用此參數主要限制最大資源成本。
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld
namespace: default
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/max-scale: "3"
初始擴容數
配置初始規模,建議配置為現有Pod數量的1.2倍左右,以便新版本可以充分處理現有流量。
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld-go
namespace: default
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/initial-scale: "3"
共享GPU調度
結合ACK共享GPU調度能力,Knative模型服務可以充分利用cGPU顯存隔離能力,高效利用GPU設備資源。
在Knative使用共享GPU只需要在Knative Service中limits
設置aliyun.com/gpu-mem
參數即可,示例如下。
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld-go
namespace: default
spec:
template:
spec:
containerConcurrency: 1
containers:
- image: registry-vpc.cn-hangzhou.aliyuncs.com/demo-test/test:helloworld-go
name: user-container
ports:
- containerPort: 6666
name: http1
protocol: TCP
resources:
limits:
aliyun.com/gpu-mem: "3"
探針配置
您可以通過配置存活探針(Liveness Probe)和就緒探針(Readiness Probe)監測Knative服務的健康和可用性。相較于 Kubernetes 的探針策略,Knative 采用更頻繁的積極探測,以最大限度減少冷啟動時間,加速 Pod 啟動到運行的過程。
Liveness Probe:存活探針用于監視容器的健康狀況。如果容器處于失敗狀態或在容器運行中服務未成功啟動,存活探針將重新啟動容器。
Readiness Probe:配置就緒探針可以有效管理應用的自動擴縮容過程,確保只有準備好的實例可以接收流量,從而提升系統的可靠性和響應效率。
在加載所有組件并且容器完全準備好之前,TCP探針不會啟動監聽端口。
在端點能夠處理請求之前,HTTP探測不應將服務標記為就緒。
調整探測間隔periodSeconds時,請保持較短的間隔。理想情況下,該時間應小于默認值10秒。
更多詳細說明及最佳實踐,請參見在Knative中配置端口探測。
按需自動縮容至零以節約資源
Knative的突出功能之一是能夠在服務不使用時將Pod縮容至零。
對于需要管理多個模型的用戶,推薦為每個獨立的模型創建單獨的Knative服務,以避免在一個服務內部集成復雜的業務邏輯。
借助Knative的縮容到零的功能,可以做到長時間未被訪問的模型不會產生資源成本。
當客戶端第一次訪問模型服務時,Knative能夠實現從零狀態開始的自動擴容。
更多詳細說明及最佳實踐,請參見配置保留實例。
基于多版本設置合理的灰度節奏
Knative優勢之一是可以確保不間斷的服務可用性,特別是在推出新版本時。當部署新代碼或對服務進行更改時Knative會保持舊版本運行,直到新版本準備就緒。
可以通過流量百分比閾值進行配置。流量百分比是一個關鍵參數,它決定Knative何時應將流量從舊版本切換到新版本。該百分比可以低至10%,也可以高達100%,取決于具體需求。對于不需要舊服務的非生產環境,可以將流量百分比設置為100%。當新版本準備就緒時,會立即關閉舊版本。
在Pod可用性有限的情況下進行大規模操作時,需要控制舊版本的縮容速度。如果某個服務在500個Pod上運行,而只有300個額外的Pod可用,那么設置過大的流量百分比可能會導致服務部分不可用。
更多詳細說明及最佳實踐,請參見基于流量灰度發布服務。
ECS和ECI資源混用
如果希望常態情況下使用ECS資源,突發流量時使用ECI,那么可以結合ResourcePolicy來實現。在常態下通過ECS資源承載流量,而在遇到突增的流量時,額外擴容的資源會使用ECI進行承載。
在擴容過程中,Knative Pod會優先利用ECS資源進行擴展。當Pod數量超過預設的最大值,或ECS資源不足時,則會轉而使用ECI來創建新的Pod。
縮容時,會根據調度節點的逆序,優先縮容在ECI上的Pod。
更多詳細說明及最佳實踐,請參見在Knative中同時使用ECS和ECI資源。