使用KEDA自动扩展Kubernetes微服务


最近,我一直在研究部署到Kubernetes上的应用程序的自动缩放选项。有很多新兴的选择。我决定试一试KEDA。KEDA代表Kubernetes事件驱动的自动缩放,而这正是它的功能。

KEDA简介 KEDA是一种可以部署到Kubernetes集群中的工具,它将基于外部事件或触发器自动扩展Pod。事件由一组缩放器收集,这些缩放器与一系列应用程序集成在一起,例如:

  • ActiveMQ Artemis
  • Apache Kafka
  • Amazon SQS
  • Azure Service Bus
  • RabbitMQ Queue
  • and about 20 others

要使用KEDA实现自动缩放,首先需要配置一个Scaler

在公制去超过某一阈值,科达可以扩展了部署自动(所谓的“缩放部署”),或创建一个作业(所谓的“缩放作业”)。当指标下降时,它还可以再次缩减部署,甚至缩减为零。它通过使用Kubernetes中的Horizo​​ntal Pod Autoscaler(HPA)来做到这一点。

由于KEDA在您的集群中作为单独的组件运行,并且使用Kubernetes HPA,因此它对于您的应用程序来说是非侵入性的,因此几乎不需要对自己扩展的应用程序进行任何更改。

keda-arch.png

Kubernetes集群上的KEDA体系结构

KEDA有许多潜在的用例。也许最明显的一个是在队列中接收到消息时扩展应用程序。

许多集成应用程序使用消息传递作为接收事件的一种方式。因此,如果我们可以根据接收到的事件数量来扩展和缩减应用程序,则有可能在不需要它们时释放资源,并在需要时提供更大的容量。

如果我们将诸如KEDA之类的东西与集群级自动缩放结合起来,那就更是如此。如果我们可以根据应用程序的需求自行扩展群集的节点,则可以帮助节省成本。

许多KEDA定标器都基于消息传递,这是一种常见的集成模式。当我想到消息传递和集成时,我立即想到Apache Camel和Apache ActiveMQ,并想探索是否可以使用KEDA来扩展使用这些流行项目的简单微服务。因此,让我们看看KEDA可以做什么。

Demo-带有Apache Camel和ActiveMQ Artemis的KEDA 我们将Java微服务部署到Kubernetes上,该服务使用队列中的消息。该应用程序使用Apache Camel作为集成框架,并使用Quarkus作为运行时。

我们还将部署ActiveMQ Artemis消息代理,并使用KEDA的Artemis缩放器来监视队列中的消息并放大或缩小应用程序。

keda-example-app.png

KEDA规模的Camel应用程序的体系结构

创建演示应用程序 我已经创建了示例Camel应用程序,该应用程序使用Quarkus作为运行时。我已将容器映像发布到Docker Hub,并在以下进一步的步骤中使用它。

我决定使用Quarkus,因为它具有超快的启动时间,比Spring Boot快得多。当我们对事件做出反应时,我们希望能够快速启动,而不是等待太长时间才能启动该应用程序。

为了创建应用程序,我使用了Quarkus应用程序生成器。

Quarkus使用扩展进行配置,因此我需要找到一个扩展来帮助我创建一个连接工厂以与ActiveMQ Artemis进行通信。为此,我们可以使用Quarkus的Qpid JMS扩展,它包装了Quarkus应用程序的Apache Qpid JMS客户端。这使我可以使用开放式AMQP 1.0协议与ActiveMQ Artemis进行交谈。

Qpid JMS扩展在找到某些配置属性时会创建到ActiveMQ的连接工厂。你只需要设置的属性quarkus.qpid-jms.urlquarkus.qpid-jms.usernamequarkus.qpid-jms.password。扩展程序将自动执行其余操作,如自述文件中所述:

keda-amqphub-quarkus.png

该表显示了Qpid JMS Quarkus扩展的配置属性

然后,我使用Camel的JMS组件来使用消息。这将检测并使用扩展创建的相同连接工厂。骆驼路线如下所示:

from("jms:queue:ALEX.BIRD")
    .log("Honk honk! I just received a message: ${body}");

最后,我将应用程序编译为本地二进制文件,而不是JAR。这将帮助它非常快速地启动。您需要GraalVM才能做到这一点。切换到您的GraalVM(例如,使用Sdkman),然后:

./mvnw package -Pnative

或者,如果您不想安装GraalVM,则可以告诉Quarkus使用内置了GraalVM的Docker容器来构建本机映像。当然,您需要运行Docker才能执行此操作:

./mvnw package -Pnative -Dquarkus.native.container-build=true

它的输出是本机二进制应用程序,它的启动速度应比典型的基于JVM的应用程序快。好的。当我们收到消息时,有利于快速扩展!

