ACK支持在控制台上安装ack-keda,提供事件驱动弹性能力。本文介绍事件驱动弹性的概念、原理及如何使用事件驱动弹性。

事件驱动弹性概述

Kubernetes中,容器水平伸缩器HPA(Horizontal Pod Autoscaler)是最常用的应用弹性方案。容器水平伸缩的核心是基于资源利用率与预设的阈值水位之间的关系,来确认伸缩的计划。容器水平伸缩的方式具有使用简单、资源指标丰富等特点,但是它对于需要即时弹性的场景,尤其是对基于事件源进行离线作业支撑不足。ACK提供了ack-keda来提供事件驱动弹性能力,事件驱动弹性适用于音视频离线转码、事件驱动作业、流式数据处理等场景。

事件驱动弹性的原理

ACK通过增强版本的ack-keda来提供事件驱动弹性能力,下图是ack-keda的基本原理。 原理
ack-keda会从事件源中进行数据的周期性消费。当消息出现堆积,即可秒级触发一个批次的离线任务伸缩。下一个周期到来时,会异步进行下一个批次的作业伸缩。ack-keda具有以下特性:
  • 丰富的事件源支持

    ack-keda支持例如Kafka、MySQL、PostgreSQL、Rabbitmq、MongoDB等数据源。更多数据源,请参见RabbitMQ Queue

  • 离线任务的并发控制

    对于大规模的离线作业而言,底层管控的稳定性会面临比较大的挑战,需要提供资源、额度、API请求的整体控制。ack-keda提供了单批次、总批次的任务并发控制,保障系统的稳定性。

  • 结束任务后自动清理元数据

    大规模离线作业执行完毕后,会留存大量的元数据信息。元数据信息的堆积会造成APIServer的稳定性下降,造成集群的性能下降、稳定性不足,甚至可能影响其他的业务。ack-keda会在任务执行结束后自动清理元数据,降低元数据的量级。

案例说明

在本案例中,准备了一个简单的转码作业。当有一个新任务到来的时候会向MongoDB插入一条类似下面的数据{"type":"mp4","state":"waiting","createTimeStamp":"1610332940","fileName":"World and peace","endTimeStamp":"","uuid":"1fae72ff-3239-42f5-af97-04711d8007e8"}。此时,容器服务的事件驱动控制器会从数据库中查询到状态为"state":"waiting"的任务,弹出与任务数目匹配的Job Pod来承载转码任务,完成转码业务并将数据中的state字段从之前的waiting修改成finished。同时Job完成后,将自动清理元数据,降低元数据对APIServer带来的压力,减轻开发者的负担。

步骤一:部署ack-keda

  1. 登录容器服务管理控制台
  2. 在控制台左侧导航栏中,选择市场 > 应用目录
  3. 应用目录页面右上角搜索框中搜索ack-keda,找到然后单击ack-keda。
  4. 应用目录 - ack-keda页面创建面板选择目标集群,单击创建
    在控制台左侧导航栏单击 集群,在 集群列表页面中,单击目标集群名称或者目标集群右侧 操作列下的 详情。在集群管理页面选择 工作负载 > 无状态。在 无状态页签左上角选择 命名空间为kube-system,可以看到创建的ack-keda。

