mcpField
N
northflank

northflank

github.com/northflank云与 DevOps39902 次安装今天更新
代码仓库

关于 northflank

northflank 是面向开发者的平台,用于在 Kubernetes 上构建、部署和扩展工作负载,支持 Northflank Cloud、自有云或自有集群。此技能指导 Agent 通过 MCP、CLI、JS 客户端或 REST API 管理平台资源,并强调部署流程与破坏性操作确认。

主要功能

  1. 01管理项目、服务、任务与数据库插件
  2. 02指导新应用和任务部署流程
  3. 03提供故障诊断与部署状态检查指引
  4. 04支持 CLI、JS 客户端及 REST API
  5. 05破坏性操作前要求逐项确认

适用场景

  1. 01将 Git 或镜像应用部署到 Northflank
  2. 02检查服务、任务或插件故障
  3. 03通过 CLI 执行容器命令或本地转发
  4. 04在删除资源前核实影响并取得确认

MCP 相关

该技能介绍连接 Northflank 托管 MCP 端点 `https://mcp.northflank.com/mcp`,并指导 Agent 使用其工具部署和管理资源。安装技能本身不会配置 MCP 服务或授予账户访问权限。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/northflank/skills --skill northflank

安装后在 Claude Code 中输入/northflank确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
api-overview.md
references/api/
_index.md
billing-api.md
copy-files.md
execute-command.md
forwarding.md
introduction.md
log-tailing.md
references/api/miscellaneous/
_index.md
references/api/miscellaneous/auth/
_index.md
get-current-authentication-info.md
references/api/miscellaneous/miscellaneous/
_index.md
list-plans.md
list-regions.md
references/api/org/
_index.md
references/api/org/api-tokens/
_index.md
delete-a-key-from-an-api-token.md
list-api-tokens.md
rotate-a-key-on-an-api-token.md
references/api/org/billing/
_index.md
get-credit-balance.md
get-invoice.md
get-usage.md
list-invoices.md
list-usage.md
references/api/org/cloud-providers/
_index.md
cordon-cluster-node.md
create-cluster.md
create-integration.md
delete-cluster.md

详细介绍

Northflank

Northflank 是一个开发者平台,可在 Kubernetes 上构建、部署和扩缩工作负载,支持 Northflank Cloud、自有云(BYOC)或自有集群(BYOK)。它可在 AWS、GCP、Azure、CoreWeave 和本地环境中处理构建、部署、发布、自动扩缩和灾难恢复。核心原语包括:项目(Kubernetes 命名空间)、服务(无状态工作负载)、附加组件(托管数据库)、作业(定时/手动)、密钥组、卷和模板(IaC/GitOps)。UI 中的所有功能也都可通过 REST API、CLI 和 JS 客户端使用。

基础 API URL: https://api.northflank.com/v1/
身份验证: Authorization: Bearer <token>
速率限制: 使用响应中的速率限制标头;限制取决于账户和服务端配置。

开始之前

使用用户指定的界面,并复用其现有的已验证身份设置。MCP 可在编码 Agent 中直接提供引导式工作流;CLI 也是执行平台操作和本地开发的不错选择。如果未指定界面,已连接的 MCP 是一个便捷的起点。请检查所用界面的前置条件:

  1. MCP: 使用其引导式工具,从 Agent 部署和管理资源。对于新建的镜像/Git 应用,使用 deploy_app;对于作业,使用 deploy_job;对于现有资源或高级设置,使用详细工具。复用连接的身份验证。
  2. CLI: 使用用户现有的 northflank login 会话进行部署、资源管理、本地隧道、exec 和 shell 工作流。使用相关命令时,请查看其 --help。
  3. JS 客户端或 REST: 编写用户之后会保留并运行的代码时,使用这些方式。只有当代码需要时,才检查 @northflank/js-client。通过用户现有设置获取凭据;切勿打印令牌。
  4. 账户和项目: 复用已知上下文。项目 ID 是 slug,例如 my-project。使用 MCP 时,仅当团队或工作负载范围未知时,才调用 get_auth_context。自有项目的工作负载凭据应使用 workload.projectId;不要枚举所有项目。对于用户要求的新项目,请将 newProject 传递给部署工作流。

MCP 尚未连接?

按照将 Agent 连接到 Northflank中的说明,进行针对特定客户端的设置和身份验证。

托管端点为 https://mcp.northflank.com/mcp。它使用带有 Authorization: Bearer <team API token> 的 Streamable HTTP。也支持团队工作负载身份令牌。此设置不提供 MCP OAuth 登录。

