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 os
import json
import sys
def 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 json
import sys
import math
def 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 CPA
FROM custompodautoscaler/python:latest
# Add config, evaluator and metric gathering Py scripts
ADD config.yaml evaluate.py metric.py /
这个 Dockerfile 只是插入咱们的两个脚本和咱们的配置文件中。当初,咱们曾经实现了主动缩放器的创立,让咱们看看它的工作原理。
6:功能测试
首先,咱们应该通过装置 Custom Pod Autoscaler Operator 在集群上启用自定义主动缩放器,对于本指南,咱们应用的是 v1.0.1,然而请从 Custom Pod Autoscaler Operator 发行版中签出最新版本,并参阅装置指南以获取最新的装置信息。
VERSION=v1.0.1
kubectl 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/v1
kind: Deployment
metadata:
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/v1
kind: CustomPodAutoscaler
metadata:
name: python-custom-autoscaler
spec:
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 完满的解决了这一痛点。