最后,我使用Docker将本机二进制文件构建到容器映像中,并将其推送到注册表中。在这种情况下,使用Docker Hub。Quarkus快速入门提供了一个Dockerfile来进行构建。然后最后一步是docker push:

docker build -f src/main/docker/Dockerfile.native -t monodot/camel-amqp-quarkus .

docker push monodot/camel-amqp-quarkus

现在,我们准备部署应用程序,部署KEDA并将其配置为自动缩放应用程序。

部署KEDA和演示应用程序

  1. 首先,在您的Kubernetes集群上安装KEDA并为演示创建一些名称空间。

要部署KEDA,您可以按照KEDA网站上的最新说明进行操作,而我使用Helm选项安装了它:

$ helm repo add kedacore https://kedacore.github.io/charts
$ helm repo update
$ kubectl create namespace keda
$ helm install keda kedacore/keda --namespace keda
$ kubectl create namespace keda-demo
  1. 现在,我们需要部署ActiveMQ Artemis消息代理。

这是一些在Kubernetes中创建Deployment,Service和ConfigMap的YAML。它在Docker Hub上使用Artemis的vromero / activemq-artemis社区映像,并公开其控制台和AMQP端口。我通过添加一个ConfigMap对其进行自定义:

将代理的内部名称更改为静态名称: keda-demo-broker 定义一个称为的队列ALEX.BIRD。如果我们不这样做,那么将在使用者连接到该队列时创建该队列,但是当该使用者按比例缩小时将再次删除该队列,因此KEDA将无法再正确获取该指标。因此,我们明确定义了队列。 YAML:

$ kubectl apply -f - <<API
apiVersion: v1
kind: List
items:
- apiVersion: v1
  kind: Service
  metadata:
    creationTimestamp: null
    name: artemis
    namespace: keda-demo
  spec:
    ports:
    - port: 61616
      protocol: TCP
      targetPort: 61616
      name: amqp
    - port: 8161
      protocol: TCP
      targetPort: 8161
      name: console
    selector:
      run: artemis
  status:
    loadBalancer: {}
- apiVersion: apps/v1
  kind: Deployment
  metadata:
    creationTimestamp: null
    labels:
      run: artemis
    name: artemis
    namespace: keda-demo
  spec:
    replicas: 1
    selector:
      matchLabels:
        run: artemis
    strategy: {}
    template:
      metadata:
        creationTimestamp: null
        labels:
          run: artemis
      spec:
        containers:
        - env:
          - name: ARTEMIS_USERNAME
            value: quarkus
          - name: ARTEMIS_PASSWORD
            value: quarkus
          image: vromero/activemq-artemis:2.11.0-alpine
          name: artemis
          ports:
          - containerPort: 61616
          - containerPort: 8161
          volumeMounts:
          - name: config-volume
            mountPath: /var/lib/artemis/etc-override
        volumes:
          - name: config-volume
            configMap:
              name: artemis
- apiVersion: v1
  kind: ConfigMap
  metadata:
    name: artemis
    namespace: keda-demo
  data:
    broker-0.xml: |
      <?xml version="1.0" encoding="UTF-8" standalone="no"?>
      <configuration xmlns="urn:activemq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">
        <core xmlns="urn:activemq:core" xsi:schemaLocation="urn:activemq:core ">
          <name>keda-demo-broker</name>
          <addresses>
            <address name="DLQ">
              <anycast>
                <queue name="DLQ"/>
              </anycast>
            </address>
            <address name="ExpiryQueue">
              <anycast>
                <queue name="ExpiryQueue"/>
              </anycast>
            </address>
            <address name="ALEX.BIRD">
              <anycast>
                <queue name="ALEX.BIRD"/>
              </anycast>
            </address>
          </addresses>
        </core>
      </configuration>
API
  1. 接下来,我们部署演示Camel应用程序并添加一些配置。

因此,我们需要创建一个部署。我正在从Docker Hub部署演示图像monodot / camel-amqp-quarkus。您可以部署我的映像,也可以根据需要构建和部署映像。

我们使用环境变量QUARKUS_QPID_JMS_*来设置ActiveMQ Artemis代理的URL,用户名和密码。这些将覆盖quarkus.qpid-jms.*我的应用程序的属性文件中的属性:

$ kubectl apply -f - <<API
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    run: camel-amqp-quarkus
  name: camel-amqp-quarkus
  namespace: keda-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      run: camel-amqp-quarkus
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        run: camel-amqp-quarkus
    spec:
      containers:
      - env:
        - name: QUARKUS_QPID_JMS_URL
          value: amqp://artemis:61616
        - name: QUARKUS_QPID_JMS_USERNAME
          value: quarkus
        - name: QUARKUS_QPID_JMS_PASSWORD
          value: quarkus

        image: monodot/camel-amqp-quarkus:latest
        name: camel-amqp-quarkus
        resources: {}