安装此技能不会配置 MCP 服务,也不会授予账户访问权限。请根据指南帮助用户配置其指定的客户端。将凭据保存在客户端的密钥存储或进程环境中,切勿放在聊天内容或已提交的文件中。托管 MCP 可独立于 CLI 进行配置。

连接后,如果团队或访问范围未知,请调用一次 get_auth_context。对于轮换的工作负载令牌,请使用在请求前读取已挂载令牌,或在身份验证失败后刷新令牌的客户端。静态环境变量不会自动刷新令牌。

使用 MCP 部署

  1. 仅检查部署所需的信息。 对于本地仓库,只读取一次远程地址、分支、HEAD 和工作区状态。检查相关的 Dockerfile 或构建配置,以及监听端口。不要克隆已有的检出目录、扫描整个应用或运行无关的检查。Git 部署使用远程内容:在声称要部署本地分支之前,先确认是否有未提交或未推送的更改。未经用户授权,不要静默丢弃更改或推送更改。
  2. 复用上下文。 保留已知的 ID 和部署选项。优先使用 MCP 内联架构。如果某项操作未直接提供,请使用 search_tools 查找,再通过 execute_tool 调用。仅在需要时,使用 get_tool_schema 请求缺失的约束。直接执行返回的 next.tool 名称,无需再次搜索。对于缺少目录工具的旧版服务,请使用其提供的资源工具。获得授权后,不要重复检查仓库或调用目录工具。
  3. 遵循工具工作流。 对受支持的新工作负载,使用 deploy_app、deploy_job 或 create_database。根据其结果进行 Git 授权、故障恢复和状态检查。保留原始输入以及返回的资源/会话 ID。如果有浏览器,请打开授权链接;否则显示链接并等待。工作负载身份需要团队成员授予缺失的 Git 访问权限。
  4. 遵循返回的阶段、后续步骤和轮询间隔。源代码修订已上线,并不能证明特定提交的重新构建已部署。声称应用运行正常之前,请检查 Web 端点。发生部分失败后,请从现有资源恢复。不要盲目重复创建或执行。

当连接的服务提供 diagnose 时,使用它诊断服务、作业或附加组件故障。它会收集运行状况、相关基础设施事件、部署修订、日志、指标和 BYOC 节点池配置。缺少权限时,收集到的证据可能不完整。将相关性视为线索,而非已证实的原因。常规轮询请使用 get_deployment_status 或 get_addon。

list_addon_types 包括 Northflank 管理的附加组件和团队自定义附加组件。对于托管数据库,它会提供版本、存储容量和副本选项。它不会发现 BYOC 集群的存储类。

破坏性操作——始终先确认

重要: 对 Northflank 执行任何破坏性操作前,务必停止并明确询问用户是否确认。不要假设先前的授权适用于其他操作或会话——每项操作都必须单独确认。

破坏性操作至少包括:

  • delete service / apiClient.delete.service——不可逆;会丢失容器状态及所有作用域限定为该服务的配置
  • delete addon / apiClient.delete.addon——格外谨慎:addon 存储持久化数据(数据库、队列、缓存)。删除不可逆,且会销毁所有数据,除非用户有近期备份。务必向用户复述 addon 名称,询问是否有备份,且必须等到用户明确回复“是,删除 <addon-id>”后才能继续。
  • delete volume——会销毁持久磁盘中的内容
  • delete project——会移除项目;MCP 工具要求项目必须为空。通过其他界面递归删除也会删除项目中的资源
  • delete secret——可能导致依赖这些密钥的运行中工作负载故障
  • patch secret / update secret / put secret / 带有 runtimeEnvironment、runtimeFiles 或 ports 的 patch service——这些操作会替换你发送的整个映射或数组,因此新增一个键会删除其他所有键。请遵循安全更新映射,并事先备份当前值
  • delete job——会移除任务及其运行历史
  • delete template / 运行会销毁资源的模板,或针对非模板编写时所用项目或环境运行任何 run template(参见模板)
  • delete domain / delete dns-record
  • delete cluster(BYOC/BYOK)——会影响该集群上的所有工作负载
  • 任何会缩减持久状态的 patch / update(例如降低 addon 的副本数——Northflank 会拒绝此操作,但绝不要尝试用这种方式绕过限制)
  • 强制取消用户未启动的运行中任务、构建或流水线

