自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

KEDA:基于事件驅(qū)動(dòng)擴(kuò)展K8S應(yīng)用的深度實(shí)踐

云計(jì)算 云原生
KEDA 提供了一個(gè)類似于 FaaS 的事件感知擴(kuò)展模型,在這種模型中,Kubernetes 部署可以基于需求和基于智能動(dòng)態(tài)地從零擴(kuò)展,而不會(huì)丟失數(shù)據(jù)和上下文。

為什么我們要自動(dòng)擴(kuò)展應(yīng)用程序?

作為 SRE,需要保證應(yīng)用彈性和高可用性。因此,自動(dòng)縮放是我們需要的必須功能。通過自動(dòng)縮放,我們能確保工作負(fù)載能夠高效的地處理業(yè)務(wù)流量。

在本文中,我們將詳細(xì)描述如何使用 KEDA 以事件驅(qū)動(dòng)的方式自動(dòng)擴(kuò)展 Kubernetes 應(yīng)用程序。

什么是KEDA?

KEDA 是一個(gè)輕量級(jí)的開源 Kubernetes 事件驅(qū)動(dòng)的自動(dòng)縮放器,DevOps、SRE 和 Ops 團(tuán)隊(duì)使用它來根據(jù)外部事件或觸發(fā)器水平擴(kuò)展 Pod。KEDA 有助于擴(kuò)展本機(jī) Kubernetes 自動(dòng)縮放解決方案的功能,這些解決方案依賴于標(biāo)準(zhǔn)資源指標(biāo),如 CPU 或內(nèi)存。我們可以將 KEDA 部署到 Kubernetes 集群中,并使用自定義資源定義 (CRD) 管理 Pod 的擴(kuò)展。

KEDA 基于 Kubernetes HPA 構(gòu)建,根據(jù)來自 AWS SQS、Kafka、RabbitMQ 等事件源的信息擴(kuò)展 Pod。這些事件源使用縮放程序進(jìn)行監(jiān)視,縮放程序根據(jù)為其設(shè)置的規(guī)則激活或停用部署。KEDA 縮放器還可以為特定事件源提供自定義指標(biāo),幫助 DevOps 團(tuán)隊(duì)觀察與其相關(guān)的指標(biāo)

我們唯一要做的就是通過選擇要用于自動(dòng)擴(kuò)展應(yīng)用程序的縮放器以及一些參數(shù)來配置 ScaledObject (KEDA CRD),KEDA 將完成剩下的工作:

  • 監(jiān)視事件源
  • 創(chuàng)建和管理 HPA 生命周期

截至目前,有 62 個(gè)內(nèi)置縮放器和 4 個(gè)外部縮放器可用。 KEDA 之所以好,是因?yàn)槭褂幂p量級(jí)組件以及原生 Kubernetes 組件,例如 HorizontalPodAutoscaler ,更重要的是“即插即用”。

部署KEDA

那么,部署 KEDA 的最簡單方法是使用官方 Helm,安裝如下所示:

helm repo add kedacore 
helm repo update
helm install keda kedacore/keda --namespace keda --create-namespace

?? 如果使用 ArgoCD 部署 KEDA,您可能會(huì)遇到有關(guān) CRD 注釋長度的問題。我們可以使用選項(xiàng) ServerSideApply=true 來解決 template.sped.syncPolicy.syncOptions 。此外,還可以在 helm中設(shè)置參數(shù),從而 禁用 CRD 部署,當(dāng)然,這種情況下也必須找到另一種方法來部署 KEDA CRD。

基于本機(jī)Cron Scaler自動(dòng)縮放Web應(yīng)用

下面讓我們深度實(shí)踐一下KEDA!

部署我們的Web應(yīng)用

對于demo,將使用一個(gè)建的 Golang Web 應(yīng)用程序。使用以下清單部署:


---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: go-helloworld
  name: go-helloworld
