- 云原生
- 微服务
- 容器编排
- 运维
【免费下载链接】flynn
[UNMAINTAINED] A next generation open source platform as a service (PaaS)
本篇技术指南围绕 Flynn 平台控制面(Controller)的 HTTP API 展开,基于仓库中的官方 API 示例文档 docs/api-examples/controller.md 与配套的完整请求/响应样例 docs/api-examples/controller.json,并结合 controller/ 模块源码进行底层原理验证。读完本文,你将掌握 Controller API 的 Basic Auth 认证机制、核心资源(App、Artifact、Release、Formation、Job、Deployment、Route、Provider/Resource)的增删改查调用方式、日志与事件流的 SSE 订阅技巧,以及各资源字段的取值规则与背后的实现逻辑。
API 概览与认证方式
Flynn 的 Controller 是集群控制面,对外提供一套基于 HTTP 的 REST 风格 API,供 CLI(如 cli/)、Dashboard 以及其他系统组件调用。其 API 根地址就是 Controller 应用自身的域名,默认形如:
https://controller.$CLUSTER_DOMAIN例如在本地开发集群中通常为https://controller.dev.localflynn.com。
认证:Basic Auth + Controller Key
所有请求都通过 Basic Auth 进行认证,规则如下:
- 用户名(username)为空字符串;
- 密码(password)为你的 Controller Key(AUTH_KEY);
- 认证请求头形如
Authorization: Basic OnMzY3IzdA==,其中OnMzY3IzdA==就是":" + key的 Base64 编码(冒号前为空的用户名)。
获取你自己的 Controller Key 的 CLI 命令:
flynn -a controller env get AUTH_KEY之所以 key 存放在名为controller的系统应用的环境变量中,是因为 Controller 进程本身以 Flynn 应用的方式运行:从 controller/controller.go 可以看到AUTH_KEY被直接作为认证密钥注入handlerConfig.keys,再传给authorizer.New(...)。
从 controller/authorizer/authorizer.go 的源码可以看到完整的认证判定顺序:
- 若请求头携带
Authorization: Bearer ...,走 JWT 风格 token 校验; - 否则解析 Basic Auth,若用户名为
Bearer,同样走 token 校验; - 其余情况一律将 Basic Auth 的密码当作 Controller Key,与配置的
authKeys列表做常数时间比较(subtle.ConstantTimeCompare,见 authorizer.go),防止时序侧信道攻击。
此外,AUTH_KEY支持逗号分隔的多 key 配置(controller.go 中按,切分),并可通过AUTH_KEY_IDS为每个 key 绑定一个 ID,用于审计日志中标识调用方身份(controller.go 会将认证 ID 写入Flynn-Auth-ID与Flynn-Auth-User请求头)。
事件流的特殊认证方式
对于SSE 事件流接口(GET /events、日志流等),除了 Basic Auth 之外,还允许通过 URL 参数key直接携带 Controller Key,例如:
https://controller.$CLUSTER_DOMAIN/events?key=$AUTH_KEY这一设计是为了让浏览器中的 JavaScript(无法自定义 Authorization 头)也能订阅事件流。注意:普通 REST 接口不支持key参数,只有事件流类接口可以使用。
App:应用生命周期管理
App 是 Process Formation(进程编排)、资源依赖和元数据的命名空间(参见 schema/controller/app.json 中对 App 的描述)。示例文档中的 App 相关端点如下:
| 端点 | 方法 | 作用 |
|---|---|---|
/apps | POST | 创建应用 |
/apps | GET | 列出所有应用 |
/apps/:apps_id | GET | 获取单个应用 |
/apps/:apps_id | POST | 更新应用(如 meta) |
/apps/:apps_id | DELETE | 删除应用 |
/apps/:apps_id/log | GET | 获取应用日志(支持 SSE 流) |
/apps/:apps_id/release | GET/PUT | 读取/设置当前 Release |
/apps/:apps_id/releases | GET | 列出应用的所有 Release |
/apps/:apps_id/resources | GET | 列出应用绑定的资源 |
/apps/:apps_id/formations | GET | 列出应用的 Formation |
/apps/:apps_id/jobs | GET/POST | 列出/运行 Job |
/apps/:apps_id/deploy | POST | 触发一次部署 |
/apps/:apps_id/routes | GET/POST | 列出/创建路由 |
创建应用
POST /apps Content-Type: application/json Authorization: Basic OnMzY3IzdA== {"name": "my-app", "meta": null}成功响应(200):
{ "id": "adcccdb4-b1a4-4209-a03a-762f4e021632", "name": "my-app", "meta": {}, "strategy": "all-at-once", "deploy_timeout": 30, "created_at": "2015-12-16T02:20:56.657428Z", "updated_at": "2015-12-16T02:20:56.657428Z" }应用名校验规则
示例文档中专门给出了一个"创建失败"的样例:当 name 不合法时,API 返回validation_error:
{ "code": "validation_error", "message": "name String must match the pattern: \"^[a-z\\d]+(-[a-z\\d]+)*$\".", "detail": {"field": "name"}, "retry": false }该正则的语义是:应用名只能由小写字母与数字组成,且只能用单个连字符-分隔各段(如my-app合法,this is not valid、MyApp、a--b均不合法)。这与 schema/controller/app.json 中name字段的约束完全一致:maxLength: 100、minLength: 1、pattern 如上。CRUD 入口的校验逻辑位于 controller/crud.go,所有写入请求在落库前都会经过 controller/schema 的 JSON Schema 校验。
App 的关键字段
id:全局唯一 ID(UUID);name:应用名,命名空间标识;meta:任意键值对元数据,可为null(创建时传null,响应会规范化为{})。系统应用会带有"flynn-system-app": "true"标记;strategy:部署策略,常见取值all-at-once、one-by-one、discoverd-meta、postgres等(从示例中 controller 集群的各系统应用可见);deploy_timeout:单次部署超时秒数,普通应用默认 30,Postgres/Discoverd/Controller 等数据面应用为 120;release:当前绑定的 Release ID;created_at/updated_at:RFC3339 时间戳。
更新与删除
更新应用使用 POST(非 PUT),例如给 meta 追加内容:
POST /apps/adcccdb4-b1a4-4209-a03a-762f4e021632 Content-Type: application/json {"id": "adcccdb4-b1a4-4209-a03a-762f4e021632", "meta": {"bread": "with hemp"}}响应中 meta 变为{"bread": "with hemp"}。从 controller/app.go 可以看到更新接口的细节:它支持部分更新(appUpdate 是map[string]interface{}),并对{"meta": null}做了特殊处理(等价于不更新 meta 字段)。
删除应用:
DELETE /apps/adcccdb4-b1a4-4209-a03a-762f4e021632删除并非同步执行,而是把app_deletion任务入队(controller/app.go),由后台 worker(controller/worker/app_deletion/)异步完成路由、资源、Job 的清理,最终会触发app_deletion类型的事件(详见下文事件流部分)。
应用日志
获取最近 10 行日志:
GET /apps/f7064b9f-c968-4f16-be0e-f2efd1b2c7b7/log?lines=10普通模式下响应为text/plain,每行是一个 JSON 对象,包含host_id、job_id、msg、process_type、source、stream、timestamp字段。若请求头带上Accept: text/event-stream,则返回 SSE 流,每条日志以data: {"event":"message","data":{...}}形式推送,结束时发送data: {"event":"eof"}。
从 controller/app.go 可以看到日志接口支持的查询参数:
lines:返回行数;follow=true:持续跟随输出(配合FlushWriter实现流式输出);job_id:只取指定 Job 的日志;process_type:只取指定进程类型(如web)的日志;stream_types:逗号分隔,可取值stdout、stderr等。
日志数据实际来自 logaggregator 组件(logaggregator/),Controller 通过logaggc.GetLog(appID, opts)拉取后再透传。
Artifact:容器镜像的描述
Artifact 代表一个可运行的容器镜像引用(如 Docker 镜像或 slug 镜像),是 Release 的基础。
| 端点 | 方法 | 作用 |
|---|---|---|
/artifacts | POST | 创建 Artifact |
/artifacts | GET | 列出所有 Artifact |
创建 Artifact:
POST /artifacts Content-Type: application/json {"type": "docker", "uri": "https://dl.flynn.io/tuf?name=flynn/slugrunner&id=..."}响应(200):
{ "id": "c1889f55-c244-43ce-af70-ead357daa6ec", "type": "docker", "uri": "https://dl.flynn.io/tuf?name=flynn/slugrunner&id=...", "created_at": "2015-12-16T02:21:06.727191Z" }示例中所有系统组件的 Artifact URI 都指向经 TUF 签名的镜像地址(dl.flynn.io/tuf?name=flynn/xxx&id=sha256...),说明 Flynn 使用 TUF(The Update Framework)做镜像分发与完整性校验(相关工具见 pkg/tufutil/)。Artifact 的字段type目前示例中均为docker。
Release:进程类型的定义
Release 将 Artifact、环境变量与进程类型(process type)绑定,描述"如何运行一个版本"。
| 端点 | 方法 | 作用 |
|---|---|---|
/releases | POST | 创建 Release |
/releases | GET | 列出所有 Release |
创建 Release 的请求体:
{ "artifact": "c1889f55-c244-43ce-af70-ead357daa6ec", "env": {"some": "info"}, "processes": { "foo": {"cmd": ["ls", "-l"], "env": {"BAR": "baz"}} } }响应(200)——注意系统会自动补全资源限额:
{ "id": "47154f8c-a604-469d-ae6a-e431990ddee8", "artifact": "c1889f55-c244-43ce-af70-ead357daa6ec", "env": {"some": "info"}, "processes": { "foo": { "cmd": ["ls", "-l"], "env": {"BAR": "baz"}, "resources": { "max_fd": {"request": 10000, "limit": 10000}, "memory": {"request": 1073741824, "limit": 1073741824} } } }, "created_at": "2015-12-16T02:21:06.731551Z" }从响应可以看出默认资源规格:max_fd的 request/limit 均为 10000,memory的 request/limit 均为 1073741824 字节(1 GiB)。这些默认值由 host 侧的资源模块注入(相关定义见 host/resource)。
Release 的processes是map[进程名]ProcessType,每个 ProcessType 可包含:
cmd/args:启动命令;env:该进程类型专属环境变量;ports:端口声明数组,每项含port、proto(如tcp)以及可选的service(含name、create、check,其中check可配置type(如http)、interval、threshold、path等健康检查参数,参见 controller/api/api.go);resources:资源规格(request与limit成对出现);omni:是否在每个宿主机上都运行;host_network:是否使用宿主机网络;data:是否为数据型进程(示例中 postgres、discoverd 进程带有"data": true);resurrect:进程退出后是否自动复活(系统关键进程均开启);service:注册到 discoverd 的服务名(如gitreceive、controller-scheduler、discoverd、postgres);mounts、volumes、linux_capabilities、allowed_devices、writeable_cgroups等高级字段(完整字段映射见 controller/api/api.go)。
将 Release 绑定到 App
PUT /apps/adcccdb4-b1a4-4209-a03a-762f4e021632/release Content-Type: application/json {"id": "47154f8c-a604-469d-ae6a-e431990ddee8"}查看 App 当前 Release:
GET /apps/adcccdb4-b1a4-4209-a03a-762f4e021632/release在示例中,gitreceive系统应用的 release 展示了完整的进程定义:其app进程声明了一个port: 0(随机端口)、proto: "tcp"、service.name: "gitreceive"、service.create: true的端口,意味着该服务会自动注册到 discoverd 并创建对应的服务条目。
Formation:进程编排与扩容
Formation 描述"某个 App 的某个 Release 各进程类型要运行多少副本",是缩放(scale)的核心对象。
| 端点 | 方法 | 作用 |
|---|---|---|
/apps/:apps_id/formations/:releases_id | PUT | 创建/更新 Formation |
/apps/:apps_id/formations/:releases_id | GET | 获取单个 Formation |
/apps/:apps_id/formations/:releases_id | DELETE | 删除 Formation |
/apps/:apps_id/formations | GET | 列出 App 的所有 Formation |
/formations | GET | 列出全部 Formation(支持active=true过滤) |
/formations?since=... | GET | Formation 变更流(SSE) |
创建 Formation:
PUT /apps/adcccdb4-b1a4-4209-a03a-762f4e021632/formations/47154f8c-a604-469d-ae6a-e431990ddee8 Content-Type: application/json {"app": "adcccdb4-b1a4-4209-a03a-762f4e021632", "release": "47154f8c-a604-469d-ae6a-e431990ddee8", "processes": {"foo": 1}}响应(200):
{ "app": "adcccdb4-b1a4-4209-a03a-762f4e021632", "release": "47154f8c-a604-469d-ae6a-e431990ddee8", "processes": {"foo": 1}, "created_at": "2015-12-16T02:21:06.748757Z", "updated_at": "2015-12-16T02:21:06.748757Z" }展开视图与活跃 Formation 流
单个 Formation 支持?expand=true展开内嵌的 app、release、artifact 完整对象:
GET /apps/adcccdb4-b1a4-4209-a03a-762f4e021632/formations/47154f8c-a604-469d-ae6a-e431990ddee8?expand=trueGET /formations?active=true则返回所有活跃(有副本数)的 Formation 的展开视图——示例响应中可以看到 controller 集群全部 12 个系统应用的完整形态,包括controller(scheduler/web/worker 三个进程类型)、router(omni: true、host_network: true、TCP 端口段 3000-3500)、postgres(data: true、端口 5432)、discoverd(data: true、端口 1111/53)等,是理解 Flynn 系统组件编排方式的绝佳样例。
Formation 变更流使用 SSE 且支持since参数回溯历史:
GET /formations?since=1970-01-01T00:00:00Z Accept: text/event-stream每帧data:携带一条完整的展开 Formation(含 app、release、artifact、processes),最后以{"updated_at":"0001-01-01T00:00:00Z"}标记结束。
Deployment:一次完整的滚动发布
Deployment 描述"从旧 Release 切换到新 Release"的一次发布动作。
| 端点 | 方法 | 作用 |
|---|---|---|
/apps/:apps_id/deploy | POST | 创建部署 |
/apps/:apps_id/deployments | GET | 列出 App 的部署历史 |
/deployments/:deployment_id | GET | 获取单个部署详情 |
创建部署:
POST /apps/adcccdb4-b1a4-4209-a03a-762f4e021632/deploy Content-Type: application/json {"id": "77e9e956-ecf9-427f-a031-222c2f394fb8"}响应(200)——返回 Deployment 对象:
{ "id": "aab1ee14-776d-4ba4-979b-1b4bda2d9b35", "app": "adcccdb4-b1a4-4209-a03a-762f4e021632", "old_release": "47154f8c-a604-469d-ae6a-e431990ddee8", "new_release": "77e9e956-ecf9-427f-a031-222c2f394fb8", "strategy": "all-at-once", "status": "pending", "processes": {"foo": 1}, "deploy_timeout": 30, "created_at": "2015-12-16T02:21:16.782263Z" }Deployment 状态机取值:pending→running→complete(异常时为failed),相关状态映射见 controller/api/api.go。部署动作由 controller/deployment.go 触发,实际执行逻辑在 controller/worker/deployment/ 中,会根据 App 的strategy(如all-at-once、one-by-one)按序拉起新 Job、摘除旧 Job,并实时推送deployment、job、scale事件(见事件流一节)。
Job:容器中的单个进程
Job 是运行在容器中的单个进程实例,其状态枚举在 schema/controller/job.json:pending、starting、up、stopping、down、crashed、failed。
| 端点 | 方法 | 作用 |
|---|---|---|
/apps/:apps_id/jobs | POST | 运行一个新 Job(一次性任务) |
/apps/:apps_id/jobs | GET | 列出 App 的所有 Job |
/apps/:apps_id/jobs/:jobs_id | GET | 获取 Job 详情 |
/apps/:apps_id/jobs/:jobs_id | PUT | 更新 Job 状态 |
/apps/:apps_id/jobs/:jobs_id | DELETE | 终止 Job |
运行一次性 Job(示例中cmd里的$BODY会被 env 展开):
POST /apps/adcccdb4-b1a4-4209-a03a-762f4e021632/jobs Content-Type: application/json {"release": "77e9e956-ecf9-427f-a031-222c2f394fb8", "cmd": ["echo", "$BODY"], "env": {"BODY": "Hello!"}}响应(200)——返回 Job ID 与命令:
{"id": "host-40cc2d07-7a48-4fda-9790-ba9768a3f616", "release": "77e9e956-ecf9-427f-a031-222c2f394fb8", "cmd": ["echo", "$BODY"]}Job ID 的格式为host-<UUID>(宿主机 ID + UUID 拼接),从 controller/jobs.go 可见其生成方式(cluster.GenerateJobID(hostID, uuid))。Job 会被随机调度到一个宿主机上,环境变量会自动注入FLYNN_APP_ID、FLYNN_RELEASE_ID、FLYNN_JOB_ID等系统变量,且 metadata 会写入flynn-controller.app、flynn-controller.app_name、flynn-controller.release标签(controller/jobs.go)。若请求头携带Upgrade: flynn-attach/0,API 会升级为双向流式 attach 通道(用于flynn run类交互式场景)。
终止 Job:
DELETE /apps/adcccdb4-b1a4-4209-a03a-762f4e021632/jobs/host-40cc2d07-7a48-4fda-9790-ba9768a3f616从 controller/jobs.go 可以看到,KillJob 会先查出 Job 所在的宿主机,再调用client.StopJob(job.ID)真正停止容器;未落宿主的 Job 无法被杀掉(返回校验错误)。
Route:HTTP 与 TCP 路由规则
Route 定义外部流量如何进入应用,目前示例覆盖 HTTP 路由。
| 端点 | 方法 | 作用 |
|---|---|---|
/apps/:apps_id/routes | POST | 创建路由 |
/apps/:apps_id/routes | GET | 列出路由 |
/apps/:apps_id/routes/:routes_type/:routes_id | GET | 获取路由 |
/apps/:apps_id/routes/:routes_type/:routes_id | PUT | 更新路由 |
/apps/:apps_id/routes/:routes_type/:routes_id | DELETE | 删除路由 |
创建 HTTP 路由:
POST /apps/adcccdb4-b1a4-4209-a03a-762f4e021632/routes Content-Type: application/json {"type": "http", "service": "my-app-web", "domain": "http://example.com"}响应(200):
{ "type": "http", "id": "5bfb9c8b-ae1f-4a5a-af0c-94fa2996d543", "parent_ref": "controller/apps/adcccdb4-b1a4-4209-a03a-762f4e021632", "service": "my-app-web", "created_at": "2015-12-16T02:21:06.704111Z", "updated_at": "2015-12-16T02:21:06.704111Z", "domain": "http://example.com", "path": "/" }HTTP 路由关键字段:
domain:对外域名(示例中既有http://example.com,也有 Flynn 自动生成的<app-name>.<cluster-domain>默认路由,如my-app-...dev.localflynn.com);path:路径前缀,默认/;service:后端 discoverd 服务名;sticky:是否开启会话粘滞(示例更新响应中出现"sticky": true);parent_ref:路由归属引用,格式controller/apps/<app-id>。
更新路由使用 PUT,可将service改为其他后端并开启 sticky。路由数据最终同步到 router/ 组件生效,Router 的 HTTP/TCP 路由类型定义见 router/types/types.go。
Provider 与 Resource:外部服务资源
Provider 描述一类外部资源服务(如 PostgreSQL、MySQL、Redis 的托管服务),Resource 则是 Provider 上实际开通的一份资源实例(如一个数据库)。
| 端点 | 方法 | 作用 |
|---|---|---|
/providers | POST/GET | 创建/列出 Provider |
/providers/:providers_id | GET | 获取 Provider |
/providers/:providers_id/resources | POST/GET | 开通/列出资源 |
/providers/:providers_id/resources/:resources_id | GET/PUT/DELETE | 管理单个资源 |
/apps/:apps_id/resources | GET | 列出 App 绑定的资源 |
创建 Provider:
POST /providers Content-Type: application/json {"url": "http://example-provider-xxx.discoverd:12345/providers/xxx", "name": "example-provider-xxx"}开通资源(config可携带 Provider 要求的参数,如数据库名):
POST /providers/0952f692-2667-4be0-a159-9d68382a262c/resources Content-Type: application/json {"config": {}}响应(200)——Provider 返回的连接信息以env键值对形式呈现:
{ "id": "100c3daa-333b-4f46-92bf-414745dc974d", "provider": "0952f692-2667-4be0-a159-9d68382a262c", "env": {"some": "data"}, "created_at": "2015-12-16T02:21:16.833363Z" }当资源已绑定到某 App 后,资源对象中会出现apps数组(被绑定的 App ID 列表)与external_id(Provider 侧的外部标识)。示例中postgresProvider 的地址为http://postgres-api.discoverd/databases,其资源(数据库)的env会包含PGHOST、PGUSER、PGPASSWORD、PGDATABASE、DATABASE_URL等标准连接信息——这在formations_list_active的系统应用展开样例中清晰可见(router、blobstore、controller 应用的 env 中都有形如postgres://user:pass@leader.postgres.discoverd:5432/dbname的DATABASE_URL)。
事件系统:Event 查询与 SSE 订阅
Controller 会为集群中的所有重要变化(app 创建/删除、job 状态迁移、deployment 推进、release 创建、resource 开通、route 变更、scale 变化等)记录事件,并可被客户端订阅。
| 端点 | 方法 | 作用 |
|---|---|---|
/events/:id | GET | 按 ID 获取单条事件 |
/events?count=10 | GET(Accept: application/json) | 列出历史事件 |
/events?count=10&past=true | GET(Accept: text/event-stream) | SSE 事件流,可回溯 |
事件对象结构
示例中的事件对象(如 resource 开通事件):
{ "id": 111, "app": "adcccdb4-b1a4-4209-a03a-762f4e021632", "object_type": "resource", "object_id": "cc9f3342-bed0-4ed3-840e-c462e05808c6", "data": {"id": "cc9f3342-bed0-4ed3-840e-c462e05808c6", "env": {"FOO": "BAR"}, "apps": ["adcccdb4-b1a4-4209-a03a-762f4e021632"], "provider": "0952f692-2667-4be0-a159-9d68382a262c", "created_at": "...", "external_id": "/foo/bar"}, "created_at": "2015-12-16T02:21:16.838613Z" }从示例可见的事件object_type包括:app、app_deletion、release、artifact、job、deployment、scale、resource、resource_deletion、route、route_deletion等。
事件列表查询参数
从 controller/events.go 的listEvents实现可以看到支持:
app_id:按应用过滤;count:返回条数(示例count=10);since_id/before_id:按事件 ID 区间过滤;object_types:逗号分隔的事件类型过滤;object_id:按对象 ID 过滤。
SSE 事件流
GET /events?count=10&past=true Accept: text/event-stream Last-Event-Id: 0要点(结合 controller/events.go 源码):
past=true:先回放历史事件(按 ID 升序逐条推送),再持续推送新事件;Last-Event-Id:断点续传,服务端会把该 ID 之后的事件补发;- 事件流帧格式:每帧为
data: {"event":"message","data":{...}},示例响应清晰展示了一次完整部署周期的事件序列(job starting → up → down、deployment pending → running、scale 变更、route_deletion、resource_deletion、app_deletion),非常适合用来观测部署全流程; - 事件 ID 为单调递增的整数,客户端可用它做去重与断点续传;
- 流结束标志:日志流发送
data: {"event":"eof"},Formation 流发送{"updated_at":"0001-01-01T00:00:00Z"}。
事件流之所以允许用keyURL 参数代替 Basic Auth,正是为了让浏览器端 SSE(EventSource,无法自定义请求头)可以正常消费(controller.md 中明确说明)。
其他系统级端点
除了上述资源类 API,Controller 还暴露若干集群级端点(路由注册见 controller/controller.go):
| 端点 | 方法 | 作用 |
|---|---|---|
/ca-cert | GET | 获取集群 CA 证书(application/x-x509-ca-cert),无需认证 |
/backup | GET | 下载集群备份 tar 包(Content-Disposition: attachment) |
/domain | PUT | 发起集群域名迁移 |
/ping | GET | 存活探测(返回 200) |
/status | GET | 健康状态(含数据库 ping 检查,见 controller.go) |
/sinks | POST/GET/DELETE | 管理日志汇聚 sink |
/volumes | GET/PUT | 管理卷 |
/active-jobs | GET | 列出全集群活跃 Job |
例如GET /backup响应:
Content-Disposition: attachment; filename="flynn-backup-2015-12-16_022126.tar" Content-Type: application/tarPUT /domain发起域名迁移的请求与响应示例展示了old_domain与domain两个核心字段,响应对象会携带迁移 ID 与新域名对应的 TLS 证书(cert/key),迁移流程由 controller/worker/domain_migration/ 后台执行,相关接口实现在 controller/domain.go。
实战要点小结
- 认证:所有请求(事件流除外)使用空用户名 + Controller Key 的 Basic Auth;事件流可改用
?key=参数,方便浏览器 SSE 消费;Key 通过flynn -a controller env get AUTH_KEY获取,支持多 Key 轮换与 Key ID 审计。 - 对象关系:App(命名空间)→ Release(版本定义)→ Artifact(镜像引用);Formation(App+Release 的副本数)驱动 Job(容器进程)运行;Deployment 负责新旧 Release 的平滑切换;Route 把外部流量导向服务的 Job;Provider/Resource 提供外部服务连接信息。
- 部署观察:发起
POST /apps/:id/deploy后,通过GET /events(Accept: text/event-stream、Last-Event-Id断点续传)可实时跟踪 job 的 starting/up/down 与 deployment 的 pending/running/complete 全流程。 - 默认资源规格:未显式指定时,Release 进程的
max_fd与memory会被补全为 10000 / 1 GiB,磁盘等资源可参考 host/resource 的默认值定义。 - 校验前置:所有写接口在落库前都经过 JSON Schema 校验(如 App 名的
^[a-z\d]+(-[a-z\d]+)*$正则),非法输入统一返回{"code":"validation_error","detail":{"field":...}}结构。
如需进一步探索,可阅读完整的请求/响应样例 docs/api-examples/controller.json(覆盖 60 余个端点的真实抓包级示例)、Controller 路由注册表 controller/controller.go、CRUD 通用实现 controller/crud.go,以及各资源的 JSON Schema 定义目录 schema/controller/。
- 云原生
- 微服务
- 容器编排
- 运维
【免费下载链接】flynn
[UNMAINTAINED] A next generation open source platform as a service (PaaS)
相关推荐
Sphinx 事件管理器 API 详解:EventManager 与核心事件系统实战
Sphinx 事件管理器 API 详解:EventManager 与核心事件系统实战 导读 Sphinx 文档生成器把整个构建过程拆分成一系列可被"挂接"的事件
文档开发工具超实用!BayesianOptimization核心API详解与实战指南
超实用!BayesianOptimization核心API详解与实战指南 BayesianOptimization是一个强大的Python库,专为黑盒函数优化设
机器学习Neovim 代码补全与片段:使用 nvim-cmp 实现 VSCode 级体验
Neovim 代码补全与片段:使用 nvim cmp 实现 VSCode 级体验 Neovim 作为一款强大的文本编辑器,通过插件可以实现媲美 VSCode 的
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考