# orca.kube

> A module of Orca's API.

Runs on Kubernetes: a dista cluster per run, made and removed by the scheduler (K8S.md).

With `ORCA_RUNNER=kubernetes`, the scheduler starts a run by creating, in
`ORCA_RUNS_NAMESPACE` (default `orca-runs`), from the image the pipeline
was registered with (`orca register --image`):

| Object | |
|---|---|
| A Job, `orca-<run>-<start>` | the driver: `<binary> resume <run>` |
| A Pod and a Service, `orca-<run>-<start>-head` | the dista head, for a pipeline with tasks |
| `workers` Pods, `orca-<run>-<start>-worker-<i>` | dista's workers, for a pipeline with tasks |

All are labelled `orca.run`, `orca.start` (the run's start count),
`orca.pipeline` and `orca.role`, and the head, its Service and the workers
are owned by the Job, so deleting the Job deletes them. The Job has
`activeDeadlineSeconds` (`ORCA_RUN_DEADLINE`, default a day) and
`ttlSecondsAfterFinished` (10 minutes), and `backoffLimit: 0`, as orca
retries runs itself. The driver reaches Postgres through the Secret
`ORCA_RUN_SECRET` (default `orca-db`, key `url`) in that namespace, and the
head through `DISTA_HEAD`; the scheduler's variables named in
`ORCA_RUN_ENV` are copied to every pod.

Every tick, `sweep` deletes the objects of a run that isn't running at that
start any more, and those of a Job that has finished, first appending its
driver pod's log to the run's `driver.log` under `ORCA_LOGS`: what's left after a
run ends, a run restarted on a new cluster, and what a scheduler that was
killed left behind. Pods ask for `ORCA_DRIVER_CPU`, `ORCA_HEAD_CPU` and
`ORCA_WORKER_CPU` (default 500m, 250m and 1) and `ORCA_POD_MEMORY` (512Mi)
each; `cpu_millis` is a run's total, which the scheduler checks against
`ORCA_VCPU_BUDGET` before making a cluster.

## Structs

### `RunSpec`

```mojo
struct RunSpec
```

What one start of a run needs made.

Implements: `Copyable`, `Movable`

Fields:

- `run: Int`
- `start: Int`
- `pipeline: String`
- `image: String`
- `binary: String`
- `workers: Int`: 0 for a pipeline without dista tasks: no head, no workers.
- `allow_new_code: Bool`

### `KubeRunner`

```mojo
struct KubeRunner
```

Implements: `Movable`

Fields:

- `k: Client`
- `namespace: String`
- `secret: String`
- `driver_cpu: Int`
- `head_cpu: Int`
- `worker_cpu: Int`
- `memory: String`
- `deadline: Int`
- `env: List[String]`: Names of the scheduler's variables copied to every pod.

#### `__init__`

```mojo
def __init__(out self)
```

#### `cpu_of`

```mojo
def cpu_of(self, workers: Int) -> Int
```

The CPU a run asks for, in thousandths: its driver, and its head and workers if it has any.

#### `start`

```mojo
def start(self, r: RunSpec)
```

Makes the run's driver Job, and its head, Service and workers if it has tasks.

#### `remove`

```mojo
def remove(self, run: Int)
```

Deletes everything labelled with the run, whatever its start.

#### `sweep`

```mojo
def sweep(self, mut db: State) -> Int
```

Deletes the objects of runs that aren't running at their start, and of Jobs that have finished; returns how many it deleted.

## Functions

### `cpu_millis`

```mojo
def cpu_millis(s: String) -> Int
```

A CPU quantity, `500m` or `2` or `1.5`, in thousandths.

## Aliases

### `DISTA_PORT`

```mojo
comptime DISTA_PORT = 6390
```