spec:
  selector:
    matchLabels:
      app: go-helloworld
  template:
    metadata:
      labels:
        app: go-helloworld
    spec:
      containers:
        - image: rg.fr-par.scw.cloud/novigrad/go-helloworld:0.1.0
          name: go-helloworld
          resources:
            requests:
              cpu: "50m"
              memory: "64Mi"
            limits:
              memory: "128Mi"
              cpu: "100m"
---
apiVersion: v1
kind: Service
metadata:
  name: go-helloworld
spec:
  selector:
    app: go-helloworld
  ports:
    - protocol: TCP
      port: 8080
      name: http
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt
  name: go-helloworld
spec:
  rules:
  - host: helloworld.jourdain.io
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: go-helloworld
            port:
              number: 8080
  tls: # < placing a host in the TLS config will indicate a certificate should be created
  - hosts:
    - helloworld.jourdain.io
    secretName: go-helloworld-tls-cert

將KEDA配置為僅在工作時(shí)間自動(dòng)擴(kuò)展Web應(yīng)用

如果,我們希望我們的應(yīng)用程序僅在工作時(shí)間可用。至于為何有如此要求,下面是一些場景。例如,在開發(fā)環(huán)境中,不一定需要保持應(yīng)用程序24小時(shí)啟動(dòng)和運(yùn)行。在云環(huán)境中,它可以為您節(jié)省大量成本,具體取決于用戶實(shí)際環(huán)境的應(yīng)用程序/計(jì)算實(shí)例的數(shù)量。 為了實(shí)現(xiàn)這一點(diǎn),我們將使用KEDA的原生Cron scaler。由于 Cron scaler 支持 Linux 格式的 cron,它甚至允許我們在工作日擴(kuò)展我們的應(yīng)用程序 要配置 Cron scaler,我們將按如下方式使用 [ScaledObject] CRD:


apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: go-helloworld
spec:
  scaleTargetRef:
    name: go-helloworld
  triggers:
  - type: cron
    metadata:
      timezone: Europe/Paris
      start: 00 08 * * 1-5
      end: 00 18 * * 1-5
      desiredReplicas: "2"

?? ScaledObject 必須與應(yīng)用程序位于同一命名空間中!讓我們深入了解一下這個(gè)配置:

  • spec.scaleTargetRef 是 Kubernetes Deployment/StatefulSet 或其他自定義資源的引用

name (必填): Kubernetes 資源的名稱

kind (可選):Kubernetes 資源的種類,默認(rèn)值為 Deployment

  • spec.triggers 是用于激活目標(biāo)資源縮放的觸發(fā)器列表
  • type (必填):縮放器名稱
  • metadata (必需):Cron 縮放器所需的配置參數(shù),使用此配置,我的應(yīng)用程序?qū)⒃谥芤坏街芪宓囊恢苤忻刻斓?08:00 到 18:00 之間啟動(dòng)并運(yùn)行兩個(gè)副本。

基于HTTP事件自動(dòng)縮放Web應(yīng)用

(使用 KEDA HTTP 外部縮放器)

借助所有 KEDA 的縮放器,我們可以通過多種方式自動(dòng)擴(kuò)展 Web 應(yīng)用程序,例如,基于 AMQP 隊(duì)列中的消息進(jìn)行縮放應(yīng)用。

目前,我們了解了 KEDA 的工作原理。我下面?zhèn)儗⑻接?KEDA 如何通過基于 HTTP 事件自動(dòng)擴(kuò)展應(yīng)用程序來幫助我們處理流量高峰。為此,我們有兩個(gè)選擇:

  • 使用Prometheus scaler
  • 使用 KEDA HTTP 外部縮放器,它的工作方式類似于附加組件,由于演示集群上沒有安裝 Prometheus,因此我們將使用 KEDA HTTP 外部縮放器。

?? KEDA HTTP插件目前處于測試階段。它主要由KEDA團(tuán)隊(duì)維護(hù)。

解決方案概述

