본문으로 바로가기 본문 바로가기
WIKI 기술 지식 베이스

Machines API로 Machines 관리하기 (Managing Machines with the Machines API)

원문 보기 위키 갱신

이 가이드는 Machines API 위에 구축할 때 실제로 필요하게 될 패턴을 다뤄요: Machine 복제, flyctl과의 동기화 유지, 서비스 구성, auto-stop/start 동작 관리, 설정 업데이트까지요. 단순히 앱을 배포하는 것이라면 fly deploy를 사용하고, 프로그래매틱한 제어가 필요할 때 이 가이드를 참고하세요.

출처: 문서

본문

Illustration by Annie Ruygt of a big book about the Machines API **[Machines 리소스 API](/machines/api/machines-resource)는 모든 엔드포인트를 문서화합니다. 이 가이드는 그 위에 구축할 때 실제로 필요하게 될 패턴을 다룹니다: Machine 복제, `flyctl`과의 동기화 유지, 서비스 구성, auto-stop/start 동작 관리, 설정 업데이트.**

그냥 앱을 배포하는 거라면 fly deploy를 사용하세요. 이 가이드는 프로그래매틱한 제어가 필요하거나, 플랫폼을 구축하거나, 자체 코드에서 Machine을 관리하거나, flyctl이 직접 지원하지 않는 일을 할 때를 위한 거예요.

시작하기 전에

Fly.io API 토큰이 필요해요. 환경 변수로 설정하세요:

export FLY_TOKEN=$(fly tokens create deploy -a YOUR_APP)

Deploy 토큰은 단일 앱으로 범위가 한정되며 API 접근에 가장 안전한 옵션이에요. 여러 앱을 관리하는 것처럼 더 넓은 접근이 필요하다면 org 수준 토큰을 사용할 수 있어요. 토큰에 대한 자세한 내용은 이 페이지에서 확인하세요.

Machines API 기본 URL은 https://api.machines.dev/v1이에요. 모든 요청에는 Authorization 헤더가 필요해요:

curl -H "Authorization: Bearer ***" \
    https://api.machines.dev/v1/apps/YOUR_APP/machines

기존 Machine에서 Machine 만들기

API로 Machine을 만드는 가장 신뢰할 수 있는 방법은 기존 Machine의 설정에서 시작하는 거예요. 새 Machine이 fly launch나 fly deploy로 만든 것처럼 동작해야 한다면 특히 유용해요. 그 명령들은 JSON을 처음부터 만들 때 놓치기 쉬운 메타데이터, 서비스, 기타 설정을 지정해요.

워크플로:

  1. 소스 Machine의 설정을 가져와요. API나 flyctl을 사용하세요:

    # Via API
    curl -H "Authorization: Bearer ***" \
        https://api.machines.dev/v1/apps/YOUR_APP/machines/MACHINE_ID
    
    # Via flyctl
    fly machine status MACHINE_ID --display-config
    
  2. 필요에 맞게 JSON을 수정해요 — 리전을 바꾸고, 리소스를 조정하고, 환경 변수를 업데이트하세요.

  3. 수정된 설정을 POST해 새 Machine을 만들어요:

    curl -H "Authorization: Bearer ***" \
      -H "Content-Type: application/json" \
      -X POST https://api.machines.dev/v1/apps/YOUR_APP/machines \
      -d @config.json
    

명령줄 플래그가 있는 fly machine run을 사용할 수도 있지만, 완전한 JSON 설정에서 시작한다면 API가 더 간단해요.

API로 만든 Machines를 flyctl에 보이게 하기

설정을 처음부터 만들거나 메타데이터를 제거하면 API로 직접 만든 Machines는 기본적으로 "분리된(detached)" 상태예요. 존재하고 실행되지만, fly deploy와 fly scale은 프로세스 그룹에 속한 Machines만 관리하므로 건드리지 않아요. flyctl이 관리하는 Machine의 설정을 복사해서 Machine을 만들면 fly_platform_version과 fly_process_group 메타데이터가 그대로 전달되므로 새 Machine이 자동으로 프로세스 그룹에 속한다는 점에 주의하세요.

Machine을 flyctl 관리 하에 두려면 두 메타데이터 키를 설정하세요:

  • fly_platform_version: v2여야 해요
  • fly_process_group: 기존 프로세스 그룹의 이름(예: app, worker)

flyctl로:

fly machine update MACHINE_ID \
  --metadata fly_platform_version=v2 \
  --metadata fly_process_group=app

또는 API로 만들 때 Machine 설정 JSON에 메타데이터를 포함하세요:

{
  "config": {
    "metadata": {
      "fly_platform_version": "v2",
      "fly_process_group": "app"
    }
  }
}

설정하면 Machine은 그 프로세스 그룹의 일부가 돼요. 다음 fly deploy가 그룹의 나머지와 함께 업데이트할 거예요. 다음 배포 전까지는 fly status에서 해당 Machine에 VERSION이 표시되지 않는다는 점에 주의하세요.

