共计 6340 个字符,预计需要花费 16 分钟才能阅读完成。
KEDA 可以对事件驱动的 Kubernetes 工作负载进行细粒度的自动缩放(包括从零到零的自动缩放)。KEDA 充当 Kubernetes Metrics 服务器,允许用户使用专用的 Kubernetes 自定义资源定义来定义自动缩放规则。
KEDA 可以在云和边缘上运行,可以与 Kubernetes 组件(例如 Horizontal Pod Autoscaler)进行本地集成,并且没有外部依赖性。
工作原理
KEDA 在 Kubernetes 中扮演着两个关键角色。首先,它充当代理来激活和停用部署,以在无事件的情况下从零扩展到零。其次,它充当 Kubernetes 指标服务器,将丰富的事件数据(例如队列长度或流滞后)暴露给水平 Pod 自动缩放器以推动横向扩展。然后由部署决定是否直接从源中使用事件。这样可以保留丰富的事件集成,并使完成或放弃队列消息之类的手势可以立即使用。
Event sources and scalers
KEDA 有许多“scalers”,它们既可以检测是否应激活或停用部署,也可以提供特定事件源的自定义指标。今天,对以下内容提供了缩放器支持:
- AWS CloudWatch
- AWS Simple Queue Service
- Azure Event Hub†
- Azure Service Bus Queues and Topics
- Azure Storage Queues
- GCP PubSub
- Kafka
- Liiklus
- Prometheus
- RabbitMQ
- Redis Lists
当然其他事件源正在增加中,如下:
规划中
- Azure IoT Hub#214
- Azure Storage Blobs#154
- Azure Cosmos DB#232
- Azure Monitor
- Azure Durable Functions
待规划
- AWS Kinesis
- Kubernetes Events
- MongoDB
- CockroachDB
- MQTT
ScaledObject 自定义资源定义
为了使部署与事件源同步,需要部署 ScaledObject 自定义资源。ScaledObjects 包含有关要扩展的部署的信息,事件源的元数据(例如,连接字符串密钥,队列名称),轮询间隔和冷却时间。ScaledObject 将产生相应的自动扩展资源(HPA 定义)以扩展部署。删除 ScaledObjects 时,将清除相应的 HPA 定义。
例如:
apiVersion: keda.k8s.io/v1alpha1
kind: ScaledObject
metadata:
name: kafka-scaledobject
namespace: default
labels:
deploymentName: azure-functions-deployment
spec:
scaleTargetRef:
deploymentName: azure-functions-deployment
pollingInterval: 30
triggers:
- type: kafka
metadata:
# Required
brokerList: localhost:9092
consumerGroup: my-group # Make sure that this consumer group name is the same one as the one that is consuming topics
topic: test-topic
lagThreshold: "50"
部署
可以使用 helm 部署,也可以 yaml 部署。利用 yaml 部署可以执行如下操作:
kubectl apply -f KedaScaleController.yaml
KedaScaleController.yaml 如下:
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: scaledobjects.keda.k8s.io
spec:
group: keda.k8s.io
version: v1alpha1
names:
kind: ScaledObject
singular: scaledobject
plural: scaledobjects
shortNames:
- sco
categories:
- keda
scope: Namespaced
additionalPrinterColumns:
- name: Deployment
type: string
JSONPath: .spec.scaleTargetRef.deploymentName
- name: Triggers
type: string
JSONPath: .spec.triggers[*].type
- name: Age
type: date
JSONPath: .metadata.creationTimestamp
validation:
openAPIV3Schema:
properties:
spec:
required: [triggers]
type: object
properties:
scaleType:
type: string
enum: [deployment, job]
pollingInterval:
type: integer
cooldownPeriod:
type: integer
minReplicaCount:
type: integer
maxReplicaCount:
type: integer
scaleTargetRef:
required: [deploymentName]
type: object
properties:
deploymentName:
type: string
containerName:
type: string
triggers:
type: array
items:
type: object
required: [type, metadata]
properties:
type:
type: string
authenticationRef:
type: object
properties:
name:
type: string
metadata:
type: object
additionalProperties:
type: string
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: triggerauthentications.keda.k8s.io
spec:
group: keda.k8s.io
version: v1alpha1
names:
kind: TriggerAuthentication
singular: triggerauthentication
plural: triggerauthentications
shortNames:
- ta
- triggerauth
categories:
- keda
scope: Namespaced
---
apiVersion: v1
kind: Namespace
metadata:
name: keda
---
kind: ServiceAccount
apiVersion: v1
metadata:
name: keda-operator
namespace: keda
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: keda-operator-service-account-role-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: keda-operator
namespace: keda
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: keda:system:auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: keda-operator
namespace: keda
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: keda-auth-reader
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
name: keda-operator
namespace: keda
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: keda-operator
name: keda-operator
namespace: keda
spec:
replicas: 1
selector:
matchLabels:
app: keda-operator
template:
metadata:
labels:
app: keda-operator
name: keda-operator
spec:
serviceAccountName: keda-operator
containers:
- name: keda-operator
image: kedacore/keda:latest
args:
- /adapter
- --secure-port=6443
- --logtostderr=true
- --v=2
ports:
- containerPort: 6443
name: https
- containerPort: 8080
name: http
volumeMounts:
- mountPath: /tmp
name: temp-vol
volumes:
- name: temp-vol
emptyDir: {}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: custom-metrics-resource-reader
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: custom-metrics-resource-reader
subjects:
- kind: ServiceAccount
name: keda-operator
namespace: keda
---
apiVersion: v1
kind: Service
metadata:
name: keda-operator
namespace: keda
spec:
ports:
- name: https
port: 443
targetPort: 6443
- name: http
port: 80
targetPort: 8080
selector:
app: keda-operator
---
apiVersion: apiregistration.k8s.io/v1beta1
kind: APIService
metadata:
name: v1beta1.external.metrics.k8s.io
spec:
service:
name: keda-operator
namespace: keda
group: external.metrics.k8s.io
version: v1beta1
insecureSkipTLSVerify: true
groupPriorityMinimum: 100
versionPriority: 100
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: custom-metrics-resource-reader
rules:
- apiGroups:
- ""
resources:
- namespaces
- pods
- services
- external
verbs:
- get
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: keda-hpa-controller-custom-metrics
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: horizontal-pod-autoscaler
namespace: kube-system
代码架构解读
关键代码在 pkg 文件夹下,如下图:
- adapter 和 provider 主要实现了一个 custom metrics 的 adapter,基本规范参照 github.com/kubernetes-incubator/custom-metrics-apiserver。如果是外部 metrics,那么主要是实现 GetExternalMetric 和 ListAllExternalMetrics 两个方法即可。
- apis 和 client 均为 k8s 架手架生成的。apis 主要存放 crd –ScaledObject 对象的定义,而 client 为 keda client 和 informer 等。通过 crd 扩展过 k8s 的应该对此比较熟悉。
- controller 即为一个 k8s 针对 ScaledObject 的控制器。实际 k8s 的开发中,crd 创建了之后,必须编写对应的 controller,针对 crd 的 add,update,delete 三种事件作出实际操作。
- signals 则比较简单,封装了 context.Context。
- kubernetes 比较简单,总体思路就是根据 config,创建 kdea client 和 kube client,供 controller 使用。
- handler 比较关键,基本上 controller 中的 sync 逻辑和 metrics-server 提供 metrics 的接口 均在这里实现的。
- scalers。就是不同事件源的实现。那么如果我们想增加一种自己的事件源,在这里实现即可。
举例说明一下,当使用客户端 –kubectl 或是 client-go 部署一个针对 deployment A 的 ScaledObject crd。想根据 kafaka 的消息积压数目进行 hpa。那么 controller 会监听到创建了 crd,将会对新增动作做出操作。具体就是,根据 crd 的具体内容创建一个 hpa 对象,crd 的 spec 内容会转换成 hpa。此时官方 k8s 的 hpa 就会通过 scalers 中的 kafka scaler 读取 kafka 指定 topic 的消息数目,然后最终由 hpa controller 做出是否扩缩的决定。
结论
KEDA 目前处于 Experimental Phase 阶段。微软和红帽希望社区共同参与。
KEDA 并没有实现了自己的 HPA,其实最终起作用的依旧是社区中的 HPA,他只是根据 crd 内容生成了 HPA 对象,只不过这个 metrics 是外部 metrics。KEDA 主要是集成了各种事件源。