NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Kubernetes API for Laravel

The Kubernetes facade

Everything starts at the Kubernetes facade (RoundlyConsulting\KubernetesApi\Facades\Kubernetes). It hands out clusters — immutable clients — and, through them, resource objects (Pod, Deployment, …) that read and write the apiserver. Calls without a cluster name go to the default cluster from config/kubernetes.php:

use RoundlyConsulting\KubernetesApi\Facades\Kubernetes;

Kubernetes::pods()->get();                                   // default cluster, default namespace
Kubernetes::namespace('shop')->deployments()->get();         // default cluster, scoped to shop
Kubernetes::cluster('production')->services()->get();        // a named cluster

Kubernetes::ping();                                          // bool — does the apiserver answer?
Kubernetes::version()->gitVersion;                           // "v1.34.0" (a VersionInfo DTO)

Kubernetes::hasCluster('production');                        // bool
Kubernetes::clusters();                                      // ['default', 'production']

Kubernetes::url('https://127.0.0.1:6443')->withToken($token); // a new, blank ad-hoc cluster
Kubernetes::fromKubeConfig(context: 'staging');              // a new cluster from a kubeconfig context

Method reference

MethodReturnsWhat it does
cluster(?string $name = null)ClusterA configured or registered cluster — the default one when null. Resolved once and reused.
hasCluster(string $name) · clusters()bool · list<string>Whether a cluster exists; every configured and registered name.
registerCluster(string $name, Closure $definition)voidDefine a cluster in code; overrides a configured one of the same name.
registerResource(string $name, string $class)voidRegister a resource class under an accessor name for every cluster.
namespace(string $namespace)ClusterThe default cluster, scoped to one namespace.
ping() · version()bool · VersionInfoHealth and build information of the default cluster.
url(string $url)ClusterA new, blank ad-hoc cluster.
connect(KubeConfig $config)ClusterA new ad-hoc cluster from a resolved connection.
fromKubeConfig(?string $path, ?string $context) · inCluster()ClusterA new ad-hoc cluster from a kubeconfig context or the pod’s service account.
resource(string $class)ResourceAny resource class, bound to the default cluster.
pods(), deployments(), services(), … (33 accessors)the resourceEvery packaged resource, bound to the default cluster.
apps(), tenantNamespace(), …resource / macro resultA custom resource registered under that name, or a Cluster macro — on the default cluster.
fake()KubernetesFakeSwap in the in-memory apiserver for tests — see Testing.

The Cluster handle

cluster(), namespace(), url(), connect(), fromKubeConfig() and inCluster() all return a RoundlyConsulting\KubernetesApi\Cluster. Every Cluster has the same 33 accessors as the facade, plus its own identity, health checks and a raw request() escape hatch that is authenticated, rate limited and faked like everything else:

$cluster = Kubernetes::cluster('production');

$cluster->name();                   // 'production' (null for ad-hoc clusters)
$cluster->defaultNamespace();       // from clusters.production.namespace
$cluster->hasResource('apps');      // is an accessor registered under that name?
$cluster->getUrl();                 // plus getToken(), getManagerName(), shouldVerify()…

// Raw escape hatch — authenticated, rate limited and faked like the typed resources
$response = $cluster->request('GET', '/apis/apps/v1/namespaces/shop/deployments', ['limit' => 10]);
$response->json('items');
Cluster methodReturnsNotes
name()?stringThe registration name; null for ad-hoc clusters (url(), connect(), fromKubeConfig(), inCluster()).
url() · with…() · without…() · withManagerName() · withDefaultNamespace()a copyConnection and credentials — see Connecting to a cluster.
namespace(string) · namespaceScope()Cluster · ?stringA copy scoped to one namespace; the scope, if any.
defaultNamespace()stringThe soft default for namespaced resources.
applyConfig(KubeConfig)a copyReplaces URL, token, certificate, key, CA and verification.
resource(class-string) · hasResource(string)Resource · boolAny resource class bound to this cluster; whether an accessor name is registered.
ping() · version()bool · VersionInfoping() is false on an apiserver error, a connection failure or a missing URL; a rate-limit exhaustion still throws.
request($method, $path, $query = [], $body = '', $contentType = null, $stream = false)ResponseRaw escape hatch through the cluster’s transport; a failed response throws KubernetesException.
getUrl() · getToken() · getManagerName() · shouldVerify() · getPathTo…()readersThe credentials the cluster carries.
  • Clusters are immutable: every with…() / without…() call, url(), withManagerName(), withDefaultNamespace() and namespace() return a new cluster, so a client handed out by the facade can never be re-pointed or re-credentialed by another caller.
  • Named clusters are resolved once and reused; url(), connect(), fromKubeConfig() and inCluster() build a new ad-hoc cluster on every call.
  • Cluster::execute() is @internal — it opens the exec WebSocket for Pod::exec(); call exec() on a pod instead.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.