Walkthrough: Build Up Your .platform/kubernetes/ Folder
The Platform Folder Anatomy
page describes the finished .platform/kubernetes/ layout. This walkthrough builds
that layout up one file at a time, so you can see what each piece adds.
The worked example is a bring-your-own ConfigMap: a plain Kubernetes ConfigMap
you author yourself, wire into your base configuration, mount into your
PlatformApplication, and then patch differently per environment. It's a small,
concrete resource that exercises every part of the folder structure.
What You'll Learn
- How to start from an empty
.platform/kubernetes/and add the basekustomization.yaml - What
application.yamlandapplication_customizations.yamldo - How to bring your own
ConfigMapand mount it into your application - How to add
dev/stg/prdoverlays and patch the ConfigMap per environment - How the rendered manifests reach your cluster through ArgoCD
Prerequisites
- An application repository with a
.platform/folder (or an empty one to fill in). - Familiarity with the PlatformApplication resource — this walkthrough mounts a ConfigMap into one.
kubectlv1.21+ (or a standalone Kustomize v4+) to render the manifests locally withkubectl kustomize. The overlays use Kustomize'spatches:field, which needs a newer Kustomize than the onekubectlbundled before v1.21.
The Big Picture
Everything under base/ is shared; each environment folder layers a small patch on
top. You render one environment by pointing kubectl kustomize at its folder — e.g.
kubectl kustomize .platform/kubernetes/dev (or .../stg, .../prd).
Step 1 — Start with the base kustomization.yaml
Create the base folder and its Kustomization. This file is the orchestrator — it lists the resources that make up your base configuration. Start with it empty; you'll add resources as you create them.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- application.yaml
configurations:
- application_customizations.yaml
resources— the manifests Kustomize includes in the output.configurations— extra transformer config; here it points atapplication_customizations.yaml(added next).
Step 2 — Add application.yaml and application_customizations.yaml
application.yaml is your main PlatformApplication manifest — the desired state of
your app. Keep the common configuration here; environment-specific values come
later via patches.
apiVersion: meta.p6m.dev/v1alpha1
kind: PlatformApplication
metadata:
name: web-application
spec:
deployment:
replicas: 3
image: my-app
config:
LOG_LEVEL: "info"
application_customizations.yaml tells Kustomize which field holds the container image,
so CI image-tag updates land in the right place:
images:
- path: spec/deployment/image
kind: PlatformApplication
spec.config is a map of key/value pairs the operator injects as environment
variables. That's ideal for a handful of settings. When you need to ship files —
a properties file, a config document, TLS-adjacent data — bring your own ConfigMap
and mount it, which is exactly what the next step does.
Step 3 — Bring your own ConfigMap
Author a plain Kubernetes ConfigMap. Nothing about it is platform-specific — this is
the "bring your own" part.
apiVersion: v1
kind: ConfigMap
metadata:
name: web-application-config
data:
app.properties: |
log.level=info
feature.x.enabled=false
greeting.txt: "Hello from base"
Wire it into the base Kustomization by adding it to resources:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- application.yaml
- configmap.yaml
configurations:
- application_customizations.yaml
Now mount it into the application. Add a volumeMounts entry to the PlatformApplication
that points at the ConfigMap by name:
apiVersion: meta.p6m.dev/v1alpha1
kind: PlatformApplication
metadata:
name: web-application
spec:
deployment:
replicas: 3
image: my-app
volumeMounts:
- name: app-config
mountPath: /etc/app-config
source:
configMap:
name: web-application-config
config:
LOG_LEVEL: "info"
The platform-application-operator turns that volumeMounts entry into a pod volume
and a container mount. The keys of your ConfigMap become files under mountPath
(/etc/app-config/app.properties, /etc/app-config/greeting.txt). ConfigMap and Secret
mounts default to read-only; set readOnly: false on the mount if your app needs to
write there.
Every Deployment the operator emits carries reloader.stakater.com/auto: "true". When
you change the ConfigMap — including via the per-environment patch in the next step —
Reloader rolls the Deployment so the pod picks
up the new files. No manual restart needed.
Step 4 — Add environment overlays
Create one folder per environment. Each references ../base and layers on patches. Start
with dev:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base
patches:
- path: application_patch.yaml
- path: configmap_patch.yaml
Patch the application for dev — here, turning on debug logging and a feature flag:
apiVersion: meta.p6m.dev/v1alpha1
kind: PlatformApplication
metadata:
name: web-application
spec:
config:
LOG_LEVEL: "debug" # Override log level for dev
ENABLE_FEATURE_X: "true" # Enable feature X in dev
And patch the ConfigMap for dev. A patches entry matches the base resource by
kind + name and strategic-merges the data keys you list — keys you don't mention keep
their base values:
apiVersion: v1
kind: ConfigMap
metadata:
name: web-application-config
data:
greeting.txt: "Hello from dev"
app.properties: |
log.level=debug
feature.x.enabled=true
stg and prd follow the same shape with their own values — e.g. prd's
configmap_patch.yaml sets greeting.txt: "Hello from production" and
log.level=warn.
Step 5 — Render and verify
Render any environment locally to see the merged result:
kubectl kustomize .platform/kubernetes/dev
The dev output shows both patches applied — the ConfigMap carries the dev greeting and
the PlatformApplication carries the dev config:
apiVersion: v1
data:
app.properties: |
log.level=debug
feature.x.enabled=true
greeting.txt: Hello from dev
kind: ConfigMap
metadata:
name: web-application-config
---
apiVersion: meta.p6m.dev/v1alpha1
kind: PlatformApplication
metadata:
name: web-application
spec:
config:
ENABLE_FEATURE_X: "true"
LOG_LEVEL: debug
deployment:
image: my-app
replicas: 3
volumeMounts:
- mountPath: /etc/app-config
name: app-config
source:
configMap:
name: web-application-config
Rendering stg or prd produces the same structure with that environment's values.
Step 6 — How it reaches the cluster
You don't apply these manifests by hand. The organization's .platform repository
points ArgoCD at each environment overlay (see
Platform Repository Anatomy and
ArgoCD Integration). ArgoCD renders the overlay
and applies the PlatformApplication and ConfigMap; the platform-application-operator
then reconciles the PlatformApplication into a Deployment whose pod mounts your
ConfigMap:
Mounts:
/etc/app-config from app-config (ro)
Volumes:
app-config:
Type: ConfigMap
Name: web-application-config
From here, editing configmap_patch.yaml in an environment and merging the change is all
it takes — ArgoCD syncs the updated ConfigMap and Reloader restarts the pod onto the new
files.
Final folder structure
.platform
└── kubernetes
├── base
│ ├── application.yaml
│ ├── application_customizations.yaml
│ ├── configmap.yaml
│ └── kustomization.yaml
├── dev
│ ├── application_patch.yaml
│ ├── configmap_patch.yaml
│ └── kustomization.yaml
├── stg
│ ├── application_patch.yaml
│ ├── configmap_patch.yaml
│ └── kustomization.yaml
└── prd
├── application_patch.yaml
├── configmap_patch.yaml
└── kustomization.yaml
Related
- Platform Folder Anatomy — reference for the finished folder structure
- Platform Repository Anatomy — how the organization's
.platformrepository references these overlays - ArgoCD Integration — how ArgoCD deploys from these manifests