부록 A. REST API 문서
Base URL: http://localhost:8081
Authentication
Section titled “Authentication”All endpoints require an API key when API key auth is enabled (default). You can provide it via:
X-API-KEYheaderapi_keyquery parameter
curl -H "X-API-KEY: <your-api-key>" http://localhost:8081/healthzcurl "http://localhost:8081/healthz?api_key=<your-api-key>"Health
Section titled “Health”GET /healthz- Response
{ "status": "ok"}GET /stats- Success:
200 OK
Response
{ "total_stacks": 7, "active_stacks": 7, "node_distribution": { "dev-worker": 3, "dev-worker2": 4 }, "used_node_ports": 7, "reserved_cpu_milli": 700, "reserved_memory_bytes": 939524096}Stack APIs
Section titled “Stack APIs”Create Stack
Section titled “Create Stack”POST /stacks- Body
{ "target_port": 80, "pod_spec": "apiVersion: v1\nkind: Pod\nmetadata:\n name: challenge\nspec:\n containers:\n - name: app\n image: nginx:stable\n ports:\n - containerPort: 80\n protocol: TCP\n resources:\n requests:\n cpu: \"100m\"\n memory: \"128Mi\"\n limits:\n cpu: \"100m\"\n memory: \"128Mi\""}- Success:
201 Created
- Failure:
400 Bad Request(invalid pod spec)400 Bad Request(LimitRange violation)503 Service Unavailable(no available nodeport)503 Service Unavailable(ResourceQuota violation)
Response
{ "stack_id": "stack-716b6384dd477b0b", "pod_id": "stack-716b6384dd477b0b", "namespace": "stacks", "node_id": "dev-worker2", "node_public_ip": "12.34.56.78", "pod_spec": "apiVersion: v1\nkind: Pod\nmetadata:\n name: challenge\nspec:\n automountServiceAccountToken: false\n containers:\n - image: nginx:stable\n name: app\n ports:\n - containerPort: 80\n protocol: TCP\n resources:\n limits:\n cpu: 100m\n memory: 128Mi\n requests:\n cpu: 100m\n memory: 128Mi\n securityContext:\n allowPrivilegeEscalation: false\n privileged: false\n seccompProfile:\n type: RuntimeDefault\n enableServiceLinks: false\n restartPolicy: Never\n securityContext:\n seccompProfile:\n type: RuntimeDefault\nstatus: {}\n", "target_port": 80, "node_port": 31538, "service_name": "svc-stack-716b6384dd477b0b", "status": "creating", "ttl_expires_at": "2026-02-10T04:02:26.535664Z", "created_at": "2026-02-10T02:02:26.535664Z", "updated_at": "2026-02-10T02:02:26.535664Z", "requested_cpu_milli": 100, "requested_memory_bytes": 134217728}List All Stacks
Section titled “List All Stacks”GET /stacks- Success:
200 OK
Response
{ "stacks": [ { "stack_id": "stack-716b6384dd477b0b", "pod_id": "stack-716b6384dd477b0b", "namespace": "stacks", "node_id": "dev-worker2", "node_public_ip": "12.34.56.78", "pod_spec": "apiVersion: v1\nkind: Pod\nmetadata:\n name: challenge\nspec:\n automountServiceAccountToken: false\n containers:\n - image: nginx:stable\n name: app\n ports:\n - containerPort: 80\n protocol: TCP\n resources:\n limits:\n cpu: 100m\n memory: 128Mi\n requests:\n cpu: 100m\n memory: 128Mi\n securityContext:\n allowPrivilegeEscalation: false\n privileged: false\n seccompProfile:\n type: RuntimeDefault\n enableServiceLinks: false\n restartPolicy: Never\n securityContext:\n seccompProfile:\n type: RuntimeDefault\nstatus: {}\n", "target_port": 80, "node_port": 31538, "service_name": "svc-stack-716b6384dd477b0b", "status": "running", "ttl_expires_at": "2026-02-10T04:02:26.535664Z", "created_at": "2026-02-10T02:02:26.535664Z", "updated_at": "2026-02-10T02:06:33.16031Z", "requested_cpu_milli": 100, "requested_memory_bytes": 134217728 } ]}Get Stack
Section titled “Get Stack”GET /stacks/{stack_id}- Success:
200 OK
Response
{ "stack_id": "stack-716b6384dd477b0b", "pod_id": "stack-716b6384dd477b0b", "namespace": "stacks", "node_id": "dev-worker2", "node_public_ip": "12.34.56.78", "pod_spec": "apiVersion: v1\nkind: Pod\nmetadata:\n name: challenge\nspec:\n automountServiceAccountToken: false\n containers:\n - image: nginx:stable\n name: app\n ports:\n - containerPort: 80\n protocol: TCP\n resources:\n limits:\n cpu: 100m\n memory: 128Mi\n requests:\n cpu: 100m\n memory: 128Mi\n securityContext:\n allowPrivilegeEscalation: false\n privileged: false\n seccompProfile:\n type: RuntimeDefault\n enableServiceLinks: false\n restartPolicy: Never\n securityContext:\n seccompProfile:\n type: RuntimeDefault\nstatus: {}\n", "target_port": 80, "node_port": 31538, "service_name": "svc-stack-716b6384dd477b0b", "status": "running", "ttl_expires_at": "2026-02-10T04:02:26.535664Z", "created_at": "2026-02-10T02:02:26.535664Z", "updated_at": "2026-02-10T02:07:29.530829Z", "requested_cpu_milli": 100, "requested_memory_bytes": 134217728}Get Stack Status
Section titled “Get Stack Status”GET /stacks/{stack_id}/status- Success:
200 OK
Response
{ "stack_id": "stack-716b6384dd477b0b", "status": "running", "ttl": "2026-02-10T04:02:26.535664Z", "node_port": 31538, "target_port": 80, "node_public_ip": "12.34.56.78"}Delete Stack
Section titled “Delete Stack”DELETE /stacks/{stack_id}- Success:
200 OK
- Failure:
404 Not Found(stack not found)
Response
{ "deleted": true, "stack_id": "stack-716b6384dd477b0b"}Stack statuses
Section titled “Stack statuses”creating: the stack is being created. The pod may not be running yet.running: the stack is running and ready to accept traffic.stopped: the stack has been stopped by the user. The pod has been deleted.failed: the stack failed to start. Check the pod events/logs for more details.node_deleted: the node where the stack was running has been deleted. The stack is no longer accessible.
Error codes
Section titled “Error codes”400: invalid request body / pod spec validation error400: KubernetesLimitRangeviolation404: stack not found503: cluster saturation, no available nodeport503: KubernetesResourceQuotaviolation500: internal server error