KEDA HTTP scaler是構(gòu)建在 KEDA 核心之上的附加組件,它擁有自己的組件:operator, scaler和 interceptor。如果你想進(jìn)一步了解它們的作用,請閱讀官方文檔??傊瑸榱藥椭蠹腋玫乩斫馑墓ぷ髟?,下面提供一個(gè)小案例:

圖片圖片

安裝KEDA HTTP附加組件

由于這個(gè)縮放器不是內(nèi)置的,我們必須手工安裝。根據(jù)官方文檔的說明,我們可以使用 Helm 來進(jìn)行安裝:

helm install http-add-on kedacore/keda-add-ons-http --namespace keda

如果安裝順利,我們應(yīng)該會(huì)看到以下pod:

? k get pods -l app=keda-add-ons-http -o name
pod/keda-add-ons-http-controller-manager-5c8d895cff-7jsl8
pod/keda-add-ons-http-external-scaler-57889786cf-r45lj
pod/keda-add-ons-http-interceptor-5bf6756df9-wwff8
pod/keda-add-ons-http-interceptor-5bf6756df9-x8l58
pod/keda-add-ons-http-interceptor-5bf6756df9-zxvw

為我們的Web應(yīng)用配置'HTTPScaledObject'

正如之前所說,KEDA HTTP 附加組件自帶組件,包括操作符,這也意味著它自帶 CRD。HTTPScaledObject 是由 KEDA HTTP 附加組件管理的 CRD。這就是我們在這里需要配置的。讓我們?yōu)?Web 應(yīng)用程序創(chuàng)建 HTTPScaledObject 資源: ?? HTTPScaleObject 必須在與 Web 應(yīng)用相同的命名空間中創(chuàng)建資源!

kind: HTTPScaledObject
apiVersion: http.keda.sh/v1alpha1
metadata:
    name: go-helloworld
spec:
    host: "helloworld.jourdain.io"
    targetPendingRequests: 10
    scaledownPeriod: 300
    scaleTargetRef:
        deployment: go-helloworld
        service: go-helloworld
        port: 8080
    replicas:
        min: 0
        max: 10

在這里,我們已經(jīng)配置了我們的 HTTPScaledObject 應(yīng)用程序,以便將我們的應(yīng)用程序 Deployment 從 0 個(gè)副本擴(kuò)展到 10 個(gè)副本。因?yàn)?,如果攔截器上有 10 個(gè)請求處于掛起狀態(tài)(應(yīng)用程序尚未接收的請求),則 KEDA 將添加一個(gè) pod。

調(diào)整我們的Web應(yīng)用程序的service和ingress

仔細(xì)觀察一下上面的圖,可以看到我們的 Web 應(yīng)用程序 ingress 需要引用 KEDA HTTP 附加組件的攔截器服務(wù),而不是 Web 應(yīng)用程序的攔截器服務(wù)。由于 ingress 無法引用另一個(gè)命名空間中的服務(wù),因此我們將在與 Web 應(yīng)用相同的命名空間 external 中創(chuàng)建類型服務(wù),該服務(wù)引用來自 keda 命名空間的攔截器服務(wù):

kind: Service
apiVersion: v1
metadata:
  name: keda-add-ons-http-interceptor-proxy
spec:
  type: ExternalName
  externalName: keda-add-ons-http-interceptor-proxy.keda.svc.cluster.local

現(xiàn)在,我們需要重新配置 Web 應(yīng)用的入口,使其引用新創(chuàng)建的服務(wù):

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt
  name: go-helloworld
spec:
  rules:
  - host: helloworld.jourdain.io
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: keda-add-ons-http-interceptor-proxy
            port:
              number: 8080
  tls: # < placing a host in the TLS config will indicate a certificate should be created
  - hosts:
    - helloworld.jourdain.io
    secretName: go-helloworld-tls-cert

?? 需要輸入新服務(wù)的名稱,但請注意端口,該端口也被攔截器的服務(wù)所取代

讓我們測試一下