确认规则:

  1. 明确说明你将删除的内容,提供准确 ID,并说明相关数据或状态。
  2. 对于 addon,还需说明 addon 类型、大小,并提醒用户没有备份时数据将无法恢复。
  3. 等待用户针对该特定资源明确回复“是” / “删除” / “继续”。“好的”、沉默或笼统的同意都不算确认。
  4. 如果用户授权删除一项资源,不要连带删除相关资源(例如“服务、它的 addon 和它的 volume”),除非逐项重新确认。
  5. 在符合用户目标时,优先选择可逆方案:使用 pause service 而不是 delete service,删除 addon 前先创建快照或备份等。

CLI 基础知识

安装、登录并选择上下文
npm i -g @northflank/cli
northflank login
northflank context ls
northflank context use
northflank context use project
  • northflank login 会创建上下文,并可打开浏览器以选择或创建令牌。
  • 使用 northflank context use project|service|job 设置默认值,之后的命令便可省略重复的 ID。
  • 使用 northflank command-overview 查看命令树。
检查资源
# Prompts for missing values interactively
northflank get service

# Explicit project and service
northflank get service --projectId <PROJECT_ID> --serviceId <SERVICE_ID>

CLI 默认采用交互模式。若未提供 ID,通常会提示你输入。

在运行中的容器内执行命令
# Interactive shell session
northflank exec service

# One-off command
northflank exec service --cmd "ls -lah /app"

# Run as a specific user
northflank exec service --user root --cmd id

对于任务,请使用 northflank exec job,而不是服务。

在本地转发私有服务或 addon
sudo northflank forward service --projectId <PROJECT_ID> --serviceId <SERVICE_ID>
sudo northflank forward addon --projectId <PROJECT_ID> --addonId <ADDON_ID>

# If sudo path/context resolution causes issues
sudo --preserve-env=PATH,HOME bash -c 'northflank forward service --projectId <PROJECT_ID> --serviceId <SERVICE_ID>'
  • 如果可以接受无根用户转发且只需要通过 IP/端口访问,请添加 --skipHostnames。
  • 使用 northflank forward all --projectId <PROJECT_ID> 一次性打开项目的所有隧道。
使用 JSON 或 YAML 创建或更新资源
northflank create project --help
northflank create project --file ./project.yaml

使用 --projectId 和 --serviceId 等 CLI 标志选择目标资源。--input 中的 JSON 或 --file 中的内容只包含 API 请求正文。将目标 ID 保留在正文之外,不要将正文封装在 SDK 的 parameters、data 或 options 结构中。

northflank patch service deployment --projectId my-project --serviceId my-api \
  --input '{"description":"Public API"}'

JS 客户端基础知识

客户端设置
import { ApiClient, ApiClientInMemoryContextProvider } from '@northflank/js-client';

const contextProvider = new ApiClientInMemoryContextProvider();
await contextProvider.addContext({
  name: 'default',
  token: process.env.NF_API_TOKEN,
});

// Pass true as second arg to throw on HTTP errors
const apiClient = new ApiClient(contextProvider, true);

所有方法都遵循以下模式:

apiClient.{verb}.{resource}({ parameters, data, options })
  • parameters — 路径参数(例如 projectId、serviceId)
  • data — 请求正文(用于创建/更新)
  • options — 查询参数(用于筛选、分页)
创建部署服务(使用镜像)
const result = await apiClient.create.service.deployment({
  parameters: { projectId: 'my-project' },
  data: {
    name: 'my-api',
    billing: { deploymentPlan: 'nf-compute-10' },
    deployment: {
      instances: 1,
      external: { imagePath: 'nginx:latest' },
      docker: { configType: 'default' },
    },
    ports: [{ name: 'http', internalPort: 80, public: true, protocol: 'HTTP' }],
  },
});
const serviceId = result.data.id; // 'my-api'

常见的方案规格:nf-compute-10(0.1 vCPU/256MB)、nf-compute-50(0.5/1GB)、nf-compute-100-2(1/2GB)、nf-compute-200(2/4GB)。完整表格、GPU SKU 以及查询实时列表的方法,请参阅计算与 GPU 方案。

