11.05 Managing Directories with Kustomize
Abstract
Kustomize can manage Kubernetes manifests spread across multiple directories.
This keeps large applications organized while still allowing one kustomization.yaml file to build and apply everything together.
Why Manage Multiple Directories?
Small projects may keep all YAML files in one folder:
This works, but as the application grows, one folder becomes hard to maintain.
Warning
Keeping every manifest in a single directory can become messy when applications include many services, databases, caches, queues, and environment-specific configs.
Better Directory Structure
A cleaner approach is to group related resources by component.
k8s/
├── api/
│ ├── api-depl.yaml
│ └── api-service.yaml
├── db/
│ ├── db-depl.yaml
│ └── db-service.yaml
└── kustomization.yaml
Apply each directory manually:
But this still requires multiple commands.
Tip
Use a top-level kustomization.yaml file to manage all directories from one place.
Top-Level kustomization.yaml
The root kustomization.yaml can reference files inside subdirectories.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- api/api-depl.yaml
- api/api-service.yaml
- db/db-depl.yaml
- db/db-service.yaml
Build the final manifests:
Apply them to the cluster:
Or use native kubectl support:
Success
This creates all resources together while keeping the source files organized by component.
Example: Larger Application
For larger systems, you may have more components:
k8s/
├── api/
│ ├── api-depl.yaml
│ └── api-service.yaml
├── db/
│ ├── db-depl.yaml
│ └── db-service.yaml
├── cache/
│ ├── redis-depl.yaml
│ ├── redis-service.yaml
│ └── redis-config.yaml
├── kafka/
│ ├── kafka-depl.yaml
│ ├── kafka-service.yaml
│ └── kafka-config.yaml
└── kustomization.yaml
Root kustomization:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- api/api-depl.yaml
- api/api-service.yaml
- db/db-depl.yaml
- db/db-service.yaml
- cache/redis-depl.yaml
- cache/redis-service.yaml
- cache/redis-config.yaml
- kafka/kafka-depl.yaml
- kafka/kafka-service.yaml
- kafka/kafka-config.yaml
Note
This approach works, but the root file can become long if every YAML file is listed individually.
Directory-Level kustomization.yaml
A better production structure is to place a kustomization.yaml inside each component directory.
k8s/
├── kustomization.yaml
├── api/
│ ├── kustomization.yaml
│ ├── api-depl.yaml
│ └── api-service.yaml
├── db/
│ ├── kustomization.yaml
│ ├── db-depl.yaml
│ └── db-service.yaml
├── cache/
│ ├── kustomization.yaml
│ ├── redis-depl.yaml
│ ├── redis-service.yaml
│ └── redis-config.yaml
└── kafka/
├── kustomization.yaml
├── kafka-depl.yaml
├── kafka-service.yaml
└── kafka-config.yaml
Root k8s/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- api/
- db/
- cache/
- kafka/
Example k8s/db/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- db-depl.yaml
- db-service.yaml
Tip
Referencing directories keeps the root file clean and allows each team or component to manage its own resources.
Applying Multiple Directories
Note
kustomize build only renders the final YAML.
It does not deploy anything unless you pipe the output to kubectl apply -f - or use kubectl apply -k.
Recommended Production Layout
k8s/
├── base/
│ ├── api/
│ ├── db/
│ ├── cache/
│ ├── kafka/
│ └── kustomization.yaml
└── overlays/
├── dev/
│ └── kustomization.yaml
├── staging/
│ └── kustomization.yaml
└── prod/
└── kustomization.yaml
Production recommendation
Use base for shared resources and overlays for environment-specific changes.
This avoids duplication and keeps dev, staging, and production consistent.
Example Base kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- api/
- db/
- cache/
- kafka/
commonLabels:
app.kubernetes.io/managed-by: kustomize
Example Prod Overlay
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
commonLabels:
environment: prod
patches:
- path: api-replica-patch.yaml
Example patch:
Example
The base defines the common application structure.
The overlay modifies only what changes for that environment.
Do's
- Group manifests by application component
- Add a
kustomization.yamlin each major directory - Keep the root
kustomization.yamlclean - Use
baseandoverlaysfor environments - Validate output before applying
Don'ts
- Don't keep hundreds of YAML files in one flat directory
- Don't manually apply many directories one by one in production
- Don't duplicate the same manifests across dev, staging, and prod
- Don't mix unrelated services in one component folder
- Don't apply generated output without reviewing it in critical environments
Production Best Practices
Recommended
- Use GitOps-friendly structure
- Keep one component per directory
- Use clear names like
api,db,cache, andkafka - Use overlays for environment-specific configuration
- Keep secrets out of plain YAML unless encrypted with tools like Sealed Secrets or SOPS
- Run validation in CI before applying manifests
Common Mistakes
Avoid these
- Forgetting to include a directory in the root
resources - Referencing files with wrong relative paths
- Creating duplicate resource names across directories
- Applying subdirectories separately and causing drift
- Mixing generated manifests with source manifests
Troubleshooting
| Issue | What to Check |
|---|---|
| Resource not created | Is the file or directory listed under resources? |
| Build fails | Check indentation and relative paths |
| Duplicate resource error | Check repeated names across directories |
| Overlay not applied | Confirm overlay references the correct base |
| kubectl apply fails | Run kustomize build first and inspect output |
Useful commands:
Tip
kubectl diff -k k8s/ is useful before applying changes in production.
Summary
Quote
- Kustomize can manage manifests across multiple directories
- A root
kustomization.yamlcan reference files or folders - Directory-level
kustomization.yamlfiles keep large projects clean - Use
baseandoverlaysfor production-ready structure - Apply with
kubectl apply -k k8s/orkustomize build k8s/ | kubectl apply -f -
Root vs Subdirectory Customizations
Kustomize applies transformations only to the resources listed in the current kustomization.yaml.
If you add a label, namespace, annotation, image transformer, or name prefix inside a subdirectory such as k8s/api/kustomization.yaml, the change applies only to the resources listed in that subdirectory file.
If you add the same transformation in the root k8s/kustomization.yaml, it applies to everything referenced from the root file, including all resources coming from subdirectories such as api/ and db/.
Note
A subdirectory kustomization.yaml controls only its local resource list. The root kustomization.yaml controls everything it includes.
Warning
Be careful with root-level transformations in production. A global namespace, namePrefix, nameSuffix, or commonLabels setting can affect every component included from the root file.
Example
In the shown structure, adding commonLabels inside k8s/db/kustomization.yaml affects only DB resources. Adding commonLabels inside the root k8s/kustomization.yaml affects both API and DB resources.