Knative 是一個基于 Kubernetes 的,用于構建、部署和管理現代 serverless 應用的平臺。Getting Started with Knative 是一本由 Pivotal 公司贊助 O’Reilly 出品的電子書,公眾號后臺回復“knative”獲取英文版下載地址。本書中文版由 ServiceMesher 社區自發翻譯系列文章,這是該系列的第6章。
通過前面的章節已經扎實掌握 Knative 的組件了,現在是時候開始研究一些更高級的主題了。Serving 為如何路由流量提供了相當大的靈活性,還有其他的構建模板使構建應用程序變得容易。只需幾行代碼即可輕松制作我們自己的事件源。在本章中,我們將深入研究這些功能,讓我們的代碼在 Knative 上更容易地運行。
第 2 章 介紹了 Knative Service 的概念。
回想一下,Knative 中的 Service 是單個配置和路由集合的組合。在 Knative 和 Kubernetes 體系內,它最終是 Pod 中的 0 個或多個容器以及其他使您的應用程序可尋址的組件。所有這些都由具有強大流量策略選項的路由層支持。
無論您將工作負載視為應用程序,容器還是流程,它都將在 Knative 中作為服務運行。這為處理許多場景提供了靈活性,具體取決于構成軟件的資產。本節提供了 Knative 為您構建和部署軟件提供的另一種選擇。
您在第 3 章中看到,Kaniko 構建模板允許您使用 Dockerfile 構建容器鏡像。此方法要求您負責編寫和維護 Dockerfile。如果您希望完全消除管理容器的負擔,您可能希望使用不同的構建模板。Buildpack 構建模板負責基礎鏡像,并引入構建和運行應用程序所需的所有依賴項。
Cloud Foundry 是一種開源平臺即服務(PaaS),它利用 buildpack 來簡化開發和運維。在 Cloud Foundry 中,buildpacks 將檢查您的源代碼,以自動確定要下載的運行時和依賴項,構建代碼以及運行應用程序。例如,使用 Ruby 應用程序,buildpack 將下載 Ruby 運行時并在 Gemfile 上運行 bundle install
以下載所有必需的依賴項。Java buildpack 將為您的應用程序下載 JVM 和任何所需的依賴項。通過使用 Buildpack Build Template,這個模型在 Knative 中也可用。
與 Kaniko Build Template 一樣,您必須將 Buildpack Build Template CRD 應用到環境:
kubectl apply -f https://raw.githubusercontent.com/knative/build-templates/master/buildpack/buildpack.yaml
Knative Services 僅依賴 Serving 組件。Build 模塊不需要在 Knative 中部署和運行 Service。那你為什么要在你的服務中嵌入 Build 呢?你怎么知道在特定情況下這是一個好主意?
考慮您的軟件開發生命周期的過程是非常重要的。您是否有一個現有的,成熟的構建流水線來生成容器鏡像并將它們推送到 registry 倉庫?如果是這樣,您可能不需要 Knative Build 為您工作。如果沒有,在 Knative Service 中定義 Build 方法可能會使事情變得更容易。
具體使用哪個構建模板還需要依據您希望如何打包代碼和依賴項而定。對于使用既定流程管理 Dockerfile 的 Docker 重度使用者而言,Kaniko 是一個很好的選擇。而 Cloud Foundry 的用戶或開發者們只喜歡編寫代碼并且不太關心基礎設施那么 Buildpack Build Template 會是更好的選擇。經驗豐富的 Java 用戶可能已經熟悉使用 Jib 來構建 Java 容器,這使得它成為正確的選擇。無論您的過程如何,Knative 都會提供一些不錯的抽象,同時允許您選擇最適合您的方法。
在 Knative 中,Buildpack 構建模板將使用 Cloud Foundry 的相同構建包,包括自動檢測要應用于代碼的構建包。如果您參考例6-1
你會看到很像 Kaniko Buildpack,你只能定義代碼的位置以及推送容器鏡像的位置。最大的區別是沒必要提供 Dockerfile。
相反,構建模板知道如何為此應用程序構建容器。
apiVersion: serving.knative.dev/v1alpha1kind: Servicemetadata: name: knative-buildpack-demo namespace: defaultspec: runLatest: configuration: build: serviceAccountName: build-bot source: git: url: https://github.com/gswk/knative-buildpack-demo.git revision: master template: name: buildpack arguments: - name: IMAGE value: docker.io/gswk/knative-buildpack-demo:latest revisionTemplate: spec: container: image: docker.io/gswk/knative-buildpack-demo:latest
在此創建和運行 Knative Services ,除了代碼和容器注冊表的路由之外,與示例3-6中的 Kaniko 構建的唯一不同之處在于模板的名稱已從 kaniko 更改為 buildpack。
例如,git 存儲庫是 Node.js 應用程序 hello.js,以及定義應用程序的依賴關系和元數據的 package.json 文件。在這種情況下,Build Template 將下載 Node 運行時和 npm 可執行文件,運行npm install
,最后構建容器并將其推送到 Docker Hub。
您可能發現已應用了大量 YAML 文件,并且不確定是否已創建所有的 Knative 對象。有一個命令方便你確認這些問題,命令如下所示:
kubectl get knative -n {NAMESPACE}
返回給定命名空間中所有的 Knative 對象列表。
kubectl get knative --all-namespaces
返回集群上存在的所有 Knative 對象。
Knative 還提供不同的部署方法,具體取決于最適合您服務的方案。我們在第 2 章展示了一個 Knative 路由如何可以用來將流量發送到特定的修訂。以下部分將詳細介紹 Knative Routes 如何實現藍綠部署和增量部署。
在第 2 章中,您了解了如何將單個路由指向多個修訂版以及如何實現零停機部署。由于修訂是不可變的,并且可以同時運行多個版本,因此可以在為舊版本提供流量時調出新版本。然后,一旦準備好將流量引導到新版本,請立即更新路由切換。這有時被稱為藍綠部署,藍和綠代表不同的版本。
例6-2 重新審視了 第 2 章中的 Route 定義。
apiVersion: serving.knative.dev/v1alpha1kind: Routemetadata: name: knative-helloworld namespace: defaultspec: traffic: - revisionName: knative-routing-demo-00001 name: v1 percent: 100
如第 2 章所述,您可以在 knative-helloworld.default.example.com
和 v1.knative-helloworld.default.example.com
上訪問修訂版 knative-routing-demo-00001
。讓我們考慮一個場景,你已經在代碼中添加了一些新功能或修復了一些錯誤,然后構建并將其推送到 Knative。這導致一個名為 knative-routing-demo-00002
的新版本。
但是,在開始向應用程序發送生產流量之前,我們希望確保它正常運行。在例6-3中有一個名為 v2 的新路由,但沒有路由到它的生產流量。
apiVersion: serving.knative.dev/v1alpha1kind: Routemetadata: name: knative-helloworld namespace: defaultspec: traffic: - revisionName: knative-routing-demo-00001 name: v1 percent: 100 - revisionName: knative-routing-demo-00002 name: v2 percent: 0
這些修訂版已命名為 v1 和 v2(盡管您可以選擇任何名稱,例如藍和綠)。這意味著您可以在 v2.knative-helloworld.default
訪問新版本。example.com 路由仍然只會將流量發送到 00001 修訂版。在更改流量之前,請訪問新版本并對其進行測試以確保它已準備好用于生產流量。當新版本準備好接收生產流量時,請再次更新路由,如例6-4 所示。
apiVersion: serving.knative.dev/v1alpha1kind: Routemetadata: name: knative-helloworld namespace: defaultspec: traffic: - revisionName: knative-routing-demo-00002 name: v2 percent: 100
應用后,新的配置流量將立即路由到 00002 版本而不會出現任何停機。發現代碼中的新錯誤并需要回滾?可以很容易的再次更新 Route 配置以指向原始版本。因為修訂版是不可變的,而 Knative 會存儲過去的版本 yaml 配置,您可以隨時路由它們。這包括對特定容器鏡像、配置以及與修訂版相關的任何構建信息的引用。
Knative Routes 支持的另一種部署模式是逐步部署新版本的代碼。這可以用于 AB 測試,或者在為每個用戶釋放功能之前將功能推廣到用戶子集。在 Knative 中,這是通過使用基于百分比的路由來實現的。
雖然類似于藍綠部署示例 6-4,你可以在例 6-5 中看到 而不是路由0% 對于 v2的流量,我們在 v1和 v2上均勻分配負載。您也可以選擇使用80-20
之類的其他拆分,甚至可以拆分三個修訂版。每個修訂版仍可通過指定的子域訪問,但用戶流量將按百分比值進行拆分。
apiVersion: serving.knative.dev/v1alpha1kind: Routemetadata: name: knative-helloworld namespace: defaultspec: traffic: - revisionName: knative-routing-demo-00001 name: v1 percent: 50 - revisionName: knative-routing-demo-00002 name: v2 percent: 50
到目前為止所涵蓋的每個示例都使用了通用示例域。
這不是用于生產應用程序的 URL。不僅如此,還不可能路由到 example.com。值得慶幸的是,Knative 提供了使用自定義域的選項。開箱即用,Knative 為每個 Route 使用{route}.{namespace}.{domain}方案,并為 example.com 使用默認域。
使用 knative-custom-domain
示例作為示例6-6中顯示的起始位置,默認情況下它接收 knative-custom-domain.default.example.com
的 Route。
apiVersion: serving.knative.dev/v1alpha1kind: Configurationmetadata: name: knative-custom-domain namespace: defaultspec: revisionTemplate: spec: container: image: docker.io/gswk/knative-helloworld imagePullPolicy: Always
由于我們已將此定義為配置而非服務,因此我們還需要為應用程序定義路由,如例6-7。將這兩種配置分開將為我們提供更高級別的定制,例如我們在討論零停機部署時所說的那些定制,但也將讓我們更新我們的域和路由,而無需重新部署整個應用程序。
apiVersion: serving.knative.dev/v1alpha1kind: Routemetadata: name: knative-custom-domain namespace: defaultspec: traffic: - revisionName: knative-custom-domain-00001 name: v1 percent: 100
正如預期的那樣,這將創建一個服務并在 knative-custom-domain.default.example.com
上創建一個 Route?,F在來看看如何將默認 URL 方案中的域名從 example.com 更改為您實際可以路由到的域名。此示例使用本書的網站 dev.gswkbook.com
的子域。這可以通過更新配置域 ConfigMap 輕松完成,該配置域由 Knative 的默認配置,如例 6-8 所示。
apiVersion: v1kind: ConfigMapmetadata: name: config-domain namespace: knative-servingdata: dev.gswkbook.com: ""
Knative 最終應該協調對域的更改。重新創建 Route 將加快進程:
$ kubectl delete -f route.yaml$ kubectl apply -f route.yaml
看一下更改后的路由,您會看到它現在已獲得 knative-custom-domain.default.dev
的更新網址。
gswkbook.com
。如果您的入口網關可公開訪問(即,在 Google 的 GKE 或類似的托管 Kubernetes 產品上設置),您可以為 *.dev.gswkbook.com
創建一個通配符 DNS 條目, 以便路由到您的 Knative 安裝并訪問您的服務和功能直接通過互聯網,如例 6-9 所示。
$ kubectl get route knative-custom-domain -o yamlapiVersion: serving.knative.dev/v1alpha1kind: Routemetadata: ...status: ... domain: knative-custom-domain.default.dev.gswkbook.com ... traffic: - name: v1 percent: 100 revisionName: knative-custom-domain-00001
您可能還希望為不同的部署設置不同的域。例如,默認情況下,您可能希望將所有內容部署到開發域,然后在測試后將其轉發到生產域。Knative 提供了一種簡單的啟用此功能的機制,允許您定義多個域并標記路由以確定它們所在的域。讓我們再次更新 config-domain
ConfigMap,設置另一個用于生產的域名 *.prod.gswkbook.com
,如圖所示例6-10
apiVersion: v1kind: ConfigMapmetadata: name: config-domain namespace: knative-servingdata: prod.gswkbook.com: | selector: environment: prod dev.gswkbook.com: ""
在例 6-11 中,我們已經定義了具有 environment: prod
標簽的 Route 將被放置在 prod.gswkbook.com
域上,否則它將默認放置在 dev.gswkbook.com
域中。您需要做的就是將應用程序移動到這個新域,然后在配置的元數據部分中使用這個新標簽更新您的 Route。
apiVersion: serving.knative.dev/v1alpha1kind: Routemetadata: name: knative-custom-domain namespace: default labels: environment: prodspec: traffic: - revisionName: knative-custom-domain-00001 name: v1 percent: 100
應用后,您的路由會自動更新,并且假設您的 DNS 配置正確,可以立即在新域中訪問。您可以通過在檢索 Route CRD 時確保域條目匹配來驗證這一點,如例 6-12 所示。
kubectl describe route knative-custom-domain
description Name: knative-custom-domainNamespace: default...Kind: RouteMetadata: ...Spec: ...Status: ... Domain: knative-custom-domain.default.prod.gswkbook.com Domain Internal: knative-custom-domain.default.svc.cluster.local ...
假設我們希望應用程序從沒有事件源的源接收事件。例如,我們可能希望定期檢查文件服務器是否有新文件,或者請求 URL 來監視更改。將這些代碼組合在一起很容易,但是運行它的最佳方法是什么?像其他 Knative 應用程序一樣運行它是沒有意義的,因為它需要永久運行,但是如果我們在 Knative 之外運行它,那么我們就需要手動管理和配置的新組件。
Knative 通過使用 ContainerSource 輕松創建自己的事件源來解決這個問題。使用此事件源,我們提供 Knative 容器,Knative 將為容器提供 POST 事件的 URL。只要滿足這幾個簡單的要求,我們就可以用我們喜歡的任何語言編寫事件源:
它可以打包成一個容器,并有一個 ENTRYPOINT 定義,所以它知道如何運行我們的代碼。
2.它希望接收一個 --sink
CLI 標志,Knative 將提供一個指向已配置目標的 URL。
讓我們看看它是如何工作的,通過構建一個事件源,它將在給定的時間間隔內發出當前時間,稱為時間事件源。首先,讓我們看看事件源的代碼例 6-13。
require 'optparse'require 'net/http'require 'uri'# 默認 CLI 選項(如果省略)options = { :sink => "http://localhost:8080", :interval => 1}# 解析 CLI 標志opt_parser = OptionParser.new do |opt| opt.on("-s", "--sink SINK", "Location to send events") do |sink| options[:sink] = sink end opt.on("-i", "--interval INTERVAL", "Poll frequency") do |interval| options[:interval] = interval.to_i endendopt_parser.parse!# 按給定間隔發送當前時間到給定的接收器uri = URI.parse(options[:sink])header = {'Content-Type': 'text/plain'}loop do http = Net::HTTP.new(uri.host, uri.port) request = Net::HTTP::Post.new(uri.request_uri, header) request.body = Time.now.to_s response = http.request(request) sleep options[:interval]end
解析 CLI 標志后,這個 Ruby 應用程序進入一個死循環,不斷地將當前時間 POST 到由 --sink
標志提供的 URL,然后根據 --interval
標志提供的秒數休眠。由于這需要打包為容器,我們還有一個用于構建它的 Dockerfile,如例 6-14 所示。
FROM ruby:2.5.3-alpine3.8ADD . /time-event-sourceWORKDIR /time-event-sourceENTRYPOINT ["ruby", "app.rb"]
這里并不奇怪。我們使用官方 Ruby 鏡像作為基礎,添加我們的代碼,并定義如何運行我們的代碼。我們可以構建我們的容器并將其發送到 Docker Hub。在我們運行事件源之前,我們需要一個發送事件的地方。我們已經開始構建一個非常簡單的 Knative 應用程序,它記錄了所有它收到的 HTTP POST 的主體請求。
apiVersion: serving.knative.dev/v1alpha1kind: Servicemetadata: name: loggerspec: runLatest: configuration: revisionTemplate: spec: container: image: docker.io/gswk/logger:latest
我們將應用在例 6-15 中所示的 YAML ,命名為 logger 并部署它。
kubectl apply -f service.yaml
剩下的就是讓我們的事件源在 Knative 中運行。YAML 與其他事件源的概述相同,我們在例 6-16 中可以看到。
apiVersion: sources.eventing.knative.dev/v1alpha1kind: ContainerSourcemetadata: labels: controller-tools.k8s.io: "1.0" name: time-eventsourcespec: image: docker.io/gswk/time-event-source:latest args: - '--interval=1' sink: apiVersion: serving.knative.dev/v1alpha1 kind: Service name: logger
這里有幾個需要注意的點。首先,我們在 image 參數中為 Knative 提供了 Event Source 容器的位置,就像我們部署 Service 時一樣。其次,我們在 args 數組中提供了 --interval
標志,但我們省略了 --sink
標志。這是因為 Knative 將查看我們提供的接收器(在本例中為我們的日志服務),查找 URL 到該資源,并自動將其提供給我們的事件源。
這意味著,在 Event Source 容器的內部,最后我們的代碼將使用類似于以下內容的命令調用:
ruby app.rb--interval=1--sink=http://logger.default.example.com
我們將使用我們期望的通常的 kubectl apply 命令來部署它:
kubectl apply -f source.yaml
很快,我們會看到一個新的 Pod 被創建出來,但重要的區別在于它將永久運行而不會降低到零個。我們可以查看記錄器務的日志,以驗證我們的事件是否符合預期,如例 6-17 所示。
$ kubectl get pods -l app = logger-00001 -o name pod/logger-00001-deployment-57446ffb59-vzg97$ kubectl logs logger-00001-deployment-57446ffb59-vzg97 -c user-container2018/12/26 21:12:59 Starting server on port 8080...[Wed 26 Dec 2018 21:13:00 UTC] 2018-12-26 21:13:00 +0000[Wed 26 Dec 2018 21:13:01 UTC] 2018-12-26 21:13:01 +0000[Wed 26 Dec 2018 21:13:02 UTC] 2018-12-26 21:13:02 +0000[Wed 26 Dec 2018 21:13:03 UTC] 2018-12-26 21:13:03 +0000[Wed 26 Dec 2018 21:13:04 UTC] 2018-12-26 21:13:04 +0000[Wed 26 Dec 2018 21:13:05 UTC] 2018-12-26 21:13:05 +0000
這種簡單的抽象使我們能夠快速輕松地提供自己的事件源。不僅如此,而且與構建模板非常相似,您可以設想如何輕松地與 Knative 社區共享這些事件源,因為它們很容易插入到您的環境中。我們還將在第七章 中查看另一個自定義事件源
到目前為止,我們的內容已經涵蓋了相當多的用例,從初級的到高級的,但我們只是自己看了這些概念,一次展示一個功能。如果你像我們一樣,真正有用的是將它們全部放在一個現實世界的例子中,觀察每個組件如何相互作用。在下一章中,我們將做到這一點并構建一個利用我們所學知識的應用程序!
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...
在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...
在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...
x99主板上市時間?x99主板于2014年10月正式上市。x99主板基于英特爾X99芯片組,8個DDR4內存插槽,4個并行GPU和4個PCI Express 3.0 x16插槽,可支持4個全速x16 SLI和CF crossfirx99主板多少年的?x99主板發布于2014年9月14日。x99主板是哪里生產的? 2015年3月16日,華碩集團在臺北發布了其新款主板TUF劍齒虎X99。這款主板全球首...
ACTION文件怎么打開?1.首先打開一個qtp文件,進入qtp界面,點擊需要動作的文件。2.然后在點擊過qtp的菜單中點擊編輯菜單。3.點擊編輯菜單后,會彈出帶有操作選項的下拉菜單。4.點擊操作選項后,下一級菜單將彈出,選擇的選項為分割操作。5.會彈出qtp的確認。單擊是。6.這樣,在拆分動作窗口的界面中,會彈出動作的默認文件名。單擊確定。7.您可以看到當前中的操作文件已打開。后綴為.actio...
阿米尼的山地車怎么樣想買一個有了解的嗎謝謝_?一般般吧,低端的平時通勤騎還行,最起碼質量還是不錯的,不過強度大了會很吃不消 好一點兒的勉強能當入門山地騎,雖然質量一般,但是比較有型,看著視覺效果還不錯 再好一點兒的其實就是組裝車,只是阿米尼廠家自己進零件組裝好后貼了自己的牌子;這種車子和自己去組裝區別不大了,并且還沒有自己去裝車子隨性,不推薦買這種車子。。??傮w來說如果錢不是很充足的話,想弄個入門...