创建组合服务(从 Git 构建并部署)
await apiClient.create.service.combined({
  parameters: { projectId: 'my-project' },
  data: {
    name: 'my-app',
    billing: { deploymentPlan: 'nf-compute-50' },
    vcsData: {
      projectUrl: 'https://github.com/org/repo',
      projectType: 'github',
      projectBranch: 'main',
    },
    buildSettings: {
      dockerfile: {
        buildEngine: 'buildkit',
        dockerFilePath: '/Dockerfile',
        dockerWorkDir: '/',
      },
    },
    deployment: { instances: 1 },
    ports: [{ name: 'app', internalPort: 3000, public: true, protocol: 'HTTP' }],
  },
});
获取/列出服务
// List all services in a project
const { data } = await apiClient.list.services({ parameters: { projectId: 'my-project' } });
const services = data.services;

// Get a single service
const svc = await apiClient.get.service({
  parameters: { projectId: 'my-project', serviceId: 'my-api' },
});
// Deployment rollout state: 'PENDING' | 'IN_PROGRESS' | 'COMPLETED' | 'FAILED'
// COMPLETED describes rollout completion, not application health or process exit.
console.log(svc.data.status.deployment?.status);
// Build state (only present for combined/build services):
// 'QUEUED' | 'PENDING' | 'STARTING' | 'BUILDING' | 'SUCCESS' | 'FAILURE' | ...
console.log(svc.data.status.build?.status);
// Pause is a separate boolean — not encoded in either status above
console.log(svc.data.servicePaused);
在服务中执行命令
// Short-lived command — returns stdout/stderr/exitCode
const result = await apiClient.exec.execServiceCommand(
  { projectId: 'my-project', serviceId: 'my-api' },
  { command: ['ls', '-lah', '/app'] },
);
console.log(result.stdOut);
console.log(result.commandResult.exitCode); // 0 = success

// Long-running / interactive session
const { exec } = apiClient;
const session = await exec.execServiceSession(
  { projectId: 'my-project', serviceId: 'my-api' },
  { shell: 'bash' },
);
session.stdErr.on('data', (chunk) => console.error(chunk));
session.stdIn.write('echo hello\n');
const result2 = await session.waitForCommandResult();

有关命令执行的更多详情,请参阅 references/api/execute-command.md。

流式传输服务日志
const logsClient = await apiClient.get.service.logTail({
  parameters: { projectId: 'my-project', serviceId: 'my-api' },
  options: { lineLimit: 20 },
});

logsClient.on('logs-received', (lines) => {
  lines.forEach((l) => console.log(`[${l.ts.toISOString()}] ${l.log}`));
});
logsClient.on('error', console.error);
await logsClient.start();
// Call await logsClient.stop() when done
暂停/恢复/重启/删除服务
const params = { parameters: { projectId: 'my-project', serviceId: 'my-api' } };

await apiClient.pause.service(params);    // stops billing, keeps config
await apiClient.resume.service(params);   // restarts from paused
await apiClient.restart.service(params);  // rolling restart (keeps running)
await apiClient.delete.service(params);   // permanent, irreversible
更新服务(patch)
// Update image or instance count
await apiClient.patch.service.deployment({
  parameters: { projectId: 'my-project', serviceId: 'my-api' },
  data: {
    deployment: {
      instances: 3,
      external: { imagePath: 'myregistry/myapp:v2' },
    },
  },
});
创建附加组件(数据库)
const { data } = await apiClient.create.addon({
  parameters: { projectId: 'my-project' },
  data: {
    name: 'my-postgres',
    type: 'postgresql',    // postgresql | mongodb | mysql | redis | rabbitmq | minio | memcached
    version: '16',
    billing: {
      deploymentPlan: 'nf-compute-10',
      storage: 4096,       // MB
      replicas: 1,
    },
    tlsEnabled: true,
  },
});
const addonId = data.id; // 'my-postgres'
获取附加组件凭据

如需连接应用,优先使用带有附加组件链接的密钥组。仅在任务需要时读取凭据值。不要将其写入日志或聊天内容。

const creds = await apiClient.get.addon.credentials({
  parameters: { projectId: 'my-project', addonId: 'my-postgres' },
});
// creds.data.username, creds.data.password, creds.data.connectionString, etc.
// Pass required credentials directly to their destination. Do not log their values.
管理密钥组

密钥组可将附加组件连接字符串关联到服务环境变量,和/或存储任意键值密钥。

