<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Knative 全鏈路流量機(jī)制探索與揭秘

          共 9516字,需瀏覽 20分鐘

           ·

          2021-04-22 08:11



          -     前言    -


          從自動(dòng)擴(kuò)縮容說起

          服務(wù)接收到流量請求后,從0自動(dòng)擴(kuò)容為N,以及沒有流量時(shí)自動(dòng)縮容為0,是一個(gè)Serverless平臺(tái)最本質(zhì)的特征。


          可以說,自動(dòng)擴(kuò)縮容機(jī)制是那顆皇冠,戴上之后你才能被稱之為Serverless。


          當(dāng)然了解Kubernetes的人會(huì)有疑問,HPA不就是用來干自動(dòng)擴(kuò)縮容的事兒的嗎?難道我用了HPA就可以搖身一變成為Serverless了。


          這里最關(guān)鍵的區(qū)別在于,Serverless語義下的自動(dòng)擴(kuò)縮容是可以讓服務(wù)從0到N的,但是HPA不能。HPA的機(jī)制是檢測服務(wù)Pod的metrics數(shù)據(jù)(例如CPU等)然后把Deployment擴(kuò)容,但當(dāng)你把Deployment副本數(shù)置為0時(shí),流量進(jìn)不來,metrics數(shù)據(jù)永遠(yuǎn)為0,此時(shí)HPA也無能為力。


          所以,HPA只能讓服務(wù)從1到N,而從0到1的這個(gè)過程,需要額外的機(jī)制幫助hold住請求流量,擴(kuò)容服務(wù),再轉(zhuǎn)發(fā)流量到服務(wù),這就是我們常說的冷啟動(dòng)。


          可以說,冷啟動(dòng)是Serverless皇冠中的那顆明珠,如何實(shí)現(xiàn)更好、更快的冷啟動(dòng),是所有Serverless平臺(tái)極致追求的目標(biāo)。


          Knative作為目前被社區(qū)和各大廠商如此重視和受關(guān)注的Serverless平臺(tái),當(dāng)然也在不遺余力的優(yōu)化自動(dòng)擴(kuò)縮容和冷啟動(dòng)功能。


          不過,本文并不打算直接介紹Knative自動(dòng)擴(kuò)縮容機(jī)制,而是先探究一下Knative中的流量實(shí)現(xiàn)機(jī)制,流量機(jī)制和自動(dòng)擴(kuò)容密切相關(guān),只有了解其中的奧秘,才能更好的理解Knative autoscale功能。


          由于Knative其實(shí)包括Building(Tekton)、Serving和Eventing,這里只專注于Serving部分。另外需要提前說明的是,Knative并不強(qiáng)依賴Istio,Serverless網(wǎng)關(guān)的實(shí)際選擇除了集成Istio,還支持Gloo、Ambassador。同時(shí),即使使用了Istio,也可以選擇是否使用envoy sidecar注入。本文介紹的時(shí)候,我們默認(rèn)使用的是Istio和注入sidecar的部署方式。



          -     簡單但是有點(diǎn)過時(shí)的老版流量機(jī)制    -


          先回顧一下Knative官方的一個(gè)簡單的原理示意圖如下所示。用戶創(chuàng)建一個(gè)Knative Service(ksv c)后,Knative會(huì)自動(dòng)創(chuàng)建Route(route),Configuration(cfg)資源,然后cfg會(huì)創(chuàng)建對應(yīng)的Revision(rev)版本。rev實(shí)際上又會(huì)創(chuàng)建Deployment提供服務(wù),流量最終會(huì)根據(jù)route的配置,導(dǎo)入到相應(yīng)的rev中。



          這是簡單的CRD視角,實(shí)際上Knative的內(nèi)部CRD會(huì)多一些層次結(jié)構(gòu),相對更復(fù)雜一點(diǎn)。下文會(huì)詳細(xì)描述。


          從冷啟動(dòng)和自動(dòng)擴(kuò)縮容的實(shí)現(xiàn)角度,可以參考一下下圖 。從圖中可以大概看到,有一個(gè)Istio Route充當(dāng)網(wǎng)關(guān)的角色,當(dāng)服務(wù)副本數(shù)為0時(shí),自動(dòng)將流量轉(zhuǎn)發(fā)到Activator組件,Activator會(huì)hold住流量,同時(shí)Autoscaler組件會(huì)負(fù)責(zé)將副本數(shù)擴(kuò)容,之后Activator再將流量導(dǎo)入到實(shí)際的Pod,并且在副本數(shù)不為0時(shí),Istio Route會(huì)直接將流量負(fù)載均衡到Pod,不再走Activator組件。這也是Knative實(shí)現(xiàn)冷啟動(dòng)的一個(gè)基本思路。



          在集成使用Istio部署時(shí),Knative Route默認(rèn)采用的是Istio Ingress Gateway實(shí)現(xiàn),大概在Knative 0.6版本之前,我們可以發(fā)現(xiàn),Route的流量轉(zhuǎn)發(fā)本質(zhì)上是由Istio virtualservice(vs)控制。副本數(shù)為0時(shí),vs如下所示,其中destination指向的是Activator組件。此時(shí)Activator會(huì)幫助轉(zhuǎn)發(fā)冷啟動(dòng)時(shí)的請求。


          apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:  name: route-f8c50d56-3f47-11e9-9a9a-08002715c9e6spec:  gateways:  - knative-ingress-gateway  - mesh  hosts:  - helloworld-go.default.example.com  - helloworld-go.default.svc.cluster.local  http:  - appendHeaders:    route:    - destination:        host: Activator-Service.knative-serving.svc.cluster.local        port:          number: 80      weight: 100


          當(dāng)服務(wù)副本數(shù)不為0之后,vs會(huì)變?yōu)槿缦滤荆瑢ngress Gateway的流量直接打到服務(wù)Pod上。


          apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:  name: route-f8c50d56-3f47-11e9-9a9a-08002715c9e6spec: hosts:  - helloworld-go.default.example.com  - helloworld-go.default.svc.cluster.local  http:  - match:    route:    - destination:        host: helloworld-go-2xxcn-Service.default.svc.cluster.local        port:          number: 80      weight: 100


          無非是通過修改vs的destination來實(shí)現(xiàn)冷啟動(dòng)中的流量保持和轉(zhuǎn)發(fā)。


          相信目前你在網(wǎng)上能找到資料,也基本上停留在該階段。不過,knative的發(fā)展是如此的迅速,以至于,上面分析的細(xì)節(jié)已經(jīng)過時(shí)。


          下面以0.9版本為例,我們仔細(xì)探究一下現(xiàn)有的實(shí)現(xiàn)方式,和關(guān)于Knative流量的真正秘密。



          -     復(fù)雜但是更優(yōu)異的新版流量機(jī)制    -


          鑒于官方文檔并沒有最新的具體實(shí)現(xiàn)機(jī)制介紹,我們創(chuàng)建一個(gè)簡單的hello-go ksvc,并以此進(jìn)行分析。ksvc如下所示:


          apiVersion: serving.knative.dev/v1alpha1kind: Servicemetadata:  name: hello-go  namespace: faasspec:  template:    spec:      containers:      - image: harbor-yx-jd-dev.yx.netease.com/library/helloworld-go:v0.1        env:        - name: TARGET          value: "Go Sample v1"

          筆者的環(huán)境可簡單的認(rèn)為是一個(gè)標(biāo)準(zhǔn)的Istio部署,Serverless網(wǎng)關(guān)為Istio Ingress Gateway,所以創(chuàng)建完ksvc后,為了驗(yàn)證服務(wù)是否可以正常運(yùn)行,需要發(fā)送http請求至網(wǎng)關(guān)。由于Gateway資源已經(jīng)在部署Knative的時(shí)候創(chuàng)建了,所以我們只需要關(guān)心一下vs。在服務(wù)副本數(shù)為0的時(shí)候,Knative控制器創(chuàng)建的vs關(guān)鍵配置如下:


          spec:  gateways:  - knative-serving/cluster-local-gateway  - knative-serving/knative-ingress-gateway  hosts:  - hello-go.faas  - hello-go.faas.example.com  - hello-go.faas.svc  - hello-go.faas.svc.cluster.local  - f81497077928a654cf9422088e7522d5.probe.invalid  http:  - match:    - authority:        regex: ^hello-go\.faas\.example\.com(?::\d{1,5})?$      gateways:      - knative-serving/knative-ingress-gateway    - authority:        regex: ^hello-go\.faas(\.svc(\.cluster\.local)?)?(?::\d{1,5})?$      gateways:      - knative-serving/cluster-local-gateway    retries:      attempts: 3      perTryTimeout: 10m0s    route:    - destination:        host: hello-go-fpmln.faas.svc.cluster.local        port:          number: 80


          vs指定了已經(jīng)創(chuàng)建好的gw,同時(shí)destination指向的是一個(gè)Service域名。這個(gè)Service就是Knative默認(rèn)自動(dòng)創(chuàng)建的hello-go服務(wù)的Service。

          不過細(xì)心的我們又發(fā)現(xiàn)vs的ownerReferences指向了一個(gè)Knative的CRD:


          ingress.networking.internal.knative.dev:  ownerReferences:  - apiVersion: networking.internal.knative.dev/v1alpha1    blockOwnerDeletion: true    controller: true    kind: Ingress    name: hello-go    uid: 4a27a69e-5b9c-11ea-ae53-fa163ec7c05f


          根據(jù)名字可以看到這是一個(gè)Knative內(nèi)部使用的CRD,該CRD的內(nèi)容其實(shí)和vs比較類似,同時(shí)ingress.networking.internal.knative.dev的ownerReferences指向了我們熟悉的route,總結(jié)下來就是:


          route -ingress.networking.internal.knative.dev -vs

          在網(wǎng)關(guān)這一層體現(xiàn)到的CRD資源就是如上這些。這里ingress.networking.internal.knative.dev的意義在于增加一層抽象,如果我們使用的是Gloo等其他網(wǎng)關(guān),則會(huì)將ingress.networking.internal.knative.dev轉(zhuǎn)換成相應(yīng)的網(wǎng)關(guān)資源配置。可見Knative正在計(jì)劃下一盤大棋。


          現(xiàn)在,我們已經(jīng)了解到Serverless網(wǎng)關(guān)是由Knative控制器最終生成的vs生效到Istio Ingress Gateway上,為了驗(yàn)證我們剛才部署的服務(wù)是否可以正常的運(yùn)行,簡單的用curl命令試驗(yàn)一下。


          和所有的網(wǎng)關(guān)或者負(fù)載均衡器一樣,對于7層http訪問,我們需要在Header里加域名Host,用于流量轉(zhuǎn)發(fā)到具體的服務(wù)。在上面的vs中已經(jīng)可以看到對外域名和內(nèi)部Service域名均已經(jīng)配置。所以,只需要:


          curl -v -H'Host:hello-go.faas.example.com'  <IngressIP>:<Port> 

          其中,IngressIP即網(wǎng)關(guān)實(shí)例對外暴露的IP。


          對于冷啟動(dòng)來說,目前的Knative需要等十幾秒,即會(huì)收到請求。根據(jù)之前老版本的經(jīng)驗(yàn),這個(gè)時(shí)候vs會(huì)被更新,destination指向hello-go的Service。


          不過,現(xiàn)在我們實(shí)際發(fā)現(xiàn),vs沒有任何變化,仍然指向了服務(wù)的Service。這時(shí)候,我們才想起來,老版本中服務(wù)副本數(shù)為0時(shí),其實(shí)vs的destination指向的是Activator組件的。但現(xiàn)在,不管服務(wù)副本數(shù)如何變化,vs一直不變。


          蹊蹺只能從destination的Service域名入手。


          創(chuàng)建ksvc后,Knative會(huì)幫我們自動(dòng)創(chuàng)建Service如下所示:


          $ kubectl -n faas get svcNAME                     TYPE           CLUSTER-IP     EXTERNAL-IP                                            PORT(S)      hello-go                 ExternalName   <none>         cluster-local-gateway.istio-system.svc.cluster.local   <none>           hello-go-fpmln           ClusterIP      10.178.4.126   <none>                                                 80/TCP             hello-go-fpmln-m9mmg     ClusterIP      10.178.5.65    <none>                                                 80/TCP,8022/TCP  hello-go-fpmln-metrics   ClusterIP      10.178.4.237   <none>                                                 9090/TCP,9091/TCP


          hello-go Service是一個(gè)ExternalName Service,作用是將hello-go的Service域名增加一個(gè)dns CNAME別名記錄,指向網(wǎng)關(guān)的Service域名。


          仔細(xì)研究hello-go-fpmln Service,我們可以發(fā)現(xiàn)這是一個(gè)沒有l(wèi)abel selector的Headless Service,它的Endpoint不是kubernetes自動(dòng)創(chuàng)建的,需要額外去創(chuàng)建。


          hello-go-fpmln-m9mmg Service和hello-go-fpmln-metrics則根據(jù)revision label selector到對應(yīng)的服務(wù)Pod。


          根據(jù)這些Service的一些annotation可以看到,Knative對hello-go-fpmln、hello-go-fpmln-m9mmg 、hello-go-fpmln-metrics這三個(gè)Service的定位分別為public Service、private Service和metric Service。


          private Service和metric Service其實(shí)不難理解。問題的關(guān)鍵就在這里的public Service,并且由上面的分析可以看到,vs的destination指向的就是這里的public Service。


          在服務(wù)副本數(shù)為0時(shí),查看一下Service對應(yīng)的Endpoint,如下所示:


          $ kubectl -n faas get epNAME                     ENDPOINTS                               AGEhello-go-fpmln           172.31.16.81:8012                       hello-go-fpmln-m9mmg     172.31.16.121:8012,172.31.16.121:8022   hello-go-fpmln-metrics   172.31.16.121:9090,172.31.16.121:9091   


          其中,public Service的Endpoint IP是Knative Activator的Pod IP,實(shí)際發(fā)現(xiàn)Activator的副本數(shù)越多這里也會(huì)相應(yīng)的增加。


          輸入幾次curl命令模擬一下http請求,雖然副本數(shù)從0開始增加到1了,但是這里的Endpoint卻沒有變化,仍然為Activator Pod IP。


          接著使用hey來壓測一下:


          ./hey_linux_amd64 -n 1000000 -c 300  -m GET -host helloworld-go.faas.example.com http://<IngressIP>:8

          果然,發(fā)現(xiàn)Endpoint變化了,通過對比服務(wù)的Pod IP,已經(jīng)變成了新啟動(dòng)的服務(wù)Pod IP,不再是Activator Pod的IP。


          $ kubectl -n faas get epNAME                     ENDPOINTS                         helloworld-go-mpk25      172.31.16.121:8012hello-go-fpmln-m9mmg     172.31.16.121:8012,172.31.16.121:8022   hello-go-fpmln-metrics   172.31.16.121:9090,172.31.16.121:9091


          原來,現(xiàn)在新版本的冷啟動(dòng)流量轉(zhuǎn)發(fā)機(jī)制已經(jīng)不再是通過修改vs來改變網(wǎng)關(guān)的流量轉(zhuǎn)發(fā)配置了,而是直接更新服務(wù)的public Service后端Endpoint,從而實(shí)現(xiàn)將流量從Activator負(fù)載均衡到真正的服務(wù)負(fù)載Pod上。
          這樣將流量的轉(zhuǎn)發(fā)功能內(nèi)聚到Kubernetes本身Service/Endpoint層,一方面減小了網(wǎng)關(guān)的配置更新壓力,一方面Knative可以在對接各種不同的網(wǎng)關(guān)時(shí)的實(shí)現(xiàn)時(shí)更加解耦,網(wǎng)關(guān)層不再需要關(guān)心冷啟動(dòng)時(shí)的流量轉(zhuǎn)發(fā)機(jī)制。
          再深入從上述的三個(gè)Service入手研究,它們的ownerReference是serverlessservice.networking.internal.knative.dev(sks),而sks的ownerReference是podautoscaler.autoscaling.internal.knative.dev(kpa)。
          在壓測過程中同樣發(fā)現(xiàn),sks會(huì)在冷啟動(dòng)過后,會(huì)從Proxy模式變?yōu)镾erve模式:


          $ kubectl -n faas get sksNAME             MODE    SERVICENAME      PRIVATESERVICENAME     READY   REASONhello-go-fpmln   Proxy   hello-go-fpmln   hello-go-fpmln-m9mmg   True
          $ kubectl -n faas get sksNAME             MODE    SERVICENAME      PRIVATESERVICENAME     READY   REASONhello-go-fpmln   Serve   hello-go-fpmln   hello-go-fpmln-m9mmg   True


          這也意味著,當(dāng)流量從Activator導(dǎo)入的時(shí)候,sks為Proxy模式。

          服務(wù)真正啟動(dòng)起來后會(huì)變成Serve模式,網(wǎng)關(guān)流量直接流向服務(wù)Pod。


          從名稱上也可以看到,sks和kpa均為Knative內(nèi)部CRD,實(shí)際上也是由于Knative設(shè)計(jì)上可以支持自定義的擴(kuò)縮容方式和支持Kubernetes HPA有關(guān),實(shí)現(xiàn)更高一層的抽象。


          現(xiàn)在為止,我們可以梳理Knative的絕大部分CRD的關(guān)系如下圖所示:




          一個(gè)更復(fù)雜的實(shí)際實(shí)現(xiàn)架構(gòu)圖如下所示。



          簡單來說,服務(wù)副本數(shù)為0時(shí),流量路徑為:網(wǎng)關(guān)-> public Service -> Activator經(jīng)過冷啟動(dòng)后,副本數(shù)為N時(shí),流量路徑為:網(wǎng)關(guān)->public Service -> Pod當(dāng)然流量到Pod后,實(shí)際內(nèi)部還有Envoy sidecar流量攔截,Queue-Proxy sidecar反向代理,才再到用戶的User Container。這里的機(jī)制背后實(shí)現(xiàn)我們會(huì)有另外一篇文章再單獨(dú)細(xì)聊。



          -     總結(jié)    -


          Knative本身的實(shí)現(xiàn)可謂是云原生領(lǐng)域里的一個(gè)集大成者,融合Kubernetes、ServiceMesh、Serverless讓Knative充滿了魅力,但同時(shí)也導(dǎo)致了Knative的復(fù)雜性。網(wǎng)絡(luò)流量的穩(wěn)定保障是Serverless服務(wù)真正生產(chǎn)可用性的關(guān)鍵因素,Knative也還在高速的更新迭代中,相信Knative會(huì)在未來對網(wǎng)絡(luò)方面的性能和穩(wěn)定性投入更多的優(yōu)化。


          作者:ethfoo

          來源:https://juejin.cn/post/6844904084005191693

          瀏覽 46
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  波多野结衣无码一区 | 五月天黄色电影网站 | 兔子先生把酒醉姐姐带回家 | 欧美日韩亚洲不卡 | 淫色综合网 |