如何使用KEDA和Prometheus扩展您的Kubernetes工作负载?

作者:djamaile  编译:沈建苗

如今人人都在使用Kubernetes,而Kubernetes的一个重要方面是扩展工作负载。借助KEDA,工作负载扩展起来异常简单!不妨看一下到底有多简单。

代码存储库:https://github.com/djamaile/keda-demo

KEDA简介

KEDA官网介绍如下:KEDA是一个基于Kubernetes的事件驱动自动扩展器。使用KEDA,您可以根据需要处理的事件数量,对Kubernetes中的任何容器进行扩展。

KEDA提供了许多“触发器”,您的应用程序可根据这些“触发器”来扩展,比如Prometheus、PubSub和Postgres等触发器。我们在这篇博文中重点介绍Prometheus。

启动

首先,不妨启动一个集群!我使用的是kind,但您也可以minikube。

$ kind create cluster

创建命名空间

$ kubectl create ns keda-demo

切换到命名空间

$ kubectl config set-context --current --namespace=keda-demo

如果集群已启动,我们可以开始部署Prometheus了。为此,我早已编写了一个prometheus清单文件,您没必要编写了。

prometheus.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus
rules:
  - apiGroups: [""]
    resources:
      - services
    verbs: ["get", "list", "watch"]
  - nonResourceURLs: ["/metrics"]
    verbs: ["get"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: keda-demo
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
  - kind: ServiceAccount
    name: keda-demo
    namespace: keda-demo
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: prom-conf
  labels:
    name: prom-conf
data:
  prometheus.yml: |-
    global:
      scrape_interval: 5s
      evaluation_interval: 5s
    scrape_configs:
      - job_name: 'go-prom-job'
        kubernetes_sd_configs:
        - role: service
        relabel_configs:
        - source_labels: [__meta_kubernetes_service_label_run]
          regex: go-prom-app-service
          action: keep
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prometheus-server
  template:
    metadata:
      labels:
        app: prometheus-server
    spec:
      serviceAccountName: keda-demo
      containers:
        - name: prometheus
          image: prom/prometheus
          args:
            - "--config.file=/etc/prometheus/prometheus.yml"
            - "--storage.tsdb.path=/prometheus/"
          ports:
            - containerPort: 9090
          volumeMounts:
            - name: prometheus-config-volume
              mountPath: /etc/prometheus/
            - name: prometheus-storage-volume
              mountPath: /prometheus/
      volumes:
        - name: prometheus-config-volume
          configMap:
            defaultMode: 420
            name: prom-conf


        - name: prometheus-storage-volume
          emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
  name: prometheus-service
spec:
  ports:
    - port: 9090
      protocol: TCP
  selector:
    app: prometheus-server

Prometheus清单文件很简单,只是拥有集群角色和集群角色绑定的Prometheus工作负载。别忘记使清单文件生效:

$ kubectl apply -f prometheus.yaml

一旦pod启动并运行起来,不妨看看它还在正常运行:

$ kubectl port-forward svc/prometheus-service 9090

现在访问http://localhost:9090,您应该会看到Prometheus的界面。

部署Keda

我们现在可以部署KEDA operator了。KEDA提供了多种方式来部署operator,但现在我们将使用k8s清单文件。

$ kubectl apply -f https://github.com/kedacore/keda/releases/download/v2.4.0/keda-2.4.0.yaml

现在命名空间keda中应该有两个pod了,您可以使用以下命令来检查它:

$ kubectl get pods -n keda

如您所见,已有两个pod启动了起来:

on 🤠 kind-kind (keda) Desktop/projects/keda-prometheus ☁️  default
🕙[ 07:35:40 ] ❯ kubectl get pods                                                         335ms
NAME                                      READY   STATUS              RESTARTS   AGE
keda-metrics-apiserver-66b8c68649-2mwf8   0/1     ContainerCreating   0          5s
keda-operator-574c6d4769-q9mlc            0/1     ContainerCreating   0          5s

metrics-apiserver将数据提供给Horizo​​ntal Pod Autoscaler(HPA),后者被deployment所使用。operator pod激活Kubernetes部署,实现向上和向下扩展。

创建应用程序(可选)

应用程序是一个简单的go应用程序,您访问它时,它增加指标http_requests。这一节内容是可选的,因为您也可以随意使用我的docker镜像。

在文件夹中执行以下操作:

go mod init github.com/djamaile/keda-demo

然后在您的main.go中,可以输入以下代码:

package main


import (
        "fmt"
        "log"
        "net/http"


        "github.com/prometheus/client_golang/prometheus"
        "github.com/prometheus/client_golang/prometheus/promhttp"
)


type Labels map[string]string


var (
        httpRequestsCounter = prometheus.NewCounter(prometheus.CounterOpts{
               Name: "http_requests",
               Help: "number of http requests",
        })
)


func init() {
        // Metrics have to be registered to be exposed:
        prometheus.MustRegister(httpRequestsCounter)
}


func main() {
        http.Handle("/metrics", promhttp.Handler())
        http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
               defer httpRequestsCounter.Inc()
               fmt.Fprintf(w, "Hello, you've requested: %s\n", r.URL.Path)
        })
        log.Fatal(http.ListenAndServe(":8080", nil))
}