為了保證我們的配置正常,本處將使用 [k6]工具 ,這是一個(gè)負(fù)載測試工具。如果想了解有關(guān)k6的更多信息,以下是Padok博客中的一些介紹:

  • [How to do distributed load testing using K6 & Kubernetes?] (https://www.padok.fr/en/blog/k6-load-testing)
  • [k6 description from the Padok tech radar] (https://www.padok.fr/en/tech-radar-resilient?category=resilient&rank=6)

下面本次使用的 k6 腳本,后續(xù)將使用它進(jìn)行測試:


import { check } from 'k6';
import http from 'k6/http';

export const options = {
  scenarios: {
    constant_request_rate: {
      executor: 'constant-arrival-rate',
      rate: 100,
      timeUnit: '1s', // 100 iterations per second, i.e. 100 RPS
      duration: '30s',
      preAllocatedVUs: 50, // how large the initial pool of VUs would be
      maxVUs: 50, // if the preAllocatedVUs are not enough, we can initialize more
    },
  },
};

export function test(params) {
  const res = http.get('');
  check(res, {
    'is status 200': (r) => r.status === 200,
  });
}

export default function () {
  test();
}

首先,讓我們看看 100 個(gè) RPS 會(huì)發(fā)生什么:


? k6 run k6/script.js

          /\\      | ̄ ̄| / ̄ ̄/   / ̄ ̄/
     /\\  /  \\     |  |/  /   /  /
    /  \\/    \\    |     (   /    ̄ ̄\\
   /          \\   |  |\\  \\ |  ( ̄)  |
  / __________ \\  |__| \\__\\ \\_____/ .io

  execution: local
     script: k6/script.js
     output: -

  scenarios: (100.00%) 1 scenario, 50 max VUs, 1m0s max duration (incl. graceful stop):
           * constant_request_rate: 100.00 iterations/s for 30s (maxVUs: 50, gracefulStop: 30s)


     ? is status 200

     checks.........................: 100.00% ? 3001      ? 0
     data_received..................: 845 kB  28 kB/s
     data_sent......................: 134 kB  4.5 kB/s
     http_req_blocked...............: avg=792.54μs min=0s     med=1μs     max=137.85ms p(90)=2μs     p(95)=2μs
     http_req_connecting............: avg=136.6μs  min=0s     med=0s      max=17.67ms  p(90)=0s      p(95)=0s
     http_req_duration..............: avg=11.38ms  min=7.68ms med=10.68ms max=100.96ms p(90)=12.78ms p(95)=14.33ms
       { expected_response:true }...: avg=11.38ms  min=7.68ms med=10.68ms max=100.96ms p(90)=12.78ms p(95)=14.33ms
     http_req_failed................: 0.00%   ? 0         ? 3001
     http_req_receiving.............: avg=89.68μs  min=8μs    med=64μs    max=6.35ms   p(90)=112μs   p(95)=134μs
     http_req_sending...............: avg=152.31μs min=14μs   med=137μs   max=2.57ms   p(90)=274μs   p(95)=313μs
     http_req_tls_handshaking.......: avg=587.62μs min=0s     med=0s      max=74.46ms  p(90)=0s      p(95)=0s
     http_req_waiting...............: avg=11.14ms  min=7.62ms med=10.48ms max=100.92ms p(90)=12.47ms p(95)=13.96ms
     http_reqs......................: 3001    99.983105/s
     iteration_duration.............: avg=12.37ms  min=7.73ms med=10.88ms max=194.89ms p(90)=13.07ms p(95)=14.99ms
     iterations.....................: 3001    99.983105/s
     vus............................: 1       min=1       max=1
     vus_max........................: 50      min=50      max=50


running (0m30.0s), 00/50 VUs, 3001 complete and 0 interrupted iterations
constant_request_rate ? [======================================] 00/50 VUs  30s  100.00 iters/s

?? 如果您想實(shí)時(shí)查看攔截器隊(duì)列中有多少請求,可以在兩個(gè)終端窗格中啟動(dòng)以下命令:

? kubectl proxy
Starting to serve on 127.0.0.1:8001

以及:

? watch -n '1' curl --silent localhost:8001/api/v1/namespaces/keda/services/keda-add-ons-http-interceptor-admin:9090/proxy/queue
{"default/go-helloworld":0}

在 100 RPS 測試中,應(yīng)用程序沒有縱向擴(kuò)展,因?yàn)閿r截器隊(duì)列中的掛起請求數(shù)不超過 1。提醒一下,我們配置為 targetPendingRequests 10 。所以一切都很正常 ??下面讓我們將 RPS x10 ,看看會(huì)發(fā)生什么:

? k6 run k6/script.js
          /\\      | ̄ ̄| / ̄ ̄/   / ̄ ̄/     /\\  /  \\     |  |/  /   /  /    /  \\/    \\    |     (   /    ̄ ̄\\   /          \\   |  |\\  \\ |  ( ̄)  |  / __________ \\  |__| \\__\\ \\_____/ .io
  execution: local     script: k6/script.js     output: -
  scenarios: (100.00%) 1 scenario, 50 max VUs, 1m0s max duration (incl. graceful stop):           * constant_request_rate: 1000.00 iterations/s for 30s (maxVUs: 50, gracefulStop: 30s)
     ? is status 200      ?  99% — ? 11642 / ? 2
     checks.........................: 99.98% ? 11642      ? 2     data_received..................: 2.6 MB 86 kB/s     data_sent......................: 446 kB 15 kB/s     dropped_iterations.............: 18356  611.028519/s     http_req_blocked...............: avg=1.07ms   min=0s     med=0s      max=408.06ms p(90)=1μs      p(95)=1μs     http_req_connecting............: avg=43.12μs  min=0s     med=0s      max=11.05ms  p(90)=0s       p(95)=0s     http_req_duration..............: avg=120.09ms min=8.14ms med=74.77ms max=6.87s    p(90)=189.49ms p(95)=250.21ms       { expected_response:true }...: avg=120.01ms min=8.14ms med=74.76ms max=6.87s    p(90)=189.41ms p(95)=249.97ms     http_req_failed................: 0.01%  ? 2          ? 11642     http_req_receiving.............: avg=377.61μs min=5μs    med=32μs    max=27.32ms  p(90)=758.1μs  p(95)=2.49ms     http_req_sending...............: avg=61.57μs  min=9μs    med=45μs    max=9.99ms   p(90)=102μs    p(95)=141μs     http_req_tls_handshaking.......: avg=626.79μs min=0s     med=0s      max=297.82ms p(90)=0s       p(95)=0s     http_req_waiting...............: avg=119.65ms min=7.95ms med=74.32ms max=6.87s    p(90)=188.95ms p(95)=249.76ms     http_reqs......................: 11644  387.60166/s     iteration_duration.............: avg=121.26ms min=8.32ms med=74.87ms max=7.07s    p(90)=189.62ms p(95)=250.28ms     iterations.....................: 11644  387.60166/s     vus............................: 44     min=25       max=50     vus_max........................: 50     min=50       max=50

running (0m30.0s), 00/50 VUs, 11644 complete and 0 interrupted iterationsconstant_request_rate ? [======================================] 00/50 VUs  30s  1000.00 iters/s

結(jié)果還不錯(cuò),我們有兩個(gè)請求 KO ,這是因?yàn)閼?yīng)用程序冷啟動(dòng)(從 0 開始),每個(gè)請求等待的時(shí)間不超過 1/2 秒。以下是部署歷史記錄:

? k get deployments.apps -w
NAME            READY   UP-TO-DATE   AVAILABLE   AGE
go-helloworld   0/0     0            0           36m
go-helloworld   0/1     0            0           36m
go-helloworld   1/1     1            1           36m
go-helloworld   1/4     1            1           36m
go-helloworld   2/4     4            2           36m
go-helloworld   3/4     4            3           36m
go-helloworld   4/4     4            4           36m
go-helloworld   4/5     4            4           37m
go-helloworld   5/5     5            5           37m

應(yīng)用程序從 0 個(gè)副本擴(kuò)展到 5 個(gè)副本;直到 Web 應(yīng)用程序的掛起請求數(shù)少于 10。

縮放指令非??欤瑧?yīng)用程序很快達(dá)到了 5 個(gè)副本。