Machine을 flyctl과 독립적으로 두고 싶다면 — 예를 들어 일회성 워커나 전적으로 자체 도구로 관리되는 Machine — 메타데이터를 남겨 두지 마세요. fly status는 그것들을 detached로 나열한다는 점을 기억하세요.

API로 서비스 구성

fly.toml에서는 [http_service]나 [[services]]를 사용해 트래픽이 앱에 도달하는 방식을 정의해요. API에 해당하는 것은 Machine 설정의 services 속성이에요.

services 구성은 Fly 프록시가 Machine으로 연결을 라우팅하는 방식을 제어해요: 포트, 프로토콜, 동시성 제한, auto-stop/start 동작까지요. 다음은 전형적인 예시예요:

{
  "config": {
    "services": [
      {
        "ports": [
          { "port": 443, "handlers": ["tls", "http"] },
          { "port": 80, "handlers": ["http"] }
        ],
        "protocol": "tcp",
        "internal_port": 8080,
        "concurrency": {
          "type": "connections",
          "hard_limit": 25,
          "soft_limit": 20
        },
        "autostop": "suspend",
        "autostart": true,
        "min_machines_running": 1
      }
    ]
  }
}
**중요:** 프로세스 그룹 안에서 모든 Machine은 동일한 서비스 구성을 가져야 합니다. Fly 프록시는 일관성을 기대해요. Machine A가 하드 한도 25로 포트 8080에서 연결을 받아들이는데 Machine B가 다른 설정을 갖고 있다면 라우팅 동작이 예측 불가능해집니다.

기존 Machine의 설정으로 작업한다면(위에서 설명한 대로) services는 이미 있어요. 필요한 부분을 수정하되 그룹 전체에서 일관성을 유지하세요.

Machine 설정 업데이트

Machines API는 PATCH를 지원하지 않아요 — 변경하려는 필드만 보낼 수는 없어요. 대신 업데이트 흐름은 다음과 같아요:

  1. 전체 Machine 설정을 GET으로 가져와요:

    curl -H "Authorization: Bearer ***" \
        https://api.machines.dev/v1/apps/YOUR_APP/machines/MACHINE_ID
    
  2. 응답에서 config 객체를 추출해 수정해요 — 서비스를 추가하고, 환경 변수를 바꾸고, 리소스를 조정하세요.

  3. 수정된 설정을 감싸서 POST로 다시 보내요. GET 응답은 설정을 Machine 객체 안에 중첩해서 반환하지만, POST 엔드포인트는 최상위에 {"config": ...} 래퍼를 기대해요:

    curl -H "Authorization: Bearer ***" \
      -H "Content-Type: application/json" \
      -X POST https://api.machines.dev/v1/apps/YOUR_APP/machines/MACHINE_ID \
      -d @updated-config.json
    

    여기서 updated-config.json은 다음과 같이 생겼어요:

    {
      "config": {
          ...your modified config object...
      }
    }
    

항상 새 GET부터 시작하세요. 오래된 설정을 캐시해두고 나중에 POST하지 마세요. 그 사이에 다른 프로세스(또는 fly deploy)가 Machine의 설정을 변경했을 수 있거든요.

참고: Machine 설정을 업데이트하면 중지/시작 주기가 트리거돼요. 핫 리로드가 아니에요. 실행 중인 Machine을 업데이트할 때는 짧은 다운타임을 계획하세요.

Auto-stop, autostart, 그리고 suspend

Fly 프록시는 유휴 Machine을 자동으로 중지하거나 suspend하고, 요청이 오면 다시 시작할 수 있어요. 이것은 fly.toml의 auto_stop_machines와 auto_start_machines에 해당하는 API로, services 속성에서 Machine별로 구성돼요.

각 서비스 항목의 관련 필드:

Field Values What it does
autostop false, true, "suspend" What happens when the Machine has no traffic and there's excess capacity. false disables autostop. true stops the Machine (cold start on restart). "suspend" suspends the Machine (preserves memory, faster resume). The API also accepts "off" and "stop" as aliases, but normalizes them to false and true respectively.
autostart true, false Whether the proxy boots this Machine when a request arrives and no running Machine can serve it. Must be a boolean — the API rejects string values.
min_machines_running integer Minimum Machines to keep running in the primary region, even when idle

프록시가 Machine을 중지하기로 결정하는 방법

프록시는 활성 연결을 추적해요. Machine에 연결이 0개이고 같은 프로세스 그룹의 다른 Machine이 부하를 처리할 수 있으면, 프록시는 이를 초과 용량으로 간주하고 autostop을 트리거해요. concurrency.soft_limit이 그 임계값이에요. 그룹 전체의 총 연결이 Machine이 불필요할 만큼 충분히 낮아지면, 그 Machine은 중지되거나 suspend돼요.