现在使用以下命令构建go应用程序:

$ go mod tidy

然后让我们为它制作一个简单的Dockerfile:

FROM golang as build-stage

COPY go.mod /
COPY go.sum /
COPY main.go /
RUN cd / && CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o go-prom-app

FROM alpine
COPY --from=build-stage /go-prom-app /
EXPOSE 8080
CMD ["/go-prom-app"]

现在就剩下构建和推送镜像了:

$ docker build -t <your_username>/keda .
$ docker push <your_username>/keda

运行应用程序

如果您没有Docker帐户或不想使用它,也没关系。您可以使用我的docker镜像!不妨让我们的go应用程序在集群中运行,为此我们需要一些k8s清单文件。别担心,因为我早已编写好:

go-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-prom-app
  namespace: keda-demo
spec:
  selector:
    matchLabels:
      app: go-prom-app
  template:
    metadata:
      labels:
        app: go-prom-app
    spec:
      containers:
        - name: go-prom-app
          image: djam97/keda
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: go-prom-app-service
  namespace: keda-demo
  labels:
    run: go-prom-app-service
spec:
  ports:
    - port: 8080
      protocol: TCP
  selector:
    app: go-prom-app

如果您愿意,可以将镜像名称换成您自己的镜像。不妨使清单文件生效:

$ kubectl apply -f go-deployment.yaml

如果pod已启动,验证它是否在正常工作

$ kubectl port-forward svc/go-prom-app-service 8080

如果您访问http://localhost:8080,应该会看到Hello, you’ve requested: /。

扩展应用程序

我们已有了go应用程序,可以编写一个清单文件来扩展该应用程序。Keda提供了可以扩展我们应用程序的许多触发器,当然我们将使用Prometheus触发器。

在一个名为scaled-object.yaml的新文件中,添加以下内容:

apiVersion: keda.sh/v1alpha1
# Custom CRD provisioned by the Keda operator
kind: ScaledObject
metadata:
  name: prometheus-scaledobject
spec:
  scaleTargetRef:
    # target our deployment
    name: go-prom-app
  # Interval to when to query Prometheus
  pollingInterval: 15
  # The period to wait after the last trigger reported active
  # before scaling the deployment back to 1
  cooldownPeriod: 30
  # min replicas keda will scale to
  # if you have an app that has an dependency on pubsub
  # this would be a good use case to set it to zero
  # why keep your app running if your topic has no messages?
  minReplicaCount: 1
  # max replicas keda will scale to
  maxReplicaCount: 20
  advanced:
    # HPA config
    # Read about it here: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/
    horizontalPodAutoscalerConfig:
      behavior:
        scaleDown:
          stabilizationWindowSeconds: 30
          policies:
            - type: Percent
              value: 50
              periodSeconds: 30
        scaleUp:
          stabilizationWindowSeconds: 0
          policies:
            - type: Percent
              value: 50
              periodSeconds: 10
  triggers:
    - type: prometheus
      metadata:
        # address where keda can reach our prometheus on
        serverAddress: http://prometheus-service.keda-demo.svc.cluster.local:9090
        # metric on what we want to scale
        metricName: http_requests_total
        # if treshold is reached then Keda will scale our deployment
        threshold: "100"
        query: sum(rate(http_requests[1m]))

阅读yaml清单文件及其注释,以了解发生的情况。还有一个重要的注意事项在advanced.horizo​​ntalPodAutoscalerConfig.scaleUp.policies中;您可以看到我指定了50%,这意味着我们的pod将按其当前pod数量的50%进行扩展。1 -> 2 -> 3 -> 5 -> 8 -> 12 -> 18 -> 20,扩展到20个Pod就停止,因为这是我们指定的限制。

使我们的清单文件生效:

$ kubectl apply -f scaled-object.yaml

这将在您的命名空间中配置一个HPA,您可以使用以下命令进行检查:

$ kubectl get hpa

但由于这是自定义CRD,您还可以使用kubectl来查询该自定义CRD:

$ kubectl get scaledobject.keda.sh/prometheus-scaledobject

您应该看到prometheus-scaledobject已准备好,所以不妨扩展我们的应用程序!记住,我们的应用程序根据指标http_requests_total进行扩展,我们的阈值仅为100,因此我们应该能够达到该阈值。为此,我们可以使用一个名为hey的简单工具。

运行应用程序:

$ kubectl port-forward svc/go-prom-app-service 8080

在另一个终端中,观察pod:

$ kubectl get pods -w -n keda-demo

对应用程序施加负载(连续执行此操作,直至有20个Pod):

$ hey -n 10000 -m GET http://localhost:8080

可能一分钟后应用程序才真正开始扩展。一段时间后,应该有20个pod启动并运行!现在不妨看看向下扩展即缩减过程。停止对应用程序施加负载,观察pod。这个过程应该是从20 -> 10 -> 5 -> 2 -> 1。这基本上就是KEDA的工作方式!

如果您喜欢KEDA,记得查看说明文档,以了解更多示例以及提供的不同类型的触发器。自动扩展愉快!

文章来源:https://hackernoon.com/how-to-use-keda-and-prometheus-to-scale-your-kubernetes-workloads

K8S中文社区微信公众号

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址