{"id":28740964,"url":"https://github.com/aliyuncontainerservice/scaler","last_synced_at":"2025-06-16T07:09:48.107Z","repository":{"id":176524550,"uuid":"650544240","full_name":"AliyunContainerService/scaler","owner":"AliyunContainerService","description":null,"archived":false,"fork":false,"pushed_at":"2023-07-26T16:13:44.000Z","size":80909,"stargazers_count":39,"open_issues_count":1,"forks_count":115,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-03-30T12:34:39.789Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AliyunContainerService.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-06-07T09:43:40.000Z","updated_at":"2024-04-18T14:37:09.000Z","dependencies_parsed_at":null,"dependency_job_id":"abbb6c34-3508-4be7-b50e-f45e03646d64","html_url":"https://github.com/AliyunContainerService/scaler","commit_stats":null,"previous_names":["aliyuncontainerservice/scaler"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/AliyunContainerService/scaler","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AliyunContainerService%2Fscaler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AliyunContainerService%2Fscaler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AliyunContainerService%2Fscaler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AliyunContainerService%2Fscaler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AliyunContainerService","download_url":"https://codeload.github.com/AliyunContainerService/scaler/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AliyunContainerService%2Fscaler/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260116644,"owners_count":22961065,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-16T07:09:43.036Z","updated_at":"2025-06-16T07:09:48.084Z","avatar_url":"https://github.com/AliyunContainerService.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# scaler实现指南\n\n本赛题需要选手实现一个 Scaler 模块的功能。在实际生产环境中一个 Scaler 模块为了实现弹性伸缩的功能，需要解决很多工程问题，而具体的工程问题往往和实际的环境和技术栈相关。所以本赛题通过仿真框架屏蔽了这些因环境而异的繁琐工程细节，选手只聚焦在 Scaler 核心逻辑即可。\n本赛题提供了go和java语言的参考实现，选手可以参考其中的任意一种语言实现，也可以自行选择其他语言实现。\n这里以go语言为例，选手实现的代码需要实现Scaler接口(go/pkg/scaler/interface.go)，确保实现的函数可以完成下述功能:\n在go/pkg/scheduler/simple.go 基础上实现`Scheduler`接口(go/pkg/scheduler/interface.go)，确保实现的函数可以完成下述功能:\n* Assign:为请求分配一个应用实例，一个应用实例只能被分配给一个请求，如果无应用实例存在则需要冷启动，重新创建一个实例。无论是Kubernetes中Pod 还是 FaaS 函数，应用实例的启动过程都包括两个部分：实例的分配（CreateSlot）以及应用环境初始化（Init）。然后，实例才可以正常的处理请求\n![img.png](images/img.png)\n* Idle:释放请求占用的应用实例，这个实例如果没有被回收， 可以被下次调用请求复用\n![img_1.png](images/img_1.png)\n\n选手可以基于赛题方给出的数据集(data/data_training.tar.gz),解压后进行本地调试。\n赛题方同时提供了用于测试选手代码实现效果的镜像(registry.cn-beijing.aliyuncs.com/cloudnative-challenge/simulator:v1.0.0)，已经嵌入了以上训练数据集，选手可以通过以下本地测试方式进行调试。\n\n## 数据集字段说明\n### requests 数据集\nrequests 数据集包含了一系列的请求记录，每条记录对应一个已经完成的任务。每条记录包含以下字段：\n\n* startTime: 这是一个以毫秒为单位的时间戳，代表任务开始的时间。\n* metaKey: 用来标识与任务相关联的元数据，它与元数据数据集中的key字段相对应。\n* durationsInMs: 表示任务的执行时间，单位为毫秒。\n* statusCode: 表示任务的执行结果。一般来说，200代表任务成功完成，其他值则可能代表有错误或异常情况，模拟的是云计算场景下后端实例偶发性的异常。\n### metas 数据集\nmetas 数据集包含了一系列的元数据记录，每条记录包含一项任务的配置信息。每条记录包含以下字段：\n\n* key: 用来唯一标识一项元数据,可以理解为任务的类型或者特征。它与requests数据集中的metaKey字段相对应。\n* runtime: 代表任务需要运行的环境，如python、nodejs、go等。\n* memoryInMb: 表示任务需要的内存数量，单位为MB。\n* timeoutInSecs: 表示任务的超时时间，单位为秒。\n* initDurationInMs: 表示任务初始化的时间，单位为毫秒。\n\n## 接口文档\n**注意：以下说明以go语言为例，其他语言请参考对应语言的数据结构定义。**\n### Assign 方法\nAssign 方法是一个核心接口，其主要目的是分配资源实例以满足任务请求。\nAssign方法的核心逻辑可能如下：\n1. 解析输入的AssignRequest，提取出元数据信息以及请求时间等。\n2. 根据元数据信息以及当前系统的资源状态，决定是否可以分配一个资源实例来执行任务，或者是否需要等待。\n3. 如果可以分配，那么创建一个资源实例，记录其创建的时间、类型等信息，并将其标记为已占用状态。\n4. 返回创建的资源实例的信息，包括其唯一ID等。\n需要注意的是，你也可以在一个AssignRequest到来时创建多个资源实例，如果你预测到后面会有大量同类型的任务到来，这样可以提前创建好资源实例，以便后续的任务可以更快的被分配到资源实例上，减少冷启动时间。\n#### 输入\nAssign方法接收context和AssignRequest对象作为输入参数。其结构和对应的数据集字段如下：\nctx: context对象，用于跨多个API请求或goroutines之间共享deadline，取消信号，和其他请求范围的值\nrequest: AssignRequest对象，定义了分配请求的所有信息\n```go\ntype AssignRequest struct {\n\t...\n\t\n    RequestId string `protobuf:\"bytes,1,opt,name=request_id,json=requestId,proto3\" json:\"request_id,omitempty\"`\n    Timestamp uint64 `protobuf:\"varint,2,opt,name=timestamp,proto3\" json:\"timestamp,omitempty\"`\n    MetaData  *Meta  `protobuf:\"bytes,3,opt,name=meta_data,json=metaData,proto3\" json:\"meta_data,omitempty\"`\n}\n```\n* RequestId: 唯一的请求 ID。\n* Timestamp: 时间戳，表示请求发起的时间，对应requests数据集中的startTime 字段。\n* MetaData: Meta 对象，包含任务运行所需的元数据信息，对应数据集matas中的字段。\n\n#### 输出\nAssign 方法返回一个 AssignReply 对象，包含分配的资源实例的唯一标识。其结构如下：\n```go\ntype AssignReply struct {\n    ...\n\n    Status       Status      `protobuf:\"varint,1,opt,name=status,proto3,enum=serverless.simulator.Status\" json:\"status,omitempty\"`\n    Assigment    *Assignment `protobuf:\"bytes,2,opt,name=assigment,proto3\" json:\"assigment,omitempty\"`\n    ErrorMessage *string     `protobuf:\"bytes,3,opt,name=error_message,json=errorMessage,proto3,oneof\" json:\"error_message,omitempty\"`\n}\n\ntype Assignment struct {\n\t...\n\t\n    RequestId  string `protobuf:\"bytes,1,opt,name=request_id,json=requestId,proto3\" json:\"request_id,omitempty\"`\n    MetaKey    string `protobuf:\"bytes,2,opt,name=meta_key,json=metaKey,proto3\" json:\"meta_key,omitempty\"`\n    InstanceId string `protobuf:\"bytes,3,opt,name=instance_id,json=instanceId,proto3\" json:\"instance_id,omitempty\"`\n}\n```\n* RequestId: 唯一的请求 ID，与输入的 AssignRequest 对象中的 RequestId 字段相同。\n* MetaKey: 与输入的 AssignRequest 对象中的 MetaData.Key 字段相同。\n* InstanceId: 资源实例的唯一标识，用于后续的 Idle 方法 以及 gc的资源回收。\n\n### Idle 方法\n方法用于处理释放实例。你可以设计自己的策略，决定是否删除相应的资源实例。例如，如果短时间内可能会有大量同类型的请求到来，可以保留实例，资源实例将继续用于其他任务，降低冷启动时间；反之，则可能选择将资源实例释放，以节约资源。\n#### 输入\nIdle 方法接收 context 和 IdleRequest 对象作为输入参数。其结构和对应的数据集字段如下：\n```go \ntype IdleRequest struct {\n\t...\n    Assigment *Assignment `protobuf:\"bytes,1,opt,name=assigment,proto3\" json:\"assigment,omitempty\"`\n    Result    *Result     `protobuf:\"bytes,2,opt,name=result,proto3\" json:\"result,omitempty\"`\n}\n``` \n* Assigment: Assignment对象，包含任务的分配信息，对应Assign方法的输出。\n* Result: Result 对象，包含任务的结果信息，对应requests数据集中的statusCode和durationsInMs字段\n```go\ntype Result struct {\n    ...\n\n\tStatusCode   int32   `protobuf:\"varint,1,opt,name=status_code,json=statusCode,proto3\" json:\"status_code,omitempty\"`\n\tDurationInMs uint64  `protobuf:\"varint,2,opt,name=duration_in_ms,json=durationInMs,proto3\" json:\"duration_in_ms,omitempty\"`\n\tNeedDestroy  *bool   `protobuf:\"varint,3,opt,name=need_destroy,json=needDestroy,proto3,oneof\" json:\"need_destroy,omitempty\"`\n\tReason       *string `protobuf:\"bytes,4,opt,name=reason,proto3,oneof\" json:\"reason,omitempty\"`\n}\n````\n* StatusCode: 任务的执行状态码，对应数据集requests中的statusCode字段。\n* DurationInMs: 任务的执行时间，对应数据集requests中的durationsInMs字段。\n* NeedDestroy: 一个布尔值，表示是否需要释放资源实例。如果为true，则需要释放资源实例；如果为false，则不需要释放资源实例。\n* Reason: 释放资源实例的原因。\n\n#### 输出\n\n```go\ntype IdleReply struct {\n    ...\n\n\tStatus       Status  `protobuf:\"varint,1,opt,name=status,proto3,enum=serverless.simulator.Status\" json:\"status,omitempty\"`\n\tErrorMessage *string `protobuf:\"bytes,3,opt,name=error_message,json=errorMessage,proto3,oneof\" json:\"error_message,omitempty\"`\n}\n```\n* Status: 状态码，表示Idle方法的执行结果。\n* ErrorMessage: 错误信息，如果Status不为OK，则ErrorMessage不为空，表示错误信息。\n\n### gcLoop方法\n除了上述两个API之外，还有一个gcLoop方法，这个方法是由scaler内部定期调用的，用于回收空闲的资源实例。\ngcLoop方法会定期运行，每次运行时，会遍历idleInstances列表，检查每个实例的空闲时间，如果有实例的空闲时间超过了配置的时间IdleDurationBeforeGC，那么这个实例就会被销毁。\n\n在销毁实例时，会调用platformClient的DeleteSlot方法删除这个slot，然后从instances映射和idleInstances列表中删除这个实例，最后会更新实例的状态为deleted。\n\n这个方法的运行时间间隔由Config对象的GcInterval字段控制。\n选手可以通过配置GcInterval 和 IdleDurationBeforeGC来控制gcLoop方法的运行频率和空闲实例的回收时间。\n\n# scaler本地开发\n\n## 运行环境\n\nlinux 运行环境\n\n\n## 构建二进制\n\n```\n# make binary\n```\n\nmake build 命令会生成一个二进制:scaler, 存放在项目根目录\n\n* scaler 是本次比赛的框架代码，选手可以通过实现根据assign/idle API来实现alloc/release实例的的功能。\n\n## 如何本地测试\n\n### 申请测试集群\n\n选手可以通过登录[阿里云官网](https://free.aliyun.com/?product=9596839\u0026crowd=personal)领取免费的ASK体验集群，选手可以在此集群上进行本地调试。\n成功申请集群后，选手需要将集群的kubeconfig文件下载到本地， 并放置在`~/.kube/config`目录下， 以便后续使用kubectl命令进行调试。\n\n### 本地安装kubectl\n\n[安装文档](https://kubernetes.io/zh-cn/docs/tasks/tools/install-kubectl-linux/)\n\n版本要求： v1.26\n\n后续的调试请使用 `kubectl ` 命令进行测试， 例如：\n\n```\nkubectl get pod\n```\n\n### 构建docker镜像并推送到镜像仓库\n\n#### 使用阿里云ACR服务\n阿里云容器镜像服务（简称 ACR）是面向容器镜像、Helm Chart 等符合 OCI 标准的云原生制品安全托管及高效分发平台。\nACR 产品页 ：https://www.aliyun.com/product/acr 。\n当前可以免费使用容器镜像服务 ACR 个人版，点击进入 ACR 控制台 https://cr.console.aliyun.com。\n\n#### 生成镜像并推送至镜像仓库\n登录ACR镜像仓库\n```\ndocker login --username=xxx registry.cn-shanghai.aliyuncs.com\n```\n构建镜像并推送至ACR镜像仓库\n```\ndocker buildx build --platform linux/amd64 -t $IMAGE_REPO:$IMAGE_TAG . --push\n```\n*  IMAGE_REPO指定镜像repo\n*  IMAGE_TAG指定镜像tag\n\n比如: 生成镜像registry.cn-shanghai.aliyuncs.com/cloudnative-challenge/scaler:v1.0， 命令如下:\n```\ndocker buildx build --platform linux/amd64 -t registry.cn-shanghai.aliyuncs.com/cloudnative-challenge/scaler:v1.0 . --push\n```\n\n### 部署测试job\n\n`kubectl apply -f hack/serverless-simulation.yaml`\n\n执行后， 会在对应命名空间下生成名为serverless-simulation 的job对象，该job的pod中包含两个容器， 一个是scaler 的容器， 一个是serverless-simulator 的容器， 可以使用kubectl命令查看:\n\n`kubectl get jobs serverless-simulation -o yaml`\n\n可以通过 `kubectl logs -f ` 命令查看pod 里两个容器产生的日志，进而进行问题的排查：\n\n```\n#查看scaler 容器日志: \nkubectl logs jobs/serverless-simulation scaler\n\n# 查看simulator 容器日志:\nkubectl logs jobs/serverless-simulation serverless-simulator\n\n# 查看当前的数据统计\nkubectl exec jobs/serverless-simulation -c scaler -- curl http://127.0.0.1:9000/\n```\n\n# 赛题提交说明\n\nhttps://tianchi.aliyun.com/forum/post/558730\n\n# 注意\n项目中的run.sh将作为容器的脚本，选手提交时请不要修改run.sh的内容，否则可能会导致评测失败。","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faliyuncontainerservice%2Fscaler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faliyuncontainerservice%2Fscaler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faliyuncontainerservice%2Fscaler/lists"}