Skip to content

Kubernetes

Host your cluster on any Kubernetes cluster: Postgres runs as a Deployment behind a ClusterIP Service, and the runners run as a Deployment beside it. Callers in the cluster reach the gateway at its Service.

src/Cluster.ts
import * as ClusterKubernetes from "@alchemy.run/effect-cluster/Kubernetes";
import * as Kubernetes from "@alchemy.run/kubernetes";
import * as Layer from "effect/Layer";
export const Kind = Kubernetes.LocalCluster("Kind", { name: "rooms" });
export const Database = ClusterKubernetes.Database("Cluster", { cluster: Kind });
export const Default = ClusterKubernetes.DeploymentPool("Default", { replicas: 2 }).pipe(
Layer.provide(Database),
);

Install @alchemy.run/kubernetes. cluster takes any cluster Alchemy manages, such as AWS.EKS.Cluster, or a Kubernetes.KubeConfig(...).

ClusterKubernetes.Database runs Postgres in a pod, so its data lives as long as the pod does: it suits development and tests. For production, run a managed Postgres and pass its URL to Cluster.Database.fromUrl.

ClusterKubernetes.DeploymentPool builds the pool’s image, pushes it to the cluster’s registry, and runs it as a Deployment. Pods reach each other at their own addresses. The Deployment’s Service serves the gateway at http://{name}.{namespace}.svc.cluster.local:34500:

src/Cluster.ts
import * as ClusterKubernetes from "@alchemy.run/effect-cluster/Kubernetes";
import * as Kubernetes from "@alchemy.run/kubernetes";
import * as Layer from "effect/Layer";
export const Kind = Kubernetes.LocalCluster("Kind", { name: "rooms" });
export const Database = ClusterKubernetes.Database("Cluster", { cluster: Kind });
export const Default = ClusterKubernetes.DeploymentPool("Default", {
replicas: 3,
serviceType: "LoadBalancer",
resources: { requests: { cpu: "500m", memory: "512Mi" } },
}).pipe(Layer.provide(Database));

serviceType: "LoadBalancer" serves the gateway outside the cluster, where the cluster provisions load balancers.

src/Api.ts
import * as Kubernetes from "@alchemy.run/kubernetes";
import * as Effect from "effect/Effect";
import * as HttpServerResponse from "effect/http/HttpServerResponse";
import { Kind } from "./Cluster.ts";
import { Room } from "./Room.ts";
export default Kubernetes.Deployment(
"Api",
{ cluster: Kind, main: import.meta.url, port: 3000 },
Effect.gen(function* () {
const rooms = yield* Room;
return {
fetch: Effect.gen(function* () {
const lobby = yield* rooms.getByName("lobby");
return yield* HttpServerResponse.json({ members: yield* lobby.Join({ name: "sam" }) });
}).pipe(Effect.orDie),
};
}),
);

Every option, with its default, is in the reference: Database and DeploymentPool.