// Create a secret group with a static env var and a linked addon credential
await apiClient.create.secret({
  parameters: { projectId: 'my-project' },
  data: {
    name: 'app-secrets',
    type: 'secret',              // 'secret' | 'config'
    secretType: 'environment',   // 'environment' | 'arguments' | 'environment-arguments'
    priority: 10,
    secrets: {
      variables: {
        NODE_ENV: 'production',
        API_KEY: 'supersecret',
      },
      // files: { '/etc/app.conf': { data: '<base64>' } },  // file contents must be base64
    },
    addonDependencies: [
      {
        addonId: 'my-postgres',
        keys: [
          { keyName: 'POSTGRES_URI', aliases: ['DATABASE_URL'] },
        ],
      },
    ],
    restrictions: {
      restricted: true,
      nfObjects: [{ id: 'my-api', type: 'service' }],
    },
  },
});

// List secrets in project
const { data } = await apiClient.list.secrets({ parameters: { projectId: 'my-project' } });

// Requires readValues permission. Read only values owned by this group.
const current = await apiClient.get.secret({
  parameters: { projectId: 'my-project', secretId: 'app-secrets' },
  options: { show: 'this' },
});
const variables = current.data.secrets.variables;
if (
  !variables || typeof variables !== 'object' || Array.isArray(variables) ||
  Object.values(variables).some(value =>
    typeof value !== 'string' || value === '[REDACTED]' || /^\*+$/.test(value)
  )
) {
  throw new Error('Cannot update secrets without a complete, unredacted variable map.');
}
await apiClient.patch.secret({
  parameters: { projectId: 'my-project', secretId: 'app-secrets' },
  data: {
    secrets: {
      variables: { ...variables, FEATURE_FLAG: 'true' },
    },
  },
});
安全更新映射(密钥组和服务环境变量)

patch 不会合并映射内部的内容。 发送 secrets.variables、secrets.files、服务的 runtimeEnvironment / runtimeFiles 或 ports 数组时,会替换整个值。未提供的顶层字段保持不变。

请求对包含 A、B、C 的密钥组产生的效果
使用 { description: 'x' } 执行 patch / update仅更改描述
使用 { secrets: { variables: { D: '4' } } } 执行 patch / update变量变为 { D }。A、B、C 将被删除
使用 { data: { D: '4' } } 执行 patch / update不会有任何变化,但调用仍会返回成功,因为未知的正文键会被忽略
put secret(根据正文中的 name 执行更新或插入)类似于 patch,但未提供的 description 和 restrictions 会重置为默认值
  1. 如需添加或更改一个键,请使用 show: 'this' 和 readValues 权限读取该组自身的值。将其合并到完整、未脱敏的映射中,再发送回去。不要将继承的附加组件值复制到该组中。没有按键 patch,也不能通过设为 null 来删除。
  2. 进行任何批量密钥或环境变量重写之前,请保存当前键名(如果用户允许,也保存值),以便出错时可以撤销。Northflank 无法恢复丢失的密钥。
  3. 每次写入后,都要再次读取该组,并在不记录密钥的情况下检查键集合和预期值。仅检查键名无法发现值被覆盖。收到 200 响应并不能证明更改已生效,因为拼写错误或位置错误的字段会被静默忽略。
  4. patch service deployment|combined|build 同样适用:runtimeEnvironment、runtimeFiles 和 ports 会被整体替换,而 deployment 等嵌套对象会逐字段合并。POST /services/{id}/ports 端点也会替换整个列表。
  5. CLI 的 get service 输出可能会省略环境变量映射。密钥组请使用 get secret,服务级别的 runtimeEnvironment 请使用 REST 或 JS 客户端的 get.service 响应。
  6. 对共享凭据,优先使用密钥组,而不是每个服务单独配置 runtimeEnvironment,以免一次服务更新将其覆盖。

没有 readValues 权限时,API 会用星号替代密钥值。MCP 也会对密钥映射进行脱敏。切勿将这些占位符写回:API 会将它们作为字面值存储。如果读取内容已脱敏或不完整,请停止合并。请使用获授权的未脱敏读取结果,或从用户的权威密钥来源获取完整映射。相同限制也适用于密钥文件和服务环境变量映射。

分页

列表端点默认返回 50 个项目。可使用以下两种选项:

// Fetch all pages automatically (multiple API calls)
const all = await apiClient.list.services.all({ parameters: { projectId: 'my-project' } });

// Manual next-page
const page1 = await apiClient.list.services({ parameters: { projectId: 'my-project' } });
if (page1.pagination?.hasNextPage) {
  const page2 = await page1.pagination.getNextPage();
}
错误处理
// Option 1: check result.error (client does NOT throw by default)
const result = await apiClient.get.service({ parameters: { projectId, serviceId } });
if (result.error) {
  console.error(result.error.status, result.error.message);
}