以下是 100 RPS 和 1k RPS 測試之間 http_req_duration k6 指標(biāo)的一些對比:

# 100 RPS
http_req_duration: avg=11.38ms  min=7.68ms med=10.68ms max=100.96ms p(90)=12.78ms p(95)=14.33ms

# 1k RPS
http_req_duration: avg=120.09ms min=8.14ms med=74.77ms max=6.87s    p(90)=189.49ms p(95)=250.21ms

根據(jù)我們的需求(SLO,SLA等),我們也許可以稍微調(diào)整一下 Web應(yīng)用程序的 targetPendingRequestsHTTPScaledObject 參數(shù) 。

縮放到零!

通過本文介紹的兩個(gè)案例,我們已經(jīng)驗(yàn)證過了如何縮放到零的場景。但是,大家真的知道它是如何工作的嗎?

由于 KEDA 根據(jù)事件自動(dòng)縮放應(yīng)用程序,因此從收到事件的那一刻起,KEDA 會(huì)將應(yīng)用程序縮放到其最小副本。例如,如果我們以 HTTP 附加組件為例,KEDA 將在第一次收到請求時(shí)擴(kuò)展到最小副本。

總結(jié)

KEDA 提供了一個(gè)類似于 FaaS 的事件感知擴(kuò)展模型,在這種模型中,Kubernetes 部署可以基于需求和基于智能動(dòng)態(tài)地從零擴(kuò)展,而不會(huì)丟失數(shù)據(jù)和上下文。在業(yè)務(wù)請求量上來后,應(yīng)用程序?qū)⑦M(jìn)行自動(dòng)化的擴(kuò)容,當(dāng)業(yè)務(wù)低谷的時(shí)候,則會(huì)自動(dòng)的縮容。這可以在緩解很多生產(chǎn)環(huán)境下的手動(dòng)擴(kuò)/縮容操作,以保障用戶的服務(wù)體驗(yàn)。

