Kubernetes提供了Horizontal Pod Autoscaler,它能够依据您提供的指标主动缩放资源(Deployment,ReplicationController,ReplicaSet,StatefulSet)中正本的数量。通常,所应用的度量规范是CPU /内存负载,对于大多数应用程序而言已足够。

Horizontal Pod Autoscaler的局限性在于它具备用于评估以下指标的硬编码算法:

desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]

如果您在缩放方面须要更大的灵活性,除了此算法之外,Horizontal Pod Autoscaler不能满足您的需要,则须要编写本人的缩放逻辑。

对于游戏服务器,按CPU负载或内存使用量进行扩大没有意义,即便您施行了自定义指标,缩放算法也不会以正当的形式进行缩放。游戏服务器应依据服务器上的玩家数量或心愿退出服务器的玩家数量进行伸缩。

Custom Pod Autoscaler (CPA)是 自定义Pod主动伸缩器框架的一部分。其容许更轻松,更快地开发Kubernetes主动伸缩器。通过应用此我的项目,能够扩大提供的Docker根本镜像并插入本人的逻辑,从而创立Custom Pod Autoscaler。

特点

  • 反对任何语言,环境和框架;惟一的要求是它必须可由Shell命令或HTTP申请启动。
  • 反对Horizontal Pod Autoscaler的所有配置选项(冷却窗口,同步周期等)
  • 容许疾速轻松地进行原型开发。
  • 摘除所有简单的Kubernetes API交互。
  • 公开HTTP REST API以与更宽泛的零碎/手动干涉集成。
  • 能够应用无限的Kubernetes API或生命周期常识编写主动伸缩器。
  • 在构建时或部署时进行配置。
  • 容许缩放到零或从零开始。
  • 能够在没有主节点拜访权限的状况下进行配置,能够在EKS或GKE等托管提供程序上进行配置。

工作原理

Custom Pod Autoscaler 具备一个根本程序,该程序处理与用户逻辑的交互,例如,通过应用shell命令并将数据传递到其中。开发自定义Pod主动缩放器时,您须要为两个阶段定义逻辑:

  • 指标收集-收集或生成指标;能够调用指标API,在本地运行计算并收回HTTP申请。
  • 评估指标-获取这些收集的指标,并应用它们来确定资源应具备多少个正本。

这两个逻辑都是构建Custom Pod Autoscaler所需的所有自定义逻辑,根本程序将解决所有Kubernetes API交互以扩大/获取资源。

示例

开发Custom Pod Autoscaler是一个简略而灵便的过程,它能够用您喜爱的任何一种语言实现,并且能够应用各种Docker镜像。对于本指南,咱们将构建一个简略的基于Python的主动缩放器,然而您能够采纳此处概述的原理并以任何语言实现主动缩放器,其余语言实现的示例。
在本指南中,咱们将创立一个基于Python的Kubernetes主动缩放器。主动缩放器将依据资源标签numPods来工作,并将标签中提供的值作为目标值。这只是一个示例,但心愿能够让让您明确编写自定义主动扩缩器的原理和办法。能够在 python-custom-autoscaler 中查阅残缺代码。

1:创立工程

为我的项目python-custom-autoscaler创立一个新目录。

mkdir python-custom-autoscaler

2:编写自定义Pod伸缩器的配置

咱们将为此主动缩放器设置Custom Pod Autoscaler配置,该配置将定义要运行的脚本,如何调用它们以及该脚本的超时工夫。创立一个新文件config.yaml

evaluate:  type: "shell"  timeout: 2500  shell:    entrypoint: "python"    command:      - "/evaluate.py"metric:  type: "shell"  timeout: 2500  shell:    entrypoint: "python"    command:      - "/metric.py"runMode: "per-resource"

该配置文件指定了咱们要增加的两个脚本,即度量收集器和评估器-定义应通过shell命令调用它们,并且它们应在2500毫秒(2.5秒)后超时。还指定了runMode,咱们抉择了per-resource-这意味着度量规范收集将仅针对资源运行一次,并且将向度量规范脚本提供资源信息。每个Pod的一个代替选项是,它将为资源所具备的每个Pod运行度量收集脚本,并为该脚本提供独自的Pod信息。

3: 编写指标收集

当初,咱们将创立主动缩放器的度量收集局部,该局部将简略地浏览所提供的资源形容,并从中提取numPods标签值,而后再将其输入回给评估者进行决策。

创立metric.py:

import osimport jsonimport sysdef main():    # Parse spec into a dict    spec = json.loads(sys.stdin.read())    metric(spec)def metric(spec):    # Get metadata from resource information provided    metadata = spec["resource"]["metadata"]    # Get labels from provided metdata    labels = metadata["labels"]    if "numPods" in labels:        # If numPods label exists, output the value of the numPods        # label back to the autoscaler        sys.stdout.write(labels["numPods"])    else:        # If no label numPods, output an error and fail the metric gathering        sys.stderr.write("No 'numPods' label on resource being managed")        exit(1)if __name__ == "__main__":    main() 

度量收集阶段从主动Pod伸缩器获取相干信息。在此示例中,咱们以per-resource运行-意味着仅对要治理的资源调用一次度量脚本,并将资源信息通过管道传递到该脚本中。例如,如果咱们正在治理部署,则主动缩放器将提供咱们正在治理的部署的残缺JSON形容,例如通过管道传递的值。

{  "resource": {    "kind": "Deployment",    "apiVersion": "apps/v1",    "metadata": {      "name": "hello-kubernetes",      "namespace": "default",      "labels": {        "numPods": "3"      },    },    ...  },  "runType": "scaler"}

