[{"data":1,"prerenderedAt":667},["ShallowReactive",2],{"navigation":3,"\u002Fen\u002Fblog\u002Fwhat-is-kustomize":4,"\u002Fen\u002Fblog\u002Fwhat-is-kustomize-surround":657},[],{"id":5,"title":6,"authors":7,"badge":13,"body":14,"date":647,"description":648,"extension":649,"image":650,"lastUpdated":13,"meta":652,"navigation":118,"path":653,"published":118,"seo":654,"stem":655,"tags":13,"__hash__":656},"posts\u002Fen\u002F3.blog\u002F59.what-is-kustomize.md","What Is Kustomize? Managing Kubernetes Configs Cleanly",[8],{"name":9,"to":10,"avatar":11},"Thomas Ens","\u002Fabout\u002Fthomasens",{"src":12},"\u002Fimages\u002Fblog\u002Fauthors\u002Fthomas.jpeg",null,{"type":15,"value":16,"toc":634},"minimark",[17,34,39,42,45,49,57,64,69,76,186,189,193,196,204,214,255,258,262,265,268,326,341,353,357,360,417,424,430,434,445,466,475,482,523,527,530,537,540,547,551,554,557,599,602,609,612,616,624,627,630],[18,19,20,21,26,27,33],"p",{},"Anyone running multiple environments on ",[22,23,25],"a",{"href":24},"\u002Fen\u002Fblog\u002Fwhat-is-kubernetes","Kubernetes"," knows the problem: the same manifests slightly tweaked for dev, staging, and prod, and at some point something just doesn't match up anymore. ",[22,28,32],{"href":29,"rel":30},"https:\u002F\u002Fkustomize.io\u002F",[31],"nofollow","Kustomize"," solves exactly this problem without falling back on a templating language. The result: YAML files that always remain valid Kubernetes YAML but can still be adapted flexibly.",[35,36,38],"h2",{"id":37},"the-problem-with-copy-paste-configurations","The problem with copy-paste configurations",[18,40,41],{},"A typical Kubernetes project starts innocently enough: a Deployment, a Service, maybe an Ingress. Then the second environment comes along, and you copy the files and change a few values. Then the third. Eventually you end up with six directories that are 90% identical and no reasonable way to roll out a change consistently.",[18,43,44],{},"This isn't a rare edge case — it's the normal state in growing teams that built out deployments quickly without a deliberate structure. Kustomize addresses exactly this: instead of duplicating files, you describe differences relative to a base.",[35,46,48],{"id":47},"what-is-kustomize-and-how-does-it-work","What is Kustomize and how does it work",[18,50,51,52,56],{},"Kustomize is an open-source tool for the declarative management of Kubernetes configurations. It was developed by Google and has been integrated directly into ",[53,54,55],"code",{},"kubectl"," since Kubernetes 1.14. The core principle: there is a base — a foundational configuration — and overlays that adapt this base to different contexts.",[18,58,59,60,63],{},"Important: Kustomize doesn't use a templating language. All files remain valid Kubernetes YAML at all times — no ",[53,61,62],{},".Values.image",", no logic, no loops. That makes the configuration significantly easier to read and reduces the cognitive load when reviewing changes.",[65,66,68],"h3",{"id":67},"the-kustomizationyaml-the-heart-of-it-all","The kustomization.yaml — the heart of it all",[18,70,71,72,75],{},"Every Kustomize structure revolves around the ",[53,73,74],{},"kustomization.yaml"," file. It describes which resources should be combined and which modifications should be applied:",[77,78,83],"pre",{"className":79,"code":80,"language":81,"meta":82,"style":82},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","apiVersion: kustomize.config.k8s.io\u002Fv1beta1\nkind: Kustomization\n\nresources:\n  - deployment.yaml\n  - service.yaml\n\nnamePrefix: dev-\n\ncommonLabels:\n  environment: development\n","yaml","",[53,84,85,102,113,120,129,138,146,151,162,167,175],{"__ignoreMap":82},[86,87,90,94,98],"span",{"class":88,"line":89},"line",1,[86,91,93],{"class":92},"swJcz","apiVersion",[86,95,97],{"class":96},"sMK4o",":",[86,99,101],{"class":100},"sfazB"," kustomize.config.k8s.io\u002Fv1beta1\n",[86,103,105,108,110],{"class":88,"line":104},2,[86,106,107],{"class":92},"kind",[86,109,97],{"class":96},[86,111,112],{"class":100}," Kustomization\n",[86,114,116],{"class":88,"line":115},3,[86,117,119],{"emptyLinePlaceholder":118},true,"\n",[86,121,123,126],{"class":88,"line":122},4,[86,124,125],{"class":92},"resources",[86,127,128],{"class":96},":\n",[86,130,132,135],{"class":88,"line":131},5,[86,133,134],{"class":96},"  -",[86,136,137],{"class":100}," deployment.yaml\n",[86,139,141,143],{"class":88,"line":140},6,[86,142,134],{"class":96},[86,144,145],{"class":100}," service.yaml\n",[86,147,149],{"class":88,"line":148},7,[86,150,119],{"emptyLinePlaceholder":118},[86,152,154,157,159],{"class":88,"line":153},8,[86,155,156],{"class":92},"namePrefix",[86,158,97],{"class":96},[86,160,161],{"class":100}," dev-\n",[86,163,165],{"class":88,"line":164},9,[86,166,119],{"emptyLinePlaceholder":118},[86,168,170,173],{"class":88,"line":169},10,[86,171,172],{"class":92},"commonLabels",[86,174,128],{"class":96},[86,176,178,181,183],{"class":88,"line":177},11,[86,179,180],{"class":92},"  environment",[86,182,97],{"class":96},[86,184,185],{"class":100}," development\n",[18,187,188],{},"This file is the only place where Kustomize \"knows\" what should happen with the resources. All other files remain untouched.",[65,190,192],{"id":191},"bases-and-overlays-in-practice","Bases and overlays in practice",[18,194,195],{},"The typical directory structure looks like this:",[77,197,202],{"className":198,"code":200,"language":201},[199],"language-text","k8s\u002F\n├── base\u002F\n│   ├── deployment.yaml\n│   ├── service.yaml\n│   └── kustomization.yaml\n└── overlays\u002F\n    ├── dev\u002F\n    │   └── kustomization.yaml\n    ├── staging\u002F\n    │   └── kustomization.yaml\n    └── prod\u002F\n        ├── kustomization.yaml\n        └── replica-patch.yaml\n","text",[53,203,200],{"__ignoreMap":82},[18,205,206,207,209,210,213],{},"The ",[53,208,74],{}," in the ",[53,211,212],{},"prod"," overlay references the base and adds a patch:",[77,215,217],{"className":79,"code":216,"language":81,"meta":82,"style":82},"resources:\n  - ..\u002F..\u002Fbase\n\npatches:\n  - path: replica-patch.yaml\n",[53,218,219,225,232,236,243],{"__ignoreMap":82},[86,220,221,223],{"class":88,"line":89},[86,222,125],{"class":92},[86,224,128],{"class":96},[86,226,227,229],{"class":88,"line":104},[86,228,134],{"class":96},[86,230,231],{"class":100}," ..\u002F..\u002Fbase\n",[86,233,234],{"class":88,"line":115},[86,235,119],{"emptyLinePlaceholder":118},[86,237,238,241],{"class":88,"line":122},[86,239,240],{"class":92},"patches",[86,242,128],{"class":96},[86,244,245,247,250,252],{"class":88,"line":131},[86,246,134],{"class":96},[86,248,249],{"class":92}," path",[86,251,97],{"class":96},[86,253,254],{"class":100}," replica-patch.yaml\n",[18,256,257],{},"The patch itself is again valid YAML and only overwrites the fields that differ in production — for example, the number of replicas.",[35,259,261],{"id":260},"patches-and-transformations","Patches and transformations",[18,263,264],{},"Kustomize supports two types of patches, each suited for different use cases.",[18,266,267],{},"A strategic merge patch works as if you were laying a YAML fragment over the original. You only specify the fields that should change, and the rest remains intact:",[77,269,271],{"className":79,"code":270,"language":81,"meta":82,"style":82},"apiVersion: apps\u002Fv1\nkind: Deployment\nmetadata:\n  name: my-app\nspec:\n  replicas: 3\n",[53,272,273,282,291,298,308,315],{"__ignoreMap":82},[86,274,275,277,279],{"class":88,"line":89},[86,276,93],{"class":92},[86,278,97],{"class":96},[86,280,281],{"class":100}," apps\u002Fv1\n",[86,283,284,286,288],{"class":88,"line":104},[86,285,107],{"class":92},[86,287,97],{"class":96},[86,289,290],{"class":100}," Deployment\n",[86,292,293,296],{"class":88,"line":115},[86,294,295],{"class":92},"metadata",[86,297,128],{"class":96},[86,299,300,303,305],{"class":88,"line":122},[86,301,302],{"class":92},"  name",[86,304,97],{"class":96},[86,306,307],{"class":100}," my-app\n",[86,309,310,313],{"class":88,"line":131},[86,311,312],{"class":92},"spec",[86,314,128],{"class":96},[86,316,317,320,322],{"class":88,"line":140},[86,318,319],{"class":92},"  replicas",[86,321,97],{"class":96},[86,323,325],{"class":324},"sbssI"," 3\n",[18,327,328,329,332,333,336,337,340],{},"A JSON patch is more precise and allows targeted operations like ",[53,330,331],{},"add",", ",[53,334,335],{},"remove",", or ",[53,338,339],{},"replace"," on individual fields via JSONPath syntax. For most use cases, the strategic merge patch is enough. JSON patch makes sense when you need to, for example, remove a single element from a list or insert something at a specific position.",[18,342,343,344,332,346,349,350,352],{},"Kustomize also offers transformations like ",[53,345,156],{},[53,347,348],{},"nameSuffix",", and ",[53,351,172],{},", which are applied globally to all resources. This is especially useful for uniquely naming resources across different overlays and avoiding confusion.",[35,354,356],{"id":355},"configmap-and-secret-generators","ConfigMap and secret generators",[18,358,359],{},"A common problem in Kubernetes projects: ConfigMaps and Secrets are updated manually, but Pods don't notice and keep running with the old values until the next restart. Kustomize solves this with generators.",[77,361,363],{"className":79,"code":362,"language":81,"meta":82,"style":82},"configMapGenerator:\n  - name: app-config\n    files:\n      - config\u002Fapp.properties\n    options:\n      disableNameSuffixHash: false\n",[53,364,365,372,384,391,399,406],{"__ignoreMap":82},[86,366,367,370],{"class":88,"line":89},[86,368,369],{"class":92},"configMapGenerator",[86,371,128],{"class":96},[86,373,374,376,379,381],{"class":88,"line":104},[86,375,134],{"class":96},[86,377,378],{"class":92}," name",[86,380,97],{"class":96},[86,382,383],{"class":100}," app-config\n",[86,385,386,389],{"class":88,"line":115},[86,387,388],{"class":92},"    files",[86,390,128],{"class":96},[86,392,393,396],{"class":88,"line":122},[86,394,395],{"class":96},"      -",[86,397,398],{"class":100}," config\u002Fapp.properties\n",[86,400,401,404],{"class":88,"line":131},[86,402,403],{"class":92},"    options",[86,405,128],{"class":96},[86,407,408,411,413],{"class":88,"line":140},[86,409,410],{"class":92},"      disableNameSuffixHash",[86,412,97],{"class":96},[86,414,416],{"class":415},"sfNiH"," false\n",[18,418,419,420,423],{},"Kustomize computes a hash from the content of the referenced files and appends it to the ConfigMap's name. When the content changes, the name changes — and Kubernetes automatically rolls out the Deployment again. If you don't want this behavior, you can disable it with ",[53,421,422],{},"disableNameSuffixHash: true",".",[18,425,426,427,429],{},"For Secrets, the principle is identical, except the values are base64-encoded. Sensitive data obviously shouldn't live directly in the ",[53,428,74],{}," — it should be supplied via external secret-management solutions. Kustomize is not a replacement for those.",[35,431,433],{"id":432},"kubectl-kustomize-directly-integrated","kubectl kustomize — directly integrated",[18,435,436,437,440,441,444],{},"Since Kubernetes 1.14, Kustomize is usable without a separate installation. Instead of ",[53,438,439],{},"kustomize build"," piped manually into ",[53,442,443],{},"kubectl apply",", a single command is enough:",[77,446,450],{"className":447,"code":448,"language":449,"meta":82,"style":82},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","kubectl apply -k overlays\u002Fprod\u002F\n","bash",[53,451,452],{"__ignoreMap":82},[86,453,454,457,460,463],{"class":88,"line":89},[86,455,55],{"class":456},"sBMFI",[86,458,459],{"class":100}," apply",[86,461,462],{"class":100}," -k",[86,464,465],{"class":100}," overlays\u002Fprod\u002F\n",[18,467,206,468,471,472,423],{},[53,469,470],{},"-k"," flag tells kubectl to interpret the directory as a Kustomize structure. If you want to inspect the generated manifests before applying, you can print them to stdout with ",[53,473,474],{},"kubectl kustomize overlays\u002Fprod\u002F",[18,476,477,478,481],{},"The version built into kubectl lags slightly behind the standalone ",[53,479,480],{},"kustomize"," binary. If you need the latest features or bug fixes, it's best to install Kustomize separately:",[77,483,485],{"className":447,"code":484,"language":449,"meta":82,"style":82},"# With brew (macOS\u002FLinux)\nbrew install kustomize\n\n# Or directly via Go\ngo install sigs.k8s.io\u002Fkustomize\u002Fkustomize\u002Fv5@latest\n",[53,486,487,493,504,508,513],{"__ignoreMap":82},[86,488,489],{"class":88,"line":89},[86,490,492],{"class":491},"sHwdD","# With brew (macOS\u002FLinux)\n",[86,494,495,498,501],{"class":88,"line":104},[86,496,497],{"class":456},"brew",[86,499,500],{"class":100}," install",[86,502,503],{"class":100}," kustomize\n",[86,505,506],{"class":88,"line":115},[86,507,119],{"emptyLinePlaceholder":118},[86,509,510],{"class":88,"line":122},[86,511,512],{"class":491},"# Or directly via Go\n",[86,514,515,518,520],{"class":88,"line":131},[86,516,517],{"class":456},"go",[86,519,500],{"class":100},[86,521,522],{"class":100}," sigs.k8s.io\u002Fkustomize\u002Fkustomize\u002Fv5@latest\n",[35,524,526],{"id":525},"kustomize-vs-helm-which-tool-when","Kustomize vs. Helm. Which tool when?",[18,528,529],{},"This is one of those questions that comes up regularly in Kubernetes teams and has no universal answer.",[18,531,532,536],{},[22,533,535],{"href":534},"\u002Fen\u002Fblog\u002Fwhat-is-a-helm-chart","Helm"," is a full package manager with a templating engine. It allows logic in configurations, manages release history, and supports rollbacks. Helm is the right choice when you're distributing packages — finished, reusable application charts that will be installed by other teams or organizations.",[18,538,539],{},"Kustomize isn't a package manager — it's a configuration overlay tool. It's the better choice when you want to ship your own deployments to different environments without needing templating logic. The configuration stays simpler, the files stay readable, and there's no additional layer of abstraction.",[18,541,542,543,546],{},"In practice, the two don't exclude each other. A common pattern is to use Helm for the initial rendering of charts (",[53,544,545],{},"helm template",") and then overlay the generated manifests via Kustomize. That combines Helm's packaging capabilities with Kustomize's simplicity for environment-specific adjustments.",[35,548,550],{"id":549},"kustomize-in-gitops-workflows","Kustomize in GitOps workflows",[18,552,553],{},"Kustomize and GitOps fit together well because both are built on the principle of \"Git as the single source of truth.\" Tools like ArgoCD and Flux have native Kustomize support built in.",[18,555,556],{},"With ArgoCD, it's enough to specify the overlay directory in the Application resource:",[77,558,560],{"className":79,"code":559,"language":81,"meta":82,"style":82},"source:\n  repoURL: https:\u002F\u002Fgithub.com\u002Fexample\u002Fk8s-config\n  targetRevision: HEAD\n  path: overlays\u002Fprod\n",[53,561,562,569,579,589],{"__ignoreMap":82},[86,563,564,567],{"class":88,"line":89},[86,565,566],{"class":92},"source",[86,568,128],{"class":96},[86,570,571,574,576],{"class":88,"line":104},[86,572,573],{"class":92},"  repoURL",[86,575,97],{"class":96},[86,577,578],{"class":100}," https:\u002F\u002Fgithub.com\u002Fexample\u002Fk8s-config\n",[86,580,581,584,586],{"class":88,"line":115},[86,582,583],{"class":92},"  targetRevision",[86,585,97],{"class":96},[86,587,588],{"class":100}," HEAD\n",[86,590,591,594,596],{"class":88,"line":122},[86,592,593],{"class":92},"  path",[86,595,97],{"class":96},[86,597,598],{"class":100}," overlays\u002Fprod\n",[18,600,601],{},"ArgoCD automatically detects that this is a Kustomize structure and renders the manifests accordingly. Changes to the base or an overlay trigger a sync — the cluster always stays aligned with the state in the repository.",[18,603,604,605,608],{},"Flux works similarly through the ",[53,606,607],{},"Kustomization"," CRD, which points to a directory in the repository and syncs either on a schedule or event-driven.",[18,610,611],{},"The result is a traceable, audited deployment process: every configuration change is a Git commit with an author, timestamp, and diff.",[35,613,615],{"id":614},"conclusion","Conclusion",[18,617,618,619,623],{},"Kustomize is a pragmatic answer to a very real Kubernetes problem: the same resources across different environments. Instead of copy-paste YAML or complex ",[22,620,622],{"href":621},"\u002Fen\u002Fblog\u002Fsimplify-kubernetes-configuration","templating logic",", base + overlays give you a clean, reviewable structure — while staying fully within valid Kubernetes YAML.",[18,625,626],{},"If you're running your own workloads and mostly need to manage variants (dev\u002Fstaging\u002Fprod, customer- or tenant-specific adjustments, feature toggles via patches), Kustomize is often the simplest and most robust choice. Helm remains strong when you want to package, distribute, and manage releases — and in many teams, the two tools even work in combination.",[18,628,629],{},"The bottom line: Kustomize reduces friction, minimizes sources of error, and makes GitOps workflows significantly more pleasant — especially when your infrastructure grows and you still want to stay in control.",[631,632,633],"style",{},"html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":82,"searchDepth":104,"depth":104,"links":635},[636,637,641,642,643,644,645,646],{"id":37,"depth":104,"text":38},{"id":47,"depth":104,"text":48,"children":638},[639,640],{"id":67,"depth":115,"text":68},{"id":191,"depth":115,"text":192},{"id":260,"depth":104,"text":261},{"id":355,"depth":104,"text":356},{"id":432,"depth":104,"text":433},{"id":525,"depth":104,"text":526},{"id":549,"depth":104,"text":550},{"id":614,"depth":104,"text":615},"2026-04-10","Kustomize manages Kubernetes configurations through bases and overlays — no templates. YAML stays readable, valid, and flexibly adaptable across environments.","md",{"src":651},"\u002Fimages\u002Fblog\u002Fwhat-is-kustomize.jpg",{},"\u002Fen\u002Fblog\u002Fwhat-is-kustomize",{"title":6,"description":648},"en\u002F3.blog\u002F59.what-is-kustomize","55_y3VVG3kAUhsJnHbtUeTuO4QFW0Ar2nPAxAeO-Xd0",[658,663],{"title":659,"path":660,"stem":661,"description":662,"children":-1},"Docker vs Kubernetes: Compose, Swarm, and K8s Compared","\u002Fen\u002Fblog\u002Fdocker-vs-kubernetes","en\u002F3.blog\u002F58.docker-vs-kubernetes","Docker, Docker Compose, Docker Swarm, and Kubernetes head-to-head: which tool fits which problem, and when does it make sense to switch?",{"title":664,"path":24,"stem":665,"description":666,"children":-1},"What Is Kubernetes? A Practical Guide to Container Orchestration","en\u002F3.blog\u002F6.what-is-kubernetes","What is Kubernetes and how does container orchestration work? Learn about K8s architecture, Pods, Services, auto-scaling, and when Kubernetes is the right fit for your project.",1776079521231]