Connecting to clusters
Every Kubernetes resource takes a cluster prop. That includes
Deployment,
Job,
Manifest, and
HelmChart. The prop accepts
three shapes:
Kubernetes.KubeConfig({ ... }). Any cluster in a kubeconfig file, such as kind, k3s, on-prem, GKE, AKS, or EKS.- A
Kubernetes.Connectionobject. An API endpoint plus a bearer token, client certificate, or exec plugin. - A cluster resource. Any resource with a
connectionattribute, such as aKubernetes.LocalClusteror an EKS cluster from the same Stack.
Every form can also say where workloads built from your code are
pushed, with a registry.
KubeConfig and Connection are plain, serializable data. Nothing
is provisioned for them and they never appear in a plan. Alchemy stores it on each
resource’s state so alchemy destroy can reach the cluster later,
even after you delete the code that declared it.
Use a kubeconfig context
Section titled “Use a kubeconfig context”Kubernetes.KubeConfig authenticates exactly like kubectl:
import * as Kubernetes from "alchemy/Kubernetes";
const cluster = Kubernetes.KubeConfig({ context: "prod-east" });
const api = yield* Kubernetes.Deployment("Api", { cluster, image: "ghcr.io/acme/api:v3", port: 8080,});All options are optional:
pathis the kubeconfig file. It defaults to the first entry of$KUBECONFIG, then~/.kube/config. A leading~is expanded.contextis the context to use. It defaults to the file’scurrent-context.registryis wheremainandcontextworkloads push their images. See Container registries.architectureis the nodes’ CPU architecture,"amd64"or"arm64". It is used as the default image build target.
Name the context explicitly for anything beyond a scratch cluster.
The current context changes whenever someone runs
kubectl config use-context, and a deploy would follow it to a
different cluster.
The file is read at deploy time, on the machine running
alchemy deploy. The API endpoint, certificate authority, and
credentials all come from the selected context. Static tokens,
client certificates, and exec credential plugins are supported.
Cloud CLI contexts
Section titled “Cloud CLI contexts”The cloud CLIs write contexts that mint short-lived tokens through
an exec credential plugin. Alchemy runs the plugin before each
request, so tokens never go stale mid-deploy:
- GKE.
gcloud container clusters get-credentials <cluster>writes a context that runsgke-gcloud-auth-plugin. - AKS.
az aks get-credentials --name <cluster> --resource-group <group>writes the context. Clusters using Microsoft Entra ID also needkubelogin. - EKS.
aws eks update-kubeconfig --name <cluster>writes a context that runsaws eks get-token. See Amazon EKS for the fuller integration.
The plugin must be installed and logged in wherever you deploy from, including CI runners.
Keep the kubeconfig next to the code
Section titled “Keep the kubeconfig next to the code”Point path at a file you control to decouple deploys from your
personal ~/.kube/config:
const cluster = Kubernetes.KubeConfig({ path: "./kubeconfig.yaml", context: "staging",});A relative path is resolved from the directory you run
alchemy deploy in. In CI, write the file from a secret before the
deploy step, or set KUBECONFIG to its location and omit path.
Connect with a bearer token
Section titled “Connect with a bearer token”A raw Kubernetes.Connection names the API endpoint and an auth
descriptor. For a ServiceAccount token or another static bearer
token:
import * as Config from "effect/Config";
const token = yield* Config.String("K8S_TOKEN");
const cluster: Kubernetes.Connection = { endpoint: "https://10.0.0.10:6443", certificateAuthorityData: "LS0tLS1CRUdJTi…", // base64-encoded PEM auth: { kind: "token", token },};certificateAuthorityData is the same base64-encoded PEM bundle a
kubeconfig carries as certificate-authority-data. For self-signed
local clusters you can set insecureSkipTlsVerify: true instead.
Connect with a client certificate
Section titled “Connect with a client certificate”For mutual TLS, pass the PEM certificate and key:
const cluster: Kubernetes.Connection = { endpoint: "https://k8s.internal:6443", certificateAuthorityData: caData, auth: { kind: "client-cert", certificate: certPem, key: keyPem },};Connect with an exec plugin
Section titled “Connect with an exec plugin”Run any command that speaks the Kubernetes ExecCredential protocol without a kubeconfig file:
const cluster: Kubernetes.Connection = { endpoint: "https://k8s.internal:6443", certificateAuthorityData: caData, auth: { kind: "exec", command: "/usr/local/bin/cluster-token", args: ["--cluster", "prod"], env: { TOKEN_PROFILE: "prod" }, },};The plugin is re-run for every request, and a client certificate it returns is used for mutual TLS.
token, client-cert, and exec connections need an explicit
endpoint. Only kubeconfig connections and cluster resources can
discover it.
Credentials in state
Section titled “Credentials in state”Alchemy persists each resource’s connection in state. A kubeconfig
connection stores only the path and context name, and an exec
connection stores the command. A token or client-cert
connection stores the credential itself. Prefer kubeconfig or exec
connections for stacks whose state is shared, and use a remote
state store with restricted access either way.
Deploy to several clusters
Section titled “Deploy to several clusters”cluster is per resource, so one Stack can span clusters:
const east = Kubernetes.KubeConfig({ context: "prod-east" });const west = Kubernetes.KubeConfig({ context: "prod-west" });
for (const [region, cluster] of [ ["East", east], ["West", west],] as const) { yield* Kubernetes.Deployment(`Api${region}`, { cluster, name: "api", image: "ghcr.io/acme/api:v3", port: 8080, });}Move a resource to another cluster
Section titled “Move a resource to another cluster”Alchemy identifies the target cluster by the connection’s auth
descriptor. That is the kubeconfig path and context, the token or
certificate, or the exec command. Changing it replaces the resource.
Alchemy creates it on the new cluster, then deletes it from the old
one. The endpoint, certificate authority, and registry are not
part of that identity, so they can change without replacing
workloads.
When no adapter is registered
Section titled “When no adapter is registered”Each auth.kind is served by a cluster adapter.
Kubernetes.providers() registers kubeconfig, token,
client-cert, and exec. Cloud platforms contribute their own.
For example, EKS clusters need AWS.providers() in the Stack. If a
deploy fails with No Kubernetes cluster adapter is registered for
auth kind …, add the provider layer that contributes it.
Where next
Section titled “Where next”- Container registries. Add a registry to a connection.
- Local clusters. Run a cluster resource on your machine.
- How objects are managed. See what happens when a cluster is unreachable or gone.
Deploymentreference. Read about theclusterprop and every other prop.