// Option 2: init client with throwOnError = true
const apiClient = new ApiClient(contextProvider, true);
try {
  await apiClient.get.service({ parameters: { projectId, serviceId } });
} catch (err) {
  console.error(err);
}
速率限制标头
const { rawResponse } = await apiClient.get.service({ parameters: { projectId, serviceId } });
const remaining = rawResponse.headers.get('x-ratelimit-remaining');
const reset = rawResponse.headers.get('x-ratelimit-reset'); // seconds

计算与 GPU 方案

所有计算方案、GPU SKU、定价和各区域 GPU 可用性的完整实时表格,均由 scripts/generate_references.js 自动生成到 references/plans.md 中。Northflank 发布新 SKU 或调整价格后,使用 --plans-only --force 重新生成以刷新数据。底层端点为公开端点,无需身份验证:

curl -s https://api.northflank.com/v1/plans   | jq '.data.plans[]   | {id, cpu: .cpuResource, ramMB: .ramResource, hr: .amountPerHour}'
curl -s https://api.northflank.com/v1/regions | jq '.data.regions[] | {id, gpus: (.gpuDevices // [] | map(.id))}'

JS 客户端 / CLI 对应命令:apiClient.list.plans({}) / apiClient.list.regions({}) 和 northflank list plans / northflank list regions。

计算方案标识

格式:nf-compute-<cpu*100>-<ram_gb>(较新版本,明确指定内存)或 nf-compute-<cpu*100>(旧版,内存为默认值)。常见选项:

  • nf-compute-10 — 0.1 vCPU / 256 MB(约 $2.70/月)——Sidecar、轻量工作进程
  • nf-compute-50 — 0.5 vCPU / 1 GB(约 $12/月)——小型 API、定时任务
  • nf-compute-200 — 2 vCPU / 4 GB(约 $48/月)——典型生产服务
  • nf-compute-400-16 — 4 vCPU / 16 GB(约 $144/月)——也可用作 buildPlan

buildPlan 仅接受至少 4 个 vCPU 的方案;若未指定,则默认为 nf-compute-400-16。所有 20 个 SKU 见 references/plans.md。

GPU 方案标识

格式:nf-gpu-<gpuType>-<count>g,方案 ID 中的下划线替换为连字符。请在 deployment.gpu.configuration.gpuType 中保留原始 GPU 类型。后缀 g 是字面字符,不代表单位。该方案已包含 GPU 对应的 CPU / 内存资源——不要将 nf-compute-* 方案与单独的 GPU 组合使用。示例:

data: {
  billing: { deploymentPlan: 'nf-gpu-a100-80-1g' },  // 1× A100 80GB
  deployment: {
    gpu: {
      enabled: true,
      configuration: { gpuType: 'a100-80', gpuCount: 1, timesliced: false },
    },
    storage: { shmSize: 32768 },
    // ...
  },
}
  • gpuType 是型号 ID(小写,不带 nvidia- 前缀)。目前包括:l4-24、a100-40、a100-80、h100-80、h200-141、b200-180、rtx_pro_6000-96。
  • gpuCount 必须是该型号 countOptions 中的一个选项(通常为 1, 2, 4, 8;H200 和 B200 仅支持 8 卡)。无效数量会被拒绝。
  • 在 deployment.gpu.configuration 下设置 GPU 配置。请包含 deployment.gpu.enabled: true;将其置于 billing 下不会启用 GPU 验证。
  • 可用数量因区域而异。请查询目标区域的 gpuDevices[].countOptions,而非使用全局数量集合。
  • H100 1×/8× 方案为 nf-gpu-h100-80-1g / nf-gpu-h100-80-8g。RTX PRO 6000 1×/8× 方案为 nf-gpu-rtx-pro-6000-96-1g / nf-gpu-rtx-pro-6000-96-8g。us-central 支持这些配置。
  • 托管 GPU 工作负载可选配临时存储。API 会根据 GPU 类型和数量设置 deployment.storage.ephemeralStorage.storageSize,并覆盖提供的值。共享内存是独立配置:deployment.storage.shmSize 为可选项。对于托管 GPU,其默认值为每块 GPU 的系统内存乘以 gpuCount;较小的显式值会保留,较大的值则会被限制。CPU 和 BYOC 工作负载的默认值为 64 MiB。示例中显式请求了 32 GiB。有关分配规则和较旧 API 的错误信息,请参阅 references/gpu-storage.md。
  • GPU 按每块 GPU 每小时计费,费用另加于其附带的计算资源之上。定价和各区域的可用性见 references/plans.md。

