---
title: "ConfigMaps, secrets & networking — Kubernetes API | Roundly"
description: "ConfigMap and Secret data helpers, TLS secrets in one call, services, ingresses and network policies with correct select-all selectors."
url: https://roundly-consulting.com/open-source/docs/kubernetes-api-for-laravel/config-networking
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Kubernetes API for Laravel](https://roundly-consulting.com/open-source/docs/kubernetes-api-for-laravel.md)

# ConfigMaps, secrets & networking

## ConfigMaps

```php
$cluster->configMaps()
    ->setNamespace('shop')
    ->setName('checkout-config')
    ->setData([
        'APP_ENV' => 'production',
        'nginx.conf' => $nginxConfig,
    ])
    ->create();

$config = $cluster->configMaps()->setNamespace('shop')->withName('checkout-config')->find();

$config->getData();                    // the whole map
$config->getData('nginx.conf');        // one key
$config->getData('MISSING', 'n/a');    // with a default

$config->addData('LOG_LEVEL', 'debug')
    ->removeData('APP_ENV')
    ->update();
```

Data keys are file names — nginx.conf, app.env — so getData(), addData() and removeData() always treat them as flat keys, never as dotted attribute paths. getData('0') reads the "0" entry; only a null key returns the whole map. The map always encodes as a JSON object, numeric-string keys included, and setData(\[\]) or removing the last key drops the data field altogether — an empty map would encode as the JSON list \[\], which the apiserver refuses.

## Secrets

Secret::setData() and addData() base64-encode values for you and getData() decodes them, so you only ever handle plain strings. Keys such as tls.crt or .dockerconfigjson stay flat:

```php
$cluster->secrets()
    ->setNamespace('shop')
    ->setName('checkout-db')
    ->setData(['username' => 'checkout', 'password' => $password])   // base64-encoded for you
    ->create();

$secret = $cluster->secrets()->setNamespace('shop')->withName('checkout-db')->find();

$secret->getData('password');          // the decoded plain string
$secret->getData();                    // every key, decoded
$secret->addData('host', 'db.shop.svc.cluster.local')->update();
```

## TLS certificate secrets

Secret supports a typed type plus a TLS convenience that base64-encodes a PEM certificate and key into a kubernetes.io/tls Secret — ready for an ingress or a Traefik TLSStore:

```php
$secret = $cluster->secrets()
    ->setNamespace('default')
    ->setName('wildcard-tls')
    ->asTlsCertificate($pemCertificate, $pemPrivateKey)   // sets type + data['tls.crt'] / data['tls.key']
    ->create();

$secret->getType();              // "kubernetes.io/tls"
$secret->getData('tls.crt');     // the decoded PEM certificate

// Or set an arbitrary Secret type explicitly:
$cluster->secrets()->setName('dockercfg')->setType('kubernetes.io/dockerconfigjson');
```

## Services

```php
use RoundlyConsulting\KubernetesApi\Resources\Types\Port;

$cluster->services()
    ->setNamespace('shop')
    ->setName('checkout')
    ->setType('ClusterIP')
    ->setSelectors(['app' => 'checkout'])
    ->addPort(Port::http(8080)->setName('http'))     // port 80 -> targetPort 8080, TCP
    ->addPort(Port::make()->setName('metrics')->setProtocol('TCP')->setPort(9090)->setTargetPort(9090))
    ->create();

$service = $cluster->services()->setNamespace('shop')->withName('checkout')->find();

$service->getClusterDns();      // checkout.shop.svc.cluster.local
$service->getType();            // 'ClusterIP'
$service->getPorts();           // Port[]
$service->getSelectors();       // ['app' => 'checkout']

// A LoadBalancer that keeps client source IPs
$cluster->services()
    ->setNamespace('shop')
    ->setName('checkout-public')
    ->setType('LoadBalancer')
    ->useLocalTrafficPolicy()                        // externalTrafficPolicy: Local
    ->setSelectors(['app' => 'checkout'])
    ->addPort(Port::http(8080)->setName('http'))
    ->create();
```

## Ingresses

addRule() writes a host, a path and a backend service in one call; addTls() attaches a certificate secret to a list of hosts:

```php
$cluster->ingresses()
    ->setNamespace('shop')
    ->setName('checkout')
    ->setIngressClassName('nginx')
    ->addRule('shop.example.com', '/', 'checkout', 80)             // pathType defaults to Prefix
    ->addRule('shop.example.com', '/api', 'checkout-api', 8080, 'Prefix')
    ->addTls(['shop.example.com'], 'wildcard-tls')
    ->create();

$ingress = $cluster->ingresses()->setNamespace('shop')->withName('checkout')->find();
$ingress->getRules();
$ingress->getTls();
$ingress->getLoadBalancerIngress();   // status.loadBalancer.ingress
```

## Network policies and select-all

An empty label selector means “select all” in Kubernetes and must be sent as the empty object {}, not \[\] — which the apiserver rejects. The selector setters handle this for you, so passing an empty array serialises correctly:

```php
// Default-deny / select-all: an empty podSelector matches every pod in the namespace.
$cluster->networkPolicies()
    ->setNamespace('shop')
    ->setName('default-deny')
    ->setPodSelector([])           // serialises to "podSelector": {}
    ->setPolicyTypes(['Ingress'])
    ->create();

// Then allow the ingress namespace to reach checkout on 8080.
$cluster->networkPolicies()
    ->setNamespace('shop')
    ->setName('allow-ingress-to-checkout')
    ->setPodSelector(['app' => 'checkout'])          // podSelector.matchLabels
    ->setPolicyTypes(['Ingress'])
    ->addIngressRule([
        'from' => [['namespaceSelector' => ['matchLabels' => ['kubernetes.io/metadata.name' => 'ingress']]]],
        'ports' => [['protocol' => 'TCP', 'port' => 8080]],
    ])
    ->create();
```

Service::setSelectors(\[\]) serialises the same way. Workload pod selectors are different: the apiserver refuses an empty selector on apps/v1 workloads (Deployment, ReplicaSet, StatefulSet, DaemonSet), so always give them at least one label, as in setPodsSelectors(\['app' => 'checkout'\]). For any other node that must be an empty object, set it to a RoundlyConsulting\\KubernetesApi\\Resources\\Types\\EmptyObject — it always serialises to {}.

## 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](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## 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.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/kubernetes-api-for-laravel.md)
