serverless knative实战
1、部署一個service應(yīng)用
在部署第一個Knative Service之前,我們先了解一下它的部署模型和對應(yīng)的Kubernetes資源。如圖6-2所示,在部署Knative Serving Service的過程中,Knative Serving控制器將創(chuàng)建configuration、Revision和Route三個資源對象。
配置(configuration):Knative configuration維護了部署的目標(biāo)狀態(tài),提供了一個干凈的代碼和配置分離、遵循12要素開發(fā)原則的機制。基于目標(biāo)狀態(tài),Knative configuration控制器為應(yīng)用創(chuàng)建了一個新的Kubernetes部署應(yīng)用。并且configuration的變更會體現(xiàn)在一個新的Kubernetes部署應(yīng)用中。
修訂版(Revision):Knative configuration遵循12要素開發(fā)原則,每次應(yīng)用的變更將會創(chuàng)建一個新的Knative Revision。Revision類似于版本控制中的標(biāo)簽。Revision一旦創(chuàng)建,是不可改變的。每個Revision都有一個對應(yīng)的Kubernetes Deployment。它允許將應(yīng)用程序回滾到任何正確的最新配置。
路由(Route):Knative Route是訪問Knative Service的URL。
接下來分別以java和node為例創(chuàng)建一個簡單的web服務(wù)。該服務(wù)接收到HTTP GET請求時,會根據(jù)環(huán)境變量Target傳遞的內(nèi)容向Response輸出Hello$TATGET!內(nèi)容。
1.1、制作service鏡像
java
啟動訪問
./mvnw package && java -jar target/helloworld-0.0.1-SNAPSHOT.jarnodejs
制作鏡像和推送鏡像和java環(huán)境一樣。
注意應(yīng)用程序和docker暴露端口必須是8080,否則會部署失敗。新版可以在service的yml中指定端口號。
1.2 部署應(yīng)用
可以采用二種方式部署應(yīng)用:
- yaml
- kn
創(chuàng)建service.yml,image指定為上一步制作的鏡像,文件如下:
apiVersion: serving.knative.dev/v1 kind: Service metadata:name: helloworld-java-springnamespace: default spec:template:spec:containers:- image: docker.io/{username}/helloworld-java-springenv:- name: TARGETvalue: "Java Spring Sample v1"利用kubectl部署
kubectl apply --filename service.yaml在創(chuàng)建服務(wù)期間,Knative 會執(zhí)行以下步驟:
- 為此版本的應(yīng)用程序創(chuàng)建一個新的不可變修訂版。
- 為您的應(yīng)用程序創(chuàng)建路由、入口、服務(wù)和負載平衡。
- 自動向上和向下擴展您的 pod,包括縮小到零活動 pod。
1.3 驗證
可以采用二種方式驗證:
- kubectl
- kn
顯示
NAME URL helloworld-java-spring http://helloworld-java-spring.default.1.2.3.4.sslip.io顯示
http://helloworld-java-spring.default.1.2.3.4.sslip.io訪問:
curl http://helloworld-java-spring.default.1.2.3.4.sslip.io Hello Java Spring Sample v1! # Even easier with kn: curl $(kn service describe helloworld-java-spring -o url)1.4 刪除service
1.4 更新Knative Service configuration
在部署完一個Knative Service后,我們會因為應(yīng)用版本的升級、配置的變更等需要更新現(xiàn)有服務(wù)的configuration。Knative服務(wù)還提供了一種機制實現(xiàn)回滾變更。
12要素應(yīng)用設(shè)計原則規(guī)定,應(yīng)用程序與配置的變更應(yīng)被視為一個新的修訂版。修訂版是不可變更的應(yīng)用和配置的狀態(tài)集合。它可以讓你回滾到任何一個有效的修訂版狀態(tài)。
應(yīng)用的更新包括容器鏡像的更新、健康檢查探針的調(diào)整、環(huán)境變量的變更。這些變更會導(dǎo)致Knative生成新的修訂版。每一個新修訂版將創(chuàng)建一個新的Kubernetes Deployment對象。
接下來,我們通過一個更新服務(wù)配置的示例來演示配置的變更。
配置文件(service.yaml)的變更如下。
1)更新修訂版的名稱(.spec.template.metadata.name)為helloworld-go-v2,區(qū)別于上一個修訂版名稱helloworld-go-v1。
2)更新環(huán)境變量TARFET(.spec.template.spec.containers[0].env[0].value)的值為Go Sample v2。
將配置更新到Knative:
檢查部署結(jié)果:
# kubectl get ksvc helloworld-go NAME URL LATESTCREATED LATESTREADY READY REASON helloworld-go http://helloworld-go. helloworld-go-v2 helloworld-go-v2 Truedefault.example.com通過curl命令訪問helloworld-go服務(wù):
##獲取集群任一節(jié)點的IP地址和nodePort端口 # IP_ADDRESS="$(kubectl get nodes-o 'jsonpath={.items[0].status.addresses[0].address}'):$(kubectl get svc istio-ingressgateway--namespace istio-system --output 'jsonpath={.spec.ports[?(@.port==80)].nodePort}')"# curl-H "Host:helloworld-go.default.example.com" http://$IP_ADDRESS Hello Go Sample v2!查看部署后生成的Kubernetes Deployment:
# kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE helloworld-go-v1-deployment 0/0 0 0 2m52s helloworld-go-v2-deployment 1/1 1 1 2m19s查看部署后生成的Kubernetes Pod:
# kubectl get pods NAME READY STATUS RESTARTS AGE helloworld-go-v2-deployment-589c5f7ff9-czpj2 3/3 Running 0 12shelloworld-go對應(yīng)的部署如果在擴縮容時間窗口期(默認60s)內(nèi)沒有請求,Knative將自動將對應(yīng)的部署縮容為零。
查看部署后生成的Revision:
我們可以看到helloworld-go的配置有兩個修訂版,分別是helloworld-go-v1和helloworld-go-v2。配置的變更產(chǎn)生了新的修訂版,然而并沒有產(chǎn)生新的路由、服務(wù)和配置對象。我們可以通過下面的命令來驗證這些資源對象的狀態(tài)。
- 獲取服務(wù)的路由信息的命令:kubectl get routes。
- 獲取Knative服務(wù)的狀態(tài)信息的命令:kubectl get ksvc。
- 獲取Knative服務(wù)的配置信息的命令:kubectl get configurations。
- Knative默認路由策略是將所有流量轉(zhuǎn)發(fā)給最新的修訂版。
1.5 流量分發(fā)到不同版本
在典型的微服務(wù)部署中,實現(xiàn)流量在不同版本中分發(fā)是實現(xiàn)金絲雀或藍綠部署方式的基礎(chǔ)。Knative提供了這種流量分發(fā)方式的支持。
在Knative Service的yaml文件配置中,traffic區(qū)塊描述了如何在多個版本之間進行流量分發(fā)。配置范例如下:
traffic區(qū)塊中可以有一個或多個條目。每個條目中帶有如下屬性。
- tag:流量分配的標(biāo)識符。此標(biāo)記將在路由中充當(dāng)前綴,以便將流量分發(fā)到特定修訂版。
- revisionName:參與流量分配的Knative服務(wù)修訂版本的名稱。
- percent:對應(yīng)修訂版被分配的流量百分比。這個值在0~100之間。在上述例子中,Knative分配給修訂版helloworld-go-v1和helloworld-go-v2各50%的流量。
- Knative Serving會為每個Tag創(chuàng)建獨特的URL。我們可以通過下面的命令查看:
通過訪問URL可以直接訪問到對應(yīng)的修訂版。
1.6 藍綠部署與灰度發(fā)布
一般情況下,升級服務(wù)端應(yīng)用需要先停掉老版本服務(wù),再啟動新版服務(wù)。但是這種簡單的發(fā)布方式存在兩個問題,一方面在新版本升級過程中,服務(wù)是暫時中斷的;另一方面,如果新版本升級失敗,回滾起來非常麻煩,容易造成更長時間的服務(wù)不可用。
所謂藍綠部署,是指同時運行兩個版本的應(yīng)用,即部署的時候,并不停掉老版本,而是直接部署一套新版本,等新版本運行起來后,再將流量切換到新版本上,如圖6-3所示。但是藍綠部署要求服務(wù)端在升級過程中同時運行兩套程序,對硬件資源的要求是日常所需的2倍。
Knative提供了一個簡單的切換流量的方法,可將流量快速從Revison1切換到Revision 2。如果Revision2發(fā)生錯誤,服務(wù)可以快速回滾變更到Revison1。
接下來,我們將通過helloworld-go這個Knative服務(wù)來應(yīng)用藍綠色部署模式。上文擁有兩個修訂版的helloworld-go服務(wù),名稱分別為helloworld-go-v1和helloworld-go-v2。通過部署helloworld-go-v2,我們可以看到Knative自動將100%的流量路由到helloworld-go-v2。現(xiàn)在,假設(shè)出于某些原因,我們需要將helloworld-go-v2回滾到helloworld-go-v1。
以下示例中Knative Service與先前部署的helloworld-go相同,只是添加了traffic部分以指示將100%的流量路由到helloworld-go-v1。
灰度發(fā)布也叫金絲雀發(fā)布。如圖所示,在灰度發(fā)布開始后,先啟動一個新版本應(yīng)用,但是并不直接將流量切過來,而是測試人員對新版本進行線上測試。啟動的這個新版本應(yīng)用,就是我們的金絲雀。如果測試沒有問題,我們可以將少量的流量導(dǎo)入新版本,然后再對新版本做運行狀態(tài)觀察,收集各種運行時數(shù)據(jù)。如果此時對新舊版本做數(shù)據(jù)對比,就是所謂的A/B測試。
當(dāng)確認新版本運行良好后,再逐步將更多的流量導(dǎo)入新版本。在此期間,我們還可以不斷地調(diào)整新舊兩個版本運行的服務(wù)器副本數(shù)量,使得新版本能夠承受更大的流量壓力,直到將100%的流量切換到新版本上,最后關(guān)閉剩下的老版本服務(wù),完成灰度發(fā)布。
如果我們在灰度發(fā)布過程中(灰度期)發(fā)現(xiàn)新版本有問題,應(yīng)該立即將流量切回老版本,這樣就會將負面影響控制在最小范圍內(nèi)。
以下示例通過不斷變更helloworld-go-v1和helloworld-go-v2的流量比例來實現(xiàn)helloworld-go服務(wù)新版本的灰度發(fā)布。
使用 Knative CLI 路由和管理流量
1.5和1.6的操作也可以通過cli命令設(shè)置。
kn service update <service-name> --traffic <revision-name>=<percent> 是您為其配置流量路由的 Knative 服務(wù)的名稱。
是要配置為接收一定百分比的流量的修訂名稱。
是要發(fā)送到 指定的修訂版的流量百分比。
例如,要拆分名為 example 的 Service 的流量,將 80% 的流量發(fā)送到 Revision 綠色,將 20% 的流量發(fā)送到 Revision blue,您可以運行以下命令:
kn service update example-service --traffic green=80 --traffic blue=20也可以將標(biāo)簽添加到修訂版,然后根據(jù)您設(shè)置的標(biāo)簽拆分流量:
kn service update example --tag green=revision-0001 --tag blue=@latest@latest 標(biāo)簽表示藍色解析為服務(wù)的最新版本。 以下示例將 80% 的流量發(fā)送到最新版本,將 20% 的流量發(fā)送到名為 v1 的版本。
kn service update example-service --traffic @latest=80 --traffic v1=201.7 Knative Service的彈性伸縮配置
無服務(wù)器計算不僅能夠終止未使用的服務(wù),還可以按需擴展計算規(guī)模。Knative Serving支持這種彈性伸縮能力。
為了讓Knative的Autoscaler更好地調(diào)度服務(wù),我們需要根據(jù)實際情況在服務(wù)中添加相應(yīng)的擴縮容配置項。下面以helloworld-go.yaml范例來演示擴縮容相關(guān)配置。
在上述配置中,revision中配置了修訂版的彈性伸縮策略。各個屬性代表的意義如下。
- autoscaling.knative.dev/class:表示Autoscaler的實現(xiàn)方式,這個屬性的可選值有kpa.autoscaling.knative.dev或hpa.autoscaling.knative.dev。KPA支持縮容到零,HPA支持基于CPU的擴展機制。
- autoscaling.knative.dev/metric:度量指標(biāo)默認為并發(fā)數(shù),該屬性還可以根據(jù)業(yè)務(wù)情況選擇每秒請求數(shù)或CPU使用率。
- autoscaling.knative.dev/target:自動縮放的目標(biāo)值是Autoscaler維護應(yīng)用的每個副本度量指標(biāo)的目標(biāo)值。
- autoscaling.knative.dev/minScale:表示每個修訂版副本需要保留的最小數(shù)量。在任何時間點,副本不會少于這個數(shù)量。通過該設(shè)置,我們可以有效地減少服務(wù)的冷啟動時間。
- autoscaling.knative.dev/maxScale:表示每個修訂版副本所能達到的最大數(shù)量。在任何時間點,副本都不會超過指定的最大值,從而避免資源被過度使用。
- containerConcurrency:限制容器在給定時間允許的并發(fā)請求的數(shù)量的硬性限制。只有當(dāng)應(yīng)用程序需要強制的并發(fā)約束時,才會使用到該屬性。
部署helloworld-go服務(wù)并配置到Knative集群:
# kubectl apply-f helloworld-go.yaml驗證部署結(jié)果:
#IP_ADDRESS="$(kubectl get nodes-o 'jsonpath={.items[0].status.addresses[0].address}'):$(kubectl get svc istio-ingressgateway--namespace istio-system--output 'jsonpath={.spec.ports[?(@.port==80)].nodePort}')" # curl-H "Host:helloworld-go.default.example.com" $IP_ADDRESS Hello World!壓力測試:
# hey-c 50-z 30s-host "helloworld-go.default.knative.k8s.arch.dapp.com" "http://$IP_ADDRESS"通過hey工具發(fā)起50個并發(fā)請求,持續(xù)30秒對hellowrold-go服務(wù)進行壓測。
查看壓測期間Pod的副本數(shù)量:
通過上面的命令,我們可以看到集群中產(chǎn)生了6個Pod副本。那么問題來了,我們發(fā)起的并發(fā)請求數(shù)是50個,服務(wù)自動縮放的目標(biāo)值是10,按照“副本數(shù)=并發(fā)數(shù)/目標(biāo)值”算法,Pod副本數(shù)應(yīng)該是5個才對呀。這是由于Knative Serving還有一個控制參數(shù)叫目標(biāo)使用率,一旦并發(fā)數(shù)達到預(yù)設(shè)目標(biāo)的70%(默認值),Autoscaler就會繼續(xù)擴容。引入目標(biāo)使用率的主要目的是在擴容時減小由Pod啟動時間帶來的延遲,使負載到達前就將Pod實例啟動起來。
引用
Hello world apps - Python - 《Knative v0.23 Documentation》 - 書棧網(wǎng) · BookStack
Knative實戰(zhàn):基于Kubernetes的無服務(wù)器架構(gòu)實踐 by 李志偉 游楊 (z-lib.org)
總結(jié)
以上是生活随笔為你收集整理的serverless knative实战的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 道理我都懂,但是这种列车为什么会自己摆动
- 下一篇: 语法俱乐部2:名词短语与冠词