咱们制作的脚本仅解析该JSON并提取numPods值。如果未提供numPods,则脚本将出错,并提供一条谬误音讯,主动缩放器将提取并记录该谬误音讯。如果提供了numPods,则该值将通过规范输入输入并由主动伸缩器读取,而后传递到评估阶段。

4:编写评估器

当初,咱们将创立评估器,该评估器将读取度量收集阶段提供的度量,并基于这些收集的度量来计算正本的数量-在这种状况下,它将简略地是上一步提供的度量值。如果该值不是整数,则脚本将返回谬误。

创立evaluate.py:

import jsonimport sysimport mathdef main():    # Parse provided spec into a dict    spec = json.loads(sys.stdin.read())    evaluate(spec)def evaluate(spec):    try:        value = int(spec["metrics"][0]["value"])        # Build JSON dict with targetReplicas        evaluation = {}        evaluation["targetReplicas"] = value        # Output JSON to stdout        sys.stdout.write(json.dumps(evaluation))    except ValueError as err:        # If not an integer, output error        sys.stderr.write(f"Invalid metric value: {err}")        exit(1)if __name__ == "__main__":    main()

传递到此步骤的JSON值如下所示:

{  "metrics": [    {      "resource": "hello-kubernetes",      "value": "3"    }  ],  "resource": {    "kind": "Deployment",    "apiVersion": "apps/v1",    "metadata": {      "name": "hello-kubernetes",      "namespace": "default",      "labels": {        "numPods": "3"      },    },    ...  },  "runType": "scaler"}

这只是指标值,在本例中为上一步中的5,但封装在JSON对象中,并带有其余信息,例如运行类型和部署名称。

此步骤输入的JSON值如下所示:

{  "targetReplicas": 5}

Custom Pod Autoscaler程序冀望该响应采纳此JSON序列化模式,并且targetReplicas定义为整数。

5: 编写dockerfile

咱们的Dockerfile将会非常简单,咱们将应用Python 3 docker镜像,并在其中内置Custom Pod Autoscaler二进制文件。创立一个新文件Dockerfile:

# Pull in Python build of CPAFROM custompodautoscaler/python:latest# Add config, evaluator and metric gathering Py scriptsADD config.yaml evaluate.py metric.py /

这个Dockerfile只是插入咱们的两个脚本和咱们的配置文件中。当初,咱们曾经实现了主动缩放器的创立,让咱们看看它的工作原理。

6:功能测试

首先,咱们应该通过装置Custom Pod Autoscaler Operator在集群上启用自定义主动缩放器,对于本指南,咱们应用的是v1.0.1,然而请从Custom Pod Autoscaler Operator 发行版中签出最新版本,并参阅装置指南以获取最新的装置信息。

VERSION=v1.0.1kubectl apply -f https://github.com/jthomperoo/custom-pod-autoscaler-operator/releases/download/${VERSION}/cluster.yaml

这将在整个集群范畴内装置Custom Pod Autoscaler Operator v1.0.1。

当初,咱们应该为主动伸缩器创立一个部署以进行治理,并创立一个部署YAML文件:

apiVersion: apps/v1kind: Deploymentmetadata:  name: hello-kubernetes  labels:    numPods: "3"spec:  replicas: 1  selector:    matchLabels:      app: hello-kubernetes  template:    metadata:      labels:        app: hello-kubernetes    spec:      containers:      - name: hello-kubernetes        image: paulbouwer/hello-kubernetes:1.5        ports:        - containerPort: 8080

这是咱们将应用自定义主动缩放器进行治理的部署,它最后设置为具备1个正本,但其中蕴含numPods:“3”标签,因而如果咱们的主动缩放器失常工作,它将读取该值并设置正本计数到3。

部署此利用:

kubectl apply -f deployment.yaml

当初,咱们须要为新的主动缩放器构建镜像,并切换到Minikube Docker注册表作为指标:

eval $(minikube docker-env)

接下来构建镜像:

docker build -t python-custom-autoscaler .

让咱们为主动缩放器创立YAML,创立一个新文件cpa.yaml

apiVersion: custompodautoscaler.com/v1kind: CustomPodAutoscalermetadata:  name: python-custom-autoscalerspec:  template:    spec:      containers:      - name: python-custom-autoscaler        image: python-custom-autoscaler:latest        imagePullPolicy: IfNotPresent  scaleTargetRef:    apiVersion: apps/v1    kind: Deployment    name: hello-kubernetes  config:    - name: interval      value: "10000"

该YAML概述了咱们的主动缩放器实例的名称,应用模板的主动缩放器的镜像定义,咱们应用scaleTargetRef定位要治理的资源以及一些根本的额定配置(距离设置为10000毫秒),这意味着主动缩放器将每10秒运行一次。

当初,咱们应该将主动缩放器部署到集群中:

kubectl apply -f cpa.yaml

如果咱们执行kubectl get pods,咱们应该看到曾经创立了一个运行主动缩放器的新Pod。应用kubectl logs <POD NAME HERE> --follow,咱们应该可能查看运行主动缩放器是否产生任何谬误,以及无关主动缩放器如何决定缩放的信息。
主动缩放器扩容后,应将托管部署的正本数减少到3(由numPods标签指定),并通过kubectl get pod进行查看。尝试更新deployment.yaml标签值,而后再次部署它,查看正本数如何变动。

思考

DigitalOcean 开源的CPA operator,做了大量的形象,能够让大家集中精力在本人的逻辑上,而无需过多理解k8s底层。

随着容器化的大规模落地,对于自定义HPA的需要也越来越多。CPA operator完满的解决了这一痛点。