对于 BYOC 集群,GPU 节点类型由云提供商提供——使用 apiClient.list.cloudProviders.nodeTypes({ options: { hasGpu: true } }) 查询,并定义自定义资源方案(见 references/guides/bring-your-own-cloud.md#create-custom-resource-plans)。BYOC 支持时间切片,托管云不支持。

对于 Northflank 发布的 GPU 基础镜像(预装 PyTorch、CUDA 和 Jupyter),请从 europe-docker.pkg.dev/northflank/public/... 拉取镜像,而不要基于原始的 pytorch/pytorch:* 构建。

常见模式

跟进部署进度并检查应用健康状态

使用 MCP 时,遵循 get_deployment_status 返回的后续操作和轮询间隔。使用 CLI 或 SDK 时,在截止时间内轮询发布状态。失败或截止时间到期时停止,并报告观察到的状态。不要重复创建操作来轮询。

COMPLETED 表示发布已完成,但不能证明应用健康。对于 Web 应用,请确保端点返回预期响应后再报告成功。对于其他工作负载,请使用适当的应用级检查。

自动扩缩配置(在 create/patch 数据中)
data: {
  deployment: { instances: 1 },
  autoscaling: {
    horizontal: {
      enabled: true,
      minReplicas: 1,
      maxReplicas: 10,
      cpu: { enabled: true, thresholdPercentage: 70 },
      rps: { enabled: true, thresholdValue: 500 },
    },
  },
}
模板

模板是 Northflank 的基础设施即代码单元:由节点(项目、服务、附加组件、作业、密钥组、流水线、操作)组成的规范。**运行模板会将其应用于实际资源。**这不是试运行,也不是项目副本。

类型范围用途
团队模板整个团队。可创建项目、集群、服务、数据库、流水线配置或复制完整技术栈
发布流程单个流水线阶段发布版本:备份、构建、迁移、提升
预览环境(预览蓝图)单条流水线为每个分支或拉取请求创建临时环境,并在关闭时拆除

预览模板会创建预览环境。不要用它部署到生产环境。如果模板或目标不明确,请询问用户要使用哪一个。

每次运行对各资源节点的处理方式(updateMode,默认值为 put):

updateMode行为
put(默认值)如果资源不存在则创建,否则用规范替换其配置。省略的可配置字段可能会被重置或清除
patch仅更新提供的字段。如果资源不存在则失败。数组和某些对象仍会替换整个值(参见安全更新映射)
create如果资源不存在则创建;否则跳过,不更改现有资源
  • 节点的 name 用于标识目标资源。更改名称会在旧资源旁边创建第二个资源。移除节点不会删除其资源。
  • 项目上下文来自节点或其父工作流,一个模板可能会影响多个项目。请检查每个节点的上下文,而不只是第一个。
  • 启用自动运行后,通过 UI、API 或 GitOps 更改模板会触发执行。仅关联 GitOps 不会启用自动运行。
  • Northflank 的试运行只会在执行前解析引用、参数和函数,不会预览哪些资源将被替换。

每次 run template 前:

  1. 阅读模板:northflank get template --template <id>(或 apiClient.get.template)。列出每个节点的类型、updateMode、项目上下文和 name。
  2. 将节点名称与目标项目中已有资源的名称进行比较。put 下的每个匹配项都会被覆盖。
  3. 向用户说明:模板 ID、类型、目标项目、将创建和替换的资源,然后等待用户针对本次运行明确确认(参见上述确认规则)。
  4. 如果模板支持通过 arguments 指定目标,请通过它传入目标,而不要编辑模板以指向其他项目。
  5. 运行后,检查运行状态并读取已更改的资源。
await apiClient.run.template({
  parameters: { templateId: 'my-template' },
  data: {
    arguments: {
      REGION: 'europe-west',
      IMAGE: 'myapp:latest',
    },
  },
});
创建 cron 作业
await apiClient.create.job({
  parameters: { projectId: 'my-project' },
  data: {
    name: 'db-migrate',
    billing: { deploymentPlan: 'nf-compute-10' },
    deployment: {
      external: { imagePath: 'myapp:latest' },
      docker: { configType: 'default' },
    },
    settings: {
      cron: { schedule: '0 2 * * *' },  // present = cron job
      concurrencyPolicy: 'Forbid',
    },
    runtimeEnvironment: { MIGRATE: 'true' },
  },
});

// Run it manually now
await apiClient.start.job.run({ parameters: { projectId: 'my-project', jobId: 'db-migrate' } });

注意事项

  1. ID 是经过 slug 化的名称——"My App" 会变成 my-api(slug)。在 API 调用中使用 ID,而不是显示名称。
  2. 附加组件的存储空间和副本数只能增加,创建后无法减少。
  3. 包含附加组件链接的密钥组会在附加组件轮换凭据或发生更改时自动更新连接字符串。
  4. 端口名称最多 8 个字符,且必须以字母开头。
  5. 速率限制各不相同——请检查响应中的速率限制标头,并据此控制操作频率。
  6. put.* 方法采用 upsert 语义——不存在时创建,存在时更新。适用于幂等的 IaC。
  7. 暂停 ≠ 删除——暂停的服务会停止计算资源计费,但会保留配置和卷。
  8. northflank exec --cmd "..." 在没有 TTY 时会丢弃输出——在 CI、Agent 调度框架或任何由 bash -c 包装的环境中,stdout/stderr 都会被静默丢弃。使用 script -q /dev/null northflank exec ...(macOS/BSD)或 script -qfc 'northflank exec ...' /dev/null(Linux)包装命令,以捕获输出。
  9. 服务的 status === "COMPLETED" 表示部署完成,而不是进程已退出。 这不能证明应用运行正常。报告成功前,请确保应用能按预期响应。

参考速查表

我想要……查看这里
从预构建镜像部署服务MCP deploy_app;apiClient.create.service.deployment / northflank create service deployment
从 Git 仓库构建并部署服务MCP deploy_app;apiClient.create.service.combined / northflank create service combined;references/guides/build.md
在容器中运行一次性命令或 Shell 会话apiClient.exec.execServiceCommand / northflank exec service;references/api/execute-command.md
查看服务、作业或插件的实时日志或获取日志apiClient.get.service.logTail / northflank get service logs -f;references/api/log-tailing.md
将私有服务或插件的端口转发到 localhostnorthflank forward service;references/api/forwarding.md
配置托管数据库(Postgres、Redis、Mongo、MySQL……)MCP create_database;apiClient.create.addon / northflank create addon;references/guides/databases-and-persistence.md
通过密钥组将数据库凭据接入服务使用 addonDependencies 的 apiClient.create.secret / northflank create secret;references/api/project/secrets/_index.md
创建 cron 或手动作业MCP deploy_job;使用 settings.cron 的 apiClient.create.job / `northflank create job cron
配置自动扩缩容、副本或资源规格autoscaling.horizontal 字段;references/guides/scale.md
选择计算或 GPU 方案(规格、价格、区域)references/plans.md — 从 /v1/plans 和 /v1/regions 自动生成;slug 模式见计算与 GPU 方案
设置 CI/CD:流水线、发布流程、预览环境references/guides/release.md
将基础设施定义为代码(模板、GitOps、OpenTofu)apiClient.create.template / northflank create template;references/guides/infrastructure-as-code.md
添加带 TLS、CDN 或路径路由的自定义域名references/guides/domains.md;references/api/team/domains/_index.md
为服务附加持久化存储 / 卷apiClient.create.volume / northflank create volume;references/api/project/volumes/_index.md
向运行中的容器上传或下载文件northflank upload service file / download service file;references/api/copy-files.md
配置端口、网络策略、出口 IP、Tailscalereferences/guides/network.md
设置日志接收端、指标、告警、运行状况检查references/guides/observe.md
运行 GPU 工作负载references/guides/gpu-workloads.md
启动 AI 沙箱 / microVM沙箱是一种服务 — 使用 MCP deploy_app,或使用 apiClient.create.service.deployment / northflank create service deployment(不存在 sandbox 动词);references/guides/sandboxes.md
在自己的集群上部署(AWS/GCP/Azure/CoreWeave 上的 BYOC/BYOK)references/guides/bring-your-own-cloud.md
管理团队、RBAC、SSO/MFA、API 令牌references/guides/secure.md、references/guides/collaborate.md
暂停、恢复、重启或删除资源apiClient.{pause,resume,restart,delete}.service / northflank {pause,resume,restart,delete} service — 执行任何删除操作前,请重新阅读破坏性操作

参考文件

平台参考
API 端点参考
操作指南

评论

支持 Markdown