KEDA 還為 Kubernetes 帶來了更多的事件源。隨著未來更多觸發(fā)器的加入,KEDA 有很大的潛力成為生產(chǎn)級(jí) Kubernetes 部署的必需品,從而使應(yīng)用程序自動(dòng)縮放成為應(yīng)用程序開發(fā)中的嵌入式組件。

責(zé)任編輯:武曉燕 來源: 新鈦云服
相關(guān)推薦

2022-09-15 08:04:54

k8skubernetes

2023-12-25 07:35:40

數(shù)據(jù)集成FlinkK8s

2023-08-04 08:19:02

2023-09-06 08:12:04

k8s云原生

2023-08-31 08:21:42

KubernetesKADA驅(qū)動(dòng)

2017-11-21 10:11:19

陌陌K8sDocker

2012-06-27 14:40:57

事件驅(qū)動(dòng)擴(kuò)展

2021-11-04 07:49:58

K8SStatefulSetMySQL

2022-04-05 09:24:57

K8s安全網(wǎng)絡(luò)安全時(shí)間響應(yīng)

2022-04-22 13:32:01

K8s容器引擎架構(gòu)

2023-11-06 07:16:22

WasmK8s模塊

2024-02-01 09:48:17

2022-04-02 09:57:51

技術(shù)京東實(shí)踐

2023-09-07 08:58:36

K8s多集群

2024-01-04 08:31:22

k8sController自定義控制器

2020-02-04 16:37:17

k8s 相關(guān)應(yīng)用

2022-04-07 10:17:18

云原生服務(wù)器優(yōu)化

2022-09-14 10:49:30

微服務(wù)Kubernetes區(qū)塊鏈

2022-09-13 09:04:20

云計(jì)算移動(dòng)辦公大數(shù)據(jù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)