步骤二:部署基于mongoDB事件源驱动弹性示例

  1. 部署Mongo DB。
    如果您已有MongoDB服务,可跳过此步骤。
    注意 此数据库只用于测试,请勿用于生产环境。
    1. 创建mongoDB.yaml
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: mongodb
      spec:
        replicas: 1
        selector:
          matchLabels:
            name: mongodb
        template:
          metadata:
            labels:
              name: mongodb
          spec:
            containers:
            - name: mongodb
              image: mongo:4.2.1
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 27017
                name: mongodb
                protocol: TCP
      ---
      kind: Service
      apiVersion: v1
      metadata:
        name: mongodb-svc
      spec:
        type: ClusterIP
        ports:
        - name: mongodb
          port: 27017
          targetPort: 27017
          protocol: TCP
        selector:
          name: mongodb
    2. 部署Mongo DB到集群的mongodb命名空间中。
       kubectl apply -f mongoDB.yaml -n mongodb
  2. 登录数据库,注册用户。
    1. 新建用户。
      //新建用户
      kubectl exec -n mongodb mongodb-xxxxx -- mongo --eval 'db.createUser({ user:"test_user",pwd:"test_password",roles:[{ role:"readWrite", db: "test"}]})'
    2. 登录数据库。
      //登录认证
      kubectl exec -n mongodb mongodb-xxxxx -- mongo --eval  'db.auth("test_user","test_password")'
    3. 创建Collection。
      //创建Collection
      kubectl exec -n mongodb mongodb-xxxxx -- mongo --eval  'db.createCollection("test_collection")'
  3. 部署TriggerAuthentication和ScaledJob。
    在ack-keda中对于事件源的登录认证需要使用TriggerAuthentication。例如对于MongoDB事件源,TriggerAuthentication中的 secretTargetRef字段会将指定Secret中的连接方式读取到ack-keda中,完成对MongoDB的登录认证。
    1. 创建auth.yaml
      apiVersion: keda.sh/v1alpha1
      kind: TriggerAuthentication
      metadata:
        name: mongodb-trigger
      spec:
        secretTargetRef:
          - parameter: connectionString
            name: mongodb-secret
            key: connect
      ---
      apiVersion: v1
      kind: Secret
      metadata:
        name: mongodb-secret
      type: Opaque
      data:
        connect: bW9uZ29kYjovL3Rlc3RfdXNlcjp0ZXN0X3Bhc3N3b3JkQG1vbmdvZGItc3ZjLm1vbmdvZGIuc3ZjLmNsdXN0ZXIubG9jYWw6MjcwMTcvdGVzdA==
    2. 部署TriggerAuthentication到集群的mongodb-test命名空间中。
      kubectl apply -f auth.yaml -n mongodb-test
  4. 部署ScaledJob。
    ScaledJob主要用于配置Job模板以及指定查询的数据库及查询表达式等。以下示例配置的是从test数据库中的test_collection中,查询满足 {"type":"mp4","state":"waiting"}的待转码数据。
    1. 创建job.yaml
      apiVersion: keda.sh/v1alpha1
      kind: ScaledJob
      metadata:
        name: mongodb-job
      spec:
        jobTargetRef:
          // Job模板配置
          template:
            spec:
              containers:
                - name: mongo-update
                  image: registry.cn-hangzhou.aliyuncs.com/carsnow/mongo-update:v6
                  args:
                    - --connectStr=mongodb://test_user:test_password@mongodb-svc.mongodb.svc.cluster.local:27017/test
                    - --dataBase=test
                    - --collection=test_collection
                  imagePullPolicy: IfNotPresent
              restartPolicy: Never
          backoffLimit: 1
        pollingInterval: 15
        maxReplicaCount: 5
        successfulJobsHistoryLimit: 0
        failedJobsHistoryLimit: 10
        triggers:
          - type: mongo
            metadata:
              dbName: test                               //要查询的数据库
              collection: test_collection                //要查询的collection
              query: '{"type":"mp4","state":"waiting"}'  //会对查询转码类型为mp4且状态是waiting的数据拉起job进行处理
              queryValue: "1"
            authenticationRef:
              name: mongodb-trigger

      query:配置数据条目。当ack-keda查询到Mongo数据库中有满足该条件的数据条目时,将启动Job资源。

    2. 部署ScaledJob到集群的mongodb-test命名空间中。
      kubectl apply -f scaledJob.yaml -n mongodb-test
  5. 插入5条待转码数据。
    //插入5条待转码数据
    kubectl exec -n mongodb mongodb-xxxxx -- mongo --eval 'db.test_collection.insert([
      {"type":"mp4","state":"waiting","createTimeStamp":"1610352740","fileName":"My Love","endTimeStamp":"","uuid":"1gae72ff-3239-42f5-af97-04711d8007e8"},
      {"type":"mp4","state":"waiting","createTimeStamp":"1610350740","fileName":"Harker","endTimeStamp":"","uuid":"1gae72ff-3239-42f5-af97-04711d8007e8"},
      {"type":"mp4","state":"waiting","createTimeStamp":"1610152940","fileName":"The World","endTimeStamp":"","uuid":"1gae72ff-3239-42f5-af97-04711d87767e8"},
      {"type":"mp4","state":"waiting","createTimeStamp":"1610390740","fileName":"Mother","endTimeStamp":"","uuid":"1gae72ff-3239-42f5-af97-04799d8007e8"},
      {"type":"mp4","state":"waiting","createTimeStamp":"1610344740","fileName":"Jagger","endTimeStamp":"","uuid":"1gae72ff-3239-42f5-af97-04711d80099e8"},
      ])'

步骤三:验证事件驱动弹性

执行以下命令,查看Job动态。
//watch job
watch -n 1 kubectl get job -n mongodb-test
Job
可以看到成功扩展出5个Job。此时再登录数据库,观察转码业务状态,可以看到数据状态已经从 waiting变成了 finished数据库