Machine이 자신의 리전에서 유일하더라도 중지될 수 있어요. 연결이 0개이고 autostop이 활성화되어 있다면 프록시는 중지하거나 suspend할 거예요. autostart가 활성화되어 있다면 다음 요청에서 자동으로 다시 시작돼요.

중지 vs suspend: 중지된 Machine은 재시작 시 처음부터 부팅되므로 콜드 스타트를 기대해야 해요. Suspend된 Machine은 메모리 상태를 보존하고 더 빨리 재개되지만, 모든 워크로드가 suspend를 깔끔하게 지원하는 것은 아니에요(자세히 읽기 — 재개 후 시계 어긋남 같은 흔한 문제).

autostart와 autostop 동기화 유지

autostop을 활성화했는데 autostart를 비활성화하면 Machine은 중지되고 다시는 돌아오지 않아요. 요청은 503을 반환할 거예요. autostart를 활성화했는데 autostop을 비활성화하면 시작된 Machine은 무기한 계속 실행되고 다시 축소되지 않아요. 일반적으로 둘 다 설정하거나 둘 다 설정하지 마세요.

오래 실행되는 백그라운드 작업

이것이 가장 흔한 함정이에요. Machine이 HTTP 요청을 받고, 백그라운드 작업을 시작한 다음 즉시 응답을 반환하면, 프록시는 활성 연결이 0이라고 보고 Machine을 autostop시켜 백그라운드 작업을 죽일 수 있어요. 백그라운드 워커에 대한 자세한 내용은 이 가이드를 확인하세요.

작동하는 접근 방식:

  • 연결을 계속 열어 두세요. 작업이 실행되는 동안 연결이 활성 상태로 유지되도록 진행 상황을 클라이언트에 스트리밍하거나 long-polling을 사용하세요. 프록시는 활성 연결이 있는 Machine은 중지하지 않아요.
  • 워커의 autostop을 비활성화하세요. autostop을 "off"로 설정하고 작업이 완료되면 애플리케이션이 process.exit()(또는 이에 상응하는 것)를 호출하게 하세요. 수명 주기를 직접 관리하면 프록시는 관여하지 않아요.
  • 별도의 프로세스 그룹을 사용하세요. 웹 반대편 Machine이 일반 autostop을 사용하는 동안 워커를 autostop: "off"로 다른 프로세스 그룹으로 실행하세요. 이렇게 하면 비용 절감이 백그라운드 처리에는 영향을 주지 않고 웹 티어에만 적용돼요.

서비스가 없는 Machines

Machine에 services 설정이 없으면(HTTP나 TCP 서비스가 없으면) Fly 프록시는 전혀 관리하지 않아요. auto-stop이나 auto-start하지 않고 — API로 중지하거나 스스로 종료할 때까지 그냥 실행돼요. 그 수명 주기는 전적으로 재시작 정책에 의해 결정돼요.

이것은 cron 스타일 작업, 작업을 폴링하는 큐 워커, 또는 인바운드 연결을 받지 않는 어떤 것에도 적합한 설정이에요.

재시작 정책 설정

서비스가 없는 Machines는 재시작 정책을 통해 자체 수명 주기를 관리해요. Machine 설정에서 재시작 정책을 설정하세요:

{
  "config": {
    "restart": {
      "policy": "on-failure",
      "max_retries": 5
    }
  }
}

사용 가능한 정책:

  • "no" — 종료 시 재시작하지 않음
  • "always" — 종료 시 항상 재시작
  • "on-failure" — 0이 아닌 종료 시에만 max_retries까지 재시작

Machines API가 지원하지 않는 작업

Machines REST API는 Machine 수명 주기와 대부분의 앱 수준 작업을 다뤄요. 조직이나 커스텀 네트워크 프로비저닝에 관련된 것 같은 일부 주변 작업은 여전히 GraphQL API를 필요로 해요. GraphQL API는 flyctl이 사용하는 내부 인터페이스이며 안정성 보장이 없어서, 예고 없이 바뀔 수 있어요.

가능하면 GraphQL API에 직접 접근하기보다 flyctl 자체를 호출하세요. CLI 플래그가 내부 API보다 더 안정적인 인터페이스예요.

flyctl을 사용할 수 없다면(예: 설정 중에 시스템이 셸 명령을 실행하지 못하는 경우) GraphQL 호출을 리버스 엔지니어링할 수 있어요:

LOG_LEVEL=debug fly <command>

이렇게 하면 GraphQL 엔드포인트와 페이로드를 포함한 전체 API 통신이 출력돼요. 이 요청들을 복사해서 자체 코드에서 실행할 수 있어요. flyctl이 업데이트되면 깨질 수 있다는 점을 기억하세요.

관련 자료

더 알아보기 (Learn more)