API

4,

我们通过创建ScaledObject来做到这一点。这告诉KEDA扩展哪个部署,以及何时扩展。所述触发器部分定义要使用的定标器。在这种情况下,它是ActiveMQ Artemis缩放器,它使用Artemis API查询地址(队列)上的消息:

$ kubectl apply -f - <<API
apiVersion: keda.k8s.io/v1alpha1
kind: ScaledObject
metadata:
  name: camel-amqp-quarkus-scaler
  namespace: keda-demo
spec:
  scaleTargetRef:
    deploymentName: camel-amqp-quarkus
  pollingInterval: 30
  cooldownPeriod:  30  # Default: 300 seconds
  minReplicaCount: 0
  maxReplicaCount: 2
  triggers:
  - type: artemis-queue
    metadata:
      managementEndpoint: "artemis.keda-demo:8161"
      brokerName: "keda-demo-broker"
      username: 'QUARKUS_QPID_JMS_USERNAME'
      password: 'QUARKUS_QPID_JMS_PASSWORD'
      queueName: "ALEX.BIRD"
      brokerAddress: "ALEX.BIRD"
      queueLength: '10'
API

顺便说一句,为了获得使用Artemis API的凭据,KEDA将查找在Camel应用程序的Deployment对象上设置的任何环境变量。这意味着您不必两次指定凭据。所以我在这里用QUARKUS_QPID_JMS_USERNAMEPASSWORD

5,

您可以通过两种不同的方式执行此操作:使用Artemis Web控制台指向并单击,或者使用Jolokia REST API。

无论哪种方式,我们都需要能够访问artemis Kubernetes服务,该服务不在Kubernetes集群外部公开。您可以通过在OpenShift中设置一个Ingress或Route来公开它,但是我只是使用kubectl的端口转发功能。这很简单。这使我可以在本地主机端口8161上访问ActiveMQ Web控制台和API :

$ kubectl port-forward -n keda-demo svc/artemis 8161:8161

让该程序在后台运行。

现在,在另一个终端中,使用curl击打Artemis Jolokia API

这部分需要冗长的API调用,因此我在此处添加了一些换行符以使其更易于阅读。这使用ActiveMQ的Jolokia REST API将消息放入Artemis队列中:

curl -X POST --data "{\"type\":\"exec\",\
\"mbean\":\
\"org.apache.activemq.artemis:broker=\\\"keda-demo-broker\\\",component=addresses,address=\\\"ALEX.BIRD\\\",subcomponent=queues,routing-type=\\\"anycast\\\",queue=\\\"ALEX.BIRD\\\"\",\
\"operation\":\
\"sendMessage(java.util.Map,int,java.lang.String,boolean,java.lang.String,java.lang.String)\",\
\"arguments\":\
[null,3,\"HELLO ALEX\",false,\"quarkus\",\"quarkus\"]}" http://quarkus:quarkus@localhost:8161/console/jolokia/

(如果对此有任何疑问,请使用Artemis Web控制台发送消息;您可以在http:// localhost:8161 / console上找到它)

  1. 将消息放入队列后,您应该看到演示应用程序pod正在启动并使用消息。在左侧的屏幕截图中,以前没有运行Pod,但是在发送消息时,KEDA放大了该应用程序(以黄色显示):

keda-scaled-dashboard.jpg

KEDA注意到提示消息后便放大了演示应用程序(camel-amqp-quarkus)

毕竟,消息已被消耗,队列上将没有消息。KEDA等待冷却时间(在本演示中,我以30秒为例),然后将部署缩减为零,因此没有Pod在运行。

如果您使用kubectl get pods监视pod,您也可以看到此行为:

$ kubectl get pods -n keda-demo -w
NAME                       READY   STATUS    RESTARTS   AGE
artemis-7d955bf44b-892k4   1/1     Running   0          84s
camel-amqp-quarkus-748c5f9c77-nrf5k   0/1     Pending   0          0s
camel-amqp-quarkus-748c5f9c77-nrf5k   0/1     Pending   0          0s
camel-amqp-quarkus-748c5f9c77-nrf5k   0/1     ContainerCreating   0          0s
camel-amqp-quarkus-748c5f9c77-nrf5k   1/1     Running             0          3s
camel-amqp-quarkus-748c5f9c77-nrf5k   1/1     Terminating         0          30s
camel-amqp-quarkus-748c5f9c77-nrf5k   0/1     Terminating         0          32s
camel-amqp-quarkus-748c5f9c77-nrf5k   0/1     Terminating         0          43s
camel-amqp-quarkus-748c5f9c77-nrf5k   0/1     Terminating         0          43s

结论

KEDA使得基于事件扩展应用程序成为可能,这是许多产品团队可能感兴趣的事情,尤其是潜在的资源节省。


原文链接:http://codingdict.com/