Building resources with value objects
Resources compose from typed value objects in RoundlyConsulting\KubernetesApi\Resources\Types, each serialising to the exact shape the apiserver expects. A pod with probes, resources, environment and volumes:
use RoundlyConsulting\KubernetesApi\Resources\ConfigMap;
use RoundlyConsulting\KubernetesApi\Resources\Secret;
use RoundlyConsulting\KubernetesApi\Resources\Types\Container;
use RoundlyConsulting\KubernetesApi\Resources\Types\Probe;
use RoundlyConsulting\KubernetesApi\Resources\Types\Volume;
$configVolume = Volume::make()->fromConfigMap(ConfigMap::make()->setName('checkout-config'));
$tlsVolume = Volume::make()->fromSecret(Secret::make()->setName('checkout-tls'));
$cacheVolume = Volume::make()->emptyDirectory('cache', ['sizeLimit' => '500Mi']);
$app = Container::make()
->setName('app')
->setImage('registry.example.com/checkout', 'v1.4.0')
->addPort(8080, 'TCP', 'http')
->setEnvironment(['APP_ENV' => 'production', 'LOG_CHANNEL' => 'stderr'])
->addToEnvironmentFromSecret('DB_PASSWORD', 'checkout-db', 'password')
->addToEnvironmentFromConfigMap('FEATURE_FLAGS', 'checkout-config', 'flags')
->addToEnvironmentFromFieldReference('POD_NAME', 'metadata.name')
->setMinimumCpu('250m')
->setMaximumCpu('1')
->setMinimumMemory(256, 'Mi')
->setMaximumMemory(512, 'Mi')
->setReadinessProbe(Probe::http('/healthz', 8080))
->setLivenessProbe(Probe::tcp(8080))
->addVolumeMount($configVolume->mountTo('/etc/checkout'))
->addVolumeMount($tlsVolume->mountTo('/etc/tls'))
->addVolumeMount($cacheVolume->mountTo('/var/cache/checkout'));
$pod = $cluster->pods()
->setNamespace('shop')
->setName('checkout-debug')
->setLabels(['app' => 'checkout', 'purpose' => 'debug'])
->setContainers([$app])
->addVolumes([$configVolume, $tlsVolume, $cacheVolume])
->addImagePullSecret('registry-credentials')
->create();Container
| Method | Writes |
|---|---|
setImage($image, ?string $tag = 'latest') | image as image:tag. A reference that already carries a tag (nginx:1.27) or a digest (nginx@sha256:…) is kept as given, and a null tag leaves the image untagged. A registry port is not a tag: registry.local:5000/app becomes …/app:latest. |
addPort($containerPort, $protocol = 'TCP', $name = null) | ports[]. |
setEnvironment([...]) · addToEnvironment($name, $value) · addMultipleToEnvironment([...]) | env[] — setEnvironment() replaces the list. |
addToEnvironmentFromSecret($name, $secretName, $key = null) | env[].valueFrom.secretKeyRef — the key defaults to the secret name. |
addToEnvironmentFromConfigMap($name, $configMapName, $key) | env[].valueFrom.configMapKeyRef. |
addToEnvironmentFromFieldReference($name, $fieldPath) | env[].valueFrom.fieldRef. |
setMinimumCpu($size) / setMaximumCpu($size) | resources.requests.cpu / resources.limits.cpu. |
setMinimumMemory($size, $measure = 'Gi') / setMaximumMemory(…) | resources.requests.memory / resources.limits.memory. |
setReadinessProbe() · setLivenessProbe() · setStartupProbe() | The three probes, from a Probe. |
addVolumeMount() · addVolumeMounts() · setVolumeMounts() | volumeMounts[], from VolumeMount objects. |
The plural forms take maps: addToEnvironmentFromSecrets(['DB_PASSWORD' => ['checkout-db', 'password']]), addToEnvironmentFromConfigMaps(['FLAGS' => ['checkout-config', 'flags']]) and addToEnvironmentFromFieldReferences(['POD_NAME' => 'metadata.name']). Anything else — command, args, imagePullPolicy — goes through the magic setters.
Probes
Probe::http(), Probe::tcp() and command() build the three probe kinds. Tune thresholds and timings, or any other probe field, with the magic setters:
use RoundlyConsulting\KubernetesApi\Resources\Types\Probe;
Probe::http('/healthz', 8080); // httpGet, scheme HTTP
Probe::http('/ready', 8443, ['X-Probe' => 'kubelet'], 'HTTPS'); // headers + scheme
Probe::tcp(5432); // tcpSocket
Probe::make()->command(['pg_isready', '-U', 'shop']); // exec
// Every probe starts with failureThreshold: 1 and successThreshold: 1
Probe::http('/healthz', 8080)
->setFailureThreshold(3)
->setPeriodSeconds(10)
->setInitialDelaySeconds(5);Volumes, mounts and ports
- Volume::fromConfigMap() and fromSecret() name the volume after its source — checkout-config-config-volume, checkout-tls-secret-volume — made a valid DNS-1123 label (dots become hyphens, cut to 63 characters), or take the volume name as a second argument: fromSecret($secret, 'tls'). Pass one when two long names share their start. An unnamed source throws InvalidResourceException.
- emptyDirectory($name, $options) adds an emptyDir volume; pass its options, such as sizeLimit — without any it sends emptyDir: {}.
- mountTo($mountPath, $subPath = null) turns any volume into a VolumeMount with the matching name.
- Pod takes them through setContainers(), setInitContainers(), addVolume(s)(), setVolumes() and addImagePullSecret(s)(), and reads them back as objects with getContainers(), getInitContainers() and getVolumes().
- Port::http($containerPort = 80) builds a TCP service port 80 targeting the container port; build other ports with Port::make() and the magic setters.
- PersistentVolumeClaimTemplate describes a stateful set’s per-replica claim — see Workloads.
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 cryptoBy 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.