日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

serverless knative实战

發布時間:2023/12/20 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 serverless knative实战 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1、部署一個service應用

在部署第一個Knative Service之前,我們先了解一下它的部署模型和對應的Kubernetes資源。如圖6-2所示,在部署Knative Serving Service的過程中,Knative Serving控制器將創建configuration、Revision和Route三個資源對象。

配置(configuration):Knative configuration維護了部署的目標狀態,提供了一個干凈的代碼和配置分離、遵循12要素開發原則的機制。基于目標狀態,Knative configuration控制器為應用創建了一個新的Kubernetes部署應用。并且configuration的變更會體現在一個新的Kubernetes部署應用中。
修訂版(Revision):Knative configuration遵循12要素開發原則,每次應用的變更將會創建一個新的Knative Revision。Revision類似于版本控制中的標簽。Revision一旦創建,是不可改變的。每個Revision都有一個對應的Kubernetes Deployment。它允許將應用程序回滾到任何正確的最新配置。
路由(Route):Knative Route是訪問Knative Service的URL。

接下來分別以java和node為例創建一個簡單的web服務。該服務接收到HTTP GET請求時,會根據環境變量Target傳遞的內容向Response輸出Hello$TATGET!內容。

1.1、制作service鏡像

java

  • 創建一個spring boot項目
  • package com.example.helloworld; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication public class HelloworldApplication {@Value("${TARGET:World}")String target;@RestControllerclass HelloworldController {@GetMapping("/")String hello() {return "Hello " + target + "!";}}public static void main(String[] args) {SpringApplication.run(HelloworldApplication.class, args);} }

    啟動訪問

    ./mvnw package && java -jar target/helloworld-0.0.1-SNAPSHOT.jar
  • 制作Dockerfile文件
  • # Use the official maven/Java 8 image to create a build artifact. # https://hub.docker.com/_/maven FROM maven:3.5-jdk-8-alpine as builder # Copy local code to the container image. WORKDIR /app COPY pom.xml . COPY src ./src # Build a release artifact. RUN mvn package -DskipTests # Use AdoptOpenJDK for base image. # It's important to use OpenJDK 8u191 or above that has container support enabled. # https://hub.docker.com/r/adoptopenjdk/openjdk8 # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds FROM adoptopenjdk/openjdk8:jdk8u202-b08-alpine-slim # Copy the jar to the production image from the builder stage. COPY --from=builder /app/target/helloworld-*.jar /helloworld.jar # Run the web service on container startup. CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/helloworld.jar"]
  • 制作鏡像、并push到Docker registry
  • # Build the container on your local machine docker build -t {username}/helloworld-java-spring . # Push the container to docker registry docker push {username}/helloworld-java-spring

    nodejs

  • 創建一個Node項目
  • npm init package name: (helloworld-nodejs) version: (1.0.0) description: entry point: (index.js) test command: git repository: keywords: author: license: (ISC) Apache-2.0
  • 安裝express包
  • npm install express
  • 創建一個主程序index.js
  • const express = require('express'); const app = express(); app.get('/', (req, res) => {console.log('Hello world received a request.');const target = process.env.TARGET || 'World';res.send(`Hello ${target}!\n`); }); const port = process.env.PORT || 8080; app.listen(port, () => {console.log('Hello world listening on port', port); });
  • 配置package.json
  • {"name": "knative-serving-helloworld","version": "1.0.0","description": "Simple hello world sample in Node","main": "index.js","scripts": {"start": "node index.js"},"author": "","license": "Apache-2.0","dependencies": {"express": "^4.16.4"} }
  • 制作Dockerfile文件
  • # Use the official lightweight Node.js 12 image. # https://hub.docker.com/_/node FROM node:12-slim # Create and change to the app directory. WORKDIR /usr/src/app # Copy application dependency manifests to the container image. # A wildcard is used to ensure both package.json AND package-lock.json are copied. # Copying this separately prevents re-running npm install on every code change. COPY package*.json ./ # Install production dependencies. RUN npm install --only=production # Copy local code to the container image. COPY . ./ # Run the web service on container startup. CMD [ "npm", "start" ]

    制作鏡像和推送鏡像和java環境一樣。
    注意應用程序和docker暴露端口必須是8080,否則會部署失敗。新版可以在service的yml中指定端口號。

    1.2 部署應用

    可以采用二種方式部署應用:

    • yaml
    • kn
  • yaml方式
  • 創建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
  • kn部署
  • kn service create helloworld-java-spring --image=docker.io/{username}/helloworld-java-spring --env TARGET="Java Spring Sample v1"

    在創建服務期間,Knative 會執行以下步驟:

    • 為此版本的應用程序創建一個新的不可變修訂版。
    • 為您的應用程序創建路由、入口、服務和負載平衡。
    • 自動向上和向下擴展您的 pod,包括縮小到零活動 pod。

    1.3 驗證

    可以采用二種方式驗證:

    • kubectl
    • kn
  • kubectl
  • kubectl get ksvc helloworld-java-spring --output=custom-columns=NAME:.metadata.name,URL:.status.url

    顯示

    NAME URL helloworld-java-spring http://helloworld-java-spring.default.1.2.3.4.sslip.io
  • kn
  • kn service describe helloworld-java-spring -o url

    顯示

    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

  • kubectl方式
  • kubectl delete --filename service.yaml
  • kn方式
  • kn service delete helloworld-java-spring

    1.4 更新Knative Service configuration

    在部署完一個Knative Service后,我們會因為應用版本的升級、配置的變更等需要更新現有服務的configuration。Knative服務還提供了一種機制實現回滾變更。
    12要素應用設計原則規定,應用程序與配置的變更應被視為一個新的修訂版。修訂版是不可變更的應用和配置的狀態集合。它可以讓你回滾到任何一個有效的修訂版狀態。
    應用的更新包括容器鏡像的更新、健康檢查探針的調整、環境變量的變更。這些變更會導致Knative生成新的修訂版。每一個新修訂版將創建一個新的Kubernetes Deployment對象。
    接下來,我們通過一個更新服務配置的示例來演示配置的變更。

    apiVersion: serving.knative.dev/v1 kind: Service metadata:name: helloworld-go # Service名稱namespace: default spec:template:metadata:name: helloworld-go-v2 # Knative Revision名稱spec:containers:- image: cnlab/helloworld-goenv:- name: TARGETvalue: "Go Sample v2"livenessProbe:httpGet:path: /readinessProbe:httpGet:path: /

    配置文件(service.yaml)的變更如下。
    1)更新修訂版的名稱(.spec.template.metadata.name)為helloworld-go-v2,區別于上一個修訂版名稱helloworld-go-v1。
    2)更新環境變量TARFET(.spec.template.spec.containers[0].env[0].value)的值為Go Sample v2。
    將配置更新到Knative:

    # kubectl apply-f service.yaml

    檢查部署結果:

    # 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服務:

    ##獲取集群任一節點的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 12s

    helloworld-go對應的部署如果在擴縮容時間窗口期(默認60s)內沒有請求,Knative將自動將對應的部署縮容為零。
    查看部署后生成的Revision:

    # kubectl get revision NAME CONFIG NAME K8S SERVICE NAME GENERATION READY REASON helloworld-go-v1 helloworld-go helloworld-go-v1 1 True helloworld-go-v2 helloworld-go helloworld-go-v2 2 True

    我們可以看到helloworld-go的配置有兩個修訂版,分別是helloworld-go-v1和helloworld-go-v2。配置的變更產生了新的修訂版,然而并沒有產生新的路由、服務和配置對象。我們可以通過下面的命令來驗證這些資源對象的狀態。

    • 獲取服務的路由信息的命令:kubectl get routes。
    • 獲取Knative服務的狀態信息的命令:kubectl get ksvc。
    • 獲取Knative服務的配置信息的命令:kubectl get configurations。
    • Knative默認路由策略是將所有流量轉發給最新的修訂版。

    1.5 流量分發到不同版本

    在典型的微服務部署中,實現流量在不同版本中分發是實現金絲雀或藍綠部署方式的基礎。Knative提供了這種流量分發方式的支持。
    在Knative Service的yaml文件配置中,traffic區塊描述了如何在多個版本之間進行流量分發。配置范例如下:

    apiVersion: serving.knative.dev/v1 kind: Service metadata:name: helloworld-go # Service名稱namespace: default spec:template:metadata:name: helloworld-go-v2 # Knative Revision名稱spec:containers:- image: cnlab/helloworld-goenv:- name: TARGETvalue: "Go Sample v2"livenessProbe:httpGet:path: /readinessProbe:httpGet:path: /traffic:- tag: v1 revisionName: helloworld-go-v1 # Revision的名稱percent: 50 #流量切分的百分比的數字值- tag: v2revisionName: helloworld-go-v2 # Revision的名稱percent: 50 #流量切分的百分比的數字值

    traffic區塊中可以有一個或多個條目。每個條目中帶有如下屬性。

    • tag:流量分配的標識符。此標記將在路由中充當前綴,以便將流量分發到特定修訂版。
    • revisionName:參與流量分配的Knative服務修訂版本的名稱。
    • percent:對應修訂版被分配的流量百分比。這個值在0~100之間。在上述例子中,Knative分配給修訂版helloworld-go-v1和helloworld-go-v2各50%的流量。
    • Knative Serving會為每個Tag創建獨特的URL。我們可以通過下面的命令查看:
    # kubectl get ksvc helloworld-go-o jsonpath='{.status.traffic[*].url}' http://v1-helloworld-go.default.example.com http://v2-helloworld-go.default.example.com

    通過訪問URL可以直接訪問到對應的修訂版。

    1.6 藍綠部署與灰度發布

    一般情況下,升級服務端應用需要先停掉老版本服務,再啟動新版服務。但是這種簡單的發布方式存在兩個問題,一方面在新版本升級過程中,服務是暫時中斷的;另一方面,如果新版本升級失敗,回滾起來非常麻煩,容易造成更長時間的服務不可用。

  • 藍綠部署
  • 所謂藍綠部署,是指同時運行兩個版本的應用,即部署的時候,并不停掉老版本,而是直接部署一套新版本,等新版本運行起來后,再將流量切換到新版本上,如圖6-3所示。但是藍綠部署要求服務端在升級過程中同時運行兩套程序,對硬件資源的要求是日常所需的2倍。

    Knative提供了一個簡單的切換流量的方法,可將流量快速從Revison1切換到Revision 2。如果Revision2發生錯誤,服務可以快速回滾變更到Revison1。
    接下來,我們將通過helloworld-go這個Knative服務來應用藍綠色部署模式。上文擁有兩個修訂版的helloworld-go服務,名稱分別為helloworld-go-v1和helloworld-go-v2。通過部署helloworld-go-v2,我們可以看到Knative自動將100%的流量路由到helloworld-go-v2。現在,假設出于某些原因,我們需要將helloworld-go-v2回滾到helloworld-go-v1。
    以下示例中Knative Service與先前部署的helloworld-go相同,只是添加了traffic部分以指示將100%的流量路由到helloworld-go-v1。

    apiVersion: serving.knative.dev/v1 kind: Service metadata:name: helloworld-go # Service名稱namespace: default spec:template:metadata:name: helloworld-go-v2 # Knative Revision名稱spec:containers:- image: cnlab/helloworld-goenv:- name: TARGETvalue: "Go Sample v2"livenessProbe:httpGet:path: /readinessProbe:httpGet:path: /traffic:- tag: v1 revisionName: helloworld-go-v1 # Revision的名稱percent: 100 # 流量切分的百分比值- tag: v2revisionName: helloworld-go-v2 # Revision的名稱percent: 0 # 流量切分的百分比值- tag: latest # 默認最新的RevisionlatestRevision: truepercent: 0 # 關閉默認流量分配
  • 灰度發布
  • 灰度發布也叫金絲雀發布。如圖所示,在灰度發布開始后,先啟動一個新版本應用,但是并不直接將流量切過來,而是測試人員對新版本進行線上測試。啟動的這個新版本應用,就是我們的金絲雀。如果測試沒有問題,我們可以將少量的流量導入新版本,然后再對新版本做運行狀態觀察,收集各種運行時數據。如果此時對新舊版本做數據對比,就是所謂的A/B測試。

    當確認新版本運行良好后,再逐步將更多的流量導入新版本。在此期間,我們還可以不斷地調整新舊兩個版本運行的服務器副本數量,使得新版本能夠承受更大的流量壓力,直到將100%的流量切換到新版本上,最后關閉剩下的老版本服務,完成灰度發布。
    如果我們在灰度發布過程中(灰度期)發現新版本有問題,應該立即將流量切回老版本,這樣就會將負面影響控制在最小范圍內。
    以下示例通過不斷變更helloworld-go-v1和helloworld-go-v2的流量比例來實現helloworld-go服務新版本的灰度發布。

    apiVersion: serving.knative.dev/v1 kind: Service metadata:name: helloworld-go # Service名稱namespace: default spec:template:metadata:name: helloworld-go-v2 # Knative Revision名稱spec:containers:- image: cnlab/helloworld-goenv:- name: TARGETvalue: "Go Sample v2"livenessProbe:httpGet:path: /readinessProbe:httpGet:path: /traffic:- tag: v1 revisionName: helloworld-go-v1 # Revision的名稱percent: 80 # 流量切分的百分比值- tag: v2revisionName: helloworld-go-v2 # Revision的名稱percent: 20 # 流量切分的百分比值- tag: latest # 默認最新的RevisionlatestRevision: truepercent: 0 # 關閉默認流量分配

    使用 Knative CLI 路由和管理流量

    1.5和1.6的操作也可以通過cli命令設置。

    kn service update <service-name> --traffic <revision-name>=<percent>

    是您為其配置流量路由的 Knative 服務的名稱。
    是要配置為接收一定百分比的流量的修訂名稱。
    是要發送到 指定的修訂版的流量百分比。

    例如,要拆分名為 example 的 Service 的流量,將 80% 的流量發送到 Revision 綠色,將 20% 的流量發送到 Revision blue,您可以運行以下命令:

    kn service update example-service --traffic green=80 --traffic blue=20

    也可以將標簽添加到修訂版,然后根據您設置的標簽拆分流量:

    kn service update example --tag green=revision-0001 --tag blue=@latest

    @latest 標簽表示藍色解析為服務的最新版本。 以下示例將 80% 的流量發送到最新版本,將 20% 的流量發送到名為 v1 的版本。

    kn service update example-service --traffic @latest=80 --traffic v1=20

    1.7 Knative Service的彈性伸縮配置

    無服務器計算不僅能夠終止未使用的服務,還可以按需擴展計算規模。Knative Serving支持這種彈性伸縮能力。
    為了讓Knative的Autoscaler更好地調度服務,我們需要根據實際情況在服務中添加相應的擴縮容配置項。下面以helloworld-go.yaml范例來演示擴縮容相關配置。

    apiVersion: serving.knative.dev/v1 kind: Service metadata:name: helloworld-go # Service名稱namespace: default spec:template:metadata:annotations:autoscaling.knative.dev/class: "kpa.autoscaling.knative.dev" # Autoscaler的實現方式,可選值有"kpa.autoscaling.knative.dev" 或 "hpa.autoscaling.knative.dev"autoscaling.knative.dev/metric: "concurrency" # 設置度量指標為Concurrency(默認值),還可以根據業務情況選擇RPS或CPUautoscaling.knative.dev/target: "10" # 設置單個Pod最大并發數為10,默認值為100autoscaling.knative.dev/minScale: "1" # minScale表示最小保留實例數為1autoscaling.knative.dev/maxScale: "100" # maxScale表示最大擴容實例數為3spec:containerConcurrency: 10 # 并發請求數的硬性限制containers:- image: cnlab/helloworld-go

    在上述配置中,revision中配置了修訂版的彈性伸縮策略。各個屬性代表的意義如下。

    • autoscaling.knative.dev/class:表示Autoscaler的實現方式,這個屬性的可選值有kpa.autoscaling.knative.dev或hpa.autoscaling.knative.dev。KPA支持縮容到零,HPA支持基于CPU的擴展機制。
    • autoscaling.knative.dev/metric:度量指標默認為并發數,該屬性還可以根據業務情況選擇每秒請求數或CPU使用率。
    • autoscaling.knative.dev/target:自動縮放的目標值是Autoscaler維護應用的每個副本度量指標的目標值。
    • autoscaling.knative.dev/minScale:表示每個修訂版副本需要保留的最小數量。在任何時間點,副本不會少于這個數量。通過該設置,我們可以有效地減少服務的冷啟動時間。
    • autoscaling.knative.dev/maxScale:表示每個修訂版副本所能達到的最大數量。在任何時間點,副本都不會超過指定的最大值,從而避免資源被過度使用。
    • containerConcurrency:限制容器在給定時間允許的并發請求的數量的硬性限制。只有當應用程序需要強制的并發約束時,才會使用到該屬性。

    部署helloworld-go服務并配置到Knative集群:

    # kubectl apply-f helloworld-go.yaml

    驗證部署結果:

    #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工具發起50個并發請求,持續30秒對hellowrold-go服務進行壓測。
    查看壓測期間Pod的副本數量:

    # kubectl get pod -l serving.knative.dev/service=helloworld-go NAME READY STATUS RESTARTS AGE helloworld-go-7t7sg-deployment-6bfbdb84fd-5l5gc 3/3 Running 0 42s helloworld-go-7t7sg-deployment-6bfbdb84fd-99cdr 3/3 Running 0 42s helloworld-go-7t7sg-deployment-6bfbdb84fd-ls4ks 3/3 Running 0 44s helloworld-go-7t7sg-deployment-6bfbdb84fd-n4s4k 3/3 Running 0 44s helloworld-go-7t7sg-deployment-6bfbdb84fd-q9kr8 3/3 Running 0 40s helloworld-go-7t7sg-deployment-6bfbdb84fd-r77tt 3/3 Running 0 22m

    通過上面的命令,我們可以看到集群中產生了6個Pod副本。那么問題來了,我們發起的并發請求數是50個,服務自動縮放的目標值是10,按照“副本數=并發數/目標值”算法,Pod副本數應該是5個才對呀。這是由于Knative Serving還有一個控制參數叫目標使用率,一旦并發數達到預設目標的70%(默認值),Autoscaler就會繼續擴容。引入目標使用率的主要目的是在擴容時減小由Pod啟動時間帶來的延遲,使負載到達前就將Pod實例啟動起來。

    引用

    Hello world apps - Python - 《Knative v0.23 Documentation》 - 書棧網 · BookStack

    Knative實戰:基于Kubernetes的無服務器架構實踐 by 李志偉 游楊 (z-lib.org)

    總結

    以上是生活随笔為你收集整理的serverless knative实战的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。